Repository: hypermail-project/hypermail Branch: master Commit: 10c9cbe6e60e Files: 566 Total size: 12.7 MB Directory structure: gitextract_0pcap6jv/ ├── .gitignore ├── COPYING ├── Changelog ├── FILES ├── INSTALL ├── KNOWN_BUGS ├── Makefile.in ├── README ├── README.CVS ├── README.git ├── TODO ├── UPGRADE ├── acconfig.h ├── aclocal.m4 ├── archive/ │ ├── .indent.pro │ ├── 1998 │ ├── Makefile.in │ ├── README │ ├── lists.h │ ├── mbox2hypermail.c │ ├── msg2archive.c │ ├── runtest │ └── test-msg ├── autogen.sh ├── config.guess ├── config.h.in ├── config.sub ├── configs/ │ ├── hmrc.example │ ├── hypermail-footer.hyp │ ├── hypermail-index.hyp │ ├── hypermail-msg.hyp │ └── hypermail.rc ├── configure ├── configure.ac ├── contrib/ │ ├── canonicalize.pl │ ├── cron_hypermail │ ├── fixhtime.pl │ ├── hoaf-28/ │ │ ├── README │ │ ├── collect_snipplets.py │ │ ├── create_archive_snipplet.py │ │ ├── footer_html.hdr │ │ ├── haof-0.1.dtd │ │ ├── hypermail-2b28-2b28+.patch │ │ └── top_html.hdr │ ├── hyperfeed.pl │ ├── hypetombox.pl │ ├── ls2mail │ ├── mailbox_date_trimmer/ │ │ ├── README.html │ │ ├── README.mailbox_reader │ │ ├── mailbox_date_trimmer.py │ │ └── mailbox_reader.py │ ├── msg2hypermailarchive.py │ └── runtest ├── docs/ │ ├── Makefile.in │ ├── archive_search.html │ ├── attachments.txt │ ├── customizing.html │ ├── hmrc.4 │ ├── hmrc.html │ ├── hypermail-faq.html │ ├── hypermail.1 │ ├── hypermail.html │ └── index_hypermail.txt ├── install-sh ├── lcc/ │ ├── README.txt │ ├── defaults.h │ ├── dirent.c │ ├── dirent.h │ ├── getdate.c │ ├── hypermail_files.txt │ ├── lcc_extras.c │ ├── lcc_extras.h │ ├── pcre.h │ ├── pcre_chartables.c │ └── pcre_config.h ├── libcgi/ │ ├── .indent.pro │ ├── Makefile.in │ ├── cgi.h │ ├── form_ent.c │ ├── form_tags.c │ ├── get_cgi_info.c │ ├── html.c │ ├── libcgi.html │ ├── main.c │ ├── mcode.c │ ├── strops.c │ ├── syn_mime.c │ ├── syn_url.c │ └── template.c ├── ltmain.sh ├── maketgz ├── patchlevel.h ├── src/ │ ├── .indent.pro │ ├── .splintrc │ ├── Makefile.in │ ├── base64.c │ ├── base64.h │ ├── date.c │ ├── defaults.h.in │ ├── dmatch.c │ ├── dmatch.h │ ├── domains.c │ ├── domains.h │ ├── file.c │ ├── finelink.c │ ├── finelink.h │ ├── fnv/ │ │ ├── Makefile.in │ │ ├── README │ │ ├── aclocal.m4 │ │ ├── config.guess │ │ ├── config.in │ │ ├── config.sub │ │ ├── configure │ │ ├── configure.in │ │ ├── configure.scan │ │ ├── fnv.h │ │ ├── fnv32.c │ │ ├── fnv64.c │ │ ├── hash_32.c │ │ ├── hash_64.c │ │ ├── have_ulong64.c │ │ ├── ltconfig │ │ └── ltmain.sh │ ├── getdate.h │ ├── getdate.texi │ ├── getdate.y │ ├── getname.c │ ├── getname.h │ ├── hypermail.c │ ├── hypermail.h │ ├── lang.c │ ├── lang.h │ ├── lock.c │ ├── mail.c │ ├── mem.c │ ├── parse.c │ ├── parse.h │ ├── pcre/ │ │ ├── 132html │ │ ├── AUTHORS │ │ ├── CMakeLists.txt │ │ ├── COPYING │ │ ├── ChangeLog │ │ ├── CheckMan │ │ ├── CleanTxt │ │ ├── Detrail │ │ ├── HACKING │ │ ├── INSTALL │ │ ├── LICENCE │ │ ├── Makefile.am │ │ ├── Makefile.in │ │ ├── NEWS │ │ ├── NON-AUTOTOOLS-BUILD │ │ ├── NON-UNIX-USE │ │ ├── PrepareRelease │ │ ├── README │ │ ├── RunGrepTest │ │ ├── RunTest │ │ ├── RunTest.bat │ │ ├── aclocal.m4 │ │ ├── ar-lib │ │ ├── cmake/ │ │ │ ├── COPYING-CMAKE-SCRIPTS │ │ │ ├── FindEditline.cmake │ │ │ ├── FindPackageHandleStandardArgs.cmake │ │ │ └── FindReadline.cmake │ │ ├── compile │ │ ├── config-cmake.h.in │ │ ├── config.guess │ │ ├── config.h.generic │ │ ├── config.h.in │ │ ├── config.sub │ │ ├── configure │ │ ├── configure.ac │ │ ├── depcomp │ │ ├── dftables.c │ │ ├── doc/ │ │ │ ├── html/ │ │ │ │ ├── NON-AUTOTOOLS-BUILD.txt │ │ │ │ ├── README.txt │ │ │ │ ├── index.html │ │ │ │ ├── pcre-config.html │ │ │ │ ├── pcre.html │ │ │ │ ├── pcre16.html │ │ │ │ ├── pcre32.html │ │ │ │ ├── pcre_assign_jit_stack.html │ │ │ │ ├── pcre_compile.html │ │ │ │ ├── pcre_compile2.html │ │ │ │ ├── pcre_config.html │ │ │ │ ├── pcre_copy_named_substring.html │ │ │ │ ├── pcre_copy_substring.html │ │ │ │ ├── pcre_dfa_exec.html │ │ │ │ ├── pcre_exec.html │ │ │ │ ├── pcre_free_study.html │ │ │ │ ├── pcre_free_substring.html │ │ │ │ ├── pcre_free_substring_list.html │ │ │ │ ├── pcre_fullinfo.html │ │ │ │ ├── pcre_get_named_substring.html │ │ │ │ ├── pcre_get_stringnumber.html │ │ │ │ ├── pcre_get_stringtable_entries.html │ │ │ │ ├── pcre_get_substring.html │ │ │ │ ├── pcre_get_substring_list.html │ │ │ │ ├── pcre_jit_exec.html │ │ │ │ ├── pcre_jit_stack_alloc.html │ │ │ │ ├── pcre_jit_stack_free.html │ │ │ │ ├── pcre_maketables.html │ │ │ │ ├── pcre_pattern_to_host_byte_order.html │ │ │ │ ├── pcre_refcount.html │ │ │ │ ├── pcre_study.html │ │ │ │ ├── pcre_utf16_to_host_byte_order.html │ │ │ │ ├── pcre_utf32_to_host_byte_order.html │ │ │ │ ├── pcre_version.html │ │ │ │ ├── pcreapi.html │ │ │ │ ├── pcrebuild.html │ │ │ │ ├── pcrecallout.html │ │ │ │ ├── pcrecompat.html │ │ │ │ ├── pcrecpp.html │ │ │ │ ├── pcredemo.html │ │ │ │ ├── pcregrep.html │ │ │ │ ├── pcrejit.html │ │ │ │ ├── pcrelimits.html │ │ │ │ ├── pcrematching.html │ │ │ │ ├── pcrepartial.html │ │ │ │ ├── pcrepattern.html │ │ │ │ ├── pcreperform.html │ │ │ │ ├── pcreposix.html │ │ │ │ ├── pcreprecompile.html │ │ │ │ ├── pcresample.html │ │ │ │ ├── pcrestack.html │ │ │ │ ├── pcresyntax.html │ │ │ │ ├── pcretest.html │ │ │ │ └── pcreunicode.html │ │ │ ├── index.html.src │ │ │ ├── pcre-config.1 │ │ │ ├── pcre-config.txt │ │ │ ├── pcre.3 │ │ │ ├── pcre.txt │ │ │ ├── pcre16.3 │ │ │ ├── pcre32.3 │ │ │ ├── pcre_assign_jit_stack.3 │ │ │ ├── pcre_compile.3 │ │ │ ├── pcre_compile2.3 │ │ │ ├── pcre_config.3 │ │ │ ├── pcre_copy_named_substring.3 │ │ │ ├── pcre_copy_substring.3 │ │ │ ├── pcre_dfa_exec.3 │ │ │ ├── pcre_exec.3 │ │ │ ├── pcre_free_study.3 │ │ │ ├── pcre_free_substring.3 │ │ │ ├── pcre_free_substring_list.3 │ │ │ ├── pcre_fullinfo.3 │ │ │ ├── pcre_get_named_substring.3 │ │ │ ├── pcre_get_stringnumber.3 │ │ │ ├── pcre_get_stringtable_entries.3 │ │ │ ├── pcre_get_substring.3 │ │ │ ├── pcre_get_substring_list.3 │ │ │ ├── pcre_jit_exec.3 │ │ │ ├── pcre_jit_stack_alloc.3 │ │ │ ├── pcre_jit_stack_free.3 │ │ │ ├── pcre_maketables.3 │ │ │ ├── pcre_pattern_to_host_byte_order.3 │ │ │ ├── pcre_refcount.3 │ │ │ ├── pcre_study.3 │ │ │ ├── pcre_utf16_to_host_byte_order.3 │ │ │ ├── pcre_utf32_to_host_byte_order.3 │ │ │ ├── pcre_version.3 │ │ │ ├── pcreapi.3 │ │ │ ├── pcrebuild.3 │ │ │ ├── pcrecallout.3 │ │ │ ├── pcrecompat.3 │ │ │ ├── pcrecpp.3 │ │ │ ├── pcredemo.3 │ │ │ ├── pcregrep.1 │ │ │ ├── pcregrep.txt │ │ │ ├── pcrejit.3 │ │ │ ├── pcrelimits.3 │ │ │ ├── pcrematching.3 │ │ │ ├── pcrepartial.3 │ │ │ ├── pcrepattern.3 │ │ │ ├── pcreperform.3 │ │ │ ├── pcreposix.3 │ │ │ ├── pcreprecompile.3 │ │ │ ├── pcresample.3 │ │ │ ├── pcrestack.3 │ │ │ ├── pcresyntax.3 │ │ │ ├── pcretest.1 │ │ │ ├── pcretest.txt │ │ │ ├── pcreunicode.3 │ │ │ └── perltest.txt │ │ ├── install-sh │ │ ├── libpcre.pc.in │ │ ├── libpcre16.pc.in │ │ ├── libpcre32.pc.in │ │ ├── libpcrecpp.pc.in │ │ ├── libpcreposix.pc.in │ │ ├── ltmain.sh │ │ ├── m4/ │ │ │ ├── ax_pthread.m4 │ │ │ ├── libtool.m4 │ │ │ ├── ltoptions.m4 │ │ │ ├── ltsugar.m4 │ │ │ ├── ltversion.m4 │ │ │ ├── lt~obsolete.m4 │ │ │ └── pcre_visibility.m4 │ │ ├── makevp.bat │ │ ├── makevp_c.txt │ │ ├── makevp_l.txt │ │ ├── missing │ │ ├── pcre-config.in │ │ ├── pcre.h.generic │ │ ├── pcre.h.in │ │ ├── pcre16_byte_order.c │ │ ├── pcre16_chartables.c │ │ ├── pcre16_compile.c │ │ ├── pcre16_config.c │ │ ├── pcre16_dfa_exec.c │ │ ├── pcre16_exec.c │ │ ├── pcre16_fullinfo.c │ │ ├── pcre16_get.c │ │ ├── pcre16_globals.c │ │ ├── pcre16_jit_compile.c │ │ ├── pcre16_maketables.c │ │ ├── pcre16_newline.c │ │ ├── pcre16_ord2utf16.c │ │ ├── pcre16_printint.c │ │ ├── pcre16_refcount.c │ │ ├── pcre16_string_utils.c │ │ ├── pcre16_study.c │ │ ├── pcre16_tables.c │ │ ├── pcre16_ucd.c │ │ ├── pcre16_utf16_utils.c │ │ ├── pcre16_valid_utf16.c │ │ ├── pcre16_version.c │ │ ├── pcre16_xclass.c │ │ ├── pcre32_byte_order.c │ │ ├── pcre32_chartables.c │ │ ├── pcre32_compile.c │ │ ├── pcre32_config.c │ │ ├── pcre32_dfa_exec.c │ │ ├── pcre32_exec.c │ │ ├── pcre32_fullinfo.c │ │ ├── pcre32_get.c │ │ ├── pcre32_globals.c │ │ ├── pcre32_jit_compile.c │ │ ├── pcre32_maketables.c │ │ ├── pcre32_newline.c │ │ ├── pcre32_ord2utf32.c │ │ ├── pcre32_printint.c │ │ ├── pcre32_refcount.c │ │ ├── pcre32_string_utils.c │ │ ├── pcre32_study.c │ │ ├── pcre32_tables.c │ │ ├── pcre32_ucd.c │ │ ├── pcre32_utf32_utils.c │ │ ├── pcre32_valid_utf32.c │ │ ├── pcre32_version.c │ │ ├── pcre32_xclass.c │ │ ├── pcre_byte_order.c │ │ ├── pcre_chartables.c.dist │ │ ├── pcre_compile.c │ │ ├── pcre_config.c │ │ ├── pcre_dfa_exec.c │ │ ├── pcre_exec.c │ │ ├── pcre_fullinfo.c │ │ ├── pcre_get.c │ │ ├── pcre_globals.c │ │ ├── pcre_internal.h │ │ ├── pcre_jit_compile.c │ │ ├── pcre_jit_test.c │ │ ├── pcre_maketables.c │ │ ├── pcre_newline.c │ │ ├── pcre_ord2utf8.c │ │ ├── pcre_printint.c │ │ ├── pcre_refcount.c │ │ ├── pcre_scanner.cc │ │ ├── pcre_scanner.h │ │ ├── pcre_scanner_unittest.cc │ │ ├── pcre_string_utils.c │ │ ├── pcre_stringpiece.cc │ │ ├── pcre_stringpiece.h.in │ │ ├── pcre_stringpiece_unittest.cc │ │ ├── pcre_study.c │ │ ├── pcre_tables.c │ │ ├── pcre_ucd.c │ │ ├── pcre_valid_utf8.c │ │ ├── pcre_version.c │ │ ├── pcre_xclass.c │ │ ├── pcrecpp.cc │ │ ├── pcrecpp.h │ │ ├── pcrecpp_internal.h │ │ ├── pcrecpp_unittest.cc │ │ ├── pcrecpparg.h.in │ │ ├── pcredemo.c │ │ ├── pcregexp.pas │ │ ├── pcregrep.c │ │ ├── pcreposix.c │ │ ├── pcreposix.h │ │ ├── pcretest.c │ │ ├── perltest.pl │ │ ├── sljit/ │ │ │ ├── sljitConfig.h │ │ │ ├── sljitConfigInternal.h │ │ │ ├── sljitExecAllocator.c │ │ │ ├── sljitLir.c │ │ │ ├── sljitLir.h │ │ │ ├── sljitNativeARM_32.c │ │ │ ├── sljitNativeARM_64.c │ │ │ ├── sljitNativeARM_T2_32.c │ │ │ ├── sljitNativeMIPS_32.c │ │ │ ├── sljitNativeMIPS_64.c │ │ │ ├── sljitNativeMIPS_common.c │ │ │ ├── sljitNativePPC_32.c │ │ │ ├── sljitNativePPC_64.c │ │ │ ├── sljitNativePPC_common.c │ │ │ ├── sljitNativeSPARC_32.c │ │ │ ├── sljitNativeSPARC_common.c │ │ │ ├── sljitNativeTILEGX-encoder.c │ │ │ ├── sljitNativeTILEGX_64.c │ │ │ ├── sljitNativeX86_32.c │ │ │ ├── sljitNativeX86_64.c │ │ │ ├── sljitNativeX86_common.c │ │ │ └── sljitUtils.c │ │ ├── test-driver │ │ ├── testdata/ │ │ │ ├── grepbinary │ │ │ ├── grepfilelist │ │ │ ├── grepinput │ │ │ ├── grepinput3 │ │ │ ├── grepinput8 │ │ │ ├── grepinputv │ │ │ ├── grepinputx │ │ │ ├── greplist │ │ │ ├── grepoutput │ │ │ ├── grepoutput8 │ │ │ ├── grepoutputN │ │ │ ├── greppatN4 │ │ │ ├── saved16 │ │ │ ├── saved16BE-1 │ │ │ ├── saved16BE-2 │ │ │ ├── saved16LE-1 │ │ │ ├── saved16LE-2 │ │ │ ├── saved32 │ │ │ ├── saved32BE-1 │ │ │ ├── saved32BE-2 │ │ │ ├── saved32LE-1 │ │ │ ├── saved32LE-2 │ │ │ ├── saved8 │ │ │ ├── testinput1 │ │ │ ├── testinput10 │ │ │ ├── testinput11 │ │ │ ├── testinput12 │ │ │ ├── testinput13 │ │ │ ├── testinput14 │ │ │ ├── testinput15 │ │ │ ├── testinput16 │ │ │ ├── testinput17 │ │ │ ├── testinput18 │ │ │ ├── testinput19 │ │ │ ├── testinput2 │ │ │ ├── testinput20 │ │ │ ├── testinput21 │ │ │ ├── testinput22 │ │ │ ├── testinput23 │ │ │ ├── testinput24 │ │ │ ├── testinput25 │ │ │ ├── testinput26 │ │ │ ├── testinput3 │ │ │ ├── testinput4 │ │ │ ├── testinput5 │ │ │ ├── testinput6 │ │ │ ├── testinput7 │ │ │ ├── testinput8 │ │ │ ├── testinput9 │ │ │ ├── testinputEBC │ │ │ ├── testoutput1 │ │ │ ├── testoutput10 │ │ │ ├── testoutput11-16 │ │ │ ├── testoutput11-32 │ │ │ ├── testoutput11-8 │ │ │ ├── testoutput12 │ │ │ ├── testoutput13 │ │ │ ├── testoutput14 │ │ │ ├── testoutput15 │ │ │ ├── testoutput16 │ │ │ ├── testoutput17 │ │ │ ├── testoutput18-16 │ │ │ ├── testoutput18-32 │ │ │ ├── testoutput19 │ │ │ ├── testoutput2 │ │ │ ├── testoutput20 │ │ │ ├── testoutput21-16 │ │ │ ├── testoutput21-32 │ │ │ ├── testoutput22-16 │ │ │ ├── testoutput22-32 │ │ │ ├── testoutput23 │ │ │ ├── testoutput24 │ │ │ ├── testoutput25 │ │ │ ├── testoutput26 │ │ │ ├── testoutput3 │ │ │ ├── testoutput3A │ │ │ ├── testoutput3B │ │ │ ├── testoutput4 │ │ │ ├── testoutput5 │ │ │ ├── testoutput6 │ │ │ ├── testoutput7 │ │ │ ├── testoutput8 │ │ │ ├── testoutput9 │ │ │ ├── testoutputEBC │ │ │ ├── valgrind-jit.supp │ │ │ ├── wintestinput3 │ │ │ └── wintestoutput3 │ │ └── ucp.h │ ├── print.c │ ├── print.h │ ├── printfile.c │ ├── printfile.h │ ├── proto.h │ ├── quotes.c │ ├── search.c │ ├── search.h │ ├── setup.c │ ├── setup.h │ ├── string.c │ ├── struct.c │ ├── struct.h │ ├── threadprint.c │ ├── threadprint.h │ ├── trio/ │ │ ├── CHANGES │ │ ├── FILES │ │ ├── Makefile.in │ │ ├── README │ │ ├── README.hypermail │ │ ├── autogen.sh │ │ ├── compare.c │ │ ├── configure │ │ ├── configure.in │ │ ├── hypermail-patches.diff │ │ ├── install-sh │ │ ├── regression.c │ │ ├── strio.h │ │ ├── trio.c │ │ ├── trio.h │ │ ├── triodef.h │ │ ├── trionan.c │ │ ├── trionan.h │ │ ├── triop.h │ │ ├── triostr.c │ │ └── triostr.h │ ├── txt2html.c │ ├── txt2html.h │ ├── uconvert.h │ ├── uudecode.c │ └── uudecode.h └── tests/ ├── README ├── diff_hypermail_archives.pl ├── mboxes/ │ ├── 1msg.mbox │ ├── critmail.mbox │ ├── embedded.msg │ ├── t1 │ ├── t2 │ ├── t3 │ ├── t4 │ ├── t5 │ ├── t6 │ ├── t7 │ ├── t8 │ └── y2k.mbox ├── stdintest.pl ├── test-footer.hyp ├── test-index.hyp ├── test-msg.hyp ├── test.rc └── testhm.in ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # ignore all files generated by configure and make autom4te.cache config.cache config.h config.log config.status Makefile *.la *.lo *.o *.so.* *.a .libs/ src/defaults.h src/getdate.c src/defaults.h src/getdate.c src/hypermail src/lang src/mail # PCRE (if using the bundled lib) src/pcre/.deps src/pcre/.deps/ src/pcre/autom4te.cache/ src/pcre/libpcre.pc src/pcre/libpcre16.pc src/pcre/libpcre32.pc src/pcre/libpcrecpp.pc src/pcre/libpcreposix.pc src/pcre/pcre_chartables.c src/pcre/pcre_scanner_unittest src/pcre/pcre_stringpiece.h src/pcre/pcre_stringpiece_unittest src/pcre/pcrecpp_unittest src/pcre/pcrecpparg.h src/pcre/stamp-h1 src/pcre/pcre.h src/pcre/pcre-config src/pcre/dftables src/pcre/libtool src/pcre/pcregrep src/pcre/pcretest # other files created when compiling archive/msg2archive archive/rdmsg tests/testhm tests/testdir tests/testmail # vi or emacs edited ones .*~ \#.* # swap files .swp ================================================ FILE: COPYING ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ================================================ FILE: Changelog ================================================ Version Changes for Hypermail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================ HYPERMAIL VERSION 2.4.1: ============================ 2022-11-04 Jose Kahan * src/Makefile.in Some C linkers require libraries to be declared after functions in that library are called, and not before. This was notably with -lm and -ltrio, where -lm had to be declared after -ltrio. (closes # 84) 2021-11-17 David Hughes * docs/hmrc.html src/parse.c Added support for strftime (3) formatting in the append_filename configuration option to allow for archived messages to be split over multiple directories (monthly or yearly for example) 2021-06-04 Baptiste Daroussin * src/uudecode.c src/parse.c Fixes for memory issues detected by libasan 2020-06-19 Jose Kahan * src/domains.c valid_root_domains() was validating a domain name against the historical DNS domains such as .org, .com. DNS has evolved and allows a bigger variety of domains than those this function verified. That part of the function has been invalidated and will be either eventually removed or evolve to a user-configurable option. 2020-06-12 Jose Kahan * configure.ac configure didn't signal an error if yacc was not installed * src/string.c parseurl(): URLs were not detected and converted when they were preceeded by a : that was not attached to a valid URL like foo: https://example.com or : https://example.com 2020-02-23 @cacsar * Makefile.in make install wasn't working ============================ HYPERMAIL VERSION 2.4.0: ============================ 2019-12-20 Jose Kahan * src/getdate.y A message's sent or received date with a specified TZ but without any seconds value was using the local date seconds value instead of 00. 2019-12-19 Jose Kahan * src/parse.c parsemail(): a Content-Transfer-Encoding header with a missing value would result in an unitialized variable being used to output an unknown encoding warning message. Hypermail now skips this header if it's empty. 2019-11-22 Jose Kahan * src/print.c printsubject() / printdates(): the "by suject" and "by dates" views were not escaping markup present in mail's Suject and From headers. 2019-11-19 Jose Kahan * src/pcre Upgraded to upstream version 8.43. This fixes some autoconf issues we had on newer debian releases. This is only relevant for people that are not linking against a system libpcre. * tests/diff_hypermail_archives.pl Rewrote diff_hypermail.pl to make it more flexible and powerful for finding the differences in two hypermail archives. 2018-12-07 Jose Kahan * If the antispamdomain config option was used, hypermail was replacing everything following a "@" character by the antispam domain. This fix makes antispamdomain only apply for the domain part of valid email addresses. 2018-11-29 Bill Shannon * string.c spamify_replacedomain(): fix another greedy "@" replacement in the middle of a string of iso-2022-jp encoded Japanese characters. 2018-11-04 Bill Shannon * string.c i18n_convstring(): When converting a utf-8 string to iso-2022-jp, hypermail always adds the "return to ASCII" escape sequence, even if the string ends with ASCII. parseemail(): hypermail attempts to transform anything that looks like an email address by replacing the at sign (and optionally the domain name) with a string (default "at") to confuse screen-scraping programs. But if there's an "@" character in the middle of a string of iso-2022-jp encoded Japanese characters, hypermail still converts it, breaking the Japanese character. 2018-10-12 Jose Kahan * setup.c PreConfig(): removed a 64-bit warning * hypermail.c main(): if the en_US locale is not available, try en_US.UTF-8 2018-10-11 Jose Kahan * string.c parseemail(): for some reason if a ',' char was concatenaned to an email address, it was being parsed as part of the email username. 2018-10-10 Jose Kahan * string.c parseurl(): remove deprecated URLs. Improve support for URLs that don't have slashes following the 'protocol:' schema. Improve support for tel: URLs. 2018-10-09 Bill Shannon * string.c parseurl(): non-URL text can be misinterpreted as a URL, causing segfault Fixes issue #39 2018-10-08 Jose Kahan * print.c, string.c, proto.h The inreplyto_command could generate invalid links if the parser interpolated the in-reply-to from the subject. If a message's in-reply-to is interpolated, hypermail won't honor it anymore for that message. 2018-10-07 Jose Kahan * print.c printauthors(), printthreads(), printsubjects, printdates() Even if set_i18n was enabled, Indexes were written with mixed charsets instead of using utf-8 throughout. * configure.ac, Makefile.in, src/Makefile.in If the system has a recent libpcre, compile against it instead of using the bundled one. This check is done by default when launching configure. New configure options to allow to link against an external pcre library (--with-external-pcre) or to force the build and link against the bundled one (--enable-bundled-pcre). New configure option to allow to compile against a system libtrio (--enable-system-libtrio). Contrary to libpcre, it's not possible to find the version of libtrio so we cannot compile automatically against it. 2018-10-04 Jose Kahan * src/pcre Upgraded to upstream version 8.42 * src/trio Upgraded to upstream version 1.16 * parse.c Only use the headers charset for text/plain if its absent. If no charset is available in the other parts, do not add it. 2018-10-04 Jose Kahan * Updated Changelog format for entries newer than version 2.3.0 * hypermail.h, parse.c, struct.c, struct.h Charset handling for multipart messages was being handled wrong, giving priority to the headers charset (if found) over that of the displayed body. Sometimes the last found charset was the one being used throughout in the generated body. The metafile for attachments was sometimes inheriting the charset of the whole body, even when not necessary or wrong. Now the meta doesn't include a charset if the attachment doesn't explicitly give one. * parse.c References header was processed multiple times as it was not being marked as parsed after being processed. The epilogue of MIME parts was not being ignored. 2018-06-19 Jose Kahan * Changed mispelled configuration option warn_surpressions to the correct spelling warn_suppressions. 2018-06-14 Jose Kahan * Hypermail would segfault or have an incorrect thread view if it was handling an archive with a message (msg1) that was a reply to a message not in the archive, if msg1 had a reply to it in the archive (msg2), msg2 was archived before msg1 and both msg1 and msg2 shared the same subject (regardless of Re: prefixes). 2018-06-07 Bill Shannon * Add charset alias for Thai and Chinese * The markup for access key "j" to jump to the start of a message was only being added when the showhtml configuration option was disabled * Setting the describe_folder configuration option has no effect on the display of the folder index page * In some cases hypermail failed to null terminate the charset name when copying it, resulting in bogus charset names * Hypermail would segfault if given the bogus From line "From: next message in thread, 'd' -> next message Jose Kahan (Oct 26, 2009) Updated hmrc.4 and hmrc.html to describe the new features. Jose Kahan (Oct 23, 2009) Various fixes / enhancements developed at W3C by Fumihiro Kato, Daigo Matsubara and myself: - Markup changes for deleted messages that are kept. - New directive: htmlmessage_deleted for setting a custom HTML message for the body of deleted messages. - New directive: delete_incremental to disable deleting of existing messages in the archive when doing an incremental add of a new message. In some setups, if this feature is enabled, replies to deleted messages will cause uncontrolled markup escape and expansion. Feature is enabled by default. - Updated list of known protocol uris that hypermail will convert into links. - Bug fix: setup.c:MakeConfig() CFG_SWITCH was using long instead of int. - New directive: fragment_prefix for customizing the prefix that is put before each URI fragment in a message. Default value is "msg", the previous hard-coded value. - New directive: email_address_obfuscation foro enablingemail address obfuscation using numeric character reference. - New directive: inline_addlink to add in-line links to content that is stored in the attachments subdirectory. 'inline_types" must also be enabled. - New directive: inreplyto_command, gives a URI template to a script that hypermail will link to if it's unable to find a corresponding Message-Id in the archive's messages. Peter McCluskey (May 13, 2008) Change from Fumihiro Kato to fix bug that sometimes caused a charset problem when Content-Type is us-ascii but message headers include other encoded text like utf-8. Peter McCluskey (Nov 14, 2007) Applied xhtml patch from Zvi Har'El. Peter McCluskey (Oct 1, 2007) Changes from Fumihiro Kato to fix bugs on 64 bit systems and some possible buffer overflow problems. Change in rules about whether to escape urls; it now seems to escape them when found in the middle of the line the same way it has been doing when they are at the start of a line. Peter McCluskey (Feb 16, 2007) Changes from Rick van der Zwet: cosmetic = tweaking the interface a small bit (right align, the message numbers, years in the date listing spamify-domain = obfuscate the body of the message as well (will also obfuscate 'ssh rick@foo.bar' this of course), moved the domain obfuscate yes/no to the general to make the function more portable Changes from Mike Fabian changing int to size_t. Peter McCluskey (Mar 27, 2006) Add rel="nofollow" to text message URLs (option txtsuffix = 1). Peter McCluskey (Mar 14, 2006) Fixed a core dump with linkquotes = 1 caused by Daigo's changes. Peter McCluskey (Sep 30, 2005) Fixed missing links at top when show_index_links is 1 or 3. Peter McCluskey (Aug 4, 2005) Fixed double counting of messages deleted with the delete_msgnum option, which sometimes caused top level index page to show wrong number of messages and not link to a folder. Peter McCluskey (Jul 29, 2005) Changed to sort on sender date rather than from date when displaying sender date as a result of use_sender_date = 1. Peter McCluskey (Jun 23, 2005) Some small changes from Vincent McIntyre to make date-range in index of folders link to default index page, to use CSS instead of to distinguish that column, and some whitespace changes. Added explanation of how to handle strcasestr prototype error to INSTALL. Peter McCluskey (Mar 19, 2005) Fixes to files_by_thread option submitted by Oliver Meili. Peter McCluskey (Dec 2, 2004) Patch from Ulf Hrnhammar to fix two format string bugs in Hypermail. They could have caused crashes if using incremental mode on edited pre-existing archives with data like "%n%n%n%n%n%n%n%n" in certain lines. Peter McCluskey (Nov 28, 2004) Add filename_base option. Peter McCluskey (Sep 29, 2004) Add support for JAVT timezone. Add mailbox_date_trimmer to contrib, faq. Peter McCluskey (Jun 2, 2004) Add language code substitution cookie patch from Shane Wegner. ============================ HYPERMAIL VERSION 2.2.0: ============================ Peter McCluskey (May 25, 2004) Changed some of the addresses to hypermail-project.org. Made the "We delete ... " message print only if progress != 0. Peter McCluskey (Mar 23, 2004) Changes to speed up incremental update when there are deleted files if using usegdbm (it's still slow if usegdbm = 0). ============================ HYPERMAIL VERSION 2.1.9: ============================ Peter McCluskey (Feb 23, 2004) Released version 2.1.9 tar file. Peter McCluskey (Feb 17, 2004) Add use_sender_date option. Fix instructions for doing "make install" so that the documentation will be installed. Peter McCluskey (Feb 5, 2004) Update much of the documentation. Peter McCluskey (Feb 4, 2004) Change default in setup.c for spamprotect and spamprotect_id to On. Peter McCluskey (Feb 2, 2004) Add set_report_new_file and set_report_new_folder options. Peter McCluskey (Jan 23, 2004) Add in missing for index files. Removed a misleading, nonportable timezone string from link titles in toplevel index pages. Peter McCluskey (Jan 9, 2004) Change to make mbox_shortened option work a little better with discard_dup_msgids = 0. Change folder_by_date option to use "From " date rather than "Date: " to decide which subdirectory to use. This makes it consistent with top level index page. Peter McCluskey (Dec 26, 2003) Add increment = -1 mode to enable automatic determination of whether to update or append in most cases. Peter McCluskey (Dec 3, 2003) Added a mbox_shortened option to handle mboxes that have had messages deleted from the start of the mbox. Peter McCluskey (Dec 1, 2003) Fix mismatch in
    ,
in date.html with indextable = 0. Peter McCluskey (Nov 17, 2003) Add a check for the problem with the starting message number that was partly fixed on Oct 1. Now old archives with a startmsgnum = 0 .hmrc but a first message of 0001.html in this case will be treated as if startmsgnum was 0. Peter McCluskey (Nov 15, 2003) Add Portugese support from Hugo Cisneiros. Peter McCluskey (Oct 1, 2003) Fix some problems with starting message number that caused bugs when increment = 1, linkquotes = 1 and using folder_by_date. Peter McCluskey (Sep 11, 2003) Fixes to make pcre work. Peter McCluskey (Sep 3, 2003) Applied patches from Mike McDonald to use nowrap option in the author and date columns in the index tables and get rid of all of the 'width=100%' options to the tables. Peter McCluskey (Sep 3, 2003) French language improvements from Olivier Kaloudoff. Peter McCluskey (Sep 1, 2003) Applied patches from Mike McDonald to make spamify_replacedomain use set_antispam_at, change printdates to include the dates in the table version of the bydate index, and make the table use the whole screen width instead of 80%. Jose Kahan (Aug 18, 2003) - Changed to lowercase the suffixes added to the message indexes. That is, from "archive name By Date" to "archive name by date" because the upper case seemed out of style as we don't have any control on what is the string used for the archive's name. Did this change only for the English messages as I don't know if this convention works well for other languages. Jose Kahan (Aug 18, 2003) - Made the links to the different indexes show the index of the current entry. This change originated from the feedback we got on the WAI enhanced archievs. People find that this small changes increases the usability of the archive. Jose Kahan (Aug 18, 2003) - The links to the first message (aka #first) were not working in the by attachment, by author, and by subject indexes. Peter McCluskey (Aug 16, 2003) - applied fix from Jean-Charles Meyrignac to handle 0x1A in mbox. Jose Kahan (Aug 14, 2003) - After receiving more feedback, reverted the changes done for converting the displayed value of the Date: header. The reason is that users like to know when they send a message. This information was getting lost because we were converting the date to the local time. - Made the Received on date be shown in converted local time. - Added a new configuration option, indexdateformat, so that people can specify a different format for indexes than the one used elsewhere. If this variable is not defined., it'll use the dateformat by default. - Made the index by date compare dates independently of the value of dateformat. Jose Kahan (Aug 13, 2003) - Made the Received on footnote line use the same date format as that used for the Date: header on top of the messages. Jose Kahan (Aug 18, 2003) - Small WAI change to the list of indexes to show the entry corresponding to the current index, but outside of a link. This comes from feedback, where people said it was less distracting to see the same index to links all the time. Jose Kahan (Aug 18, 2003) - Add the WAI enhancement that I had forgotten to do for messages. The new format is: [subject] from [author] on [date] ([mailing list label]). I also removed the 64 characters maximum limit check we had on the title. The reason is that this is not part of the HTML specification, but rather a writing style. Dominique says we shouldn't be so strict in this case. In addition, just adding a \0 after 64 characters could break entity names and generate invalid HTML. Jose Kahan (Aug 13, 2003) - The mailcommand option didn't work when applied to a paragraph that had a previously converted href string that includes the '@' char. I added a quick hack to ConvURlsString to avoid doing the mailto: convertion if an href already exists in that line. The best solution would be to do something similar to ConvURLsWithHrefs. Also fixed a memory leak. Peter McCluskey (Aug 8, 2003) - Applied haof fixes from Bernhard Reiter. Jose Kahan (Aug 4, 2003) - As a side effect of PNK's use of an SGML entity for the @ char, the mailcommand option stopped working on all the headers except for the To: one. Jose Kahan (Aug 1, 2003) - In order to guarantee the validity of XHTML documents, changed the behavior of hypermail when including customized footers. Previously, when using this option, the custom markup had to include the </body> and </html> end tags. As we also need to include a </div> in some cases for XHTML and it's much harder to guess when to add it, I made hypermail always add those three end tags as needed, regardless of whether the custom footer option is being used. Jose Kahan (Jul 30, 2003) - After talking with Dom Hazel-Massieux, I added some extra WAI enhancements to the list of indexes generated by hypermai. Specifically, the date is shown in a verbose name in the title attribute of each entry and in an abbreviated version in the markup that's being displayed. Jose Kahan (Jul 30, 2003) - When rebuilding an archive, the attachment files were not being overwritten correctly. . Fixed this by adding an O_TRUNC flag. Jose Kahan (Jul 29, 2003) - Removed a memory leak in file.c as reported by insure. - The ietf-mbox option didn't work on "quoted printable" encoded attachments. Peter McCluskey (July 22, 2003) Fix show_msg_links = 3 option (Jose's changes assumed it didn't exist). Updates to German from Tobias Weber. Kent Landfield (Jul 14, 2003) - When show_headers was used in print.c, the newline was not recognized early enough in printheaders. A check was added to assure the newline was recognized properly. Kent Landfield (Jul 10, 2003) - Small typo in print.c corrected. fprintf(fp, "%s ^lt;<em>%s</em>>"... ======================== HYPERMAIL VERSION 2.1.8: ======================== Kent Landfield (Jun 28, 2003) - Updated pcre library with pcre-4.3 sources. We were distributing a much older version. We were distributing version was 3.3 from August 1, 2000. - Updated FILES with the lcc files and the pcre changes. - Removed the deprecated "show_hr" from the tests/test.rc file. Jose Kahan (Jul 2, 2003) - parseurl didn't work well when an URL was quoted and enclosed inside tags. Such as: <dd>some url</dd> </dd was put as part of the url. Jose Kahan (Jul 1, 2003) - Added WAI enhancements to the list of indexes generated by hypermail. To make things perfect, we would need a new configuration option to give the format of the date in the list of indexes format. I hard coded it for the moment as I ran out of time to do it right now. As it has to use an abbreviated date format to avoid having a too big list of indexes, we can' t reuse the standard set_dateformat value. - Removed warnings detected thru gcc Wall. Peter McCluskey (June 30, 2003) - Increased max_tokens used to allocate space for linkquotes data struct. Jose Kahan (Jun 28, 2003) - Code cleaning. Removed the deprecated code for set_showhr and set_usetable options. Kent Landfield (Jun 28, 2003) - Arkadiusz Miskiewicz <arekm@sse.pl> reported progerr() was being called with NULL instead of the previously constructed error message. His supplied patches were applied. Peter McCluskey (June 27, 2003) - Made dates in subdirectory index files reflect subdirectory date range, rather than the date range for the whole archive. Peter McCluskey (June 24, 2003) - Fix print_index_header_links to print MSG_ENDING date correctly (had been using 2 getdatestr() calls in one argument list). Peter McCluskey (June 20, 2003) - Fix a core dump with empty Date:. Jose Kahan (Jun 10, 2003) - Some extra WAI enhancements requested during the period of public comments: Order the date index by dates, like in subjects, add <dfn> to the start and end period in the indexes, change the title of "jump to first message" to "jump to list of messages". - The top respond link didn't take into account the msgid or subject. It was just a plain mailto. Made it work as the bottom one. Jose Kahan (Jun 10, 2003) - Adding new messages using the -u option to an existing file sometimes resulted in warnings saying "Message-ID is missing, ignoring message with subject..." Patch idea submitted by Peter. Jose Kahan (Jun 10, 2003) - The incremental option (-u) always started new archives with 0001, rather than 0000. It will now start with 0000 as before For those people who had this problem and don't want to break any links to their archives when rebuilding them, there's a new configuration option allowing you to tell from which number you want to start your archive: startmsgnum. You should only set it up once and not modify it for an existing archive or your links may break. A warning message appeared systematically because the showhr, which is now deprecated, was turned on by default. Peter McCluskey (May 22, 2003) - add Italian support from Gabriele Bartolini and Marco Nenciarini. Peter McCluskey (May 16, 2003) - Fixed initialization of prior_subdir when dirs created out of order. That fixes a case where a subdir wasn't in index files with reverse_folders = 1. Jose Kahan (May 13, 2003) - Add the WAI enhancements proposed in http://www.w3.org/2002/03/archives-improvements/. As a consequence of this change, the sethr and usetable configuration options are deprecated. The new markup takes into account the changes that those options proposed and offers them in a WAI friendly way. Some code cleaning needs yet to be done to remove all the cases where those rules were used. Previous code version is tagged as "before-wai". Fixed some invalid XHTML markup too. Peter McCluskey (May 12, 2003) - fix txtsuffix to not crash on null pointer. - fix discard_dup_msgids to work when showprogress = 0. Peter McCluskey (April 24, 2003) - spam encoding from Peter Karlsson. Currently enabled via the spamprotect option. Jose Kahan (Apr 23, 2003) - As a consequence of the XHTML convertion, unconvchars() wasn't storing information into the buffer when there were no entities. Jose Kahan (Apr 10, 2003) - Converted hypermail to XHTML. The only remaining issue concerns charsets. Some mail clients don't specify a correct charset or specify a charset and include characters belonging to other charset spaces. The solution to detect and convert the foreign charset into a Unicode entity or, for the adventurous hacker, convert hypermail's output to UTF-8. For the moment, only the former is implemented partially; there is only one a winlatin1 (Windows CP 1252) to Unicode convertion/detection being done. See string.c:convchars, unconvwinlatin1, and uconvert.h for more details. The best solution will be to move to UTF-8, but this has to be planned. If you have a charset issue, your XHTML document will be invalid. As XHTML is backwards compatible with HTML, you can avoid this problem by continuing to use the text/html MIME type. Peter McCluskey (April 3, 2003) - Fixed so attachment.html doesn't list .meta directory. Kent Landfield (Mar 20, 2003) - Added Splint (www.splint.org) support to src/Makefile.in - Corrected Initializer block for ltable[12]. Had 2 fields, but struct language_entry has 3 fields. - Removed unused gp variable in update_deletions(). - modified print_main_header() to assure title meets HTML recommendations of no longer than 64 characters. - Updated docs/hypermail.rc Peter McCluskey (Mar 18, 2003) - Fixed overwrite = 0 to avoid rewrite of many files involved in replies with folder_by_date option. Peter McCluskey (Mar 14, 2003) - Fixed two bugs with deleting messages with the incremental mode. One bug meant that the message body was only rewritten or removed with the delete_msgnum option, not delete_older / delete_newer. The other bug involved only updating the is_deleted flag in the gdbm file if the message body was redone to update a MSG_IN_REPLY_TO line. Kent Landfield (Mar 9, 2003) - updated domains.h to accurately reflect the current set of root domains. Peter McCluskey (Mar 7, 2003) - Fixed problem with reverse_folders option that caused the index file to leave out folders when there were some unusual mismatches between the 2 dates in one message. Kent Landfield (Feb 28, 2003) - changed wait.h sys/wait.h for portability in msg2archive - removed unused variable in finelink.c Kent Landfield (Feb 20, 2003) - corrected docs/Makefile.in to create the images dir if it does not exist. Kent Landfield (Feb 20, 2003) - added wait.h to msg2archive that was needed for s_popen() - removed unused variable in finelink.c ======================== HYPERMAIL VERSION 2.1.7: ======================== Peter McCluskey (Feb 20, 2003) - Made version 2.1.7 tar file. Jose Kahan (jose@w3.org) (Feb 20, 2003) - makemailcommand wasn't escaping non-ascii characters in the URLS that it generated. Peter McCluskey (Feb 19, 2003) - Fix to append option to handle some lines getting discarded in mdecodeQP. Kent Landfield (Feb 19, 2003) - Updated TODO with configure issues and other corrections we want to make to the code in the near future. Jose Kahan (jose@w3.org) (Feb 19, 2003) - Upgraded extract_rfc2047_content() as the previous extracting algorithm was broken. Kent Landfield (Feb 18, 2003) - Added missing contrib utilities, contrib/msg2hypermailarchive.py and contrib/runtest to FILES - Added checking in struct.c to limit the length of Subject: line to avoid theoretical Denial-of-Service - Removed code that was ifdef'ed NOTUSED Peter McCluskey (Feb 17, 2003) - Fix to attachment Content-Type parsing to strip all whitespace off end of type rather than just newline. Kent Landfield (Feb 17, 2003) - Added safe_tmpfile() usage instead of internal usage. Peter McCluskey (Feb 14, 2003) - Disabled conversion of file:// into href - it seemed to allow anyone who could access the web server via local host could read any file that the web server had permission to read rather than just files in the archive directory. Peter McCluskey (Feb 13, 2003) - Add -DTRIO_MINIMAL. Solves a trio compile problem in SunOS and makes binary a little smaller. - Strip mail.c down to minimal warning message so we don't have to worry about analyzing it's security problems. - Changes to get strerror, memmove from pcre when missing (e.g. on SunOS). How was this working on SunOS before? - Fix faulty sizeof in snprintf for MSG_ENCODING_IS_NOT_SUPPORTED. Kent Landfield (kent@hypermail.org) (February 12, 2003) - Converted msg2archive.c to use Thomas Biege's <thomas@suse.de> s_popen() instead of popen(). Kent Landfield (kent@hypermail.org) (February 11, 2003) - Modified configure.in to test for snprintf. This is needed since Solaris 2.5.1 does not have snprintf. This only affects the msg2archive and mbox2hypermail in the archive directory. Kent Landfield (kent@hypermail.org) (February 10, 2003) - Modified configure to assure on Solaris that the ctype functions were used instead of the macroes. New NO_MACRO define in config.h. - Added most of the patches submitted by Thomas Biege <thomas@suse.de> - Cleaned up compilation commenting out unused variables with NOT_USED. Need to remove them and other unnecessary code soon. - Various other minor compilation issues. - Corrected prototype issue in print.c - Added parameter checking to archive/*.c source Peter McCluskey (Feb 10, 2003) - Fixed the append option to handle lines between end of headers through mime boundary correctly. Jose Kahan (jose@w3.org) (February 06, 2003) - Added a protection against the use of the nonsequential messaging option when hypermail wasn't compiled with the libfnv. Kent Landfield (kent@hypermail.org) (February 06, 2003) - Hypermail 2.1.6 runs on a DEC Alpha running TRU64 when compiled with GCC 2.95. It does however require the -mieee flag be set for the trionan.c sources. - Modified configure.in script to support setting the the -mieee flag for an Alpha TRU64 build. - Modified various Makefile.in files to assure clean/clobber/distclean worked universally. Peter McCluskey (Feb 1, 2003) - Changes to make stack overflow less common. Peter McCluskey (January 29, 2003) - Fixed faulty freeing of memory that caused core dump with files_by_thread option. - Fixed missing function call argument with files_by_thread option. I suspect this was causing some random behavior, but I only found it due to valgrind. - Fix for placement of link to next msg with incremental update, usetable = 0. Peter McCluskey (January 28, 2003) - Fix from Zvi Har'El to leading zeroes in anchors in index pages with indextable=0. - Changes to Swedish from Peter Karlsson. Peter McCluskey (January 26, 2003) - Fix for placement of link to next msg with incremental update. ======================== HYPERMAIL VERSION 2.1.6: ======================== Peter McCluskey (January 24, 2003) - Released version 2.1.6 tar file. - Fix buffer overflow when progress = 2 (triggered by long attachment names). Was a security risk. - Fix buffer overflow in mail (cgi) program that probably created security risk if gethostbyaddr returned h_name of about 80 chars for an ip address. - Disabled the functionality of the mail program and replaced it by default with warning about abuse by spammers. Added warnings about use of program. - Change size of boundbuffer (in parse.c) to 256, limit sscanf that fills it to 255 bytes. This prevents a buffer overflow with long mime boundaries. The buffer overflow didn't seemed to produce only minor problems, but it's hard to rule out security risks. - Add check for inline attachment name overflowing attachname buffer (like the check that Jose added today for non-inlined attachments). - Add check for append_filename and alts_text exceeding buffer size. - Delete attachment directory of messages that are discarded due to a missing or duplicate message-id. Jose Kahan (jose@w3.org) (January 24, 2003) - Fixed a buffer overflow reported by Ulf Harnhammar from VSU security. Peter McCluskey (January 22, 2003) - If mime message has an end boundary but no start boundary (as a buggy version of Microsoft Outlook seems to create), the body is now treated as a plain text message rather than discarded. - Update trio code to trio version 1.9. Peter McCluskey (January 20, 2003) - Several fixes to avoid uninitialized memory reads reported by valgrind. Peter McCluskey (January 18, 2003) - Fix random behavior in parseurl which sometimes caused core dumps on lines ending in http://, ftp://, etc. Peter McCluskey (December 19, 2002) - Apply patch from Wolfgang Spraul fixing link from subdir attachment.html to index.html when defaultindex = date Peter McCluskey (November 26, 2002) - Changed attachment naming back to what it was before Jose added set_nonsequential. - Changed attachment naming so that files are stored using the names provided without any %d- prepended whenever that doesn't cause conflicts. Kent Landfield (kent@hypermail.org) (November 24, 2002) - Made some updates to the docs. Still need to update the docs to include writehaof, nonsequential, msgsperfolder and assure other config file directives are listed and current. Kent Landfield (kent@hypermail.org) (November 24, 2002) - Added Russian language support. Submitted by Igor Solovyoff" <siv@intear.com.ua> Kent Landfield (kent@hypermail.org) (November 24, 2002) - Made the "_at_" antispam bit configurable by config file, using antispam_at = __somestring__ (does not have to have __ in it) Anything hardcoded by default, can be figured out and used by spammers. Particularly something like "_at_". Submitted by Philip Brown <phil@bolthole.com> Jose Kahan (jose@w3.org) (October 17, 2002) - URL generation was broken when a URL had a '@' char and hypermail was using the mailcommand option. parseemail() didn't take this case into account yet (there's just an empty statement). I added a quick patch to convert the '@' into an HTML entity when doing the convertion inside a URL. The change is in translateurl(). Jose Kahan (jose@w3.org) (October 2, 2002) - In order to avoid hashed filename collisions, the filename is now built with a hash of the msgid concatenated to the Epoch seconds of the From date. This gives a total of 16 characters (all data is represented in hex). Only messages that have the same msgid and that arrive in the same second will have a collision. I also compiled with the Warning flags and removed some warnings. Jose Kahan (jose@w3.org) (October 2, 2002) - The access righs of the msgindex file (for the hashed filenames) were not being set at all. Jose Kahan (jose@w3.org) (October 1, 2002) - The non-sequential msgid mode didn't work when updating the archives by one message. Fixed a confusion in the generation of the msgindex file. Jose Kahan (jose@w3.org) (September 26, 2002) - Cleaned the autoconf files for passing the libnvf compile parameters (what a difference does reading the manual make). Peter McCluskey (September 25, 2002) - Fix threading bug with incremental update and spamprotect_id = 1, usegdbm = 0. Jose Kahan (jose@w3.org) (September 25, 2002) - Commited the ~/hypermail/ltmain.sh file and also put it in the FILES section. Somehow, without this file, it was impossible to compile the file generated thru a make tgz. The same kind of file already existed in the pcre and fnv directories. Added a rule to pass the FNV optional CFLAGS from the ~/hypermail/Makefile file, so that you can do a make from the top-level (previously, you had to do it in the src directory... oops!). Jose Kahan (jose@w3.org) (September 25, 2002) - Updated the FILES tgz file (added libfnv, removed two non-existent tests). - Fixed the make tgz rule (how long was it since it was last used?) Jose Kahan (jose@w3.org) (September 25, 2002) - Added a new option to compute the archived filenames using an fnv hash of the msgid + received From date. The resulting filename is 8 bytes long (a space of 2^32 bits) + the extension. You can eventually change it to 16 bytes if this is too short. Just look at the code. The advantage of this is that you can add and remove items from the archive and not worry anymore about broken links if the sequence changes (e.g., if you are rebuilding an archive). To activate this option, you need to do a ./ configure --enable-libfnv, then recompile hypermail. The name of the new option is nonsequential (lack of imagination!). Peter McCluskey (September 17, 2002) - Added reverse_folders option. Peter McCluskey (August 30, 2002) - Fix segfaults in mdecodeRFC2047 (with headers encoded as quoted printable), and in ConvURLsString. - Add files_by_thread option. Peter McCluskey (August 20, 2002) - Change preferedcontent to fall back on type "text/" or on encoding if it can't find any prefered types. - Fix mdecodeRFC2047 to decode headers of any length (removing 128 byte limit). - Add classes to default stylesheet to set colors of headers, standard links, and of quoted text according to quote nesting depth. Peter McCluskey (August 16, 2002) - Fix bug internal error in crossindexthread2 resulting from message with unterminated mime. Peter McCluskey (August 11, 2002) - Add Norwegian language support from Bosse Klykken. Peter McCluskey (August 7, 2002) - Add contrib/msg2hypermailarchive.py from Bernhard Reiter. - Add antispamdomain option from Vincent McIntyre. - Add delete_newer option. Peter McCluskey (August 3, 2002) - Fix expires option to work in incremental mode. - Add delete_older option. ======================== HYPERMAIL VERSION 2.1.5: ======================== Peter McCluskey (July 31, 2002) - Release version 2.1.5 tar file. Peter McCluskey (July 22, 2002) - Apply gdbm patch from Bernhard Reiter, mainly altering messages. - Apply German language patch from Bernhard Reiter. - Apply haof patch from Bernhard Reiter. Peter McCluskey (July 15, 2002) - Fix some missing links to multipart attachments with save_alts option. Peter McCluskey (July 11, 2002) - Add base_url option, and warning about it being needed when the latest_folder option is used and the folder_by_date option contains a '/'. Peter McCluskey (July 8, 2002) - Fix endless loop that save_alts option often produced. Peter McCluskey (June 18, 2002) - Applied changes from Carlos Martn Ugalde to Spanish text. Peter McCluskey (June 13, 2002) - Fix call to compute_quoted_percent so that it doesn't crash on deleted msg with incremental update. Peter McCluskey (May 14, 2002) - Add spamprotect_id option. Peter McCluskey (Apr 26, 2002) - Changed to convert ampersands in urls to &. Peter McCluskey (Apr 22, 2002) - Add Greek language support from Akis Karnouskos. - Surpress <p> within <pre>. Peter McCluskey (Mar 22, 2002) - Fixed to rewrite old messages that have new replies (some links to replies/next in thread had been missing for overwrite=0, increment=0, and also for linkquotes = 1). - Updated configure to reflect Daniel's changes to fix --without-gdbm in configure.in. Peter McCluskey (Mar 19, 2002) - Increase MAXSTACK from 20 to 200. Peter McCluskey (Feb 4, 2002) - Fix to avoid converting strings like ftp://user@host.com to mailto's. Peter McCluskey (Feb 4, 2002) - Patch from William R. Knox to add meta date tag. Jose Kahan (jose@w3.org) (Jan 25, 2002) - When a message had a charset of type US-ASCII or ISO-8959-1, it wasn't being stored in the HTML version of the message. This could result in a correct decoding of the message, as browsers assume a user-given default charset in those cases. Peter McCluskey (Jan 11 2002) - Patch from William R. Knox to fix possible race condition in creating dirs. Peter McCluskey (Jan 10 2002) - Add %t substitution cookies to provide path to top folder. Peter McCluskey (Jan 5 2002) - Fix segfault in incremental mode with linkquotes. ======================== HYPERMAIL VERSION 2.1.4: ======================== Peter McCluskey (Dec 19 2001) - Create version 2.1.4 tarball. Peter McCluskey (Dec 14 2001) - Applied patch from William King adding </li>'s. Peter McCluskey (Dec 10 2001) - Fix bug in chronological ordering of folders. Peter McCluskey (Dec 6 2001) - Applied patch from William King to fix footer links on attachment index. Peter McCluskey (Dec 4 2001) - Change to detect start of new message when mime boundary missing, treat unbounded text as plain text body. Peter McCluskey (Dec 2 2001) - Applied patches from William King: - DTD changed to strict. - </p> now emitted. - Some tags were not contained properly. Now wrapped in <p></p>. Peter McCluskey (Dec 1 2001) - Applied patches from William King to string function defines and gdbm configuration. Peter McCluskey (Nov 30 2001) - Add Polish language support from Piotr Waskiewicz. Change some hardcoded From's to new macro MSG_FROM, change a Date to MSG_CDATE. - update config.sub, config.guess from ftp.gnu.org/gnu/config/. Peter McCluskey (Nov 26 2001) - Applied patches from William King to update man pages for body, lang options changes, and add new domain codes. Peter McCluskey (Nov 24 2001) - Applied patch from William King to add lang= to <html> tag, get rid of duplicate <em>. Peter McCluskey (Nov 23 2001) - Added support for locales of form en_US. Changed language code "se" to "sv", provide warning for old code. Peter McCluskey (Nov 22 2001) - Applied patch from William King to create meta tag with hypermail version number. - better French support from Emmanuel Blot. Daniel Stenberg (Nov 21 2001) - Updates to congfiure and trio. Peter McCluskey (Nov 21 2001) - Applied patches from William King to conform better to HTML 4.01: * remove body option, replace default <body> bgcolor=, text= with inline style sheet (unless user-defined style sheet present). * change <div align=...> to <div class=...>, same for <h1 align=...> - add $BINARY, $NONPLAIN types to ignore_types option. - add warn_surpressions option - add unsafe_chars option - Remove tmpname from parse.c (to get rid of warning about mktemp). Peter McCluskey (Nov 19 2001) - Applied patches from William King to conform better to HTML 4.01: * remove noshade from <hr> * change the default DTD * escape &'s, add image/png in test.rc, hmrc.example - Changed the fix*header() routines so that they handle incremental updates sensibly when given a mailbox with multiple messages. In the process, I fixed 2 problems with single-message incremental updates, one which left out the "Next message" link, and one which created a "Reply" link that should have been a "Maybe reply". - Add warning for mbox that starts with different msg than gdbm file if not using -u (overwrite) option. - Change default for overwrite option to off. - Fixed segfault that happened when %m parsed in header but mailto was NULL. Peter McCluskey (Nov 18 2001) - Folder list now sorted chronologically. Peter McCluskey (Nov 16 2001) - Added save_alts and alts_text options. Peter McCluskey (Nov 15 2001) Updated some old documentation, added some security warnings. Peter McCluskey (Nov 14 2001) - Changes relevant to security: 1. attachment filenames ending in .shtml get changed to .html. 2. attachment descriptions are passed through convchars to prevent html tags from being used there. Peter McCluskey (Nov 13 2001) - Fixed malloc bug that caused segfault with linkquotes=1. Peter McCluskey (Nov 12 2001) - Update to trio-1.4 (from 1.2) to fix Alpha compile problem. Peter McCluskey (Nov 7 2001) - Changes to hypetombox.pl: 1. add some support for handling attachments. 2. fixed some problems arising from some tags being changed to lowercase. 3. add -S option to specify htmlsuffix. 4. changed to convert <p> to blank line (instead of to nothing). 5. additions to improve handling of archives produced linkquotes=1 option. Peter McCluskey (Nov 5 2001) - change parse.c to treat lines containing only a carriage return as blank lines for purpose of deciding whether they indicate the end of headers or a continued header line. ======================== HYPERMAIL VERSION 2.1.3: ======================== Peter McCluskey (Aug 22 2001) - fix Makefile to clean pcre directory. Peter McCluskey (Aug 7 2001) - removed In-Reply-To from mailcommand default. Peter McCluskey (Jul 25 2001) - fix to abort before unlinking gdbm file if need it and cannot open it. - fix latest_folder option (didn't work in incremental mode). Peter McCluskey (Jul 17 2001) - patch from Brian Kirkby to fix links between folders with usetable. Peter McCluskey (Jun 26 2001) - fixed parsing of integer/octal/switch environment variable values. - fixed bugs in latest_folder option (includes fix from David Bau <davidbau@hotmail.com>). Peter McCluskey (Jun 23 2001) - fixed FILES so that hypermail.html gets into tarballs. Peter McCluskey (May 31 2001) - patches from Moritz Willers to surpress empty "messages sorted by:" line, add | after "Previous Folder, Thread view", etc. Peter McCluskey (May 30 2001) - changes to Swedish from peter karlsson. ======================== HYPERMAIL VERSION 2.1.2: ======================== Peter McCluskey (May 22 2001) - change default value for avoid_top_indices to none. - fixed make to handle pcre properly. Peter McCluskey (May 16 2001) - fix pathnames in inline attachments with msgsperfolder/folder_by_date Peter McCluskey (May 11 2001) - add filter options (using pcre regular expressions): filter_out filter_require filter_out_full_body filter_require_full_body Peter McCluskey (May 9 2001) - fix links to attachments in subdir index files. Peter McCluskey (May 8 2001) - fixed bug with incremental update that caused the index files to ignore messages beyond set_searchbackmsgnum. Daniel Stenberg (May 8 2001) - Removed the last traces of mprintf.[ch] and made the trio stuff work completely as a replacement. Peter McCluskey (May 7 2001) - fixes to trio configuration. Peter McCluskey (May 4 2001) - another fix to avoid_top_indices = folders. - enhance show_msg_links to support links only at top or only at bottom. - add show_index_links option to control links from message page to indices. - add txtsuffix option - On/Yes now converted to 1 for CFG_INTEGER options (for compatibility with options that used to be CFG_SWITCH's) - fix append option so that it handles uuencoded attachments and mdecodeQP() calls correctly. Kent Landfield (May 4 2001) - corrected compilation issue for Sun CC in string.c - corrected check for set_custom_archives in hypermail.c Peter McCluskey (May 1 2001) - convert mprintf calls to trio calls Peter McCluskey (Apr 27 2001) - allow incremental update with folder_by_date on empty archive, improve error messages for missing gdbm file with folder_by_date, incremental update. Peter McCluskey (Apr 26 2001) - fixed so that avoid_top_indices = folders works. Peter McCluskey (Apr 24 2001) - fix urls at end of index page with folder_by_date. Peter McCluskey (Apr 20 2001) - patch from Hisashi Gotoh <gotoh@horae.dti.ne.jp> to fix message/rfc822 handling with showhtml = 0. ======================== HYPERMAIL VERSION 2.1.1: ======================== Peter McCluskey (Apr 18 2001) - changed configure script to check several directories for gdbm.h, provide --with-gdbm=DIR option. Peter McCluskey (Apr 16 2001) - added patch from David Eisner <cradle@glue.umd.edu> to prevent subject matching on subject lines which have no Re:. - made hashreplylookup use the same code as hashreplynumlookup (fixes missing "Maybe in reply to" links in some messages. - made find_quote_prefix more cautious about recognizing nonstandard prefixes as quote prefixes (affects linkquotes and showhtml=2 options). Peter McCluskey (Apr 14 2001) - add missing <ul> when set_show_msg_links == 0, pointed out by Emre Bastuz <info@emre.de> Peter McCluskey (Apr 13 2001) - fixed portability problem in strcasestr. - fixed custom_archives to handle NONE properly. - removed a poorly thought out maybereply check in crossindexthread2 that was apparently dropping some messages from the thread list. Peter McCluskey (Apr 12 2001) - convert html tags for monthly_index, yearly_index to lowercase. - fixed indexing error in getname reported by David Eisner <cradle@glue.umd.edu> - fixed set_usegdbm compile error reported by Daniel. - fixed parentheses in printattachments Peter McCluskey (Apr 10 2001) - Add check for *html deleted, gdbm index still present. - fix count of messages. - sped up linkquotes 2.5x by better mallocs - replaced strcasestr with faster one from glibc via Scott Rose - PushNString, PushString speedups - fixed bug in parseemail (faulty sscanf return value check) that added bogus strings in odd mailto's. Peter McCluskey (Apr 9 2001) - add new options: deleted, expires, delete_msgnum, delete_level - togdbm args: fix misuse of secs_to_iso which made email->date == email->fromdate - fix subdir bug with thread_file_depth - fix threading bugs with linkquotes - fixreplyheader with linkquotes bugs fixed Peter McCluskey (Apr 6 2001) - patch from Hisashi Gotoh <gotoh@horae.dti.ne.jp> adding iso2022jp option and fixing bug when config file not found. Peter McCluskey (Apr 5 2001) - fixed faulty urls in thread index files in subdirs with folder_by_date, msgsperfolder Peter McCluskey (Apr 3 2001) - changed htmlfilename, articlehtmlfilename to allocate mem dynamically. - redid config section of hypermail.html to describe some of the most important options and refer to hmrc.html for a full description. Changed style of hmrc.html, added folder_by_date mention to hypermail-faq.html. - fixed typo in FILES. ======================== HYPERMAIL VERSION 2.1.0: ======================== Peter McCluskey (Mar 31 2001) - fixed core dump with showhtml=2 created by yesterday's checkin. - added isodate, gmtime options. - bug fixes to mime decoding and to libcgi/form_ent.c from Greg Shenaut <greg@bogslab.ucdavis.edu> - add fixhtime.pl (changes timestamps to match From:) Peter McCluskey (Mar 30 2001) - Reorganized hmrc.html. - Add options to split archive into subdirectories: folder_by_date msgsperfolder latest_folder describe_folder avoid_top_indices Peter McCluskey (Mar 22 2001) - Enabled attachments index file, added sublists of attachment names and file sizes. Peter McCluskey (Mar 22 2001) - Fixed problem with GDBM defines. - Improved speed by replacing O(N^2) code in these functions with code that is at least typically close to O(N): addreply, crossindexthread1, crossindexthread2, nextinthread, writearticles (if set_showreplies) Accidentally improved threading under linkquotes option in the process. Overall performance probably scales up linearly with the number of messages under normal conditions (but not with linkquotes, which has other performance problems as well). Code is ifdef'd under FASTREPLYCODE for now. Peter McCluskey (Mar 19 2001) - Added new usegdbm and append options from Scott Rose. Peter McCluskey (Mar 14 2001) - Added avoid_indices option. Peter McCluskey (Mar 13 2001) - Sped up by balancing the datelist tree a bit (it had been virtually a linked list) and by removing redundant call to nextinthread. Peter McCluskey (Mar 12 2001) - Added contrib/cron_hypermail - Added some files in contrib and tests/mboxes to FILES. Peter McCluskey (Mar 2 2001) Added features originally implemented in critmail. New source files: finelink.c finelink.h quotes.c search.c search.h txt2html.c txt2html.h New options: - showhtml: new option value 2 gives richer conversion to html borrowed from txt2html.pl. - monthly_index: create additional index files broken up by month. - yearly_index: create additional index files broken up by year. - thread_file_depth: break the threads index file into multiple files, roughly one per thread. - linkquotes: creates fine-grained links from quoted text to the text where the quote originated. It also improves the threads index file by more accurately matching messages with replies. - searchbackmsgnum: with linkquotes and -u, speeds up processing, with some risk that linkquotes won't find all links it should. - link_to_replies: generate links from original quoted text to the location(s) in replies which quote them. - quote_hide_threshold: If the linkquotes option is on, replaces quoted text with links in messages which quote too much. - quote_link_string: with quote_hide_threshold, use this text in place of first line of quoted text. Peter McCluskey (Feb 20 2001) - replaced the bodymailcommand with the following, to be more compatible: * mailcommand - works as before unless replymsg_command specified * replymsg_command - used for sending a reply to the list; if not specified, is set to the value in mailcommand for compatibility with old .hmrc's * newmsg_command - used for sending a new message to the list ======================== HYPERMAIL VERSION 2.0.0: ======================== Peter McCluskey (Feb 19 2001) applied patches from "W. Tasin" <tasin@fhm.edu> - some changes in the german translation - if a Content-Base is found set content=CONTENT_IGNORE because it is on another server and it would never be parsed well inside the mail... (this is more a workaround than a good patch... a better way would be to include this to every link inside the content... to show up also this external site... but I think it is an easy way to handle this problem) - add NONE as value for set_mailcommand, so "New Message" will not be shown - improve handling of inline attachments after signature. - prevent "(no email)" in emailaddr from becoming mailto. - add option set_bodymailcommand to configure mailto's other than one used in MSG_NEW_MESSAGE or MSG_REPLY. - changes to makemailcommand to prevent (nil) from showing when no Subject:. Daniel Stenberg (Jan 3, 2001) - Added checks for more functions in the configure script Ashley M. Kirchner (May 31, 2000) - I converted all uppercase HTML tags to lowercase in the main hypermail base source. Stuff that got contributed (under the contrib directory) were not touched. I'm going to leave those for their respective contributors to change. Daniel Stenberg (daniel@haxx.nu) (May 25, 2000) - Added 'spamprotect' as a new flag. It replaces @-letters with "_at_" to confuse spam-email-robots a bit. - Found a terrible bug when an URL contains a @-letter, since it'll first become <href>-tagged and then <mailto>-converted... :-/ - Added https:// as a recognized URL type (deja-vu, didn't I do this before?) - Corrected the alternative parser not being reset at the end of all mails Daniel Stenberg (daniel@haxx.nu) (May 23, 2000) - Corrected the output on %> appearences in the template files - Applied the beauty fix supplied by Darryl Lee <lee@darryl.com> Daniel Stenberg (Apr 10, 2000) - I made %<unknown letter> in printfile display exactly as used the other day. Today I changed my email address all over! - Added https:// to the recognized URL types to <a>-ify Jose Kahan (jose@w3.org) (Jan 17, 2000) - The quoted printable decoding didn't take into account the ietf-mbox option. Jose Kahan (jose@w3.org) (Dec 24, 1999) - Removed an invalid </A> tag when using tables. - When using the showhtml option, invalid HTML was generated in the headers: <P><P> before the </PRE>. - Stopped the generation of a Mailto on msgid's. - Rearranged the format of the index and messages when not using tables. My aim was to make the format more symetrical. - Added a new item, "Mail actions", in the control menu. This item is only active when using the mailcommand and hmail options, and when the tables are turned off. This option duplicates the one found in the table. - Added two new options for linking external stylesheets to the index and the messages, respectively: icss_url, mcss_url. The link is added as a META element in the header. - The default value of the mailcommand mailto: had some typos: non escaped chars, use of reply-to instead of in-reply-to. - Two protections were missing to avoid having empty HREFs when the about and archives options were defined in the .hmrc file, but wihout any given value. Jose Kahan (jose@w3.org) (Dec 15, 1999) - The inline changes from 29/Nov had the side effect that other inline attachments, like text/html were being linked like inline images. Kent Landfield <kent@landfield.com> (Dec 8, 1999) - Bjarni R. Einarsson <bre@netverjar.is> pointed out that the "Reply:" and "Maybe Reply:" output was not correct. pcm@rahul.net (Peter C. McCluskey) submitted a patch that fixes them as well as the current threading allows. Kent Landfield <kent@landfield.com> (Dec 7, 1999) - Added hoaf-28 python index generator written and contributed by Bernhard Reiter <bernhard@climate2.geog.uwm.edu> to the basline. - Added ls2mail script written by David Kilzer <ddkilzer@ti.com> to the basline. - Converted libcgi.doc to libcgi.html. Kent Landfield <kent@landfield.com> (Dec 1, 1999) - hypermail-2b28 rolled. Kent Landfield <kent@landfield.com> (Nov 29, 1999) - Corrected a parsing error in parsemail when dealing with attachments. If the filename was "quoted" things worked properly. If the filename was not quoted then the name of the attachment was dropping the first letter of the filename and adding '_' to the end. - Corrected a conditional statement that was limiting storage of 'inline' types to only recording inline types that were of type image/. - Changed strstr usage when searching MIME headers to use strcasestr instead as the case sensitivity was getting in the way. Kent Landfield <kent@landfield.com> (Nov 28, 1999) - Inconsistencies in write* routines called in hypermail.c pointed out by Bernhard Reiter <bernhard@uwm.edu>. set_* variables were used but still passing values in with the function call. Removed unneeded parameters. Kent Landfield <kent@landfield.com> (Nov 22, 1999) - The .hmrc resources didn't seem to override the default values, but rather got added to them. This was corrected for list usage. If a list value is set in the .hmrc file, it should completely replace the default values. This need only occur on the first occurance after the builtin initialization. - Jeff Katcher pointed out 'At the bottom of index.html and date.html, "Last message date:" is output twice. It's only present once on the author and subject pages.' This has been corrected so it is only printed once. Jose Kahan <jose@w3.org> (Nov 23, 1999) - A typo in setup.c:PreConfig gave problems (memory overwrite) when dealing with CFG_LIST configuration options. - uudecode wasn't working with the ietf-mbox option. Kent Landfield <kent@landfield.com> (Nov 22, 1999) - Error in setting of defaultindex in configure.in caused no index.html file to be created. configure.in was corrected to set the default index to "thread" instead of thread.html. - Added .indent.pro files to FILES file. - Added "-p" option to mkdir so all parent directories will be made if needed. - Added requests to TODO file. Kent Landfield <kent@landfield.com> (Nov 17, 1999) - hypermail-2b27 rolled. Kent Landfield <kent@landfield.com> (Nov 17, 1999) - Changed the install dependencies for the Makefile.in files so that install-sh is used through out. - Assured all includes are checked for in configure. - Updated FILES - Corrected dependencies on defaults.h Kent Landfield <kent@landfield.com> (Nov 14, 1999) - Corrected CFG_LIST storage of defaults other than NULL in the function ConfigAddItem(). - Assured struct hmlist variables set_text_types, set_inline_types, set_prefered_types, set_ignore_types, and set_show_headers set to NULL initially. Othewise add_list was checking garbage when called from ConfigAddItem(). - Reworked some of the defaults in setup.c - Added a dump_configI() routine to print out all internal variables for debugging. Use #ifdef DEBUG to get it included. - Removed unused defines in setup.h - Added defaults.h.in so sites could setup reasonable global defaults. - Added additional configure support for setting defaults for language, htmlsuffix, defaultindex and domainaddr in defaults.h. - Added cleanup of defaults.h and mail-archive test directory to Makefile - Removed old method from Makefile.in and lists.h in the archive directory. - Regenerated configure from configure.in. - Regenerated the dependencies in src/Makefile.in - Removed some #if 0 code in date.c - Changed strdup calls to strsav calls in getname.c and mail.c - Cleaned up html page output if usetable was selected. - Removed unnecessary variable passing into the writedates(), writethreads(), writesubjects(), writeauthors() routines. - Freed up memory alocated for configfile variable. - Removed unneeded variables in hypermail.h (previously #if 0'ed) - Updated README a bit. - Updated Changelog Kent Landfield <kent@landfield.com> (Nov 11, 1999) - Removed strdup declarations that were causing gcc to fail on certain systems. - Added French language support contributed by Nicolas NOBLE <pixels@chez.com> - Updated documents about "is" and "fr" language support. Kent Landfield <kent@landfield.com> (Nov 9, 1999) - Added checking the return value of getpwuid() in readconfigs. If the value is NULL then see if the $HOME is set in the environment. This avoids a crash for Win32 users who don't bother to set up /etc/passwd in cygwin environment. - Added support for proper naming of executables (hypermail on Unix hypemail.exe on Dos/Windows/NT). - Corrected getlocaltime so it would not print the timezone twice if the timezone was also specified in the dateformat directive. - Corrected print.c so From: is printed when the email address is the same as email name. - Removed tests/testhm from the baseline. Replaced it with testhm.in so configure can generate the proper path to the test hypermail executable. - Modified configure.in so that it can determine if it is running in cygwin environment. Added tests/testhm.in support. - Removed acconfig.h from the baseline as it is no longer needed with the current configure changes. - Assured destination directories exist for all installed files. - Added uninstall option in makefiles. - Cleaned up the docs/Install-win32.txt to reflect the changes made. Bjarni R. Einarsson <bre@netverjar.is> (Nov 5, 1999) - "is" message table translation. - Added a stripsubject feature to hypermail, which makes it remove all occurances of a given word from the subject line, which is really useful for un-cluttering the subjects of some mailing lists (my lists all have their subjects prefixed with [listname]: - which is quite redundant in an archive). Jose Kahan <jose@w3.org> (Nov 4, 1999) - Cleaned a bit the HTML format as well as the arranging of the indexes, to make them look a bit more coherent. - Commented the code that assumed we have an HTML text when finding a line with <HTML>. The best way is to send HTML text using a correct content type. - New configuration option, custom_archives, that allows to define a proprietary HTML text to be shown in the Other mailing archives item. - New configuration option, ietf_mbox, for parsing IETF-formatted mboxes (see the doc). Jose Kahan <jose@w3.org> (Nov 2, 1999) - When using the showhtml option, </PRE> tags were being added to each line of the signatures. Martin Schulze <joey@infodrom.north.de> (October 27, 1999) - Some where the showheaders functionality was lost. It has been partially added in. The 'hm_show_headers = list_of_RFC_Headers_to_display' functionality did not work and has been corrected. - If the show_headers directive contains the special character ``*'', hypermail will display all header lines. - Hypermail 2.x can now read hypermail 1.02 config files. Needed to assure minimal impact of existing sites that use the older version of hypermail. - hmrc.4 and hypermail.1 have been updated. Kent Landfield <kent@landfield.com> (October 27, 1999) - Edited documentation to the text more readable by using two spaces after a fullstop. - Cleaned up prototypes so they are consistent through out the include files. - Found many locations where a local variable was shadowing a global variable. Renamed certain variables to assure no compiler confusion. - Extended the warning switches in WARNINGS in the Makefile.in. Kent Landfield <kent@landfield.com> (October 23, 1999) - Added additional checks in configure for the operating system. Set -Ae for HP-UX and added checks for functions in libsocket and libnsl. Added sanity checks to assure you are on the same machine if you are using the existing config.cache and added acconfig.h config.guess config.sub support files. Additional cleanup to configure.in and a regenerated configure script. Scott Rose <srose@direct.ca> (October 20, 1999) - When a URL has trailing punctuation, it is almost certainly not part of the URL. This version of parseurl() therefore excludes trailing punctuation from URLs it finds. - If the content-description of a message was empty, and at the end of a line, the link to the associated attachment was anchored on null text. Fixed to assure the text is anchored on the filename in the generated HTML. Scott Rose <srose@direct.ca> (October 19, 1999) - Added contrib/canonicalize.pl Comparing two archives is complicated by the fact that each message is marked by the time at which it's archived. Attached is a script that standardizes that date, if weakly, useful for such comparisons. - Added contrib/hyperfeed.pl Feed messages from an mbox into hypermail one at a time so as to test the incremental mode of hypermail. - The idea here is that we are zipping along through an mbox, gathering information about a message, when we encounter a "From " line that signals the start of the next message. A side effect is populating dp with the date from that "From " line. In the existing code, that value is copied into fromdate[] just before the old message is hashed, which causes it to be associated with the previous message. This caused different output depending on incremental or mbox updating. This patch corrects that by moving the date copy until after the addhash function is called. Kent (October 18, 1999) - Updated parseurl fuction as done by Scott Rose <srose@direct.ca> provided 25% faster processing than the existing version while maintaining the same functionality. Kent (October 8, 1999) - Changed msg2archive.c to be able to use the command line - Made changes to runtest to assure msg2archive could be tested. - Added the indent file .indent.pro in archive, src and lib. - Ran indent on all sources in archive, src, and lib. - Made changes to configure.in to better support libsocket.a - Corrected configure.in check from gethostbyname to gethostbyaddr. - Added configure check for inet_addr - Added addition header checks and function checks in configure.in - Regenerated config.h.in with autoheader - Regenerated configure with autoconf - Updated the source files to use the HAVE_* definitions in config.h - Minor editing on the README - Minor updates to the TODO file and Changelog file. - Updated KNOWN_BUGS with the content of tests/Problems - Removed tests/Problems from the baseline as it was duplicating KNOWN_BUGS - Removed src/Formatting from the baselien as it was a junk working file of mine that should never have been baselined originally. - Added tests/mboxes/embedded.msg as a test file and updated tests/testhm to exersize it. - Removed the listing for tests/Problems and src/Formatting, while adding tests/mboxes/embedded.msg to the FILES file. - Added the corrected version of hypetombox.pl done by Peter McCluskey (pcm@rahul.net) to the baseline. Jose (October 7, 1999) - Changed the HTML DTD string of the generated strings to HTML 4.0 Transitional. - Updated the doc to correspond to the suppression of the options's hm_ prefix. Made the doc's HTML documents valid HTML 4.0 docs. Kent (September 20, 1999) - Cleanup of prototypes. - Removed the generated getdate.c from the baseline. (Generated from getdate.y. - Purified and removed array bounds read problems. Daniel (September 17, 1999) - Applied language patches from Jyrki Kuoppala <jkp@kaapeli.fi> - Applied Kent Landfields lots of changes. getname() is reverted to an older version since the newer did out-of-bounds reads. - Paul Haldane's fix is applied. - Peter C. McCluskey <pcm@rahul.net> suggested fixreplyheader() correction has beed applied. Daniel (September 13, 1999) - Kent Landfield found a bunch of weirdnesses that were corrected, in: * threadprint.c/print_all_threads() * print.c, makemailcommand() usage Jose (September 8, 1999) - (This is a big commit as I'm merging my independent developments into the public hypermail tree, which I'll use from now on) If there's a Content-Description header, we now use it to describe MIME attachments (unless they are inlined). Two new options (see the hmrc.4 or hmrc.html file for more info): + hm_uselock to turn off hypermail's internal locking mechanism + hm_usemeta to store the content type of a MIME attachment in a metadata file (also available thru commandline option -M) If the usemeta option is turned on, the Content-Type header of an attachment is stored in a .meta directory (see hmrc.4 or hmrc.html for more info). Files where MIME attachments are now prefixed with a two-digit counter, a la dd-name. This is to avoid having having to create temporary files, and to preserver links. The counter is incremented for each attachment, regardless of it's being inline or not. I disabled the call to emptydir as it's not useful (will add it as an option later on). External MIME attachments that don't have a filename, are given the name dd-part. Improved handling of MIME rfc822 attachments. Improved handling of Content-Disposition Ashley (September 7, 1999) - Added configure options for --httpddir, --cgidir and --htmldir with Apache's layout as the default (/usr/local/apache) Daniel (August 23, 1999) - Removed the 40-letter limit for subjects in the thread-index when the table option was enabled. jose.kahan@w3.org - When the boundary is declared without quotes, parse.c failed to get it properly. - print.c: There was a missing <PRE> and this resulted in a not-readable text Daniel (August 10, 1999) - I hade a terrible bug that made the attachment directories to get created relative the wrong directory! They were also not getting the proper permissions set. Tim Witham <twitham@pcocd2.intel.com> (August 10, 1999) - Had to fix a realloc() with NULL pointer which sunos doesn't handle. 2a24 ==== Daniel (August 9, 1999) - I'm consider renaming the series of archives that I'm releasing, back to the beta label. It would be more correct. Kent is with us again and I don't think anyone is gonna continue on the now forever sleeping beta-series. This seems to be the one and only hypermail development branch and I believe we now have it stable enough. - 'attachmentlink' is a new config file item that controls how attachments' links are made. By using this you can make a wrapper cgi script on your server that issues a warning to the user that it may be dangerous to run attachments or whatever you think is appropriate. Default it behavs as it used to do before this feature was added. Daniel (August 8, 1999) - Applied Jose Kahan <Jose.Kahan@inrialpes.fr>'s patches: The alternate content parsing was broken in that you couldn't give a list of preferences. Also, if you first parse an alternate with a low priority, then another one with a higher priority, the memory and, eventually, files created to store the former alternate content weren't erased. I found a minor bug. When decoding messages with multiple MIME attachments, the decode variable (where the content encoding format is stored), isn't updated. Daniel (August 6, 1999) - Fixed the subject overflow - Made attachments get saved in their own subdirectories. 2a23 ==== Daniel - I'm making a release out of this now since I'm off for a longish vacation next week... Paul - Applied Tom van Alten's patch to correct improper formatting of messages when hm_showhtml = 0 and showheaders = 1. - New code to (optionally) accept messages wth no msgid. Default is to require msgids in all messages - use hm_require_msgids = 0 to avoid this check. - Made handling of duplicate msgids optional. By default duplicates are discarded. To accept them (replacing the msgid with a generated msgid) use hm_discard_dup_msgids = 0. - Check return value from addhash when reading old messages. Messages already archived should be valid but safer to check. 2a22 ==== Daniel - Applied a boundary parsing bug correcting patch supplied by Andreas Fuchs <asf@ycom.at> Paul Haldane o (May 16th 1999) 1) changes to the way we construct threadlist (so that all the messages that should be in the thread are included even if they don't have valid in-reply-to headers) 2) changes to threadprint.c - simplification of print_all_threads. Now uses the information in threadlist to find the relationship between messages. This speeds things up a bit when adding single messages to large archives (I saw a reduction from 28s to 18s for adding a message to a 1,100 message archive). Slight speed-up when converting large archives - not as noticeable as a large part of time now seems to be in fopen(). I've updated/added some comments. I've added msgnum to the reply struct - this is just a copy of msgnum in ->data->msgnum - this was intended as an optimisation but I suspect it doesn't make much difference. Threading is now much better (well, I would say that wouldn't I :->). it still gets things wrong occasionally - often not really its fault. Known problems include 1) duplicate message-ids - results in messages being attached to the wrong thread - actually found an instance of this in my test mailbox. The obvious heuristic to avoid this would be to compare the subject as well, though this breaks threads where the sender has deliberately changed the subject but intends to continue the thread. 2) occasionally gets messages in the wrong order because they get attached to different sub-threads - wouldn't happen if MUAs used in-reply-to. I've done a quick tweak to duplicate msgid handling in addhash. Now replaces duplicate msgids with a locally constructed one. This keeps things happier. 2a21 ==== Daniel o (May 12th) - Added the tests/stdintest.pl script. It is a small perl hack that passes a series of generated mails into hypermail on stdin. One by one. I've got reports about bugs in that area, but I can't seem to repeat any with this tool. I thought I'd better include this here anyway to better enable others to run more torture tests on hypermail. Paul Haldane o (May 6th) - Here's a patch that allows the user to decide on the format used to present dates on the generated pages. If dateformat is set then it uses that (that's the new functionality) otherwise it uses the standard format or euro format depending on the config file. I've not given the option to use the date string as originally given in the mail message. This could be done without too much hassle. Daniel o (May 5th) - Corrected a crash in parse.c - Added a missing "From:" in print.c - Made the bin-names get prefixed with "att-" too. - Adjusted getname() to skip all starting white spaces and quotes, and to skip trailing quotes as well as white spaces. o (May 4th) - Attachment names could miss the first letter. 2a20 ==== Daniel o (May 3 1999) - Implementing my new From:-parser into the new source file: getname.c. This should hopefully not only be much better at parsing from lines, but also to it in a more stable manner. - Found some additional problems with From-lines I've tried to correct. Like a single-mail archive or mails with no From:-lines at all. Ron Brogden <rb@islandnet.com> o A small correction to hypermail.c lets it compile properly on sunos 4. 2a19 ==== Daniel o Now I prefix filenames with "att-" when I save attachments. o Several errors correct, most of them by Paul Haldane. 2a18 ==== Daniel o (Apr 7 1999) - Added 'locktime' as a configurable item. It defines the maximum number of seconds to wait for an existing lock to dissapear before it is overridden. If this is 0 or less, the lockfile will lose its power completely. locktime is 3600 by default. - I made the 'indextable' option work as Glen Steward wanted it to (that March 30 patch apply wasn't such a big hit). You can either set "indextable = on" in the config file or use the -T command line option to get the indexes in "table" version. Paul Haldane o (Apr 7 1999) - Major date-parsing re-arrangement. getdate.c added, lots of functions patched. Speed improvements. 2a17 ==== Daniel o (Mar 30, 1999) - First atttempt at applying Glen Steward's table patches. It wasn't a complete success but it can be adjusted from here. o (Mar 29, 1999) - Ashley M. Kirchner found a silly bug that occured if the last mail in the box was a double message-id (or similar that makes that particular function return NULL). o (Mar 25, 1999) - Threaded index seems to work yet again! - Paul Haldane <Paul.Haldane@newcastle.ac.uk> brought me lots of various patches that made hypermail do better! o (Mar 25, 1999) - Corrected the problem with "re: subject" and "subject" being sorted differently. The explanation was that the "re:" subject had a space left in the beginning of the string! o (Mar 25, 1999) My giant work of redoing things now finally seems to work a little at least. What's been done the last week: - All emails now get only ONE single struct allocated for it. - Remade the hash stuff. Hashed entries in the table only stores a struct, links it in the list and POINTS to the email struct. - Added a hash on the 'inreplyto' string to better enable finding mails a mail replies to. - Rewrote the whole darned threaded index functions. threadprint.c is a new source file for threaded index functions. - All indexes will now have full access to the complete email struct and will thus enable dates all over etc. This will enable me to introduce a template feature for how to write an entry in an index. I.e what to include for each entry, subject, author, date, charset, bla bla bla... - Changed the way single mail's "next in thread" links are found. - As a "side-effect" I added a filter to prevent the same message ID twice. The reason for this is that it is more likely for it to be able to screw up the threading if I allow them to co-exist. o Ashley M. Kirchner <ashley@pcraft.com> works on the bug report web. o (Mar 15, 1999) Roman Shterenzon <roman@xpert.com> pointed out a bug in the HTML-reader that made hypermail crash if the variables were set to "". I mailed back a patch to him I think will correct this problem. 2a16 ==== Daniel o (Mar 14, 1999) "text_types" is now a recognized config file item, where you can specify MIME types that should be treated by hypermail _exactly_ as if they were text/plain. o Corrected the list-check routine, so that the items in the list are the ones using wildcards. This means that suddenly, all those mime-list items support wildcards! o (Mar 13, 1999) Craig A Summerhill <craig@cni.org> found a bug. It turned out to be the fact that parse.c wronly assumed content-type text/plain to use ENCODE_NORMAL. It was really silly, since the Content-Transfer-Encoding header could've already appeared and stated another encoding! o Adjusted configure.in to do a slightly better -libnsl check. o (Mar 11, 1999) CVS server is up again. Added the UPGRADE file to the tree. Thanks to Glen Stewart. o (Mar 10, 1999) Pretty extensive re-write of parse.c to deal with the "Content-Disposition" headers better. That line can give a hint whether the file should be stored as a file or showed inlined. It can also have the filename (RFC1806 for details). o (Mar 10, 1999) The CVS server is down due to admin work there. o (Mar 10, 1999) Fixed parseurl(). It now deals with <www.foobar.com> and similar constructions better. Craig A Summerhill <craig@cni.org> reported. o (Mar 8, 1999) Corrected src/Makefile.in to not use options.h anymore! Roman Shterenzon <roman@xpert.com> made me aware of this. 2a15 ==== Daniel o (Mar 5, 1999) Made "text" equal text/plain in content-type: header lines. o Removed options.h completely to reduce the number of mistakes from people trying to edit it! o (Mar 4, 1999) Applied Glen Stewart's patch to remove a few <li> tags. o Bailey, Raymond <bailey9@MARSHALL.EDU> pointed out a problem in the getname() function. When you got a mail with a From: line where there is a name within quotes that were "attached" to the email part without spaces in between as in "name"<email@email.com> the parser failed to get a name part of this and caused hypermail to dump core. o Alisdair Davey <ard@mithra.physics.montana.edu> Helped me point out a bug in mprintf.c. It made the *printf() routines fail on %.*s constructions. I am considering an upgrade of the mprintf stuff to my newer "trio" stuff... o Made %f insert the file name of the generated HTML file in headers and footers. 2a14 Pl 2 ========= Daniel o Removed a bug that occured when converting a mail into html that had a "in-relpy-to" header but the replied-to mail was not present in the mailbox. 2a14 Pl 1 ========= Daniel (now CVS'ed at cvs.hypermail.yeehaw.net:/cvs/hypermail) o Made it de-mime headers even without the mime-version: header present 2alpha14 ======== Daniel o It should now accept white space in the beginning of config file lines. o SetupCleanup() bugs somehow, I'm no longer using it == dirty fix. o Updated the "name/email" scanner. o Total mail counter was wrong when updating. o Renamed to alpha to avoid confusion. 2b13 ==== Daniel o Two corrections in the mprintf.c. One of them being serious o (parse.c) now the QP decoder accepts question marks in the encoded-words o Corrected the mprintf() replacement define in mprintf.h o Added some more missing free()s in print.c 2b12 ==== Daniel o Now strips trailing white spaces from values in the config file if written without quotes. Paradise Cowgirl <minerva@phix.com> reported. o List types in the config were insanely written and caused memory disaster at times. Byron C. Darrah <bdarr@sse.FU.HAC.COM> and Jenni Baier <jenni@renewed.net> both probably experienced this. o Decreased the amount of memory allocations used when building hash tables for index sorting. (see addhash() in struct.c) 2b11 ==== Daniel o Tom von Alten <alien@hpdmlad.boi.hp.com> pointed out a really nasty bug in fixreplyheader() I had introduced! :-( 2.0b10 ====== Daniel o %c is recognized and replaced with a charset tag in mail headers. It should be set as early as possible within the HEAD tag. o Saves <!-- charset=blablabla --> in articles. o dprintf() was not a successful name, Linux uses it for some odd purpose even in stdio.h! :-/ Renamed my line of functions to m*. o Adjusted getname() to be slightly smarter. o Started working at adding charset to each single mail. It should be stored per-mail basis now, even though it is never used anywhere... It should now make a proper META HTTP-EQUIV tag! 2.0b9 ===== Daniel o Added a new -o option that can set any config options on the command line. E.g set label with -o "label=my new label". o Major rewrites of struct.c. There were just too many functions that passed data between them by strcpy()ing them to char buffers. They now pass char pointers in a lot higher degree. In fact, there aren't that many strcpy()s left in the source now. Not that I notice any faster operations, I just know it is neater code. o I really don't like the way proto.h has *ALL* prototypes and therefore everything is dependent on that file. I've stared to slowly extract the protos for each .c file into its own .h file. This will allow me to change prototype for a single function without having to recompile the whole lot. o Added general "Re:" - awareness functions. isre() returns TRUE if the input string starts with a re-thing and findre() returns the position of the first instance of re in the input string, or NULL if there is none. It knows and recognizes "Re:", "Fw:" and "Re[<number>]:" strings. If we ever intend to support local variations of this, I've now made that easier... o The new getname() had problems with parens in the real name part when quoted. As in From: "Windle, Alan M. (PA62)" <test@site.com> It shouldn't be a problem now. It should also work with from-lines like: From: ("Windle, Alan M. (PA62)") test@site.com There might be an idea to simply ignore everything within that level of parentheses. I mean, not add that text to the name. o The sorted datelist was broken because I must've destroyed unre() when I turned it dynamic. I improved printsubjects() to deal with pointers and it now strcpy()s a lot less data. Did the same change to the printauthors() too. o increment and readone are now separate options. Read stdin or use mailbox are mutually exclusive but don't modify increment or readone. The previous system was very confusing and didn't allow e.g updating an archive with two mails passed on stdin! I've now tried to update an existing archive with 3 mails passed on stdin and it seemed to work. Works if read from a mailbox too. Even works with the new -1 flag (to indicate there's one mail only). It has an accompanying config file keyword named 'readone'. I think the new -v flag is really great for this, cause it shows all built-in variables and kind of automatically documents them! o Ok, I wasn't aware the config file did assume quotes around the strings. I've added support for that (too) now. Distributed this small change to Kent, Tom and John as a patch for 2b8. 2.0b8 ===== Daniel (Nov 24, 1998) o So, just before I was gonna announce the b7 to the guys I got another report from John Petrakis that pointed out two bugs. One bad free() which he identified and one From:-line that b7 couldn't get name and email from properly. I got really tired and rewrote the whole getname() function to work with all the combinations mentioned in the source, and more. I think this function also has another benefit: it is easier to read than the old one. o I found some other bugs with my new setup system which caused the hm_htmlbody = NONE to not work. I am actually against that a line that says NONE sets it to the default. NONE should be NONE, if the keyword isn't used at all it should use the default. Well well, one thing at a time I guess. 2.0b7 ===== Daniel (getting deeper and deeper into this now ;-) o Entirely new config file parser. Does make adding new config items a lot easier and smoother. Run hypermail -v to make it output a fully working config file (after reading the given input parameters). There is no need for the "hm_" prefix on keywords in the config file. You can still use it if you want, but you don't have to. Internally, all configurable variables are now named 'set_XXXXX' to better make it visible in the code. o readoldheaders() is a lot more robust now. The order of the variables are not set and empty files no longer cause it to dump core. o Hypermail from now on only stores the variables inside HTML files that are actually set. name="" is not needed to store. 2.0b6 ===== Daniel continues: o parseemail() and ConvURLs() needed to deal with NULLs better. o loadoldheaders() are no longer dependent on the order of the variables in previously written HTML files. o Mails with no subject confused the parser.c o Tom von Alten <Tom_vonAlten@boi.hp.com> sent me two files he appearantly got from Kent after the b4 he sent me. (date.c and msg2archive.c) o All kinds of lists like hm_show_headers, hm_inline_types and hm_ignore_types now offer the below mentioned wildcards. o Added dmatch.c for dos-style * and ? wildcard matching. o Cleaning up more memory leaks. 2.0b5 as sent to John Petrakis 19 Nov 1998 ========================================== Daniel: o Added 'maketgz' to the archive. It is for creating release archives, without having to remove a lot of files first. * first asks for the version number of choice * uses the file FILES to know what files to include. * updates the patchlevel.h file to the entered version number * creates the archive with a directory based on the entered version number * names the archive based on the entered version number o Added a whole bunch of more free() calls. o Inlined HTML that was base64 or uuencoded were not previously dealt with properly. o Mails with no Message-Id: caused a crash in the hash function. o HM_INLINEHTML can now be set to 0 to prevent hypermail from inlining mail parts in HTML. 2.0b4 as sent to Tom von Alten Nov 19, 1998. ============================================ Daniel: o Dynamic strings all over. I added a generic dynamic-string system which I think works pretty good. Using functions and macros it should also be pretty easy to extend, modify and optimize without any other source modifications. I had to modify stuff all over the place and pretty much too. I hope I've removed at least the worst uses of static buffers and my initial tests prove me right. No lenght limits of any fields of a mail is my goal, and I think it is a fair goal. Beware of leaking memory now though. We need to setup some debug-system to track them easily. The dynamic string routines could very well be optimized too. o My dsprintf system was added. This system offers snprintf() - sprintf with a buffer length parameter and aprintf() - returns an allocated string with the text. I did this to better deal with fully dynamic buffers. o Corrected the swedish texts. All 8bit letters were gone! o (Nov 16) I recevied the 981013-b4 version. Started work. 2.0b4 ==================== Kent: o Date routine corrections. - Y2K capable. Hypermail used a two digit representation for the year through out. It now uses a 4 digit representation. - In hypermail.h, October was listed in monthdays as only having 30 days. - hypermail did not deal with all the major date string formats. Date: formats starting with a digit (09 Sep 1998 01:27:30 +0300) would cause parsing and threading problems. It now supports that format. - Added code to deal correctly with two digit years. The idea as to how to approach this and the basis for the solution is thanks to Byron Darrah. - Corrected an off by one day error in getyearsecs(). It was adding the current day && adding the hours, minutes, and seconds for that day as well. It only needed to count all the days UP TO the current day and then add the hours, minutes, and seconds for the current day. - Incorrect data type passed to fprint_summary(), needed to be long instead of int. - Corrected an off by one day in getdatestr(). Days in a month start at 1, not 0. o Add the ability to save hypermail generated html files with any configurable html suffix such as ".htm", ".html" or ".shtml", etc. This works for the index files as well as the message files. (New .hmrc variable, hm_htmlsuffix, new environment variable HM_HTMLSUFFIX, and HTMLSUFFIX define in options.h.) o Removed a conditional "if (use_mbox) increment = 0;" that was preventing the ability to read one message from a file and update an existing archive and its indexes. o Corrected parseurl to allow for a ',' (comma) character to be embedded in the URL. o Corrected parseurl to allow for a '&' (ampersand) character to be embedded in the URL. o Using -p with -iu on a new archive directory caused a core dump begause 'bignum' was zero. Corrected to assure bignum > 0. o Added language abilities to hypermail. English - en Spanish - es German - de Swedish - se initially supported. (lang.c and lang.h added.) Thanks to Francisco Iacobelli <fiacobelli@ibersis.cl> for the "es" message table translation. Thanks to Martin Schulze <joey@kuolema.Infodrom.North.DE> for the "de" message table translation. Thanks to Daniel Stenberg <Daniel.Stenberg@sth.frontec.se> for the "se" message table translation. o Changed how error messages are displayed so options message only displayed where appropriate instead of for every message. o Corrected getname() to parse yet another funky name format. o Corrected printing error when a invalid domain was encountered in an email address. o Converted some static internal buffers to dynamically allocated ones at startup saving 6+K. Also resulted in setstrval() not being needed so it was removed. o Corrected MIME parsing problem with previously parsed headers. o Corrected default labeling problem with stdin generated archives when no label is supplied. o Fixed hypermail so it would not crash if started with no arguments and an article on stdin. o Added locking to the archive so that there is less chance of corruption of the archive due to multiple copies of hypermail trying to update the same archive at the same time with multiple messages. This could be improved so as to check for pid of process that owns it... o Extended the configure support. o Extended the use of hm_progress so that more information about attachment files can be displayed. o Updated documentation to reflect changes o Corrected getname to deal with names that are all spaces. o Corrected configuration variable setting. Moved checks to the right place in the code. o Hypermail now supports listproc mailboxes as well as general Unix formated mailboxes. It does not require that a blank line exists between mail messsages in a mailbox. Thanks to Craig A Summerhill <craig@cni.org> for the push and the test data. 2.0b3 - 8/15/98 ================= o Added validation of domains so that the generation of mailto: is much more accurate than the previous method. o Added support for Content-Disposition MIME Header so as to get the filename from the header. o Added verification of filenames to assure they are safe to use and will not cause filesystem problems o Fixed a problem with parsing the ending MIME boundary (it expended headers following that) o Found and removed a one-byte buffer overflow in the line continuation code. o Corrected docs/hypermail.1 and TODO to reflect the proper RFC 822 parsing was actually included in version 2.0b1 o Corrected a typo in string.c that prevented the proper generation of mailto: links for email names with numbers [0-9] in them. o Corrected the base64 decoder error which caused files to get an extra zero-byte appended at times. (When storing attachments to disk.) o Added additional ported systems to the README o Removed the "#ifndef" from the defines in options.h. We do not want to inherit any define values from other places. If there are confilcts then I need to correct them. Inheriting defines can lead to unforeseen results. o attachments: - comments are now generated in the output mail for each attachment that is written in a separate file. The comment looks like: '<!-- attachment="filename" -->' in the standard comment style. o buffers and overflows - mdecodeRFC2047() now has an output buffer size argument - had to remove the use of rmcr() at two places, since that function uses a very strict static buffer limiting the maximum line length pretty bad. - parseurl() now features an output buffer size argument - parseemail() now features an output buffer size argument o multipart/alternative - added awareness and parser "intelligence" to pick the last prefered content-type within a series of alternatives (as MIME tells us to do). This has not yet been very thoroughly tested. - added the preferedcontent() function that returns wether a content-type is prefered or not (as set with hm_prefered_types). Default prefered type is 'text/plain' (if hm_prefered_types is unused). o output - added the experiment function printhtml(). It strips off unwanted html tags from the output, even if they are used in attached HTML files. I.e <HTML> and </HTML>. - made 'showheaders' not use <BR> or newlines since the BRs are ignored anyway, and the newlines are already present in each header line. - added 'hm_show_headers' which is a list of what headers to include when the 'showheaders' option is used. For now, it also controls which headers to show when attached mails are shown. Although I can imagine that you'd like separate lists (since for attached mails, you'd like i.e subject which you may not need for the main mail itself). If 'hm_show_headers' isn't used, all headers will be shown. - made the <PRE> system in the printbody() function a little smarter, and now it prevents multiple </PRE> and <P> tags better. It did however introduce another side effect (although a less serious one imho) and that is an extra pair of <PRE></PRE> after the last attachment when using 'showhtml'. o parsing - made the multi-line merger function to make all lines get a regular white space between them when they're put together. Previously, this character was left as-is, which could be a space or a tab (or any other isspace()) letter. - check changed to check for "<!-- received" as the start of parsing previous html files in the event that the archive maintainer whishes to add comments in the header template HTML files. - in_list() now checks for list items case insensitive - corrected so Message-ID:, References and Supersedes: lines are not converted into mailto: URLs. - corrected off-by-one in isquote that was causing array boundary read errors. - corrected off-by-one in printbody line output that was causing array boundary read errors. Real thanks are in order for Daniel Stenberg and David D. Kilzer. They helped greatly with making this release possible by sending in enhancements, comments and bug fixes. Thanks Guys! 2.0b2 - 6/07/98 ================= o Corrected command line processing for individual messages received on standard input. o Corrected formating of Next message links when incremental updating is done. o Corrected the template filenames in docs/hmrc.html. Added "file" to them. o Added additional systems to the list of ported systems. o Reset certain options back to the proper defaults. o Corrected problem in printbody in regards to printing HTML embedded in a message. Still work to do here. o Changed address options to assure I didn't get landfield.com information inadvertantly set in hundreds of archives because the admins just took the defaults. ;) 2.0b1 6/05/98 - Kent Landfield =============================== WARNING: There have been too many changes to this version to list them all here. What appears below are some of the highlights. o Command line settings override what is in the config file. In the past the command line variables were read and set before the config file was read. (Needed to get the name of the config file from the command line.) This made it hard to have a default list configuration file and make single runs with only one variable changed. Now processing sets the hypermail internal options by: Using Compiled in defaults specified in options.h, then reads Hypermail Environment variables if set, then looks for and reads any Configuration file specified and finally uses the Command line settings specified by the user. NOTE: THIS IS DIFFERENT THAN PAST HYPERMAIL USAGE. o Configurable Setting (.hmrc file) or Compile Time Variable to Domain-ize Addresses -- addresses appearing in the RFC822 field which lack hostname can't be made into proper HREFs when Hypermail does it's thing. They are coded with: mailto:(no%20email) Because the MTA resides on the same host as the list, it is often not require to domain-ize these addresses for delivery. In such cases, I think it would nice if Hypermail could be programmed to output: mailto:kent@landfield.com instead. This would probably work well as a *required* definition during compilation; however, it should not simply rely on the output from `hostname` in case you want to override with an MX entry or alternate domain (if you run virtual domains) o Added capability to have customizable index html headers, message html headers and html footers. Able to use substitution cookies in the header and footer template files. Substitution cookies supported: %% - '%' character %~ - storage directory %e - email addr of message author - Not valid on index pages %h - HMURL %i - Message-id - Not valid on index pages %l - archive label %m - Mailto address %p - PROGNAME %s - Subject of message or Index Title %v - VERSION %u - Expanded version link (HMURL,PROGNAME,VERSION) \n - newline character \t - tab character Additional cookies generate the complete META lines: %A - Author META HTML - Not valid on index pages <META NAME="Author" CONTENT="name (email)"> %B - <BODY> html statement %S - Subject META TAG - Not valid on index pages <META NAME="Subject" CONTENT="subject"> o Generates META tags in articles Author and Subject. o Now uses "configure" to generate the makefiles. This is rather weak at present and needs to be added to/tested on other systems but at least it's a start. o The config.h was renamed to options.h to support configure usage. o patchlevel.h added to facilitate better patches in the future. Still need to fully integrate it's useage in version displays. o Added example .rc files to show how to customize list's and their looks. o Removed the _print.c files that had existed in the 103b2 release and replaced them with template headers/footer files. o Extended archive path creation to make missing directories. o Added capabilities dir pathing to allow archive creation by date variables. %d - two digit day of month (1-28/30/31) %D - three letter day of the week %m - two digit month of year (1-12) %M - three letter month of year (Jan, Feb, ..., Dec) %y - four digit year (1990,..2001) RC example: hm_dir = /some/archive/listname/%y/%M ENV example: HM_DIR=/some/archive/listname/%y/%M Command line example: -d /some/archive/listname/%y/%M Expands to: /some/archive/listname/1998/May All files would be archived during that run in that directory. Subsequent executions will put the messages in the directories according to the date the messages were received on the archive site. o All "mailto:" links can include the "subject" so that the Subject: line of netscape mailer is automatically filled in. o Fixed "Re:" and redundant "Re:" variation && MS FW... o Greatly enhanced getname() to correctly deal with most all email addresses. X.400 addresses are not well supported yet. o Corrected getreply() to better support the In-Reply-To: formats. The routine needs to revisited when a readline routine is inserted to properly deal with continuation lines. o Added additional documentation describing the Hypermail configuration file. o Added additional documentation describing how to customize HTML generated pages. o Corrected many petty problems such as: - recursive '%' substitution. A % in a subject line could cause an ugly recursion problem in a mail command expansion. - title length problem. Length of a title needs to be limited to less than 64 characters as indicated by HTML specs. - Weblinted the generated output and corrected various things. - Removed unused and unneeded variables o Change various storage length defines in hypermail.h Patches Contributed From: "Roy T. Fielding" <fielding@kiwi.ics.uci.edu> ------------------------------------------------------------------------ o Fixed the umask default, o Fixed default directory and file creation modes, o Fixed the many date problems, o Corrected one of the Message-ID bugs, o Removed annoying #start/#end fragments that mess up the browser history. Patches Contributed By: Byron Darrah <bdarr@sed.hac.com> ---------------------------------------------------------- o Added a menu bar for a header and footer on all pages and removed the bulleted list items that it replaces. o Reworked the general appearance of header and footer parts of html pages. o Added the "hm_hmail" configuration parameter and -n command line option for specifying an email address for input to a hypermail archive. o Added "New Message" and "Reply" buttons to the menu bar for submitting messages to a hypermail based list. Patches Contributed From: Jared Reisinger <feety@hhhh.org> --------------------------------------------------------- o Fixed configfile substring problem. o SHOWBR, IQUOTES, SHOWHR, EURODATE, SHOWREPLIES, and MAILCOMMAND now run-time configurable. o Fixed post leap-day error. o More robust Message-ID parsing. o Better SHOWHTML handling for indented lines. o Allow IQUOTES when not using SHOWHTML. Patches Contributed From: Daniel Stenberg <Daniel.Stenberg@sth.frontec.se> -------------------------------------------------------------------------- o I had all calls to the decodeRFC2047() function moved to *after* the merging of long lines. o decodeRFC2047() now correctly concatenates two succeeding "encoded words". I now call the function mdecodeRfc2047() since it now allocates the new string. o Now informs if the attachment wasn't properly decoded when stored to disk. This happens if the Content-Transfer-Encoding specified isn't known to the parser. When this happens, the attachment is stored as 8bit octet- stream. o Now supports the encoding type 'x-uue' for uudecoding. I think there are mailers that use different names for the same encoding type so we better watch out for them in the future... o Added the 'demimed' field to the body struct to keep track of header lines+ that have been RFC2047 converted already. o Kent Landfield sent me an interesting mail that showed me several weird bugs in the MIME area. A. The Quoted-Printable decoder bugged. A quick fix solved that. B. The quoted printable decoder didn't support unlimited size of the line the encoded text decodes into. I wrote a new function that seems to do it properly. C. Some important headers were not properly supported if they were split up on several lines. I had to rewrite the header parsing system to make this work. It now scans all headers and concatenate them into single lines before any function is trying to parse or decode them. D. It also showed a need for a uudecoder for the 'x-uue' encode type. This is only noted for the future as I haven't written any decoder for this format [yet]. o decodeRFC2047 replaces the former RFC1522 function. I made it support 'encoded-words' anywhere in the line and several different ones on the same line is now supported. The only flaw I'm still aware of now, is that if there are two encoded-words next to each other, the result should not show the spaces between them. My function unfortunately still does. o renamed decodeRFC1522 to decodeRFC2045. o decodeRFC1522 (quoted printable header decoding) didn't do well if the ending ?= sequence was in the middle of the line. I think this function will need more extensive testing. o Attached mails' headers (To:, From:, Date: and Subject:) are now shown in the html. o Attached mails that contains attachments did force me to add a stack system for the multipart boundary strings. Seems to work now. (Can't wait to see an attached mail that contains an attached mail that contains ... ) o strcpymax() introduced to prevent buffer overflows on extra-long headers o Lines starting with 'from ' messed up the parser pretty badly. It now checks for 'From ' lines (case sensitive) with an empty preceding line to split mails. o Now extracts attachments to separate binary files. o Supports multiple lined headers. o Supports quoted-printable and base64 encoded headers. o Supports base64 encoded text/plain o Rewrote the URL and email parsing to allow multiple URLs and email addresses on each line. o Extended the original functionality to much better deal with MIMEd mails and the standards from RFC 1521 and 1522. There are still flaws in compliance with those but the majority of all mails using mimed texts will be presented in a fairly decent fashion. Patches Contributed From: David D Kilzer <ddkilzer@ti.com> ----------------------------------------------------------- o Fixed problem with 'From: ' header lines in messages with the following format: "From: <email@address.com>" wherein the "name" from the previous email message would be used instead of reverting to the address itself. o URLs can now include ampersands (&) if they are preceded by question marks (?) in the URL string. o Email messages with no Subject line no longer grab the previous email's subject. o Reworked the order of output so that "message" links are always at the top of the page in article pages and date/thread/subject/author pages. o Now escape '%' in mail URLs. o Escape for '+' was wrong, changed to '%2B' (was '%22'). o Updated replace() function to recurse on 'afterstring' variable rather than the whole 'newstring'. More efficient and allows '%' escaping. o config.h: Added configuration option for SHOW_MESSAGE_LINKS which turns all message headers and footers off (except for the links to the date, subject, thread and author pages). SHOW_MESSAGE_LINKS overrides the setting of SHOWREPLIES. o print.c (writearticles): Removed use of currentemail, currentid, and currentsubject by forcing use of email2, msgid2, inreply2, subject2, and name2 when calling struct.c (hashreplylookup). This was needed after I rearranged the order in which articles were printed. o string.c (convurls): Added code in two locations for the Message-Id code segment to recurse on the remaining portion of the line being processed. Each Message-Id found forces a return from convurls() after a recursive call. This prevents infinite recursion (a Bad Thing generally speaking). Note: we assume that Message-Ids and URLs/email addresses do NOT appear in the same line. o string.c (convurls): Changed format string from "%.3d" to "%.4d". Fixed major bug in outputting links for Message-Ids. o string.c (convurls): Fixed assumption in code for identifying Message-Ids that there was only one Message-Id per line. We now stop gobbling up text used for a link with a space (' ') or a tab ('\t'). o string.c (convurls): Added int got_question_mark in URL processing code to permit an ampersand ('&') in a URL provided it comes after a question mark in the same URL (a GET method with POST data). Added one line of code and changed another to accomplish this. o string.c (convurls): Added code to check whether the next item to URL-ize is an email address (containing an at sign, '@'). If it is, we break out of the URL for loop and go process the email address. o parse.c (loadoldheaders): Modified initial fgets() call to skip any non-comment lines (i.e. "<html>" and "<head>"). o string.c (makemailcommand): Added code to escape percent signs ('%') when escaping spaces (' ') and plus signs ('+'). Percent signs must be escaped first since other escape sequences use the percent sign followed by a two-digit hexadecimal number. We're now a little more MIME-compliant. o string.c (replace): Changed the replace() function to recurse only on the 'afterstring' portion of the URL instead of the whole rebuilt URL. This is both more efficient and prevents infinite recursion problems when escaping percent signs ('%') with '%25'. o string.c (makemailcommand): Fixed escape sequence for plus signs ('+') from '%22' to '%2B'. LOTS of other small patches from lots of other helpful people. I hope to be able to more accurately list them in the final 2.0 version. 1.03b2 3/10/98 - Kent Landfield ================================= o Header corrections made, o all current memory leaks plugged, o variable initialization corrected, o expanded response message recognition, o fixed many threading related bugs. o Restructuring directory layout for ease of support and to make adding utilities easier. o Added additional archive utilities. 1.03b1 4/6/97 - Kent Landfield ================================ o Corrected memory leaks, o cleaned up HTML produced, o ran purify, lint and insight and cleaned up output. o Added the ability to customize header/footers via crude means but hey, it works. 1.02 8/1/94 - Kevin Hughes ============================ Fixed configfile problem, different usage() output, days[] space fix, NODATE, stripzone() fix, insig fix, SHOWBR, SHOWHR, IQUOTES, THRDLEVELS. 1.01 7/29/94 - Kevin Hughes ============================ Printfooter declaration, getdate() and timezone names changed to avoid library conflicts. Bad #define fixed (null) bug. 1.0 7/29/94 - Kevin Hughes ============================ Configuration file, logic fixes, better "re:" stripping, name tags, default index.html (HM_DEFAULTINDEX), default directory name can be mailbox name, mailto: fix, better dates, better error messages, numbered files are padded to four digits, headers are always in <pre>, next in thread, maybe in reply and maybe reply, MAILCOMMAND, EURODATE, commented source, chmods only new files, <html>, custom mail command variables. 1.0b3 7/14/94 - Kevin Hughes ============================ Environment variables added, ampersands are converted. 1.0b2 7/13/94 - Kevin Hughes ============================ Incremental updating added and various parsing bugs fixed. 1.0b1 7/6/94 - Kevin Hughes ============================ Hypermail rewritten in C. Because the source is so new and relatively untested, it's still considered to be in beta until feedback from users is received. ================================================ FILE: FILES ================================================ # # FILES: Automatically generated by mkFILES: # - Wed Mar 20 19:50:32 CET 2013 # ################## # Top-level files # Changelog COPYING KNOWN_BUGS FILES INSTALL Makefile.in README TODO UPGRADE acconfig.h aclocal.m4 config.guess config.h.in config.sub configure configure.ac install-sh ltmain.sh maketgz patchlevel.h # # - Archive directory files # archive/.indent.pro archive/1998 archive/Makefile.in archive/README archive/lists.h archive/mbox2hypermail.c archive/msg2archive.c archive/runtest archive/test-msg # # - Sample configs # configs/hmrc.example configs/hypermail-footer.hyp configs/hypermail-index.hyp configs/hypermail-msg.hyp configs/hypermail.rc # # - Contributed utilities # contrib/hoaf-28/haof-0.1.dtd contrib/hoaf-28/README contrib/hoaf-28/collect_snipplets.py contrib/hoaf-28/create_archive_snipplet.py contrib/hoaf-28/footer_html.hdr contrib/hoaf-28/hypermail-2b28-2b28+.patch contrib/hoaf-28/top_html.hdr contrib/canonicalize.pl contrib/cron_hypermail contrib/fixhtime.pl contrib/hyperfeed.pl contrib/hypetombox.pl contrib/ls2mail contrib/mailbox_date_trimmer/README.html contrib/mailbox_date_trimmer/README.mailbox_reader contrib/mailbox_date_trimmer/mailbox_date_trimmer.py contrib/mailbox_date_trimmer/mailbox_reader.py contrib/msg2hypermailarchive.py contrib/runtest # # - Documentation # docs/Makefile.in docs/archive_search.html docs/attachments.txt docs/customizing.html docs/hmrc.4 docs/hmrc.html docs/hr.yellow.png docs/hypermail-faq.html docs/hypermail.1 docs/hypermail.html docs/hypermail.png docs/index_hypermail.txt docs/stars.png # # - LCC-Win32 Build Support # lcc/README.txt lcc/pcre_chartables.c lcc/config.h lcc/pcre_config.h lcc/defaults.h lcc/dirent.c lcc/dirent.h lcc/getdate.c lcc/hypermail_files.txt lcc/lcc_extras.c lcc/lcc_extras.h lcc/pcre.h # # libcgi - mail suport lib # libcgi/.indent.pro libcgi/Makefile.in libcgi/cgi.h libcgi/form_ent.c libcgi/form_tags.c libcgi/get_cgi_info.c libcgi/html.c libcgi/libcgi.html libcgi/main.c libcgi/mcode.c libcgi/strops.c libcgi/syn_mime.c libcgi/syn_url.c libcgi/template.c # # - Hypermail source # src/.indent.pro src/.splintrc src/Makefile.in src/base64.c src/base64.h src/date.c src/defaults.h.in src/dmatch.c src/dmatch.h src/domains.c src/domains.h src/file.c src/finelink.c src/finelink.h src/getdate.h src/getdate.texi src/getdate.y src/getname.c src/getname.h src/hypermail.c src/hypermail.h src/lang.c src/lang.h src/lock.c src/mail.c src/mem.c src/parse.c src/parse.h src/print.c src/print.h src/printfile.c src/printfile.h src/proto.h src/quotes.c src/search.c src/search.h src/setup.c src/setup.h src/string.c src/struct.c src/struct.h src/threadprint.c src/threadprint.h src/txt2html.c src/txt2html.h src/uconvert.h src/uudecode.c src/uudecode.h # # - Source to pcre supporting library # src/pcre src/pcre/pcre_dfa_exec.c src/pcre/PrepareRelease src/pcre/pcre32_jit_compile.c src/pcre/pcre_ord2utf8.c src/pcre/pcre_maketables.c src/pcre/makevp.bat src/pcre/config.h.in src/pcre/pcre32_byte_order.c src/pcre/pcre_newline.c src/pcre/compile src/pcre/pcre32_printint.c src/pcre/pcre.h.generic src/pcre/pcre32_ord2utf32.c src/pcre/pcre32_fullinfo.c src/pcre/pcre16_valid_utf16.c src/pcre/pcre_study.c src/pcre/sljit src/pcre/sljit/sljitNativeTILEGX-encoder.c src/pcre/sljit/sljitNativeMIPS_32.c src/pcre/sljit/sljitNativeARM_T2_32.c src/pcre/sljit/sljitUtils.c src/pcre/sljit/sljitNativeMIPS_common.c src/pcre/sljit/sljitNativePPC_64.c src/pcre/sljit/sljitLir.c src/pcre/sljit/sljitNativeX86_32.c src/pcre/sljit/sljitLir.h src/pcre/sljit/sljitNativeTILEGX_64.c src/pcre/sljit/sljitNativeX86_64.c src/pcre/sljit/sljitNativeSPARC_common.c src/pcre/sljit/sljitNativePPC_32.c src/pcre/sljit/sljitConfigInternal.h src/pcre/sljit/sljitExecAllocator.c src/pcre/sljit/sljitConfig.h src/pcre/sljit/sljitNativePPC_common.c src/pcre/sljit/sljitNativeARM_32.c src/pcre/sljit/sljitNativeSPARC_32.c src/pcre/sljit/sljitNativeX86_common.c src/pcre/sljit/sljitNativeMIPS_64.c src/pcre/sljit/sljitNativeARM_64.c src/pcre/pcre16_tables.c src/pcre/pcre_tables.c src/pcre/pcre32_string_utils.c src/pcre/pcre_stringpiece.h.in src/pcre/libpcre16.pc.in src/pcre/pcreposix.c src/pcre/pcre32_config.c src/pcre/pcre_printint.c src/pcre/pcre_jit_test.c src/pcre/pcre16_newline.c src/pcre/CMakeLists.txt src/pcre/CheckMan src/pcre/pcreposix.h src/pcre/pcre16_refcount.c src/pcre/Makefile.in src/pcre/config.sub src/pcre/pcre32_ucd.c src/pcre/pcre16_version.c src/pcre/makevp_l.txt src/pcre/pcre32_valid_utf32.c src/pcre/pcre16_study.c src/pcre/pcre16_exec.c src/pcre/COPYING src/pcre/pcre16_ord2utf16.c src/pcre/pcre_valid_utf8.c src/pcre/pcre32_version.c src/pcre/AUTHORS src/pcre/pcre16_jit_compile.c src/pcre/depcomp src/pcre/pcre_stringpiece.cc src/pcre/pcre16_dfa_exec.c src/pcre/HACKING src/pcre/pcre32_get.c src/pcre/pcre32_newline.c src/pcre/pcre16_config.c src/pcre/pcre16_string_utils.c src/pcre/pcre32_exec.c src/pcre/pcre_xclass.c src/pcre/pcre_exec.c src/pcre/makevp_c.txt src/pcre/m4 src/pcre/m4/pcre_visibility.m4 src/pcre/m4/ltversion.m4 src/pcre/m4/ltsugar.m4 src/pcre/m4/ax_pthread.m4 src/pcre/m4/lt~obsolete.m4 src/pcre/m4/ltoptions.m4 src/pcre/m4/libtool.m4 src/pcre/pcregexp.pas src/pcre/cmake src/pcre/cmake/COPYING-CMAKE-SCRIPTS src/pcre/cmake/FindPackageHandleStandardArgs.cmake src/pcre/cmake/FindEditline.cmake src/pcre/cmake/FindReadline.cmake src/pcre/pcre_ucd.c src/pcre/missing src/pcre/pcre32_dfa_exec.c src/pcre/pcre_scanner_unittest.cc src/pcre/LICENCE src/pcre/configure src/pcre/pcre_compile.c src/pcre/ucp.h src/pcre/pcretest.c src/pcre/INSTALL src/pcre/pcre32_globals.c src/pcre/pcre16_printint.c src/pcre/config.guess src/pcre/pcre16_globals.c src/pcre/libpcre32.pc.in src/pcre/CleanTxt src/pcre/testdata src/pcre/testdata/testinput5 src/pcre/testdata/testoutput5 src/pcre/testdata/saved8 src/pcre/testdata/grepfilelist src/pcre/testdata/testoutput20 src/pcre/testdata/testoutput3A src/pcre/testdata/testoutput26 src/pcre/testdata/testoutput16 src/pcre/testdata/testinput10 src/pcre/testdata/saved16 src/pcre/testdata/greplist src/pcre/testdata/testoutput4 src/pcre/testdata/testinput21 src/pcre/testdata/testinput25 src/pcre/testdata/testoutput21-16 src/pcre/testdata/testoutput12 src/pcre/testdata/saved32BE-1 src/pcre/testdata/grepoutput src/pcre/testdata/saved32 src/pcre/testdata/testinput23 src/pcre/testdata/testoutput15 src/pcre/testdata/testinput24 src/pcre/testdata/testoutput11-8 src/pcre/testdata/grepinput src/pcre/testdata/saved16BE-1 src/pcre/testdata/testinput3 src/pcre/testdata/saved32BE-2 src/pcre/testdata/testinput20 src/pcre/testdata/testinput15 src/pcre/testdata/testinputEBC src/pcre/testdata/testinput17 src/pcre/testdata/testoutput22-16 src/pcre/testdata/testoutput25 src/pcre/testdata/wintestoutput3 src/pcre/testdata/testinput7 src/pcre/testdata/testoutput11-32 src/pcre/testdata/grepinput8 src/pcre/testdata/saved32LE-1 src/pcre/testdata/testoutput23 src/pcre/testdata/testoutput18-16 src/pcre/testdata/wintestinput3 src/pcre/testdata/testinput11 src/pcre/testdata/testoutputEBC src/pcre/testdata/saved16LE-2 src/pcre/testdata/testinput1 src/pcre/testdata/saved16LE-1 src/pcre/testdata/grepinputx src/pcre/testdata/grepoutput8 src/pcre/testdata/testoutput24 src/pcre/testdata/testoutput19 src/pcre/testdata/testoutput6 src/pcre/testdata/testinput9 src/pcre/testdata/testoutput3B src/pcre/testdata/grepbinary src/pcre/testdata/grepinputv src/pcre/testdata/testoutput14 src/pcre/testdata/testinput8 src/pcre/testdata/testinput6 src/pcre/testdata/testoutput21-32 src/pcre/testdata/testinput13 src/pcre/testdata/testoutput17 src/pcre/testdata/testinput2 src/pcre/testdata/testoutput18-32 src/pcre/testdata/testinput16 src/pcre/testdata/testoutput8 src/pcre/testdata/valgrind-jit.supp src/pcre/testdata/grepoutputN src/pcre/testdata/testoutput7 src/pcre/testdata/testoutput3 src/pcre/testdata/testoutput1 src/pcre/testdata/testoutput2 src/pcre/testdata/testoutput22-32 src/pcre/testdata/greppatN4 src/pcre/testdata/testinput14 src/pcre/testdata/testinput18 src/pcre/testdata/testoutput10 src/pcre/testdata/testoutput11-16 src/pcre/testdata/saved16BE-2 src/pcre/testdata/saved32LE-2 src/pcre/testdata/testinput22 src/pcre/testdata/testinput19 src/pcre/testdata/grepinput3 src/pcre/testdata/testinput4 src/pcre/testdata/testoutput9 src/pcre/testdata/testoutput13 src/pcre/testdata/testinput12 src/pcre/testdata/testinput26 src/pcre/pcre32_study.c src/pcre/aclocal.m4 src/pcre/pcre32_refcount.c src/pcre/pcre_stringpiece_unittest.cc src/pcre/pcre_jit_compile.c src/pcre/test-driver src/pcre/pcre32_compile.c src/pcre/ChangeLog src/pcre/pcre_globals.c src/pcre/Detrail src/pcre/pcre_string_utils.c src/pcre/pcre32_maketables.c src/pcre/pcre_chartables.c.dist src/pcre/libpcrecpp.pc.in src/pcre/pcre32_xclass.c src/pcre/dftables.c src/pcre/pcredemo.c src/pcre/config-cmake.h.in src/pcre/pcrecpparg.h.in src/pcre/config.h.generic src/pcre/RunGrepTest src/pcre/pcre32_utf32_utils.c src/pcre/pcre_internal.h src/pcre/ar-lib src/pcre/ltmain.sh src/pcre/pcre16_xclass.c src/pcre/pcre16_maketables.c src/pcre/pcre_fullinfo.c src/pcre/configure.ac src/pcre/132html src/pcre/pcre_get.c src/pcre/pcre16_fullinfo.c src/pcre/NEWS src/pcre/pcre16_ucd.c src/pcre/pcre_scanner.h src/pcre/pcregrep.c src/pcre/libpcreposix.pc.in src/pcre/pcre32_chartables.c src/pcre/pcre32_tables.c src/pcre/pcre_version.c src/pcre/pcre-config.in src/pcre/pcre16_chartables.c src/pcre/perltest.pl src/pcre/pcrecpp_internal.h src/pcre/libpcre.pc.in src/pcre/pcrecpp.h src/pcre/pcrecpp_unittest.cc src/pcre/pcre16_get.c src/pcre/pcre16_utf16_utils.c src/pcre/Makefile.am src/pcre/pcrecpp.cc src/pcre/pcre16_byte_order.c src/pcre/README src/pcre/pcre_scanner.cc src/pcre/NON-AUTOTOOLS-BUILD src/pcre/pcre_config.c src/pcre/pcre_byte_order.c src/pcre/RunTest.bat src/pcre/pcre.h.in src/pcre/NON-UNIX-USE src/pcre/doc src/pcre/doc/pcrebuild.3 src/pcre/doc/pcre_get_substring_list.3 src/pcre/doc/pcre_free_study.3 src/pcre/doc/pcrelimits.3 src/pcre/doc/pcre_get_stringnumber.3 src/pcre/doc/pcre_jit_exec.3 src/pcre/doc/pcre16.3 src/pcre/doc/pcre-config.txt src/pcre/doc/perltest.txt src/pcre/doc/pcretest.1 src/pcre/doc/pcrematching.3 src/pcre/doc/pcre_jit_stack_alloc.3 src/pcre/doc/pcreprecompile.3 src/pcre/doc/pcre_dfa_exec.3 src/pcre/doc/pcre_pattern_to_host_byte_order.3 src/pcre/doc/pcre_compile.3 src/pcre/doc/pcredemo.3 src/pcre/doc/pcre_utf16_to_host_byte_order.3 src/pcre/doc/pcre_study.3 src/pcre/doc/pcrecallout.3 src/pcre/doc/pcre_version.3 src/pcre/doc/pcre_utf32_to_host_byte_order.3 src/pcre/doc/pcre_jit_stack_free.3 src/pcre/doc/pcrecpp.3 src/pcre/doc/pcregrep.1 src/pcre/doc/pcre_assign_jit_stack.3 src/pcre/doc/pcre_exec.3 src/pcre/doc/pcre-config.1 src/pcre/doc/pcrepattern.3 src/pcre/doc/pcre_get_stringtable_entries.3 src/pcre/doc/pcre_free_substring.3 src/pcre/doc/pcre_get_substring.3 src/pcre/doc/pcrepartial.3 src/pcre/doc/pcre.3 src/pcre/doc/pcreunicode.3 src/pcre/doc/pcretest.txt src/pcre/doc/pcre_copy_named_substring.3 src/pcre/doc/pcre_maketables.3 src/pcre/doc/pcreapi.3 src/pcre/doc/pcre.txt src/pcre/doc/pcre_copy_substring.3 src/pcre/doc/pcre_config.3 src/pcre/doc/pcre32.3 src/pcre/doc/pcrestack.3 src/pcre/doc/pcre_compile2.3 src/pcre/doc/pcrecompat.3 src/pcre/doc/pcreposix.3 src/pcre/doc/pcre_refcount.3 src/pcre/doc/pcre_fullinfo.3 src/pcre/doc/pcregrep.txt src/pcre/doc/pcresample.3 src/pcre/doc/pcresyntax.3 src/pcre/doc/pcre_get_named_substring.3 src/pcre/doc/index.html.src src/pcre/doc/pcrejit.3 src/pcre/doc/html src/pcre/doc/html/pcre_free_substring_list.html src/pcre/doc/html/pcre_assign_jit_stack.html src/pcre/doc/html/pcre_config.html src/pcre/doc/html/pcre16.html src/pcre/doc/html/pcrelimits.html src/pcre/doc/html/pcrejit.html src/pcre/doc/html/pcre-config.html src/pcre/doc/html/pcre_jit_exec.html src/pcre/doc/html/pcre_refcount.html src/pcre/doc/html/pcrepartial.html src/pcre/doc/html/pcreunicode.html src/pcre/doc/html/index.html src/pcre/doc/html/pcre_exec.html src/pcre/doc/html/pcre_fullinfo.html src/pcre/doc/html/pcrecompat.html src/pcre/doc/html/pcreapi.html src/pcre/doc/html/pcre_get_stringnumber.html src/pcre/doc/html/pcre_get_substring.html src/pcre/doc/html/pcrecpp.html src/pcre/doc/html/pcrecallout.html src/pcre/doc/html/pcre_free_study.html src/pcre/doc/html/pcre_pattern_to_host_byte_order.html src/pcre/doc/html/pcreprecompile.html src/pcre/doc/html/NON-AUTOTOOLS-BUILD.txt src/pcre/doc/html/pcrematching.html src/pcre/doc/html/pcre_get_stringtable_entries.html src/pcre/doc/html/pcre_jit_stack_alloc.html src/pcre/doc/html/pcre_free_substring.html src/pcre/doc/html/pcre_version.html src/pcre/doc/html/pcresyntax.html src/pcre/doc/html/pcre_jit_stack_free.html src/pcre/doc/html/pcretest.html src/pcre/doc/html/pcre_utf16_to_host_byte_order.html src/pcre/doc/html/pcre_maketables.html src/pcre/doc/html/pcrestack.html src/pcre/doc/html/pcre_copy_substring.html src/pcre/doc/html/pcreposix.html src/pcre/doc/html/README.txt src/pcre/doc/html/pcrepattern.html src/pcre/doc/html/pcre_get_named_substring.html src/pcre/doc/html/pcrebuild.html src/pcre/doc/html/pcresample.html src/pcre/doc/html/pcre.html src/pcre/doc/html/pcre_study.html src/pcre/doc/html/pcre_copy_named_substring.html src/pcre/doc/html/pcre_compile.html src/pcre/doc/html/pcre_compile2.html src/pcre/doc/html/pcregrep.html src/pcre/doc/html/pcre32.html src/pcre/doc/html/pcre_utf32_to_host_byte_order.html src/pcre/doc/html/pcredemo.html src/pcre/doc/html/pcre_get_substring_list.html src/pcre/doc/html/pcre_dfa_exec.html src/pcre/doc/html/pcreperform.html src/pcre/doc/pcreperform.3 src/pcre/doc/pcre_free_substring_list.3 src/pcre/pcre_refcount.c src/pcre/pcre16_compile.c src/pcre/install-sh src/pcre/RunTest # # - Source to ctrio supporting library # src/trio src/trio/hypermail-patches.diff src/trio/triodef.h src/trio/README src/trio/README.hypermail src/trio/install-sh src/trio/strio.h src/trio/compare.c src/trio/autogen.sh src/trio/Makefile.in src/trio/trio.h src/trio/trio.c src/trio/regression.c src/trio/triop.h src/trio/CHANGES src/trio/configure.in src/trio/trionan.c src/trio/configure src/trio/triostr.c src/trio/triostr.h src/trio/trionan.h src/trio/FILES # # - Source to fnv supporting library # src/fnv/Makefile.in src/fnv/README src/fnv/aclocal.m4 src/fnv/config.guess src/fnv/config.in src/fnv/config.sub src/fnv/configure src/fnv/configure.in src/fnv/configure.scan src/fnv/fnv.h src/fnv/fnv32.c src/fnv/fnv64.c src/fnv/hash_32.c src/fnv/hash_64.c src/fnv/have_ulong64.c src/fnv/ltconfig src/fnv/ltmain.sh # # - Hypermail testing support # tests/stdintest.pl tests/README tests/diff_hypermail_archives.pl tests/test-footer.hyp tests/test-index.hyp tests/test-msg.hyp tests/test.rc tests/testhm.in # # - Hypermail test mailboxes # tests/mboxes/1msg.mbox tests/mboxes/critmail.mbox tests/mboxes/embedded.msg tests/mboxes/t1 tests/mboxes/t2 tests/mboxes/t3 tests/mboxes/t4 tests/mboxes/t5 tests/mboxes/t6 tests/mboxes/t7 tests/mboxes/t8 tests/mboxes/y2k.mbox ================================================ FILE: INSTALL ================================================ Quick summary: ./configure make make install See the Upgrading section at the end for changes that might affect users of older versions. ========================== SECURITY WARNING: Do not put hypermail's output anyplace where a web server might have server side includes (SSI) enabled, unless you are sure you know what you are doing. If in doubt, check your web server configuration. If you are using Apache, look for an Options line that mentions Includes or IncludesNOEXEC. The author of an email normally has substantial control over what files hypermail creates, particularly via attachments. Hypermail is designed to insure that filenames don't end in .shtml and don't contain characters like / or \, which prevent some security problems, but there are few restrictions on what can go in a file (e.g. possibly malicious html tags - try the "text_types = *" option or "ignore_types = $NONPLAIN" option if you want to restrict this). You might also want to look at the attachmentlink and unsafe_chars options to restrict attachment filenames. Also, it is probably a bad idea to enable cgi execution on a directory that hypermail puts files in. Do not use the crappy cgi program called "mail". Before Building Hypermail: ========================== Hypermail now uses "configure" to generate the Makefiles. In the top level directory, type "configure" to create the Makefiles. If it does not work on your system, please let me know. Building Hypermail: =================== Hypermail has been normally compiled and run on Unix-based systems in the past. Today it can be configured and built using Cygwin software. I have either compiled and tested this code successfully on the following platforms or others have told me of their success. Solaris, SunOS 4.1.3, FreeBSD 2.2.5 and later, BSDI/3.x, Linux kernel 2.0.18 and 2.0.30, Redhat 5.x and later, NT using CygWin-b19 <http://www.cygnus.com/misc/gnu-win32>, Irix6.2, HP-UX 10.20 and later, SCO OS 5.0.5, and TRU64/OSF1 on a DEC Alpha Hypermail compiles on MacOSX, tested with X.2.6. Beware that you may need to configure it to use --disable-shared and manually execute make in src/pcre before. For more information on Cygwin and build hypermail on a Windows-based system, see the file docs/Install-win32.txt. Generic Build: 1) Type "./configure". This creates the makefiles and the config.h file needed to build the software. If you want to install Hypermail somewhere other than in /usr/local, run something like this instead: ./configure --prefix=$HOME 2) Type "make". This will build the software. If it has trouble finding gdbm (e.g. if it fails with a message such as "cannot open -lgdbm", you may need to disable gdbm with: ./configure --without-gdbm and type "make clean" and then "make" again. (Note that without gdbm, you can't do incremental updates using the folder_by_date option). On some systems you may need to add "-R/usr/local/lib -L/usr/local/lib" to the CFLAGS variable in the Makefiles, or alter your LD_LIBRARY_PATH environment variable (Willi Kernen reports that on a 64-bit Solaris, changing LD_LIBRARY_PATH to: /usr/lib:/usr/local/lib:/usr/ccs/lib:/usr/ucb/lib:/usr/openwin/lib fixed a problem). If the make fails at this line: ar cq libpcre.a maketables.o get.o study.o pcre.o and the configure had said: checking whether to build static libraries... no then you probably should try: ./configure --disable-shared If the make fails with a message such as: proto.h:99: conflicting types for `strcasestr' /usr/include/string.h:86: previous declaration of `strcasestr' then you should try removing the line in proto.h that refers to strcasestr. Testing Hypermail: ================== If you wish to test the new hypermail before installing it - chdir to tests/ - copy a mailbox you have to a local file named "testmail" - type "sh ./testhm" This will generate an archive under a newly created "testdir/" directory. Check it out with your favorite browser. When you are done testing, - remove the testdir directory, - remove the testmail file. (See the README in tests/ for more information.) Installing Hypermail: ===================== You may need to login as root for this step. To install just the Hypermail programs: - chdir to the src/ directory - Type "make install". (Or, if you prefer, just copy "hypermail" to wherever you want it). If you want a full install of Hypermail and its documentation, do make install in the main Hypermail directory (the one where you did ./configure). If it fails with something like: mkdir: "/usr/local/apache/htdocs/hypermail": Permission denied then you may need to rerun ./configure giving it the directory in which you want to install html documentation files using this option: --with-htmldir=/var/www/htdocs Upgrading: ============== The body option has been disabled as of version 2.1.4 for strict HTML 4.01 compatibility. You should replace any body command you have in your .hmrc with a style sheet (such as a file called hypermail.css in the archive directory), and set icss_url and mcss_url to the url of that style sheet. If you want the appearance that was the default before 2.1.4, your style sheet should contain this: body {color: black; background: #ffffff} h1.center {text-align: center} div.center {text-align: center} Also, if you have been using the icss_url and/or mcss_url options and are upgrading to 2.1.4 or higher, you might want to add those statements to your style sheet, as their style is no longer being provided by <body ...> tags, etc. (For users not specifying an icss_url and mcss_url, default style sheets have been put in all files to maintain that style.) The overwrite option defaulted to On for many versions. Starting with version 2.1.4, it defaults to off again. You may want to turn it on again occasionally to insure that all of your archive uses the same style (assuming you have a copy of the archive in mbox format). ::: SPECIAL NOTE::: The cgi program called "mail" has been disabled. If you've been using it, you should either stop using it or look carefully enough at what it does to understand whether it is safe for you to enable its functionality. This could be a security concern for your site. ================================================ FILE: KNOWN_BUGS ================================================ This is a list of know problems with the current version of Hypermail ================================================= Problem: Converting existing hypermail archives to use a different HTML file suffix: If you are going to change the filename suffix used from the default ".html" to something else, you must deal with the existing files first. Otherwise, hypermail does not know they are there and starts numbering files from the begining. This means that you need to either start out fresh, regenerate the archive from an existing mailbox or convert all existing files and the links within the existing archive files to use the proper extension. ================================================= Problem: File Locking On NFS Mounted Directories: File locking doesn't work all that well over NFS. For that reason you are encouraged to run Hypermail on the same system that the disk is on. This is due to possible timing issues within NFS. Hypermail based network locking is not expected to work at this time. ================================================= Problem: Message Dates: Dates on messages prior to 1970 are not processed correctly. ================================================= Problem: Not parsing correctly. The following line is not parsing correctly. news:fr.comp.os.ms-windows.win95 post news:34EF975C.4097FF89@club-internet.fr ================================================= Problem: Embedded HTML If HTML file included in message it is just putting it there without concern of BASE, TITLE, HEAD, BODY ... ================================================= Problem: Blank name not interpreted correctly. Puts out a <STRONG></STRONG> if name is blank. ================================================= Problem: Memory leaks Leaking < 30 bytes per message processed. ================================================= Problem: Empty container elements Putting out empty container elements <P>. Should be <P> </P> ================================================= Problem: No verification of link syntax Not verifying a valid HTML link syntax before converting somthing with a http://. ================================================= Problem: indextable format problem The message list column widths for "subject" "author" and "date" are sized based on the content. Subjects and dates are fairly predictably riddled with white space on which long lines can wrap. The "author" string is not -- in particular, I have a person with a long pseudonym (having a descriptive pseudo-middle name, used to distinguish between several people with the same first and last name), and a long machine.domain identifier -- coming out to 52 (!) characters total. His MUA does not give a "real name" string that hypermail could use. In a typical browser display, this forces the 'author' column to about 2/3rds of the display width, and the subject and date get crammed into the remaining 1/3rd. The "hm_usetable" resource only affects headers and footers, and not the bulk of the index display itself. Is there an existing configuration choice that could help me? ================================================= Problem: corrupt mailbox handing. If the parser never finds the end-boundary in the alternative section it leaves the parser in an undefined state, it still treats "^From_" (underscore to display space) lines as the beginning of a new mail. The problem I think is more related to that the "alternative parser" never really finishes its work until it finds the end-boundary and when the following "From " line starts a new mail, something bad happens. Hypermail should process corrupt messages a bit better. ================================================= Problem: Building on DEC Alpha systems. Make sure and use the GCC compiler and not the native DEC compiler when building on a DEC Alpha using TRU64 (OSF1). ================================================ FILE: Makefile.in ================================================ # # Makefile for hypermail package. # @SET_MAKE@ prefix=@prefix@ datarootdir = @datarootdir@ datadir = @datadir@ exec_prefix=@exec_prefix@ # This is where you want hypermail to be installed bindir=@bindir@ # This is where the man page goes mandir=@mandir@ srcdir=@srcdir@ # This is where the HTML documentation goes htmldir=@htmldir@ # This is where your CGI programs live cgidir=@cgidir@ INSTALL_PROG=@INSTALL@ #WNOERROR=-Werror #WARNINGS=$(WNOERROR) -ansi -pedantic -Wall -Wtraditional -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Dlint # Compiler to use CC=@CC@ CFLAGS=@CFLAGS@ $(WARNINGS) CPPFLAGS=@CPPFLAGS@ @INCLUDES@ LIBS=@LIBS@ LDFLAGS=@LDFLAGS@ all: hypermail support hypermail: @cd src; $(MAKE) all CC="$(CC)" \ CFLAGS="$(CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ cgidir="$(cgidir)" bindir="$(bindir)" LIBS="$(LIBS)" support: @cd archive; $(MAKE) all CC="$(CC)" CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" install: @cd src; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ cgidir="$(cgidir)" bindir="$(bindir)" LIBS="$(LIBS)" @cd docs; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(MAKEFLAGS) mandir="$(mandir)" htmldir="$(htmldir)" @cd archive; $(MAKE) install CC="$(CC)" CFLAGS="$(CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ bindir="$(bindir)" uninstall: @cd src; $(MAKE) uninstall cgidir="$(cgidir)" bindir="$(bindir)" @cd docs; $(MAKE) uninstall mandir="$(mandir)" htmldir="$(htmldir)" @cd archive; $(MAKE) uninstall bindir="$(bindir)" lint: @cd src; $(MAKE) lint @cd archive; $(MAKE) lint clean: @cd src; $(MAKE) clean @cd docs; $(MAKE) clean @cd archive; $(MAKE) clean rm -f lint.out clobber: clean rm -f config.h rm -f config.cache rm -f config.log rm -f config.status rm -f archive/Makefile rm -f docs/Makefile rm -f libcgi/Makefile rm -f src/Makefile rm -f src/defaults.h rm -f tests/testhm rm -rf tests/testdir rm -rf tests/mail-archive rm -f Makefile distclean: clobber rm -f tests/testmail tgz: @(dir=`pwd`;name=`basename $$dir`;echo Creates $$name.tar.gz; cd .. ; \ tar -cf $$name.tar \ `cat $$name/FILES | grep -v "^#" | sed "s:^:$$name/:g"` ; \ gzip $$name.tar ; chmod a+r $$name.tar.gz ; mv $$name.tar.gz $$name/) ================================================ FILE: README ================================================ Hypermail Version: 2.4.x This is a release of the 2.4.x version of hypermail. Hypermail is a program that takes a file of mail messages in UNIX mailbox format and generates a set of cross-referenced HTML documents. SECURITY WARNING: Do not put hypermail's output anyplace where a web server might have server side includes (SSI) enabled unless you are sure you know what you are doing. WARNING: There once existed a program call "mail" that came with hypermail. 'mail' utility has not installed by default for the last two years. This program has been disabled because it was probably easy for spammers to use as an open relay. It also had problems with enabling malicious use of JavaScript and CRLF Injection. The 'mail' utility is a historic reclic and will not be supplied in future versions. Its functionality has been replaced with a warning that anyone using it should remove it immediately. See the INSTALL file to get started. For a description of how to use it, see the hypermail.html, hmrc.html, and hypermail-faq.html files that come in the docs/ directory. Please refer to Changelog for the list of recent changes. Hypermail is distributed under the GNU GPL license (see the file COPYING for details). Some programs that are distributed with it in the archive and contrib directories have different licenses - check the individual files for details. Hypermail Background: ===================== Hypermail was originally designed and developed by Tom Gruber for Enterprise Integration Technologies (EIT) using Common Lisp. It was later rewritten in C by Kevin Hughes in 1994 while Kevin worked at EIT. License Evolution: ------------------ In the spring of 1997, Kevin Hughes heavily pressed Hewlett-Packard (who was now the legal owner of Hypermail, since EIT was bought by VeriFone, which was bought by Hewlett-Packard) into placing a free software license onto his old EIT software. They officially put the GNU GPL license on *all* of Kevin's old EIT software, opening it up to more open methods of development and distribution. So now Hypermail is under GPL. EIT's net.disappearance: ------------------------ A very old and established government contractor company called Electronic Instrumentation and Technology Inc. made legal moves to obtain the eit.com domain. Since VeriFone/HP had no interest in keeping EIT, dissolved it completely. As this company had a trademark on EIT, the domain name was given to them. Elizabeth Batson of EIT/VeriFone/HP informed Kevin he could maintain all his old software himself wherever he wished to put it. Kevin and ongoing Hypermail Development: ---------------------------------------- Kevin left Hewlett-Packard in 1997 and helped form a new company called Veo Systems (www.veosystems.com) with his old boss Marty Tenenbaum, who founded EIT. Kevin did not have the time to maintain any of his old software, so he was looking for different parties to help maintain it and take over different pieces. For instance, Getstats has been obsoleted by Analog (http://www.statslab.cam.ac.uk/~sret1/analog/). SWISH has been taken over by the SWISH-E project (http://sunsite.berkeley.edu/SWISH-E/) and many people have been doing good things with it. April 17, 1998 Kevin passed hypermail development to Kent Landfield (http://www.hypermail.org/). Kent had been supporting an enhanced version of hypermail he had been using for the last few years. It has gradually become a group effort, with Peter McCluskey <pcm@rahul.net> often acting as the leader during its heydays. Since a couple of years, it is stable and mostly unmaintained. W3C continues to contribute to this repository, although infrequently, sharing with the community enhancements and bug fixes originating from its use of hypermail. General: ======== This version has been tested on the platforms listed below. If you would like to send portability patches or confirmation that it works on a certain platform, please do. There should not be toooo many changes that need to be made. This version of hypermail has substantial support for attachments and for splitting archives into subdirectories. It also allows an administrator to customize the header and footers to match their local needs. This allows you to have hypermail facilities better integrated into your web site. This version is an integration of patches that Kevin had received through the years, and new features through the individual efforts many people. This has been run through lint, Insight and Purify and has been cleaned up accordingly. * archive - general archive utilites that are useful in managing list archives. Much of the functionality here has been rendered obsolete by the folder_by_date option. * contrib - contributed hypermail relate utilities * configs - sample hypermail configuration files, * docs - documentation and documentation support files, * libcgi - support library for the mail utility, * src - here's the beef, * tests - directory for supporting local testing, Warning: ======== Take the time to read the KNOWN_BUGS file so that you are aware of things that might affect your use of hypermail. GIT Repository: =============== Hypermail's code base has migrated from CVS to git and after a residence at sourceforge, now resides at github: https://github.com/hypermail-project/hypermail/ CVS Server: =========== The hypermail CVS repository has been retired. Hypermail's code base now resides at github (see above). Thanks to Ashley M. Kirchner <ashley@pcraft.com> for having hosted and keep alive the CVS repository during the years. Getting Help: ============= There is no active dedicated mailing list for hypermail support or development. Please use hypermail's github repository issue tracker for all bug reports, feature requests, patches, and other program-related things. This project is under low-maintenance priority. You can browse the old hypermail development mailing list archives from the historical hypermail project homepage: http://hypermail-project.org/ Additionally: ============= You'll find the image "hypermail.gif" included with the source; this icon is for your use in your Hypermail-related pages and links to them. If you are talented with graphics and would like to donate new icons and images to the hypermail effort, please feel free. Regular expression support is provided by the PCRE library package, which is open source software, written by Philip Hazel, and copyright by the University of Cambridge, England. See http://www.pcre.org/. ================================================ FILE: README.CVS ================================================ [ DEPRECATED We're now using github : https://github.com/hypermail-project/hypermail ] Hypermail CVS Server Access ---- Hypermail Development has a CVS server, where we (try to) keep the latest changes (usually hot out of the oven) and anyone is welcome to use it. Thanks to Elliot Lee <sopwith@redhat.com> for helping with setting it up, Daniel Stenberg <Daniel.Stenberg@haxx.nu> with his contributions. And many thanks to Ashley M. Kirchner <ashley@pcraft.com> for hosting and managing the hypermail CVS server. ------------------------------------ Setting up the CVS software locally: If you system does not have cvs installed on it already then you need to do the following to install the client locally. - Obtain the cvs source at ftp://ftp.cvshome.org/pub/ For more information on CVS stop by http://www.cvshome.org/ - Compile and install the client (you can disable the server with the --disable-server during the 'configure' command. Read the INSTALL file once you're uncompressed the archive) ------------------------------------ General information on accessing the Hypermail CVS repository: Hypermail CVS Archive Address: :pserver:cvs@cvs.hypermail.org:/CVS The 'cvs' user doesn't have a password, so just hit return when it asks you for one. The cvs user is setup for read access only. ------------------------------------ Step by Step information on accessing the Hypermail CVS repository: Aftering installing the CVS software: - Set your CVSROOT enviroment: For sh, bash and ksh users, execute the following commands: CVSROOT=:pserver:cvs@cvs.hypermail.org:/CVS export CVSROOT (or you can stick them in your .profile and/or .bash_profile file) For C shell users (csh, tcsh), you can do the following: setenv CVSROOT :pserver:cvs@cvs.hypermail.org:/CVS (or stick it in your .cshrc and/or .login file) - From here you can login to the server with: $ cvs login (Logging in to cvs@cvs.hypermail.org) CVS password: <-- hit RETURN (cvs user password is blank) - Now you're ready to grab the source $ cvs checkout hypermail This will create a mirror of the sources in your account/on your machine called 'hypermail' that you can then compile and play with. - Once done, don't forget to log out: $ cvs logout All of the above commands can be performed without having to set a CVSROOT enviroment if you want, it's just a lot more to type in since you'll have to specify the directory every time with: -d :pserver:cvs@cvs.hypermail.org:/CVS For example, you would need to use the following to execute the login command cvs -d :pserver:cvs@cvs.hypermail.org:/CVS login cvs -d :pserver:cvs@cvs.hypermail.org:/CVS checkout hypermail cvs -d :pserver:cvs@cvs.hypermail.org:/CVS logout ------------------------------------ Browsing the Hypermail CVS Archive: You can also browse the repository at: http://cvsweb.hypermail.org/ ---- ================================================ FILE: README.git ================================================ Hypermail GIT Server Access ---- Hypermail Development has a GIT server, where we (try to) keep the latest changes (usually hot out of the oven) and anyone is welcome to use it. ------------------------------------ General information on accessing the Hypermail CVS repository: Hypermail git repository address: http://sourceforge.net/scm/?type=git&group_id=18117&source=navbar git://hypermail.git.sourceforge.net/gitroot/hypermail/hypermail (read-only) A mirror is also availabe on github: https://github.com/hypermail-project/hypermail See the sourceforge documentation for more information about git and how to checkout the hypermail repository: http://sourceforge.net/scm/?type=git&group_id=18117&source=navbar ------------------------------------ Browsing the Hypermail git repository: You can also browse the repository at: http://hypermail.git.sourceforge.net/git/gitweb-index.cgi ---- ================================================ FILE: TODO ================================================ This is a file of things to do. If you have other ideas or needs send them to hypermail-dev@hypermail.org. =============== General Things: =============== - Need to use splint to clean up the code. - Need to clean up the code and remove old code that is commented/ifdefed out. - Update the doc files to assure all configuration file directives are included appropriately in the documentation. Currently the documentation does not completely list all options. - Update the pcre library to a much more recent version. - Modify configure to locate the appropriate htdocs directory locations for installing the documentation and image files. - Add the msgid hash to the emailinfo structure to speed-up looking of this value when we already know it. - Finish the libtool work on the fnv library so that we can link to shared libraries _and_ install/uninstall them. - Need to lowercase HTML tags to support XHTML 1.0 in the future. - Need to add XHTML support - Configurable ? - Make the "New List Message" and "Reply To List" features available when usetable == 0 - system() should be replaced by fork()+execvp() (or maybe by s_popen()) in archive/ mbox2hypermail.c - HTML code should be escaped where appropriate. - Make it possible to insert the FONT to use in the tables. <TH><FONT ...>string</FONT></TH> Fonts are not be inherited correctly in many browsers. - Have configure look at the language selected and if it is not "en" set the EURODATE to 1. - Add date/subject/author filters for articles that are read in - Need to create a library of hypermail functions so that other utilities can be generated without making things real ugly. (i.e. removal, other indexing.) - Combine mbox2hypermail.c and msg2archive.c into a single program instead of having the two do the same general job... - There is an irreversible aspect to piping messages into hypermail; what gets written into HTML does not readily convert back to RFC822 form such that it could be re-archived (put in another archive, etc.) - Convert the doc files to a SGML system like linuxdoc, which will allow generating html, text, and man pages from the same source. - You currently look for text in messages of the form http://... and turn them into hyperlinks. You also look for text in the form foo@bar.com and turn that into a mailto: hyperlink. I suggest you also look for text in for form of mailto:foo@bar.com?subject=bat and turn the whole of it into a mailto: link, with the correct subject line. ============= Index Issues: ============= - Make the formating of index pages use magic cookies for all parts of the page. - It seems strange and undesireable to have the message date shown only in the subject and author indexes. It seems *really* strange to not have it show up in the date index! I wanted it "on" for our archives, and did that in my latest beta, which required changing the "reply" structure to include it (for the thread index). I think ideally it would be configureable on or off. - Make it optional that a site generate index files with the listings sorted by date in one file and reverse sorted in the other index. This pertains to all index types as well. For example: one thread-index with the newest mails topmost one thread-index with the oldest mails topmost one author-index in alphabetical order one author-index in reversed alphabetical or etc. ============ Attachments: ============ o Make it configurable to get test/plain attachments to have a link created for them, instead of having them printed out beneath the original email. o If a filename is not known and the MIME type is known, the proper extension should be added to the randomly generated file name. o For security reasons, *all* binary attachments should be written to disk with file permissions of 444 or equivalent read-only access and should *never* allowed to be executable. o The user should be able to 1 indicate if attachments are stored to be stored as separate files from the original message. (Turn it on or off.) o Specifying a list with 'preferred' content-types when receiving/decoding mixed/alternative attachments. Support is there in the config file but not in the code. Currently the "text" is always preferred. o It is doubtful that hypermail deals with all kinds of uuencoded attachments as defined with 'x-uue' in the current hypermail. Other MIME resources mention a whole set of different names for this kind of encoding, but are they in use? o Hypermail should be able to deal with Sun's (silly) mailtool attachments in a manner similar to how it deals with mime attachments. It would be really cool if the output would be identical and the differences hidden from the user(s). ================= Configure issues ================= Defines not used in config.h.in: HAVE_STRFTIME, HAVE_GETOPT, HAVE_GETPWUID, HAVE_LSTAT, HAVE_MKDIR, HAVE_STRCASECMP, HAVE_STRDUP, HAVE_STRSTR, HAVE_STRTOL, HAVE_ALLOCA_H, HAVE_ARPA_INET_H, HAVE_MALLOC_H, HAVE_NDIR_H , HAVE_NETDB_H, HAVE_NETINET_IN_H, HAVE_STDARG_H, HAVE_STDIO_H, HAVE_SYS_DIR_H, HAVE_SYS_NDIR_H , HAVE_SYS_SOCKET_H, HAVE_TIME_H HAVE_BCOPY is only used in in pcre and not hypermail sources. Configure needs to support SunOS4x. Change prototype definitions for certain systems (FREBSD 4.6 for example) ============ Misc. Needs: ============ - EURODATE Given that these two formats are ambiguous, and many companies have people of both sorts, need an alternate, unambigous date format. - Should recognize and parse indented HTML tags better - Don't ignore umask - HM_UMASK variable? - A better icon for hypermail! - Ability to check for duplicate message IDs using cksum to assure that duplicate message are infact truely duplicated and not just a different message with the same msg-id header. - Ability to refer to articles via message ID as well - The ability to cap the archive to X most recent messages - Allow for multiple mailbox formats to be recognized, like news articles, listproc, elm mailboxes, etc. - In parsing header fields, check for extra spaces, tabs, etc. - Check for zero-length headers - Search for "HTTP" and "http" when making links - Parse archives with only one or zero messages - Make sure "sort by..." groups all messages in same thread - Add sort by "in reply to" as well ============================= Administrative Things to do: ============================= o Get a good set of test files. For now you can use your own... o Get to develop a complete regression test suite =========================== :Requests: =========================== * Do you know if there is any way to cutomize the index sort of Hypermail? I am using Solaris mailbox and the header field can be modified by user (i.e. add more headers if required). However, the default index sort of Hypermail only support Author, Thread and Subject. Is there any way to customize the index sort of Hypermail so that we can map the UNIX mail to HTML mail with cutomize headers. * Would like to see a reindex option. Would like to remove a message from the mailbox and click on reindex to delete the message. * There should be an option I can set in the Hypermail command to cause it to write html files as a specified user. Right now Hypermail is writing files as daemon and this is causing problems. We'd prefer that it run as something/someone else. * One more: I still think that hypermail should also save the full mail body part additionally, when there is an OpenPGP(PGP/MIME rfc2015) signed Mail. If we do it first, maybe somebody enhances a webbrowser to take advantage of it. Would be cool, if it could check the signature then. * It would be nice to be able to throttle hypermail. Could we add a config option that would allow hypermail to renice itself ? ================================================ FILE: UPGRADE ================================================ Upgrade Notes ============== From Hypermail 2.3.0 to Hypermail 2.4.0 ----------------------------------------- Hypermail will now detect and link with a system libpcre if it's available and current. Otherwise, it will compile the bundled libpcre. You can force the compile with the bundled one with the --enable-bundled-pcre configure option. The configuration directive "htmlmessage_deleted" has been renamed "htmlmessage_deleted_spam". The "deleted" configuration directive has been deprecated in favor of "annotated". However, for backwards compatibility with legacy archives, it will continue to be honored. From Hypermail 1.x to Hypermail 2.x ----------------------------------- !!!!WARNING!!!! Hypermail 2.x HTML output files, indexes, etc are not compatible with 1.x files. When installing 2.x, all existing HTML files in the specified output directory must be removed first. Use the original 1.x mailbox files to regenerate the new 2.x archive. If the mailboxes are not available it should be possible to use the script hypetombox.pl in the contrib/ directory. ================================================ FILE: acconfig.h ================================================ #undef HAVE_GDBM_H ================================================ FILE: aclocal.m4 ================================================ dnl Some macros borrowed from Apache's httpd config file. Thanks! dnl dnl APR_SUBDIR_CONFIG(dir [, sub-package-cmdline-args, args-to-drop]) dnl dnl dir: directory to find configure in dnl sub-package-cmdline-args: arguments to add to the invocation (optional) dnl args-to-drop: arguments to drop from the invocation (optional) dnl dnl Note: This macro relies on ac_configure_args being set properly. dnl dnl The args-to-drop argument is shoved into a case statement, so dnl multiple arguments can be separated with a |. dnl dnl Note: Older versions of autoconf do not single-quote args, while 2.54+ dnl places quotes around every argument. So, if you want to drop the dnl argument called --enable-layout, you must pass the third argument as: dnl [--enable-layout=*|\'--enable-layout=*] dnl dnl Trying to optimize this is left as an exercise to the reader who wants dnl to put up with more autoconf craziness. I give up. dnl AC_DEFUN([APR_SUBDIR_CONFIG], [ # save our work to this point; this allows the sub-package to use it AC_CACHE_SAVE echo "configuring package in $1 now" ac_popdir=`pwd` apr_config_subdirs="$1" test -d $1 || $mkdir_p $1 ac_abs_srcdir=`(cd $srcdir/$1 && pwd)` cd $1 changequote(, )dnl # A "../" for each directory in /$config_subdirs. ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` changequote([, ])dnl # Make the cache file pathname absolute for the subdirs # required to correctly handle subdirs that might actually # be symlinks case "$cache_file" in /*) # already absolute ac_sub_cache_file=$cache_file ;; *) # Was relative path. ac_sub_cache_file="$ac_popdir/$cache_file" ;; esac ifelse($3, [], [apr_configure_args=$ac_configure_args],[ apr_configure_args= apr_sep= for apr_configure_arg in $ac_configure_args do case "$apr_configure_arg" in $3) continue ;; esac apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" apr_sep=" " done ]) dnl autoconf doesn't add --silent to ac_configure_args; explicitly pass it test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" dnl AC_CONFIG_SUBDIRS silences option warnings, emulate this for 2.62 apr_configure_args="--disable-option-checking $apr_configure_args" dnl The eval makes quoting arguments work - specifically the second argument dnl where the quoting mechanisms used is "" rather than []. dnl dnl We need to execute another shell because some autoconf/shell combinations dnl will choke after doing repeated APR_SUBDIR_CONFIG()s. (Namely Solaris dnl and autoconf-2.54+) if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir $2 then : echo "$1 configured properly" else echo "configure failed for $1" exit 1 fi cd $ac_popdir # grab any updates from the sub-package AC_CACHE_LOAD ])dnl dnl dnl APR_ADDTO(variable, value) dnl dnl Add value to variable dnl AC_DEFUN([APR_ADDTO], [ if test "x$$1" = "x"; then test "x$silent" != "xyes" && echo " setting $1 to \"$2\"" $1="$2" else apr_addto_bugger="$2" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $$1; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to $1" $1="$$1 $i" fi done fi ])dnl dnl dnl APR_REMOVEFROM(variable, value) dnl dnl Remove a value from a variable dnl AC_DEFUN([APR_REMOVEFROM], [ if test "x$$1" = "x$2"; then test "x$silent" != "xyes" && echo " nulling $1" $1="" else apr_new_bugger="" apr_removed=0 for i in $$1; do if test "x$i" != "x$2"; then apr_new_bugger="$apr_new_bugger $i" else apr_removed=1 fi done if test $apr_removed = "1"; then test "x$silent" != "xyes" && echo " removed \"$2\" from $1" $1=$apr_new_bugger fi fi ]) dnl ================================================ FILE: archive/.indent.pro ================================================ -nbad -bap -nbbo -nbc -br -brs -c33 -cd33 -ncdb -nce -ci4 -cp33 -ncs -d0 -di1 -nfc1 -nfca -hnl -i4 -ip0 -l75 -lp -npcs -npsl -nsc -nsob -nss -Tform_entry -Tcgi_info -TFILE ================================================ FILE: archive/1998 ================================================ #!/bin/sh # # set -x # bug squisher # # The purpose of this script is to allow you to re-generate your # hypermail archives at will. What you need to do is have a Unix # mailbox copy of the archive that you want to rebuild. # # Please read throught the script to see what it does. Basically # it takes a set of mailbox files and converts them into a hypermail # archive of messages and will install an index.html file if you have # specified one. Might want to edit this a bit. I maintain 20+ # list archives with hypermail so I have 20+ copies of this script # around, each customized for the individual archives. Easyier # to do that then have to remember complicated command line options # and archive structures. The scripts are self documenting. # # Paths to things on disk # # ARCHIVE_DIR = The base directory of the archive # MAILBOX_DIR = Mailbox version of the archive # RDMSG = Location of mbox2hypermail utility # ARCHIVE_DIR=/ftp/hypermail/mail-archive MAILBOX_DIR=${ARCHIVE_DIR}/mailbox RDMSG=hrdmsg LISTNAME=hypermail # # Ownership of the archives # # Beware: Hypermail needs to be able to potentially # write these directories. Know who your mailer # runs as. # OWNER=lists GROUP=daemon # # Create_archive YYYY MON path-to-mailbox # # YYYY - 4 digit year # MON - 3 Letter month abreviation # create_archive() { year=$1 month=$2 mailbox=$3 if [ ! -d ${ARCHIVE_DIR}/$year ]; then mkdir ${ARCHIVE_DIR}/$year fi if [ ! -d ${ARCHIVE_DIR}/$year/$month ]; then mkdir ${ARCHIVE_DIR}/$year/$month else rm -r ${ARCHIVE_DIR}/$year/$month mkdir ${ARCHIVE_DIR}/$year/$month fi ${RDMSG} -v -Y $year -M $month $mailbox chown -R ${OWNER}.${GROUP} ${ARCHIVE_DIR}/$year/$month } # # Ye Olde Main # create_archive 1998 Jan ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9801 create_archive 1998 Feb ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9802 create_archive 1998 Mar ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9803 create_archive 1998 Apr ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9804 create_archive 1998 May ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9805 create_archive 1998 Jun ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9806 create_archive 1998 Jul ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9807 create_archive 1998 Aug ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9808 create_archive 1998 Sep ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9809 create_archive 1998 Oct ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9810 create_archive 1998 Nov ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9811 create_archive 1998 Dec ${ARCHIVE_DIR}/mailbox/${LISTNAME}.9812 if [ -f index.html ]; then cp index.html ${ARCHIVE_DIR}/1998 fi # # C'ya # exit 0 ================================================ FILE: archive/Makefile.in ================================================ ################################################### # Sample Makefile for mail archive maintenance. # # Define variables and Macros # ################################################### prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ SUFFIX=@suffix@ #WNOERROR=-Werror #WARNINGS=$(WNOERROR) -ansi -pedantic -Wall -Wtraditional -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Dlint CC=@CC@ $(WARNINGS) CFLAGS=@CFLAGS@ INSTALL_PROG=@INSTALL@ ################################################### # # Build the executable images # ################################################### # # PLEASE read the README in this directory before continuing. PROGS = msg2archive$(SUFFIX) rdmsg$(SUFFIX) all: $(PROGS) msg2archive$(SUFFIX): msg2archive.c lists.h $(CC) $(CFLAGS) -o $@ msg2archive.c rdmsg$(SUFFIX): mbox2hypermail.c lists.h $(CC) $(CFLAGS) -o $@ mbox2hypermail.c ######################################## # # Commands # ######################################## lint: lint $(LINT_FLAGS) $(SOURCE) | tee Lint.out clean: rm -f $(OBJS) Lint.out rm -f $(PROGS) clobber: clean distclean: clean install: $(bindir)/msg2archive$(SUFFIX) $(bindir)/rdmsg$(SUFFIX) $(bindir)/msg2archive$(SUFFIX): msg2archive$(SUFFIX) @if [ ! -d $(bindir) ]; then mkdir -p $(bindir); fi $(INSTALL_PROG) -c msg2archive$(SUFFIX) $@ $(bindir)/rdmsg$(SUFFIX): rdmsg$(SUFFIX) @if [ ! -d $(bindir) ]; then mkdir -p $(bindir); fi $(INSTALL_PROG) -c rdmsg$(SUFFIX) $@ uninstall: rm -f $(bindir)/msg2archive$(SUFFIX) rm -f $(bindir)/rdmsg$(SUFFIX) ################################################### # # Object file include dependencies. # The object file include dependencies are required. # ################################################### depend: makedepend -- $(CFLAGS) -- $(SOURCE) # DO NOT DELETE THIS LINE -- make depend depends on it. ================================================ FILE: archive/README ================================================ This directory contains the archive specific information for maintaining mailing list archives. Much of the functionality here has been rendered obsolete by the folder_by_date option. See ../docs/hmrc.html for more info about that option. Also see ../contrib/msg2hypermailarchive.py for another program with similar functionality. It's author says: It can almost do everything that msg2archive could do. Together with "formail" it also replaces mailbox2archive for me. (e.g. like cat hypermail-test.9907 | formail -s msg2hypermailarchive.py --month 7 --year 1999 -L hypermail-test -v ) README - This file. 1998 - script for recreation of the hypermail archives from the mailbox version Makefile.in - configure Makefile input msg2archive.c - Individual message archiver. mbox2hypermail.c - Read messages from a mailbox and calls hypermail. The contents of this directory support automatic generation of hypermail archives from inbound messages *as well as* the generation of a hypermail archive from a Unix mailbox of stored messages. This is how I do it so... Your mileage might vary... 1. First you will need to decide where you want the archive stored at. 2. Then you will need to edit the file lists.h with the appropriate info. Simply add a section such as is shown below. I have a section for each list. If you are not familiar with 'C' might want to get someone else to assist. Notice that HYPERMAIL is different in the two entries. This is because in the case of the wu-ftpd list, it is using a stock hypermail executable to save the messages. The nfr-announce list is using a customized version (very useful for testing too.) #ifdef WU_FTPD #define HYPERMAIL "/usr/local/bin/hypermail" #define ARCHIVE "/ftp/wu-ftpd/mail-archive" #define MAILBOXDIR "/ftp/wu-ftpd/mail-archive/mailbox" #define LABEL "WU-FTPD Development Mailing List" #define ABOUT_LINK "/wu-ftpd" #define LISTNAME "wu-ftpd" #define CONFIGFILE "NONE" #else #ifdef NFR_ANNOUNCE #define HYPERMAIL "/usr/local/bin/nfrhypermail" #define ARCHIVE "/ftp/nfr/mail-archive/nfr-announce" #define MAILBOXDIR "/ftp/nfr/mail-archive/nfr-announce/mailbox" #define LABEL "Network Flight Recorder Announcements" #define ABOUT_LINK "/nfr/mail-archive" #define LISTNAME "nfr-announce" #define CONFIGFILE "/usr/local/lib/hypermail/nfr-announce.rc" ... If you specify a CONFIGFILE path, it will be used to set hypermail options and is call as "HYPERMAIL -u -i -c CONFIGFILE". If you do not specify a CONFIGFILE path, hypermail is called using the other information as "HYPERMAIL -u -i -d ARCHIVE/year/month -l \"LABEL\" -b ABOUT_LINK" 3. Next make sure that you have a properly compiled version of hypermail installed on the system. 4. Edit the Makefile and add the appropriate entries. For example: wuftpdmail: msg2archive.c $(CC) -DWU_FTPD -o $@ msg2archive.c wu-rdmsg: mbox2hypermail.c $(CC) -DWU_FTPD -o $@ mbox2hypermail.c 5. Compile and install the new programs. Now everything software-wise is in place. Time to setup your mailer to process the inbound messages. 6. You need to add an entry to your /etc/aliases file such as wuftpd: "|/usr/local/bin/wuftpdmail" 7. Assure that your mailer is aware of the new alias, i.e. might need to type 'newaliases'. Now you are ready to start receiving messages. Time to subscribe your new alias to the list you want to archive. If you are running the list then this is easy. In some cases you have to play games to get an alias subscribed with other than you normal account. What ever the case get the new alias subscribed. ====================== So what happens now ? ====================== Messages sent to a list and are resent to the members of the list. The alias you subscribed is now a member of the list. Messages are sent to the list archive alias. The "msg2archive" process is started for each message and the messages are stored into the location specified in the MAILBOXDIR define. Messages are stored in the directory in a "month' file or as specified in the configuration file. These are Unix mailbox formatted files. Once the message is archived in mailbox format, it is also then archived in hypermail format. The appropriate hypermail is called with the inbound message sent to it to add to the hypermail archive. In this manner each article is available to those who want to read them online and to those who want to download an entire month's worth of traffic to read with their favorite mail Unix reader. If there is ever a problem with the hypermail archives, be it a new look and feel wanted or a bug fix that requires regeneration of the archive, the mailbox versions will be used as input to the process. The script `1998' and the `mbox2hypermail.c' program in this directory are being used for testing and archive re-creation. If you want to change the look and feel of the individual hypermail archive pages, that can be done easily by creating the list specific header and footer HTML template files as described in the hypermail.1 and hmrc.4 man pages. =========================== Integrating with Majordomo: =========================== If you are running a majordomo list and want to integrate this with majordomo then make sure that the ftp mailbox directory is symlinked to ~majordomo/Archives/listname directory so that this scheme does not break majordomo. DO NOT HAVE MAJORDOMO DO ANY ARCHIVING. The symlink'ed directory is so people will be able to request archives and index listing from majordomo as normal. Now the list archives are reachable via the web, ftp or email. ================================================ FILE: archive/lists.h ================================================ /* ** FILE: lists.h - %W% %G% ** AUTHOR: Kent Landfield ** ** ABSTRACT: Define the lists supported by hypermail ** ** This software is Copyright (c) 1996 by Kent Landfield. ** ** Permission is hereby granted to copy, distribute or otherwise ** use any part of this package as long as you do not try to make ** money from it or pretend that you wrote it. This copyright ** notice must be maintained in any copy made. ** */ #ifdef HYPERDEV #define HYPERMAIL "/usr/local/bin/hypermail" #define ARCHIVE "/ftp/hypermail/mail-archive" #define MAILBOXDIR "/ftp/hypermail/mail-archive/mailbox" #define LABEL "Hypermail Development List" #define ABOUT_LINK "/hypermail/mail-archive" #define LISTNAME "hypermail" #define CONFIGFILE "/usr/local/lib/hypermail/hypermail.rc" #else # ifdef HYPERTEST #define HYPERMAIL "../src/hypermail" #define ARCHIVE "../tests/mail-archive" #define MAILBOXDIR "../tests/mail-archive/mailbox" #define LABEL "Hypermail Test Archive" #define ABOUT_LINK "../" #define LISTNAME "hypermail-test" #define CONFIGFILE "../tests/test.rc" # else #define HYPERMAIL "/usr/local/bin/hypermail" #define ARCHIVE "NONE" #define MAILBOXDIR "NONE" #define LABEL "NONE" #define ABOUT_LINK "NONE" #define LISTNAME "NONE" #define CONFIGFILE "NONE" # endif /* HYPERTEST */ #endif /* HYPERDEV */ ================================================ FILE: archive/mbox2hypermail.c ================================================ /* ** FILE: mbox2hypermail.c ** AUTHOR: Kent Landfield ** ** ABSTRACT: read mailbox and print out messages individually and *** ship to hypermail to update a database. ** ** This software is Copyright (c) 1989 by Kent Landfield. ** ** Permission is hereby granted to copy, distribute or otherwise ** use any part of this package as long as you do not try to make ** money from it or pretend that you wrote it. This copyright ** notice must be maintained in any copy made. ** */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #include "lists.h" #undef isspace #define USAGE "usage: %s -D YYYY [ -tvd ] [ mailbox ]\n" #define MAX_MONTH_LEN 20 char *progname; /* name of executable */ char lastline[BUFSIZ]; /* read-behind buffer */ char s[BUFSIZ]; /* read buffer */ char *year; char *month; char *configfile; int debug; int verbose; int test; FILE *errfp; /* standard error file pointer */ FILE *logfp; /* standard output file pointer */ FILE *mailbox; extern char *optarg; extern int optind; #ifdef lint extern int getopt(int, char * const *, const char *); extern int strcasecmp(const char *, const char *); extern char *strdup(const char *); #endif static FILE *safe_tmpfile(void) { int fd; char *tfile; tfile = strdup("hn-inXXXXXX"); if ((fd = mkstemp(tfile)) < 0) return(NULL); unlink(tfile); if (fchmod(fd, S_IRUSR | S_IWUSR) != 0) return(NULL); return(fdopen(fd, "w+b")); } static FILE *efopen(char *file, char *mode) { FILE *fp; if ((fp = fopen(file, mode)) == NULL) { (void)fprintf(errfp, "Can't open file %s\n", file); exit(10); } return (fp); } static char *readline(int size, FILE *file) { /* ** If not first time through, save the previous line read into lastline. */ if (s[0] != '\0') (void)strcpy(lastline, s); if (fgets(s, size, file) == NULL) return (NULL); return (s); } static int blankline(char *line) { register char *cp; for (cp = line; *cp; cp++) { if (!isspace(*cp)) return (0); } return (1); } static void process_messages(char *flname) { char msgfile[BUFSIZ]; char cmdstr[BUFSIZ]; char from[BUFSIZ]; int cntr; int first; FILE *msgfp; if (verbose) fprintf(stderr, "Processing mailbox %s\n", flname); /* ** Standard input or a mailbox file ? */ if (flname != NULL) mailbox = efopen(flname, "r"); else mailbox = stdin; first = 1; cntr = 0; lastline[0] = '\0'; /* ** Create message file */ if ((msgfp = safe_tmpfile()) == NULL) { fprintf(stderr,"%s: Can't open tempfile\n",progname); exit(10); } if (month != NULL) { /* AUDIT biege: external input -> cmd exec + bof */ if (configfile != NULL) { #ifdef HAVE_SNPRINTF snprintf(cmdstr, sizeof(cmdstr), #else sprintf(cmdstr, #endif "/bin/cat %s | %s -u -i -c %s -d %s/%s/%s", msgfile, HYPERMAIL, configfile, ARCHIVE, year, month); } else { #ifdef HAVE_SNPRINTF snprintf(cmdstr, sizeof(cmdstr), #else sprintf(cmdstr, #endif "/bin/cat %s | %s -u -i -d %s/%s/%s -l \"%s\" -b %s", msgfile, HYPERMAIL, ARCHIVE, year, month, LABEL, ABOUT_LINK); } } else { if (configfile != NULL) { #ifdef HAVE_SNPRINTF snprintf(cmdstr, sizeof(cmdstr), #else sprintf(cmdstr, #endif "/bin/cat %s | %s -u -i -c %s -d %s/%s", msgfile, HYPERMAIL, configfile, ARCHIVE, year); } else { #ifdef HAVE_SNPRINTF snprintf(cmdstr, sizeof(cmdstr), #else sprintf(cmdstr, #endif "/bin/cat %s | %s -u -i -d %s/%s -l \"%s\" -b %s", msgfile, HYPERMAIL, ARCHIVE, year, LABEL, ABOUT_LINK); } } if (debug) { fprintf(stderr, "cmdstr == [%s]\n", cmdstr); exit(0); } while (readline(sizeof(s), mailbox) != NULL) { if (strncmp(s, "From ", 5) == 0) { strcpy(from, s); if (first == 1) { /* First From in file ? */ first = 0; } else if (blankline(lastline)) { /* ** If From and last line is a blank line we have ** found the message separator. Time to go to work. */ fflush(msgfp); fclose(msgfp); if (verbose) fputs(from, errfp); if (!test) system(cmdstr); ++cntr; msgfp = efopen(msgfile, "w"); } } (void)fputs(s, msgfp); } fclose(mailbox); fflush(msgfp); fclose(msgfp); if (verbose) fputs(from, errfp); if (!test) system(cmdstr); if (!first) ++cntr; if (verbose) fprintf(stderr, "%d messages processed\n", cntr); } /* ** Ye Olde Main */ int main(int argc, char **argv) { int c; progname = argv[0]; debug = verbose = 0; logfp = stdout; errfp = stderr; configfile = CONFIGFILE; if (argc > 1) { while ((c = getopt(argc, argv, "c:dtvY:M:")) != EOF) { switch (c) { case 'c': configfile = strdup(optarg); break; case 'M': month = optarg; if (strlen(month) > MAX_MONTH_LEN) { (void)fprintf(errfp, "%s: Invalid month format, %d character month maximum.\n", progname, MAX_MONTH_LEN); return (1); } break; case 'Y': year = optarg; /* check and make sure it is a year.*/ if (strlen(year) > 4) { (void)fprintf(errfp, "%s: Invalid year format, 4 digit year maximum.\n", progname); return (1); } break; case 'd': debug++; break; case 'v': verbose++; break; case 't': test++; verbose++; break; default: (void)fprintf(errfp, USAGE, progname); return (1); } } } if (year == NULL) { (void)fprintf(errfp, "%s: must specify the 4 digit year\n", progname); (void)fprintf(errfp, USAGE, progname); return (1); } if (strcasecmp(configfile, "NONE") == 0) configfile = NULL; /* if no month just put it in the year directory */ if ((optind >= argc) || (argc == 1)) { /* file from stdin */ process_messages(NULL); } else { for (; optind < argc; optind++) /* process files to print */ process_messages(argv[optind]); } return (0); /* terminate this process */ } ================================================ FILE: archive/msg2archive.c ================================================ /* ** FILE: msg2archive.c ** AUTHOR: Kent Landfield ** ** ABSTRACT: update archived mailbox and *** ship to appropriate hypermail to update a database. ** ** This software is Copyright (c) 1996 by Kent Landfield. ** ** Permission is hereby granted to copy, distribute or otherwise ** use any part of this package as long as you do not try to make ** money from it or pretend that you wrote it. This copyright ** notice must be maintained in any copy made. ** */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <fcntl.h> #include <time.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/stat.h> #include "lists.h" #include "../config.h" char s[BUFSIZ]; /* read buffer */ char cmdstr[BUFSIZ]; char *progname; /* name of executable */ char *month; /* 3 letter mon abreviation */ /* ** List information variables */ char *configfile = CONFIGFILE; /* list's configuration file */ char *listname = LISTNAME; /* name of the list */ char *hypermail = HYPERMAIL; /* path to hypermail executable */ char *archive = ARCHIVE; /* list archive base directory */ char *mailboxdir = MAILBOXDIR; /* path to mailbox directory */ char *label = LABEL; /* list's title/lable */ char *about_link = ABOUT_LINK; /* list's about link */ int year; /* 4 digit year */ int verbose; int test; int c; time_t clk; struct tm *now; FILE *msgfp; FILE *mailbox; FILE *hypfp; char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; extern int opterr; extern char *optarg; FILE *s_popen(char *cmd, const char *type); static int usage(void) { (void)fprintf(stderr, "usage: %s [options] (file on stdin only)\n", progname); (void)fprintf(stderr, " -A archive-basedir\n"); (void)fprintf(stderr, " -b about_link\n"); (void)fprintf(stderr, " -c configfile\n"); (void)fprintf(stderr, " -H hypermail executable\n"); (void)fprintf(stderr, " -L listname\n"); (void)fprintf(stderr, " -l list lable\n"); (void)fprintf(stderr, " -M mailbox directory\n"); (void)fprintf(stderr, " -t testing (no execution, assumes -v)\n"); (void)fprintf(stderr, " -v verbose\n"); return (-1); } static FILE *safe_tmpfile(void) { int fd; char *tfile; tfile = strdup("/tmp/hn-inXXXXXX"); if ((fd = mkstemp(tfile)) < 0) return(NULL); fprintf(stderr,"%s: mkstemp(%s) succeeded\n", progname, tfile); /* unlink(tfile); if (fchmod(fd, S_IRUSR | S_IWUSR) != 0) return(NULL); */ return(fdopen(fd, "w+b")); } int main(int argc, char **argv) { int inheader; verbose = 0; test = 0; opterr = 0; if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; else progname++; if (argc > 1) { while ((c = getopt(argc, argv, "A:b:c:H:L:l:M:tv")) != EOF) { switch (c) { case 'A': archive = optarg; break; case 'b': about_link = optarg; break; case 'c': configfile = optarg; break; case 'H': hypermail = optarg; break; case 'L': listname = optarg; break; case 'l': label = optarg; break; case 'M': mailboxdir = optarg; break; case 'v': verbose++; break; case 't': test++; verbose++; break; default: return (usage()); } } } if (strcasecmp(configfile, "NONE") == 0) configfile = NULL; /* get the year and the month so that we can set up archive info */ clk = time((time_t *) 0); now = localtime(&clk); year = 1900 + now->tm_year; month = months[now->tm_mon]; /* ** Create temporary message file ** and save the inbound message. */ if ((msgfp = safe_tmpfile()) == NULL) { perror("tempfile open failed"); fprintf(stderr,"%s: Can't open tempfile\n",progname); fprintf(stderr, "uid = %ld - gid = %ld euid = %ld - egid = %ld\n", (long)getuid(), (long)getgid(), (long)geteuid(), (long)getegid()); exit(10); } inheader = 1; /* guilty until proven innocent */ while (fgets(s, sizeof(s), stdin) != NULL) { /* ** Need to escape lines in the body that ** start with a "^From " */ if (*s == '\n') inheader = 0; if (!inheader) { if (!strncmp(s, "From ", 5)) fputs(">", msgfp); } fputs(s, msgfp); } fflush(msgfp); /* ** Append it to the current month's message file */ /* AUDIT Thomas Biege: mailboxdir + listname are cmd line options */ #ifdef HAVE_SNPRINTF snprintf(cmdstr, sizeof(cmdstr), #else sprintf(cmdstr, #endif "%s/%s.%.2d%.2d", mailboxdir, listname, year, now->tm_mon + 1); if (verbose) fprintf(stderr, "Appending message to [%s]\n", cmdstr); if (!test) { /* AUDIT Thomas Biege: "../" in mailboxdir or listname can be used ** to write to files below the target direc.! ** Take Care! I'll not fix it. */ if ((mailbox = fopen(cmdstr, "a+")) == NULL) { fprintf(stderr,"%s: Can't append message to %s\n",progname,cmdstr); fprintf(stderr, "uid = %ld - gid = %ld euid = %ld - egid = %ld\n", (long)getuid(), (long)getgid(), (long)geteuid(), (long)getegid()); exit(10); } rewind(msgfp); while (fgets(s, sizeof(s), msgfp) != NULL) fputs(s, mailbox); fclose(mailbox); } /* ** Send it to hypermail to archive it in the current month's archive */ if (configfile == NULL) #ifdef HAVE_SNPRINTF snprintf(cmdstr, sizeof(cmdstr), #else sprintf(cmdstr, #endif "%s -u -i -d %s/%d/%s -l \"%s\" -b %s", hypermail, archive, year, month, label, about_link); else #ifdef HAVE_SNPRINTF snprintf(cmdstr,sizeof(cmdstr), #else sprintf(cmdstr, #endif "%s -u -i -c %s",hypermail,configfile); if (verbose) fprintf(stderr, "Piping message to [%s]\n", cmdstr); if (!test) { /* ** Need to consider replacing with a safer popen. if ((hypfp = popen(cmdstr, "w")) != NULL) { pclose(hypfp); */ if ((hypfp = s_popen(cmdstr, "w")) != NULL) { rewind(msgfp); while (fgets(s, sizeof(s), msgfp) != NULL) fputs(s, hypfp); fflush(hypfp); fclose(hypfp); } } fclose(msgfp); /* not needed for [s_]tmpfile() */ return (0); /* terminate this process */ } #define __SEC_POPEN_TOKEN " " FILE *s_popen(char *cmd, const char *type) { pid_t pid; int pfd[2]; int rpipe = 0, wpipe = 0, i; char **argv; char *ptr; char *cmdcpy; if(cmd == NULL || cmd == "") return(NULL); if(type[0] != 'r' && type[0] != 'w') return(NULL); if ((cmdcpy = strdup(cmd)) == NULL) return(NULL); argv = NULL; if( (ptr = strtok(cmdcpy, __SEC_POPEN_TOKEN)) == NULL) { free(cmdcpy); return(NULL); } for(i = 0;; i++) { if( ( argv = (char **) realloc(argv, (i+1) * sizeof(char *)) ) == NULL) { free(cmdcpy); return(NULL); } if( (*(argv+i) = (char *) malloc((strlen(ptr)+1) * sizeof(char))) == NULL) { free(cmdcpy); return(NULL); } strcpy(argv[i], ptr); if( (ptr = strtok(NULL, __SEC_POPEN_TOKEN)) == NULL) { if( ( argv = (char **) realloc(argv, (i+2) * sizeof(char *))) == NULL) { free(cmdcpy); return(NULL); } argv[i+1] = NULL; break; } } if(type[0] == 'r') rpipe = 1; else wpipe = 1; if (pipe(pfd) < 0) { free(cmdcpy); return(NULL); } if((pid = fork()) < 0) { close(pfd[0]); close(pfd[1]); free(cmdcpy); return(NULL); } if(pid == 0) { /* child */ if((pid = fork()) < 0) { close(pfd[0]); close(pfd[1]); free(cmdcpy); return(NULL); } if(pid > 0) { exit(0); /* child nr. 1 exits */ } /* child nr. 2 */ if(rpipe) { close(pfd[0]); /* close reading end, we don't need it */ if (pfd[1] != STDOUT_FILENO) dup2(pfd[1], STDOUT_FILENO);/* redirect stdout to writing end of pipe */ dup2(STDOUT_FILENO, STDERR_FILENO); } else { close(pfd[1]); /* close writing end, we don't need it */ if (pfd[0] != STDIN_FILENO) dup2(pfd[0], STDIN_FILENO); /* redirect stdin to reading end of pipe */ } if(strchr(argv[0], '/') == NULL) execvp(argv[0], argv); /* search in $PATH */ else execv(argv[0], argv); close(pfd[0]); close(pfd[1]); free(cmdcpy); return(NULL); /* exec failed.. ooops! */ } else { /* parent */ waitpid(pid, NULL, 0); /* wait for child nr. 1 */ if(rpipe) { close(pfd[1]); free(cmdcpy); return(fdopen(pfd[0], "r")); } else { close(pfd[0]); free(cmdcpy); return(fdopen(pfd[1], "w")); } } } ================================================ FILE: archive/runtest ================================================ #!/bin/sh # DIR=`pwd` Msg2archive=$DIR/msg2archive TestMsg=$DIR/test-msg if [ ! -d ../tests/mail-archive ]; then mkdir ../tests/mail-archive fi if [ ! -d ../tests/mail-archive/mailbox ]; then mkdir ../tests/mail-archive/mailbox fi #cat test-msg | htestmail -v # Tests for generic msg2archive executable # # usage: msg2archive [options] (file on stdin only) # -A archive-basedir (#define ARCHIVE) # -b about_link (#define ABOUT_LINK) # -c configfile (#define CONFIGFILE) # -H hypermail executable (#define HYPERMAIL) # -L listname (#define LISTNAME) # -l list lable (#define LABEL) # -M mailbox directory (#define MAILBOXDIR) # -t testing (no execution, assumes -v) # -v verbose (cd ../tests; cat $TestMsg | $Msg2archive -v -A mail-archive -b ../ -c test.rc -H ../src/hypermail -L hypermail-test -l "Hypermail Test Archive" -M mail-archive/mailbox) ================================================ FILE: archive/test-msg ================================================ From bel@llnl.gov Fri Aug 28 11:15 PDT 1998 Received: from pierce.llnl.gov (pierce.llnl.gov [128.115.18.253]) by k2.llnl.gov (8.8.5/8.8.5/LLNL-Jun96) with ESMTP id LAA17195 for <perra@k2.llnl.gov>; Fri, 28 Aug 1998 11:15:55 -0700 (PDT) Received: from popcorn.llnl.gov by pierce.llnl.gov (8.8.8/LLNL-1.18/llnl.gov-04.5) id LAA02432; Fri, 28 Aug 1998 11:15:55 -0700 (PDT) Received: from archive-xke.llnl.gov (archive-xke.llnl.gov [128.115.172.48]) by popcorn.llnl.gov (8.8.8/LLNL-3.0.2) with SMTP id LAA28465; Fri, 28 Aug 1998 11:15:53 -0700 (PDT) Message-Id: <4.0.5.32.19980828111501.00903100@popcorn.llnl.gov> X-Sender: e546171@popcorn.llnl.gov X-Mailer: QUALCOMM Windows Eudora Pro Version 3.0.5 (32) Date: Fri, 28 Aug 1998 11:15:01 -0700 To: Joanne Perra <perra1@llnl.gov> From: "DeMarotta, Louis Joseph, Jr. (LZD) " <lzd@ornl.gov> " <bel@llnl.gov>) Subject: RE: When NWIG grows up... Cc: kent@landfield.com Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Length: 145 has any one seen it,yet??? Lou > -----Original Message----- ... deleted content ... From the beginning From the start From now until tomorrow Joanne and Kent, Here's a message redirected from Eudora. ---- Gordon H. Buchan gordon@pobox.com http://gordon.anadas.com ----------------------------------------------------------------------------- To unsubscribe from the CUSIDnet mailing list, send a message to cusid-request@anadas.com with the following command in the message unsubscribe your@nfr.net, dave@where or sam@hear.com Follow CUSIDnet on the web at http://cusidnet.anadas.com ----------------------------------------------------------------------------- ================================================ FILE: autogen.sh ================================================ #!/bin/sh autoconf rm -rf autom4te.cache ================================================ FILE: config.guess ================================================ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-03-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner <per@bothner.com>. # Please send patches to <config-patches@gnu.org>. Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi dummy=dummy-$$ trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int dummy(){}" > $dummy.c ; for c in cc gcc c89 c99 ; do ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; if test $? = 0 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. cat <<EOF >$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF eval $set_cc_for_build $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then case `./$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; esac fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy \ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <sys/systemcfg.h> main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include <stdlib.h> #include <unistd.h> int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <unistd.h> int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include <features.h> #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says <Richard.M.Bartel@ccMail.Census.GOV> echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes <hewes@openmarket.com>. # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c <<EOF #ifdef _SEQUENT_ # include <sys/types.h> # include <sys/utsname.h> #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include <sys/param.h> printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include <sys/param.h> # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 <<EOF $0: unable to guess system type This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from ftp://ftp.gnu.org/pub/gnu/config/ If the version you run ($0) is already up to date, please send the following data and any information you think might be pertinent to <config-patches@gnu.org> in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: config.h.in ================================================ /* config.h.in. Generated automatically from configure.in by autoheader. */ /* Define if you have the strftime function. */ #undef HAVE_STRFTIME /* Define to `unsigned' if <sys/types.h> doesn't define. */ #undef size_t /* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */ #undef STAT_MACROS_BROKEN /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you can safely include both <sys/time.h> and <time.h>. */ #undef TIME_WITH_SYS_TIME /* Define if your <sys/time.h> declares struct tm. */ #undef TM_IN_SYS_TIME #undef HAVE_GDBM_H #undef HAVE_ICONV #undef HAVE_ICONV_H /* Define if you're using the FNV hash library */ #undef HAVE_LIBFNV /* Define if you have the getopt function. */ #undef HAVE_GETOPT /* Define if you have the getpwuid function. */ #undef HAVE_GETPWUID /* Define if you have the lstat function. */ #undef HAVE_LSTAT /* Define if you have the memcpy function. */ #undef HAVE_MEMCPY /* Define if you have the memset function. */ #undef HAVE_MEMSET /* Define if you have the mkdir function. */ #undef HAVE_MKDIR /* Define if you have the strcasecmp function. */ #undef HAVE_STRCASECMP /* Define if you have the strcasestr function. */ #undef HAVE_STRCASESTR /* Define if you have the strdup function. */ #undef HAVE_STRDUP /* Define if you have the strstr function. */ #undef HAVE_STRSTR /* Define if you have the strtol function. */ #undef HAVE_SNPRINTF /* Define if you have the strtol function. */ #undef HAVE_STRTOL /* Define if you have the <alloca.h> header file. */ #undef HAVE_ALLOCA_H /* Define if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H /* Define if you have the <ctype.h> header file. */ #undef HAVE_CTYPE_H /* Define if you have the <dirent.h> header file. */ #undef HAVE_DIRENT_H /* Define if you have the <errno.h> header file. */ #undef HAVE_ERRNO_H /* Define if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H /* Define if you have the <locale.h> header file. */ #undef HAVE_LOCALE_H /* Define if you have the <malloc.h> header file. */ #undef HAVE_MALLOC_H /* Define if you have the <ndir.h> header file. */ #undef HAVE_NDIR_H /* Define if you have the <netdb.h> header file. */ #undef HAVE_NETDB_H /* Define if you have the <netinet/in.h> header file. */ #undef HAVE_NETINET_IN_H /* Define if you have the <pwd.h> header file. */ #undef HAVE_PWD_H /* Define if you have the <stdarg.h> header file. */ #undef HAVE_STDARG_H /* Define if you have the <stdio.h> header file. */ #undef HAVE_STDIO_H /* Define if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H /* Define if you have the <string.h> header file. */ #undef HAVE_STRING_H /* Define if you have the <sys/dir.h> header file. */ #undef HAVE_SYS_DIR_H /* Define if you have the <sys/ndir.h> header file. */ #undef HAVE_SYS_NDIR_H /* Define if you have the <sys/param.h> header file. */ #undef HAVE_SYS_PARAM_H /* Define if you have the <sys/socket.h> header file. */ #undef HAVE_SYS_SOCKET_H /* Define if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H /* Define if you have the <sys/time.h> header file. */ #undef HAVE_SYS_TIME_H /* Define if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H /* Define if you have the <time.h> header file. */ #undef HAVE_TIME_H /* Define if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H /* Whether you have GDBM */ #undef GDBM /* Whether you want function version of ctype functions */ #undef NO_MACRO /* The following two definitions are mainly for the benefit of SunOS4, which doesn't have the strerror() or memmove() functions that should be present in all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should normally be defined with the value 1 for other systems, but unfortunately we can't make this the default because "configure" files generated by autoconf will only change 0 to 1; they won't change 1 to 0 if the functions are not found. If HAVE_MEMMOVE is set to 1, the value of HAVE_BCOPY is not relevant. */ #define HAVE_STRERROR 0 #define HAVE_MEMMOVE 0 #define HAVE_BCOPY 0 ================================================ FILE: config.sub ================================================ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-03-07' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to <config-patches@gnu.org>. Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dsp16xx \ | fr30 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el | mips64vr4300 \ | mips64vr4300el | mips64vr5000 | mips64vr5000el \ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ | mipsisa32 | mipsisa64 \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; c4x*) basic_machine=c4x-none os=-coff ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: configs/hmrc.example ================================================ # # hmrc.example: # # This is a sample Hypermail configuration file. If you wish # to use it, copy it to a new filename and edit as appropriate # for you list needs. # # language = [ en | de | es | fi | fr | is | pl | pt | sv | no | el | gr | ru | it ] # # This is a two-letter string specifying the default language to use. # Set this the value of the language table you wish to use when running # and generating archives. language = en # htmlsuffix = html # # Use this to specify the html file suffix to be used when Hypermail # generates the HTML files. This is dependent on local needs. # # NOTE: Do not put a '.' in the value. It would result in \"file..html\ htmlsuffix = html # mbox = [ filename | NONE ] # # This is the default mailbox to read messages in from. Set this # with a value of NONE to read from standard input as the default. mbox = NONE # ietf_mbox = [ 0 | 1 ] # # Set this to On to read mboxes using the IETF convention. ietf_mbox = 0 # label = [ Title | NONE ] # # This is the default title you want to call your archives. # Set this to NONE to use the name of the input mailbox. label = Hypermail Development List # archives = [ URL | NONE ] # # This will create a link in the archived index pages labeled # 'Other mail archives' to the specified URL. Set this to NONE # to omit such a link archives = NONE # custom_archives = [ text | NONE ] # # If this variable is defined, a navigation entry will be # created below the sorted_by_x list entry, with the text # Other mail archives: followed by the value of this variable. # Set it to NONE to ommit such an entry. #custom_archives = # about = [ URL | NONE ] # # This creates a link in the archived index pages labeled # "About this archive". Set this to NONE to omit such a link. about = NONE # dir = [ directory path | NONE ] # # This is the default directory that Hypermail uses when creating # and updating archives. If set to NONE, the directory will have the # same name as the input mailbox. dir = NONE # defaultindex = [ thread | date | subject | author | attachment ] # # This indicates the default type of main index hypermail will generate. # Users see this type of index when the archive is first accessed. # Valid types are date, thread, author, subject, and attachment. When # using the folder_by_date or msgsperfolder options, this option applies # to subdirectories. defaultindex = thread # default_top_index = [ thread | date | subject | author | folders | attachment ] # # This specifies the default index that users can view when # entering the top level of an archive that uses the folder_by_date # or msgsperfolder option. Valid types are date, thread, author, # subject, attachment, and folders. default_top_index = folders # avoid_indices = [ thread | date | subject | author | folders | attachment ] # # This is a list of index files to not generate. Valid types are # date, thread, author, and subject. When using the folder_by_date or # msgsperfolder options, this option applies to subdirectories. #avoid_indices = # avoid_top_indices = [ thread | date | subject | author | folders | attachment ] # # This is a list of index files to not generate for the top # directory of an archive using the folder_by_date or # msgsperfolder option. Valid types are date, thread, author, # subject, folders, and attachment. avoid_top_indices = date thread author subject # inlinehtml [ 0 | 1 ] # # This is used to make text/html parts to get inlined within the # mail messages. If not set on, HTML-parts will be stored as separate # files. inlinehtml = 1 # reverse = [ 0 | 1 ] # # Setting this variable to 1 will reverse-sort the article # entries in the date and thread index files by the date they # were received. That is, the most recent messages will appear # at the top of the index rather than the other way around. # Set to 0 if you want latest message on the bottom for date and # thread indexes. reverse = 0 # usetable = [ 0 | 1 ] # # Setting this variable to 1 will tell Hypermail to generate an # index menu at the top and bottom of each page in a table format. # Set to 0 if you want the standard Hypermail page look and feel. usetable = 0 # indextable [ 0 | 1 ] # # Setting this variable to 1 will tell Hypermail to generate # message index Subject/Author/Date listings using a nice table # format. Set to 0 if you want the original Hypermail index look. indextable = 0 # progress = [ 0 | 1 | 2 ] # # Set this to 1 or 2 to always show a progress report as Hypermail # works. With a setting of 1, hypermail overwrites the progress # information relating to attachment creation. With a setting of 2, # attachment creation information is listed individually with the # number of the message the attachments relate to. Set to 0 for # silent operation. Output goes to standard output. progress = 0 # show_msg_links = [ 0 | 1 | 3 | 4 ] # # Set this to 1 if you want links to Next, Prev, Next thread, Reply to, # etc, displayed on the article pages. Setting this to 0 disables these # links from appearing on the generated pages. # Set it to 3 to show the links only at the top of the message # pages, or 4 to produce those links only at the bottom of the # message. show_msg_links = 1 # showheaders = [ 0 | 1 ] # # Set this to 1 to show the article header lines in the archived HTML # files. These lines typically include the To:, From:, and Subject: # information found in most email messages. Set to 0 if you want to # hide mail headers in articles. showheaders = 0 # showreplies = [ 0 | 1 ] # # Set to 1 to show all replies to a message as links in article files. # If this is set to 0 no reply links are generated. showreplies = 1 # showhtml = [ 0 | 1 | 2 ] # # Set this to 1 to show the articles in a proportionally-spaced # font rather than a fixed-width (monospace) font. # Set this to 2 for more complex conversion to html # similar to that in <a href="http://www.cs.wustl.edu/~seth/txt2html/">txt2html.pl</a>. # Showhtml = 2 will normally produce nicer looking results than # showhtml = 1, and showhtml = 0 will look pretty dull, but # 1 and 2 run risks of altering the appearance in undesired ways. showhtml = 1 # showbr = [ 0 | 1 ] # # Set this to 1 if you want article lines to end with the <br> tag. # Else set to 0 to have non-quoted lines word-wrap. Only takes effect # if showhtml is set to 1. showbr = 1 # iquotes = [ 0 | 1 ] # # Set this to 1 if you want quoted lines to be shown in italics. Only # take effect if showhtml is set to 1. iquotes = 1 # showhr = [ 0 | 1 ] # # Set to 1 if you want horizontal rules <HR> before and after # the articles. Set to 0 if you don't. showhr = 1 # overwrite = [ 0 | 1 ] # # Set to 1 to make Hypermail rewrite all messages. # Set to 0 to rewrite as few messages as possible. # Rewriting all messages is slower, but if you change the options # that control the appearance of the messages you may want to rewrite # all the messages to make the appearance consistent throughout the archive. overwrite = 0 # increment = [ -1 | 0 | 1 ] # # Define as 1 to append all input messages to the end of existing archives. # Define as 0 for it to read a mailbox that corresponds to the entire # archive. (See the mbox_shortened option for an exception to the requirement # that it be the entire archive). # If there are any existing html messages, it will figure out which # ones at the end of the mailbox are new, and add only those that haven't been # converted yet. # Define as -1 to have hypermail figure out whether the input # is entirely new messages to be appended or whether it contains # messages that are already in the archive. A value of -1 cannot be # used with the mbox_shortened option or with the -i command line # option or with mbox = NONE. increment = 0 # readone [ 0 | 1 ] # # Set this to On to specify there is only one message in the input. readone = 0 # thrdlevels = number # # This specifies the number of thread levels to outline in the thread # index. For instance, if thrdlevels is 2, replies to messages will # be indented once in the index, but replies to replies, etc., will only # be indented once as well. The normal value is 4. thrdlevels = 4 # eurodate = [ 0 | 1 ] # # Set this to reflect how you want dates displayed in the index files. # Set as 1 to to use European date format "DD MM YYYY". # Define as 0 to to use American date format "MM DD YYYY". eurodate = 0 # isodate = [ 0 | 1 ] # # Set this to On to display article received dates in # YYYY-MM-DD HH:MM:SS format. If used with the gmtime option, a # Z will be inserted between the DD and HH. #isodate = 0 # gmtime = [ 0 | 1 ] # # Set this to On to display article received dates using # Greenwich Mean Time (UTC) rather than local time. #gmtime = 0 # dateformat = strftime() date format # # Format used in strftime(3) call for displaying dates. # See strftime(3)) for the valid conversion specifications. dateformat = %c # attachmentlink = attachment link format # # Format of the attachment links. # %p for the full path to the attachment # %f for the file name part only # %d for the directory name only # %n for the message number # %c for the content type string attachmentlink = %p # discard_dup_msgids = [ 0 | 1 ] # # Set this to Off to accept messages with a Message-ID matching # that of a message already in this archive. # By default such messages are discarded. discard_dup_msgids = 1 # require_msgids = [ 0 | 1 ] # # Set this to 0 to accept messages without a Message-ID header. # Set this to 1 to discard messages without a Message-ID header. # By default such messages are discarded. require_msgids = 1 # usemeta = [ 0 | 1 ] # # Set this to 1 to store the content type of a MIME attachment in # a metadata file. usemeta = 1 # uselock = [ 0 | 1 ] # # Set this to 1 to use Hypermail's internal locking mechanism. # uselock = 1 # locktime = number-of-seconds # # The number of seconds that a lock should be honored when processing # inbound messages. locktime = 3600 # dirmode = octal number # # This is an octal number representing the permissions (rwx modes) that new # directories are set to when they are created. If the archives will be made # publically available, it's a good idea to define this as 0755. This must # be an octal number. dirmode = 0755 # filemode = octal number # # This is an octal number representing the permissions that new files # are set to when they are created. If the archives will be made publically # available, it's a good idea to define this as 0644. This must be an octal # number. filemode = 0644 # mailcommand = [ direct mailto | cgi-bin script path | NONE ] # # This is the mail command that email links go to, for instance # "mailto:$TO" or "/cgi-bin/mail?to=$TO&replyto=$ID&subject=$SUBJECT" # # In constructing this command, you can specify variables: # # $TO : the email address of the person you're sending mail to. # $ID : the ID of the message you're replying to. # $SUBJECT: the subject you're replying to. # # NONE disables mailcommand usage. mailcommand = mailto:$TO?subject=$SUBJECT&replyto=$ID # mailto = [ email-address | NONE ] # # The address of the contact point that is put in the HTML header line # <link rev="made" href="mailto:mailto"> # # The <link...> header can be disabled by default by setting # mailto to NONE. mailto = webmaster@hypermail.org # domainaddr = [ domainname | NONE ] # # Domain-ize Addresses -- addresses appearing in the RFC822 field # which lack hostname can't be made into proper HREFs. Because the # MTA resides on the same host as the list, it is often not required # to domain-ize these addresses for delivery. In such cases, hypermail # will add the DOMAINADDR to the email address. domainaddr = hypermail.org # hmail = [ Mailing List Submission Address | NONE ] # # Set this to the list's submission address. When enabled, this can be # used to submit a new message to the list served by the hypermail archive. # "NONE" means don't use it. hmail = hypermail@hypermail.org # ihtmlheaderfile = [ path to index header template file | NONE ] # # Set this to the path to the Index header template file containing # valid HTML statements and substitution cookies for runtime expansion. # This will be included at the top of every index page. ihtmlheaderfile = /lists/hypermail-idxheader.hyp # ihtmlfooterfile = [ path to index footer template file | NONE ] # # Set this to the path to the Index footer template file containing # valid HTML statements and substitution cookies for runtime expansion. # This will be included at the bottom of every index page. ihtmlfooterfile = /lists/hypermail-idxfooter.hyp # mhtmlheaderfile = [ path to message header template file | NONE ] # # Set this to the path to the Message header template file containing # valid HTML statements and substitution cookies for runtime expansion. # This will be included at the top of every message page. mhtmlheaderfile = /lists/hypermail-msgheader.hyp # mhtmlfooterfile = [ path to message footer template file | NONE ] # # Set this to the path to the Message footer template file containing # valid HTML statements and substitution cookies for runtime expansion. # This will be included at the bottom of every message page. mhtmlfooterfile = /lists/hypermail-msgfooter.hyp ###################### # Multiline variables ###################### # show_headers = list of RFC 822 Headers to display if hm_showheaders # is set to 1 (TRUE) # # This is the list of headers to be displayed. They can be listed # comma or space separated all on a single line such as # show_headers = From,Subject,Date,Message-ID # or they can be listed individually or any combination of. # show_headers = From # show_headers = Subject # show_headers = Date # show_headers = Message-ID show_headers = From,Subject,Date,Message-ID # inline_types = indicate which types of data should be inlined # # This is the list of MIME types that you want inlined with <img> tags # as opposed to simply linked into the message with a <a href>. They # can be listed individually on multiple lines or comma or space # separated on a single line. # inline_types = image/gif image/jpeg # or # inline_types = image/gif # inline_types = image/jpeg inline_types = image/gif image/jpeg image/png # ignore_types = indicate which types of attachments to ignore and # not process. # # This is the list of MIME attachment types that you do not want to # do anything with. They are quietly ignored. They can be listed # individually on multiple lines or comma or space separated on a # single line. # ignore_types = text/x-vcard application/x-msdownload # or # ignore_types = text/x-vcard # ignore_types = application/x-msdownload ignore_types = text/x-vcard ignore_types = application/x-msdownload # prefered_types = indicate which of the alternative types to use # # When mails using multipart/mixed types are scanned, this is the # list of alternative MIME types that you want used. This can be # listed individually on multiple lines or comma or space separated # on a single line. # prefered_types = text/plain text/html # or # prefered_types = text/plain # prefered_types = text/html # Order is important. # # NOTE: This option is not fully implemented at present. prefered_types = text/plain text/html # text_types = indicate the MIME types to be treated as text/plain. # # This is a list of MIME types that you want hypermail to treat # exactly as if they were text/plain. This can be listed # individually on multiple lines or comma or space separated # on a single line. text_types = text/x-vcard # usegdbm = [ 0 | 1 ] # # Set this to On to use gdbm to implement a header cache. #This will speed up hypermail, especially if your filesystem is slow. #It will not provide any speedup with the linkquotes option. #usegdbm = Off # append = [ 0 | 1 ] # # Set this to On to maintain a parallel mbox archive. The file #name defaults to mbox in the directory specified by -d or by the dir option. #append = 0 # append_filename = [ string ] # # Specifies the filename to be used by the append option. #$DIR may be used to specify a name relative to the directory #specified in the -d or dir option. #append_filename = # newmsg_command = [ string ] # # This specifies the mail command to use when converting the # set_hmail address to links in replies. The variables $TO, $SUBJECT, # and $ID can be used in constructing the command string. #newmsg_command = mailto:$TO # replymsg_command = [ string ] # # This specifies the mail command to use when converting the # set_hmail address to links in replies. The variables $TO, $SUBJECT, # and $ID can be used in constructing the command string. The value # from mailcommand will be used if this option is not specified. #replymsg_command = mailto:$TO # icss_url = [ URL ] # # Specifies a URL to an external CSS stylesheet for the index pages. The CSS will be associated to the indexes thru an HTML LINK element. #icss_url = # mcss_url = [ URL ] # # Specifies a URL to an external CSS stylesheet for the message pages. The CSS will be associated to the indexes thru an HTML LINK element. #mcss_url = # spamprotect = [ 0 | 1 ] # # Set this to On to make hypermail not output real email addresses # in the output HTML but instead it will obfuscate them a little. spamprotect = 1 # spamprotect_id = [ 0 | 1 ] # # Set this to On to make hypermail not output real email message # ids in HTML comments (sometimes used internally by hypermail) but # instead it will obfuscate them a little so they don't look like # email addresses to spammers. spamprotect_id = 1 # attachmentsindex = [ 0 | 1 ] # # Set this to Off to make hypermail not output an index of # messages with attachments. attachmentsindex = 1 # linkquotes = [ 0 | 1 ] # # Set this to On to create fine-grained links from quoted # text to the text where the quote originated. It also improves # the threads index file by more accurately matching messages # with replies. Note that this may be rather cpu intensive (see # the searchbackmsgnum option to alter the performance). #linkquotes = 0 # searchbackmsgnum = number # # If the linkquotes option is on and an incremental update is being# done (-u option), this controls the tradeoff between speed and # the reliability of finding the right source for quoted text. # Try to set it to the largest number of messages between a # message and the final direct reply to that message. searchbackmsgnum = 500 # link_to_replies = string # # If the linkquotes option is on, specifying a string here # causes it to generate links from original quoted text to the # location(s) in replies which quote them. The string # is used to display the link. #link_to_replies = # quote_hide_threshold = percentage-number # # If the linkquotes option is on, setting this to an # integer less than 100 will cause it to replace quoted # text with one-line links if the percent of lines in the # message body (exluding the signature) consisting of # quoted text exceeds the number indicated by this option. #quote_hide_threshold = 100 # quote_link_string = string # # If the quote_hide_threshold option is being used, the # quote_link_string will be used if available to display the # link that replaces the quoted text. If no string is specified # here, the first line of each section of quoted text will used. #quote_link_string = # monthly_index = [ 0 | 1 ] # # Set this to On to create additional index files broken up # by month. A summary.html file will provide links to all the # monthly indices. #monthly_index = Off # yearly_index = [ 0 | 1 ] # # Set this to On to create additional index files broken up # by year. A summary.html file will provide links to all the # yearly indices. #yearly_index = Off # thread_file_depth = [ 0 | 1 ] # # If nonzero, break the threads index file into multiple files, # with the initial message of each thread in the main index file # along with links to files containing the replies. Setting this # to 1 creates one file for each thread that has replies, and is # recommended for archives with over a few hundred messages. # Setting this greater than 1 will produce multiple levels of files # for each thread whose replies are nested by more than 1 level, # but that is rarely useful. This option is currently disabled # if the indextable option is turned on, and probably needs to # be less than thrdlevels. #thread_file_depth = 0 # folder_by_date = strftime() date format # # This string causes the messages to be put in subdirectories # by date. The string will be passed to strftime(3) to generate # subdirectory names based on message dates. Suggested values are # "%y%m" or "%b%y" for monthly subdirectories, "%Y" for # yearly, "%G/%V" for weekly. Do not alter this for an existing # archive without removing the old html files. If you use this # and update the archive incrementally (e.g. with -u), you must # use the usegdbm option. # folder_by_date = %b%y # msgsperfolder = number # # Put messages in subdirectories with this many messages per # directory. Do not use this and folder_by_date on the same archive. # Do not alter this for an existing archive without removing the old # html files. Deleted/expired messages ARE COUNTED for the purpose # of deciding how many messages to put in a subdirectory. #msgsperfolder = 0 # describe_folder = format string # # Controls the labels used in folders.html to describe the # directories created by the folder_by_date or msgsperfolder # options. For folder_by_date labels, the describe_folder string # will be passed to strftime(3) the same as the folder_by_date string. # For msgsperfolder: # %d for the directory number (starts with 0) # %D for the directory number (starts with 1) # %m for the number of the first message in the directory # %M for the number of the last message that can be put in the # directory. #describe_folder = # latest_folder = string # # If folder_by_date or msgsperfolder are in use, create # a symbolic link by this name to the most recently created # subdirectory. Note that many web servers are configured to # not follow symbolic links for security reasons. The link will # be created in the directory specified by the "dir" or "-d" option. #latest_folder = current # iso2022jp = [ 0 | 1 ] # # Set this to On to support ISO-2022-JP messages. #iso2022jp = Off # deleted = list of headers # # This is the list of headers that indicate the message should # not be displayed if the value of this header is 'yes'. deleted = X-Hypermail-Deleted X-No-Archive # expires = list of headers # # This is the list of headers that indicate the message should # not be displayed if the value of this header is a date in the past. expires = Expires # delete_msgnum = list of message numbers # # This is the list of message numbers that should be deleted from the # html archive. The mbox is not changed. #delete_msgnum = # delete_level = [ 0 | 1 | 2 | 3 ] # # 0 - remove deleted and expired files. Note that with this choice threading may be screwed up if there are replies to deleted or expired options and the archive is updated incrementally # 1 - remove message body # 2 - remove message body for deleted messages, leave expired messages # 3 - leave all messages # Deleted and expired messages are removed from the index files # regardless of the delete_level selection. delete_level = 1 # txtsuffix = [ string ] # # If you want the original mail messages archived in individual files, # set this to the extension that you want these messages to have # (recommended value: txt). # # txtsuffix = # show_index_links = [ 0 | 1 | 3 | 4 ] # # Set this to 1 to show links to index pages from the top and # bottom of each message file. Set it to 0 to avoid those links. # Set it to 3 to show the links only at the top of the message # pages, or 4 to produce those links only at the bottom of the # message. show_index_links = 1 # filter_out # # Delete from the html archives any message having a header line # which matches any of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_out = # filter_require # # Delete from the html archives any message not having header lines # which match each of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_require = # filter_out_full_body = string # # Delete from the html archives any message having a line # which matches any of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_out_full_body = # filter_require_full_body = string # # Delete from the html archives any message not having lines # which match each of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_require_full_body = # save_alts = [ 0 | 1 | 2 ] # # This controls what happens to alternatives (other than the prefered # alternative) for multipart/alternative messages. # 0 - discard non-prefered alternatives # 1 - show all alternatives inline # 2 - put non-prefered alternatives in a separate file. # #save_alts = 0 # alts_text = descriptive text # # If save_alts is 1, this text is put between the alternatives. # If save_alts is 2, this text is used to describe the link to each # alternative file. # the default if save_alts = 2: #alts_text = "alternate version of message" # the default if save_alts = 1: #alts_text = <hr> # warn_suppressions = [ 0 | 1 ] # # Set this to 1 to get warnings (on stdout) about messages that # are not converted because of they are missing a msgid (if # require_msgids is On) or because one of the following options # suppressed it: deleted expires delete_msgnum filter_out # filter_require filter_out_full_body filter_require_full_body. # warn_suppressions = 1 # unsafe_chars = list of chars to prohibit # Any characters listed in this string are removed from user-specified # attachment filenames. Those characters will be replaced by a "_" # (which means that specifying "_" here won't have any effect). # Note that many characters (including / and \) are removed by the # safe_filename in parse.c regardless of what this option says. There # might be some security problems that can be prevented if you specify # "." here (e.g. if a web server is configured to enable server side # includes on filenames ending in something other than .shtml), but # that will prevent browsers from recognizing many file types. #unsafe_chars = "." # files_by_thread = [ 0 | 1 ] # # Set this to 1 to generate (in addition to the usual files), # a file for each thread that contains all the messages in that # thread. The first line in each thread of the thread index page # links to this file instead of to a single message. #files_by_thread = 0 # href_detection = [ 0 | 1 ] # # Set this to On to assume that any string on the body of the message # that says <A HREF=" ... </A> is a URL, together with its markup # and treat it as such. #href_detection = 0 # mbox_shortened = [ 0 | 1 ] # # Set this to 1 to enable use of mbox that has had some of its # initial messages deleted. Requires usegdbm = 1 and increment = 0. # The first message in the shortened mbox must have a Message-Id header. # If discard_dup_msgids is 0, the first message in the shortened mbox # may not have the same Message-Id as a message that was deleted. # The mbox may not be altered in any way other than deleting from # beginning of the mbox or appending new messages to the end (unless # you rebuild the archive from scratch using a complete mbox). #mbox_shortened = 0 # report_new_folder = [ 0 | 1 ] # # Set this to On to have it print (on stdout) the names of any # new directories created pursuant to the folder_by_date or # msgsperfolder option, or the initial creation of the archive. # It will print the full path if that is what you use to specify # the archive directory. Does not print anything when attachment # or metadata directories are created. #report_new_folder = 0 # report_new_file = [ 0 | 1 ] # # Set this to On to have it print (on stdout) the names of any # new files created for new messages. It will print the full path # if that is what you use to specify the archive directory. #report_new_file = 0 # use_sender_date = [ 0 | 1 ] # # Set this to On to have it use the Date: header (created by the # the system that sent the message) rather than the date/time the # message was received, for purposes such as putting in folders # or sorting. Details of which purposes this affects may change # in the future. # use_sender_date = 0 # filename_base = string # # This option overrides the normal rules for creating attachment # file names, and creates file names from the string that this # option is set to plus a file name extension if one can be found # in the name supplied by the message. This option is mainly for # languages that use different character sets from English. # filename_base = ================================================ FILE: configs/hypermail-footer.hyp ================================================ <p align="center"><img src="http://www.hypermail.org/images/common/yellowline.gif" width="400" height="4" alt="---------"></p> <small><small>\n<em>This archive was generated by %u. </em></small></small> </body> </html> ================================================ FILE: configs/hypermail-index.hyp ================================================ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <html> <head> <meta name="description" content="Hypermail Development List Archives"> <meta name="keywords" content="hypermail Archives, hypermail, email, mail2html, Email Archives"> <title>%l: %s

%l
%s

---------

================================================ FILE: configs/hypermail-msg.hyp ================================================ %A %S %l: %s

%s

---------

================================================ FILE: configs/hypermail.rc ================================================ ################################################################# # # Sample config file used for hypermail@hypermail.org list. # For example purposes only. If you are setting up a new # hypermail archive, run # # $ hypermail -v > your-list.rc # # and then edit the file as appropriate for your list.. # # Additionally, see the hmrc.example file and read hmrc.html # # $ man hmrc # #hm_listname = hypermail #hm_mboxdir = /ftp/hypermail/mail-archive/mailbox # replace any @ sign with this string, if spam flags enabled antispam_at = _at_ # A two-letter string specifying the language to use! # For example 'en' for English language = en # Use this to specify the html file suffix to be used # when Hypermail generates the html files. This is depen- # dent on local needs. Do not put a '.' in the value. It # would result in "file..html", probably not what you want. htmlsuffix = html # This is the mailbox to read messages in from. Set this with # a value of NONE to read from standard input. mbox = NONE # Set this to On to read mboxes using the IETF convention. ietf_mbox = Off # This will create a link in the archived index pages # labeled 'Other mail archives' to the specified URL. Set # this to NONE to omit such a link. # archives = NONE # If this variable is defined, a navigation entry will be # created below the sorted_by_x list entry, with the text # Other mail archives: followed by the value of this variable. # Set it to NONE to ommit such an entry. custom_archives = # This will create a link in the archived index pages # labeled 'About this archive' to the specified URL. Set # this to NONE to omit such a link. about = /hypermail/mail-archive/ # Define this as the label to put in archives. label = Hypermail Development List # This is the directory that Hypermail will look for when # creating and updating archives. If defined as NONE the # directory will have the same name as the input mailbox. # Note that the date that Hypermail was run will be used, not # a date from the message (use the folder_by_date option to # have Hypermail use dates from messages). dir = /ftp/hypermail/mail-archive/%y/%M # This specifies the default index that users can view when # entering the archive. Valid types are date, thread, author, # subject, and attachment. When using the folder_by_date or # msgsperfolder options, this option applies to subdirectories. defaultindex = thread # This specifies the default index that users can view when # entering the top level of an archive that uses the folder_by_date # or msgsperfolder option. Valid types are date, thread, author, # subject, attachment, and folders. default_top_index = folders # This is a list of index files to not generate. Valid types are # date, thread, author, and subject. When using the folder_by_date or # msgsperfolder options, this option applies to subdirectories. #avoid_indices = subject author avoid_indices = # This is a list of index files to not generate for the top # directory of an archive using the folder_by_date or # msgsperfolder option. Valid types are date, thread, author, # subject, folders, and attachment. #avoid_top_indices = date thread avoid_top_indices = # Set to On to make Hypermail rewrite all messages. # Set to Off to rewrite as few messages as possible. # Rewriting all messages is slower, but if you change the options # that control the appearance of the messages you may want to rewrite # all the messages to make the appearance consistent throughout the archive. overwrite = Off # Define to On to make text/html parts to get inlined with the mails. # If set to Off, HTML-parts will be stored as separate files. # A "Content-Disposition: attachment;" line in the mail will # cause an HTML-part to be stored as a separate file even if this # option is On. inlinehtml = On # Define as 1 to append all input messages to the end of existing archives. # Define as 0 for it to read a mailbox that corresponds to the entire # archive. (See the mbox_shortened option for an exception to the requirement # that it be the entire archive). # If there are any existing html messages, it will figure out which # ones at the end of the mailbox are new, and add only those that haven't been # converted yet. # Define as -1 to have hypermail figure out whether the input # is entirely new messages to be appended or whether it contains # messages that are already in the archive. A value of -1 cannot be # used with the mbox_shortened option or with the -i command line # option or with mbox = NONE. increment = 1 # Set this to On to specify there is only one message in the input. readone = Off # Setting this variable to On will reverse-sort the article # entries in the date and thread index files by the # date they were received. That is, the most recent messages # will appear at the top of the index rather than the other # way around. reverse = Off # Setting this variable to On will reverse-sort the list of # folders. That is, the most recent folders will appear at # the top of the index rather than the other way around. reverse_folders = Off # Set this to 1 or 2 to always show a progress report as # Hypermail works. With a setting of 1, hypermail # overwrites the progress information relating to attachment # creation. With a setting of 2, attachment creation information # is listed individually with the number of the message the # attachments relate to. This is written to stdout. progress = 0 # Set this to On to show the article header lines in the archived HTML # files. These lines typically include the To:, From:, and Subject: # information found in most email messages. showheaders = Off # Set this to 1 to show the articles in a proportionally-spaced # font rather than a fixed-width (monospace) font. # Set this to 2 for more complex conversion to html # similar to that in
txt2html.pl. # Showhtml = 2 will normally produce nicer looking results than # showhtml = 1, and showhtml = 0 will look pretty dull, but # 1 and 2 run risks of altering the appearance in undesired ways. showhtml = 1 # Set this to On to place
tags at the end of article lines. # Otherwise, all non-quoted article lines will word wrap. This # only takes effect if hm_showhtml is 1. showbr = On # Set this to On to place horizontal rules before and after articles. showhr = On # Set this to On to show all replies to a message as links # in article files. showreplies = Off # Set this to 1 to put the individual message links at the top # of the individual message pages. Set this to 0 to produce pages # without the Next, Previous, Reply, In-Reply-To, etc. links. Set # it to 3 to produce those links only at the top of the message # pages, or 4 to produce those links only at the bottom of the # message. show_msg_links = 1 # Set this to 1 to show links to index pages from the top and # bottom of each message file. Set it to 0 to avoid those links. # Set it to 3 to show the links only at the top of the message # pages, or 4 to produce those links only at the bottom of the # message. show_index_links = 1 # Setting this variable to On will tell Hypermail to generate # an index menu at the top and bottom of each page in a table # format. Set to Off if you want the standard Hypermail page look # and feel usetable = On # Setting this variable to On will tell Hypermail to generate # message index Subject/Author/Date listings using a nice table # format. Set to Off if you want the original Hypermail index look. indextable = Off # Set this to On to italicize quoted lines. iquotes = On # Set this to On to display article received dates with # days before months instead of months before days. eurodate = Off # Set this to On to display article received dates in # YYYY-MM-DD HH:MM:SS format. If used with the gmtime option, a # Z will be inserted between the DD and HH. isodate = Off # Set this to On to display article received dates using # Greenwich Mean Time (UTC) rather than local time. gmtime = Off # Set this to Off to accept messages with a Message-ID matching # that of a message already in this archive. # By default such messages are discarded. discard_dup_msgids = On # Set this to Off to accept messages without a Message-ID header. # By default such messages are discarded. require_msgids = On # Set this to On to store the content type of a MIME attachment in # a metadata file. usemeta = Off # Set this to On to use hypermail's internal locking mechanism. uselock = On # Set this to On to use gdbm to implement a header cache. # This will speed up hypermail, especially if your filesystem is slow. # It will not provide any speedup with the linkquotes option. usegdbm = Off # Set this to On to let hypermail write an XML archive overview file # in each directory. The filename is archive_overview.haof. writehaof = Off # Set this to On to maintain a parallel mbox archive. The file # name defaults to mbox in the directory specified by -d or dir. append = Off # Specifies the filename to be used by the append option. # $DIR may be used to specify a name relative to the directory # specified in the -d or dir option. # append_filename = $DIR/INBOX append_filename = # Set this to On to generate filenames that are not sequential, but # rather a hash of the message properties. # (This particular binary has been build with LIBFNV disabled. # This option won't work) nonsequential = Off # This specifies the number of thread levels to outline # in the thread index. thrdlevels = 4 # This is an octal number representing the permissions # that new directories are set to when they are created. dirmode = 0755 # This is an octal number representing the file permissions # that new files are set to when they are created. filemode = 0644 # This specifies the mail command to use when converting # email addresses to links. The variables $TO, $SUBJECT, # and $ID can be used in constructing the command string. #mailcommand = mailto:$TO?Subject=$SUBJECT mailcommand = mailto:$TO?subject=$SUBJECT&replyto=$ID # The address of the contact point that is put in the HTML header # line . Setting this to NONE # disables header generation. mailto = webmaster@hypermail.org # Set this to the list's submission address. hmail = hypermail@hypermail.org # This specifies the mail command to use when converting the # set_hmail address to links in replies. The variables $TO, $SUBJECT, # and $ID can be used in constructing the command string. newmsg_command = mailto:$TO # This specifies the mail command to use when converting the # set_hmail address to links in replies. The variables $TO, $SUBJECT, # and $ID can be used in constructing the command string. The value # from mailcommand will be used if this option is not specified. replymsg_command = mailto:$TO?Subject=$SUBJECT # Set this to the domainname you want added to a mail address # appearing in the RFC822 field which lack a hostname. # domainaddr = NONE domainaddr = hypermail.org # This obsolete entry kept around to help warn users with old config files. body = # Specifies a URL to an external CSS stylesheet for the index pages. # The CSS will be associated to the indexes thru an HTML LINK element. icss_url = # Specifies a URL to an external CSS stylesheet for the message pages. # The CSS will be associated to the indexes thru an HTML LINK element. mcss_url = # This is a list of MIME types that you want hypermail to treat # exactly as if they were text/plain. #text_types = message/DELIVERY-STATUS text_types = # This is the list of MIME types that you want tags to as # opposed to simply to from the message. inline_types = image/gif image/jpeg image/png # When mails using multipart/mixed types are scanned, this list of # MIME types defines which part you want presented in the result. # See the save_alts option for how non prefered types are treated. prefered_types = text/plain text/html # This is the list of MIME attachment types that you do not want # to do anything with. Two special types may be used here: # $BINARY - ignore all types that would be stored as separate files. # $NONPLAIN - ignore all types not treated as text/plain, and all $BINARY types. # Note: the behavior of these may be affected by the inlinehtml option. ignore_types = text/x-vcard ignore_types = application/x-msdownload # This is the list of headers to be displayed if 'showheaders' # is set to On). They can be listed comma or space separated # all on a single line. # show_headers = # show_headers = * show_headers = From,Subject,Date,Message-ID # Define path as the path to a template file containing # valid HTML formatting statements that you wish to # included at the top of every index page. ihtmlheaderfile = /usr/local/lib/hypermail/hypermail-index.hyp # Define path as the path to a template file containing # valid HTML formatting statements that you wish to # included at the bottom of every index page. ihtmlfooterfile = /usr/local/lib/hypermail/hypermail-footer.hyp # Define path as the path to a template file containing # valid HTML formatting statements that you wish to use # at the top of every message page. mhtmlheaderfile = /usr/local/lib/hypermail/hypermail-msg.hyp # Define path as the path to a template file containing # valid HTML formatting statements you wish to use at the # bottom of every message page. mhtmlfooterfile = /usr/local/lib/hypermail/hypermail-footer.hyp # Specify number of seconds to wait for a lock before we # override it! . locktime = 3600 # Format (see strftime(3)) for displaying dates. # dateformat = %Y/%m/%d - %H:%M %Z dateformat = # A word to be stripped from all subject lines. Helps unclutter # mailing lists which add tags to subject lines. stripsubject = "[hypermail]" # Format of the attachment links. # %p for the full path to the attachment # %f for the file name part only # %d for the directory name only # %n for the message number # %c for the content type string attachmentlink = # Set this to On to make hypermail not output real email addresses # in the output HTML but instead it will obfuscate them a little. # You can control the obfuscation with set_antispamdomain. spamprotect = Off # By default hypermail only does a small amount of massaging # of email addresses. Use this to completely replace the domain # from which a message originates (everything after the @) # with some string to confuse screen-scraping programs. # It is probably wise to make this an invalid mail domain. # antispamdomain = #correctly ignored # antispamdomain = "" #leaves quote marks in the url # antispamdomain = " " #works, leaves a space in the url # antispamdomain = "email_protected" #works # antispamdomain = "email.domain.hidden" #works antispamdomain = # Set this to On to make hypermail not output real email message # ids in HTML comments (sometimes used internally by hypermail) but # instead it will obfuscate them a little so they don't look like # email addresses to spammers. spamprotect_id = Off # Set this to Off to make hypermail not output an index of # messages with attachments. attachmentsindex = On # Set this to On to create fine-grained links from quoted # text to the text where the quote originated. It also improves # the threads index file by more accurately matching messages # with replies. Note that this may be rather cpu intensive (see # the searchbackmsgnum option to alter the performance). linkquotes = Off # If the linkquotes option is on and an incremental update is being# done (-u option), this controls the tradeoff between speed and # the reliability of finding the right source for quoted text. # Try to set it to the largest number of messages between a # message and the final direct reply to that message. searchbackmsgnum = 500 # If the linkquotes option is on, specifying a string here # causes it to generate links from original quoted text to the # location(s) in replies which quote them. The string # is used to display the link. #link_to_replies = Reply link_to_replies = # If the linkquotes option is on, setting this to an # integer less than 100 will cause it to replace quoted # text with one-line links if the percent of lines in the # message body (exluding the signature) consisting of # quoted text exceeds the number indicated by this option. quote_hide_threshold = 100 # If the quote_hide_threshold option is being used, the # quote_link_string will be used if available to display the # link that replaces the quoted text. If no string is specified # here, the first line of each section of quoted text will used. # quote_link_string = Link quote_link_string = # Set this to On to create additional index files broken up # by month. A summary.html file will provide links to all the # monthly indices. monthly_index = Off # Set this to On to create additional index files broken up # by year. A summary.html file will provide links to all the # yearly indices. yearly_index = Off # If nonzero, break the threads index file into multiple files, # with the initial message of each thread in the main index file # along with links to files containing the replies. Setting this # to 1 creates one file for each thread that has replies, and is # recommended for archives with over a few hundred messages. # Setting this greater than 1 will produce multiple levels of files # for each thread whose replies are nested by more than 1 level, # but that is rarely useful. This option is currently disabled # if the indextable option is turned on, and probably needs to # be less than thrdlevels. thread_file_depth = 0 # This string causes the messages to be put in subdirectories # by date. The string will be passed to strftime(3) to generate # subdirectory names based on message dates. Suggested values are # "%y%m" or "%b%y" for monthly subdirectories, "%Y" for # yearly, "%G/%V" for weekly. Do not alter this for an existing # archive without removing the old html files. If you use this # and update the archive incrementally (e.g. with -u), you must # use the usegdbm option. #folder_by_date = %y%m folder_by_date = # Put messages in subdirectories with this many messages per # directory. Do not use this and folder_by_date on the same archive. # Do not alter this for an existing archive without removing the old # html files. Deleted/expired messages ARE COUNTED for the purpose # of deciding how many messages to put in a subdirectory. msgsperfolder = 0 # Controls the labels used in folders.html to describe the # directories created by the folder_by_date or msgsperfolder # options. For folder_by_date labels, the describe_folder string # will be passed to strftime(3) the same as the folder_by_date string. # For msgsperfolder: # %d for the directory number (starts with 0) # %D for the directory number (starts with 1) # %m for the number of the first message in the directory # %M for the number of the last message that can be put in the # directory. # describe_folder = "%b %Y" describe_folder = # If folder_by_date or msgsperfolder are in use, create # a symbolic link by this name to the most recently created # subdirectory. Note that many web servers are configured to # not follow symbolic links for security reasons. # latest_folder = current latest_folder = # The url of the archive's main directory. This is needed when # the latest_folder option is used and the folder_by_date makes # directories more than one level deep (e.g. with '%y/%m'). #base_url = http://www.hypermail.org/mail-archive/ base_url = # Set this to On to support ISO-2022-JP messages. iso2022jp = Off # This is the list of headers that indicate the message should # not be displayed if the value of this header is 'yes'. deleted = X-Hypermail-Deleted X-No-Archive # This is the list of headers that indicate the message should # not be displayed if the value of this header is a date in the past. expires = Expires # Any message older than this date should not be displayed. #delete_older = "Wed, 14 Mar 2001 12:59:51 +0200" delete_older = # Any message newer than this date should not be displayed. #delete_newer = "Wed, 28 Mar 2001 12:59:51 +0200" delete_newer = # This is the list of message numbers that should be deleted from the # html archive. The mbox is not changed. #delete_msgnum = 0 42 649 delete_msgnum = # 0 - remove deleted and expired files. Note that with this choice # threading may be screwed up if there are replies to deleted or # expired options and the archive is updated incrementally # 1 - remove message body # 2 - remove message body for deleted messages, leave expired messages # 3 - leave all messages # Deleted and expired messages are removed from the index files # regardless of the delete_level selection. delete_level = 1 # If you want the original mail messages archived in individual files, # set this to the extension that you want these messages to have # (recommended value: txt). # txtsuffix = txt txtsuffix = # Delete from the html archives any message having a header line # which matches any of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_out=From:.+@spammers.com filter_out = # Delete from the html archives any message not having header lines # which match each of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_require = hypermail filter_require = # Delete from the html archives any message having a line # which matches any of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_out_full_body = BUY filter_out_full_body = # Delete from the html archives any message not having lines # which match each of these expressions. Uses the same rules for # deletion as the expires option. The expressions use the same # syntax as Perl regular expressions. #filter_require_full_body = [Ff]ree filter_require_full_body = # This controls what happens to alternatives (other than the prefered # alternative) for multipart/alternative messages. # 0 - discard non-prefered alternatives # 1 - show all alternatives inline # 2 - put non-prefered alternatives in a separate file. save_alts = 0 # If save_alts is 1, this text is put between the alternatives. # If save_alts is 2, this text is used to describe the link to each # alternative file. alts_text = "alternate version of message" # Set this to On to get warnings (on stdout) about messages that # are not converted because of they are missing a msgid (if # require_msgids is On) or because one of the following options # suppressed it: deleted expires delete_msgnum filter_out # filter_require filter_out_full_body filter_require_full_body. warn_suppressions = On # Any characters listed in this string are removed from user-specified # attachment filenames. Those characters will be replaced by a "_" # (which means that specifying "_" here won't have any effect). # Note that many characters (including / and \) are removed by the # safe_filename in parse.c regardless of what this option says. There # might be some security problems that can be prevented if you specify # "." here (e.g. if a web server is configured to enable server side # includes on filenames ending in something other than .shtml), but # that will prevent browsers from recognizing many file types. unsafe_chars = "." # Set this to On to generate (in addition to the usual files), # a file for each thread that contains all the messages in that # thread. files_by_thread = Off ================================================ FILE: configure ================================================ #! /bin/sh # From configure.ac Revision: 1.2 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" as_awk_strverscmp=' # Use only awk features that work with 7th edition Unix awk (1978). # My, what an old awk you have, Mr. Solaris! END { while (length(v1) && length(v2)) { # Set d1 to be the next thing to compare from v1, and likewise for d2. # Normally this is a single character, but if v1 and v2 contain digits, # compare them as integers and fractions as strverscmp does. if (v1 ~ /^[0-9]/ && v2 ~ /^[0-9]/) { # Split v1 and v2 into their leading digit string components d1 and d2, # and advance v1 and v2 past the leading digit strings. for (len1 = 1; substr(v1, len1 + 1) ~ /^[0-9]/; len1++) continue for (len2 = 1; substr(v2, len2 + 1) ~ /^[0-9]/; len2++) continue d1 = substr(v1, 1, len1); v1 = substr(v1, len1 + 1) d2 = substr(v2, 1, len2); v2 = substr(v2, len2 + 1) if (d1 ~ /^0/) { if (d2 ~ /^0/) { # Compare two fractions. while (d1 ~ /^0/ && d2 ~ /^0/) { d1 = substr(d1, 2); len1-- d2 = substr(d2, 2); len2-- } if (len1 != len2 && ! (len1 && len2 && substr(d1, 1, 1) == substr(d2, 1, 1))) { # The two components differ in length, and the common prefix # contains only leading zeros. Consider the longer to be less. d1 = -len1 d2 = -len2 } else { # Otherwise, compare as strings. d1 = "x" d1 d2 = "x" d2 } } else { # A fraction is less than an integer. exit 1 } } else { if (d2 ~ /^0/) { # An integer is greater than a fraction. exit 2 } else { # Compare two integers. d1 += 0 d2 += 0 } } } else { # The normal case, without worrying about digits. d1 = substr(v1, 1, 1); v1 = substr(v1, 2) d2 = substr(v2, 1, 1); v2 = substr(v2, 2) } if (d1 < d2) exit 1 if (d1 > d2) exit 2 } # Beware Solaris /usr/xgp4/bin/awk (at least through Solaris 10), # which mishandles some comparisons of empty strings to integers. if (length(v2)) exit 1 if (length(v1)) exit 2 } ' test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="src/hypermail.c" ac_default_prefix=/usr/local enable_option_checking=no # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS INCLUDES EXTRA_LIBS HAVE_STRERROR HAVE_MEMMOVE FNV_DEP PCRE_DEP PCRE_CONFIG TRIO_DEP EGREP GREP domainaddr defaultindex htmlsuffix language cgidir httpddir suffix INSTALL RANLIB AR SET_MAKE LN_S INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM YACC_CHECK YFLAGS YACC CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_warnings with_httpddir with_cgidir with_htmldir with_language with_htmlsuffix enable_defaultindex with_domainaddr with_gdbm enable_i18n enable_system_libtrio enable_bundled_pcre with_external_pcre enable_libfnv ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP YACC YFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-warnings Enable -Wall if using gcc. --enable-defaultindex=type Default index page type thread --disable-i18n Disable I18N support --enable-system-libtrio Use the system libtrio instead of compiling the bundled one --enable-bundled-pcre Force the use of the bundled PCRE library instead of the system one --enable-libfnv use the fnv hash library for generating non-sequential filenames [no] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-httpddir=DIR webserver's root directory /usr/local/apache --with-cgidir=DIR where to install CGI scripts --with-htmldir=DIR where to install Hypermail HTML pages --with-language=xx two character language indicator en --with-htmlsuffix=xx two character language indicator html --with-domainaddr=YOURDOMAIN domain address of local domain --with-gdbm=DIR Include GDBM support --with-external-pcre=PATH_TO_PCRE_DIR|PATH_TO_PCRE_CONFIG_SCRIPT Use an external PCRE library instead of the system or the bundled one Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor YACC The `Yet Another Compiler Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" LDFLAGS="" LIBS="" EXTRA_LIBS="" INCLUDES="" CPPFLAGS="" GDBM_INCLUDE="" GDBM_LIB="" FNV_DEP="" TRIO_DEP="" PCRE_DEP="" PCRE_MIN_VERSION="8.39" ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- { $as_echo "$as_me:${as_lineno-$LINENO}: checking cached information" >&5 $as_echo_n "checking cached information... " >&6; } hostcheck="$host" if ${ac_cv_hostcheck+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_hostcheck="$hostcheck" fi if test "$ac_cv_hostcheck" != "$hostcheck"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: changed" >&5 $as_echo "changed" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: config.cache exists!" >&5 $as_echo "$as_me: WARNING: config.cache exists!" >&2;} as_fn_error $? "you must do 'make clobber' first to compile for different host or different parameters." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_YACC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_YACC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" # Extract the first word of "$YACC", so it can be a program name with args. set dummy $YACC; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_YACC_CHECK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC_CHECK"; then ac_cv_prog_YACC_CHECK="$YACC_CHECK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_YACC_CHECK="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC_CHECK=$ac_cv_prog_YACC_CHECK if test -n "$YACC_CHECK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC_CHECK" >&5 $as_echo "$YACC_CHECK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$YACC_CHECK" != x"yes"; then : as_fn_error $? "Please install either bison or yacc and run configure again" "$LINENO" 5 fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="echo" fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$no_ranlib"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi else RANLIB=":" fi INSTALL="install-sh" case "$host" in *-*-solaris*) # Solaris flags $as_echo "#define NO_MACRO 1" >>confdefs.h ;; *-*-hpux*) # HPUX flags if test -z "$GCC"; then CFLAGS="$CFLAGS -Ae" fi ;; *-dec-osf*) # DEC OSF flags CFLAGS="$CFLAGS -mieee" INSTALL="install-sh" ;; esac export CFLAGS CC { $as_echo "$as_me:${as_lineno-$LINENO}: checking that the compiler works" >&5 $as_echo_n "checking that the compiler works... " >&6; } if test "$cross_compiling" = yes; then : as_fn_error $? "Could not compile and run even a trivial ANSI C program - check CC." "$LINENO" 5 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ main(int ac, char **av) { return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Could not compile and run even a trivial ANSI C program - check CC." "$LINENO" 5 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi case "$build" in *-*-cygwin*) suffix=.exe ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable -Wall" >&5 $as_echo_n "checking whether to enable -Wall... " >&6; } # Check whether --enable-warnings was given. if test "${enable_warnings+set}" = set; then : enableval=$enable_warnings; if test -n "$GCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: adding -Wall to CFLAGS." >&5 $as_echo "adding -Wall to CFLAGS." >&6; } CFLAGS="$CFLAGS -Wall" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-httpddir was given. if test "${with_httpddir+set}" = set; then : withval=$with_httpddir; httpddir=$with_httpddir else httpddir=/usr/local/apache fi # Check whether --with-cgidir was given. if test "${with_cgidir+set}" = set; then : withval=$with_cgidir; cgidir=$with_cgidir else cgidir=$httpddir/cgi-bin fi # Check whether --with-htmldir was given. if test "${with_htmldir+set}" = set; then : withval=$with_htmldir; htmldir=$with_htmldir else htmldir=$httpddir/htdocs/hypermail fi # Check whether --with-language was given. if test "${with_language+set}" = set; then : withval=$with_language; language=$with_language else language=en fi # Check whether --with-htmlsuffix was given. if test "${with_htmlsuffix+set}" = set; then : withval=$with_htmlsuffix; htmlsuffix=$with_htmlsuffix else htmlsuffix=html fi # Check whether --enable-defaultindex was given. if test "${enable_defaultindex+set}" = set; then : enableval=$enable_defaultindex; defaultindex=$enableval else defaultindex="thread" fi # Check whether --with-domainaddr was given. if test "${with_domainaddr+set}" = set; then : withval=$with_domainaddr; domainaddr=$with_domainaddr else domainaddr=NONE fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in alloca.h arpa/inet.h ctype.h dirent.h errno.h \ fcntl.h locale.h malloc.h netdb.h netinet/in.h pwd.h stdarg.h \ stdio.h stdlib.h string.h sys/dir.h sys/param.h sys/socket.h \ sys/stat.h sys/time.h sys/types.h time.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat file-mode macros are broken" >&5 $as_echo_n "checking whether stat file-mode macros are broken... " >&6; } if ${ac_cv_header_stat_broken+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if defined S_ISBLK && defined S_IFDIR extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1]; #endif #if defined S_ISBLK && defined S_IFCHR extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1]; #endif #if defined S_ISLNK && defined S_IFREG extern char c3[S_ISLNK (S_IFREG) ? -1 : 1]; #endif #if defined S_ISSOCK && defined S_IFREG extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1]; #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stat_broken=no else ac_cv_header_stat_broken=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stat_broken" >&5 $as_echo "$ac_cv_header_stat_broken" >&6; } if test $ac_cv_header_stat_broken = yes; then $as_echo "#define STAT_MACROS_BROKEN 1" >>confdefs.h fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRFTIME 1 _ACEOF else # strftime is in -lintl on SCO UNIX. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 $as_echo_n "checking for strftime in -lintl... " >&6; } if ${ac_cv_lib_intl_strftime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strftime (); int main () { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_strftime=yes else ac_cv_lib_intl_strftime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 $as_echo "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes; then : $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done for ac_func in mkdir strdup strstr strtol memcpy memset lstat strcasecmp \ strcasestr getpwuid getopt snprintf memmove strerror do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi if test $ac_cv_func_snprintf != no; then $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h fi # Check whether --with-gdbm was given. if test "${with_gdbm+set}" = set; then : withval=$with_gdbm; given_gdbm=$withval fi if test "$given_gdbm" != "no"; then for i in /usr/local /usr $withval; do if test -f "$i/include/gdbm.h"; then GDBM_INCLUDE="$i/include" THIS_PREFIX="$i" fi done unset ac_cv_lib_gdbm_gdbm_open old_LDFLAGS="$LDFLAGS" LDFLAGS="-L$THIS_PREFIX/lib $LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdbm_open in -lgdbm" >&5 $as_echo_n "checking for gdbm_open in -lgdbm... " >&6; } if ${ac_cv_lib_gdbm_gdbm_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdbm_open (); int main () { return gdbm_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gdbm_gdbm_open=yes else ac_cv_lib_gdbm_gdbm_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_gdbm_open" >&5 $as_echo "$ac_cv_lib_gdbm_gdbm_open" >&6; } if test "x$ac_cv_lib_gdbm_gdbm_open" = xyes; then : GDBM_LIB="-lgdbm" fi LDFLAGS="$old_LDFLAGS" if test "$THIS_PREFIX" != "" && test "$THIS_PREFIX" != "/usr"; then THIS_LFLAGS="$THIS_PREFIX/lib" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GDBM support" >&5 $as_echo_n "checking for GDBM support... " >&6; } if test "$GDBM_LIB" = "" && test "$given_gdbm" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdbm_open in -lgdbm" >&5 $as_echo_n "checking for gdbm_open in -lgdbm... " >&6; } if ${ac_cv_lib_gdbm_gdbm_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gdbm_open (); int main () { return gdbm_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gdbm_gdbm_open=yes else ac_cv_lib_gdbm_gdbm_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_gdbm_open" >&5 $as_echo "$ac_cv_lib_gdbm_gdbm_open" >&6; } if test "x$ac_cv_lib_gdbm_gdbm_open" = xyes; then : $as_echo "#define GDBM 1" >>confdefs.h DBM_TYPE=gdbm; GDBM_LIB=-lgdbm else DBM_TYPE="" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking gdbm library" >&5 $as_echo_n "checking gdbm library... " >&6; } if test "a$DBM_TYPE" = a; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: none found" >&5 $as_echo "none found" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No gdbm library found - will limit a few features" >&5 $as_echo "$as_me: WARNING: No gdbm library found - will limit a few features" >&2;} else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DBM_TYPE found" >&5 $as_echo "$DBM_TYPE found" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$GDBM_LIB" = "-lgdbm" && test "$GDBM_INCLUDE" = ""; then ac_fn_c_check_header_mongrel "$LINENO" "gdbm.h" "ac_cv_header_gdbm_h" "$ac_includes_default" if test "x$ac_cv_header_gdbm_h" = xyes; then : GDBM_INCLUDE="" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Try /usr/local/include/gdbm.h" >&5 $as_echo "Try /usr/local/include/gdbm.h" >&6; } ac_fn_c_check_header_mongrel "$LINENO" "/usr/local/include/gdbm.h" "ac_cv_header__usr_local_include_gdbm_h" "$ac_includes_default" if test "x$ac_cv_header__usr_local_include_gdbm_h" = xyes; then : GDBM_INCLUDE="-I/usr/local/include" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Try /opt/local/include/gdbm.h" >&5 $as_echo "Try /opt/local/include/gdbm.h" >&6; } ac_fn_c_check_header_mongrel "$LINENO" "/opt/local/include/gdbm.h" "ac_cv_header__opt_local_include_gdbm_h" "$ac_includes_default" if test "x$ac_cv_header__opt_local_include_gdbm_h" = xyes; then : GDBM_INCLUDE="-I/opt/local/include" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Try /usr/pkg/include/gdbm.h" >&5 $as_echo "Try /usr/pkg/include/gdbm.h" >&6; } ac_fn_c_check_header_mongrel "$LINENO" "/usr/pkg/include/gdbm.h" "ac_cv_header__usr_pkg_include_gdbm_h" "$ac_includes_default" if test "x$ac_cv_header__usr_pkg_include_gdbm_h" = xyes; then : GDBM_INCLUDE="" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Giving up - You need to install gdbm.h somewhere" >&5 $as_echo "Giving up - You need to install gdbm.h somewhere" >&6; } exit fi fi fi fi fi if test -n "$GDBM_LIB"; then if test "$GDBM_INCLUDE" != "/usr/include"; then if test -z "$GDBM_INCLUDE" || echo "$GDBM_INCLUDE" | grep '^/' >/dev/null ; then ai_p="$GDBM_INCLUDE" else ep_dir="`echo $GDBM_INCLUDE|sed 's%/*[^/][^/]*/*$%%'`" ep_realdir="`(cd \"$ep_dir\" && pwd)`" ai_p="$ep_realdir/`basename \"$GDBM_INCLUDE\"`" fi unique=`echo $ai_p|sed 's/[^a-zA-Z0-9]/_/g'` cmd="echo $ac_n \"\$INCLUDEPATH$unique$ac_c\"" if test -n "$unique" && test "`eval $cmd`" = "" ; then eval "INCLUDEPATH$unique=set" INCLUDES="$INCLUDES -I$ai_p" fi fi $as_echo "#define HAVE_GDBM_H 1" >>confdefs.h EXTRA_LIBS="$EXTRA_LIBS $GDBM_LIB" fi # Check whether --enable-i18n was given. if test "${enable_i18n+set}" = set; then : enableval=$enable_i18n; given_iconv=$enableval fi if test "$given_iconv" = "no"; then echo "disabled I18N support." else for ac_func in iconv do : ac_fn_c_check_func "$LINENO" "iconv" "ac_cv_func_iconv" if test "x$ac_cv_func_iconv" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ICONV 1 _ACEOF fi done for ac_header in iconv.h do : ac_fn_c_check_header_mongrel "$LINENO" "iconv.h" "ac_cv_header_iconv_h" "$ac_includes_default" if test "x$ac_cv_header_iconv_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ICONV_H 1 _ACEOF fi done fi # Check whether --enable-system_libtrio was given. if test "${enable_system_libtrio+set}" = set; then : enableval=$enable_system_libtrio; fi if test "${enable_system_libtrio}" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for system libtrio" >&5 $as_echo "$as_me: checking for system libtrio" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing trio_printf" >&5 $as_echo_n "checking for library containing trio_printf... " >&6; } if ${ac_cv_search_trio_printf+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char trio_printf (); int main () { return trio_printf (); ; return 0; } _ACEOF for ac_lib in '' trio; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_trio_printf=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_trio_printf+:} false; then : break fi done if ${ac_cv_search_trio_printf+:} false; then : else ac_cv_search_trio_printf=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_trio_printf" >&5 $as_echo "$ac_cv_search_trio_printf" >&6; } ac_res=$ac_cv_search_trio_printf if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "unable to find trio_copy() function" "$LINENO" 5 fi ac_fn_c_check_header_mongrel "$LINENO" "trio.h" "ac_cv_header_trio_h" "$ac_includes_default" if test "x$ac_cv_header_trio_h" = xyes; then : else as_fn_error $? "unable to find trio.h header file (dev version not installed?)" "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: using bundled libtrio" >&5 $as_echo "$as_me: using bundled libtrio" >&6;} if test "x$INCLUDES" = "x"; then test "x$silent" != "xyes" && echo " setting INCLUDES to \""-Itrio"\"" INCLUDES=""-Itrio"" else apr_addto_bugger=""-Itrio"" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $INCLUDES; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to INCLUDES" INCLUDES="$INCLUDES $i" fi done fi if test "x$LDFLAGS" = "x"; then test "x$silent" != "xyes" && echo " setting LDFLAGS to \""-Ltrio"\"" LDFLAGS=""-Ltrio"" else apr_addto_bugger=""-Ltrio"" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $LDFLAGS; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" LDFLAGS="$LDFLAGS $i" fi done fi if test "x$CPPFLAGS" = "x"; then test "x$silent" != "xyes" && echo " setting CPPFLAGS to \""-DTRIO_MINIMAL"\"" CPPFLAGS=""-DTRIO_MINIMAL"" else apr_addto_bugger=""-DTRIO_MINIMAL"" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $CPPFLAGS; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to CPPFLAGS" CPPFLAGS="$CPPFLAGS $i" fi done fi TRIO_DEP="trio/libtrio.a" # save our work to this point; this allows the sub-package to use it cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache echo "configuring package in src/trio now" ac_popdir=`pwd` apr_config_subdirs="src/trio" test -d src/trio || $mkdir_p src/trio ac_abs_srcdir=`(cd $srcdir/src/trio && pwd)` cd src/trio # A "../" for each directory in /$config_subdirs. ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` # Make the cache file pathname absolute for the subdirs # required to correctly handle subdirs that might actually # be symlinks case "$cache_file" in /*) # already absolute ac_sub_cache_file=$cache_file ;; *) # Was relative path. ac_sub_cache_file="$ac_popdir/$cache_file" ;; esac apr_configure_args= apr_sep= for apr_configure_arg in $ac_configure_args do case "$apr_configure_arg" in --with-pcre=*|\'--with-pcre=*) continue ;; esac apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" apr_sep=" " done test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" apr_configure_args="--disable-option-checking $apr_configure_args" if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir CFLAGS=-DTRIO_MINIMAL then : echo "src/trio configured properly" else echo "configure failed for src/trio" exit 1 fi cd $ac_popdir # grab any updates from the sub-package if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi fi # Check whether --enable-bundled_pcre was given. if test "${enable_bundled_pcre+set}" = set; then : enableval=$enable_bundled_pcre; fi # Check whether --with-external_pcre was given. if test "${with_external_pcre+set}" = set; then : withval=$with_external_pcre; fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PCRE regular expressions library" >&5 $as_echo "$as_me: checking for PCRE regular expressions library" >&6;} if test ! -z ${enable_bundled_pcre}; then with_external_pcre="" fi case $with_external_pcre in /*) { $as_echo "$as_me:${as_lineno-$LINENO}: --with-external-pcre => checking for an external libpcre" >&5 $as_echo "$as_me: --with-external-pcre => checking for an external libpcre" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre-config" >&5 $as_echo_n "checking for pcre-config... " >&6; } if test -d "$with_external_pcre" && test -x "$with_external_pcre/pcre-config"; then PCRE_CONFIG=$with_external_pcre/pcre-config elif test -x "$with_external_pcre"; then PCRE_CONFIG=$with_external_pcre else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "${PCRE_CONFIG} does not point to a directory or pcre-config" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${PCRE_CONFIG}" >&5 $as_echo "${PCRE_CONFIG}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre version equal or greater than ${PCRE_MIN_VERSION}" >&5 $as_echo_n "checking for pcre version equal or greater than ${PCRE_MIN_VERSION}... " >&6; } if test -f "${PCRE_CONFIG}" && test -x "${PCRE_CONFIG}"; then PCRE_VERSION=$(${PCRE_CONFIG} --version) as_arg_v1="${PCRE_VERSION}" as_arg_v2="${PCRE_MIN_VERSION}" awk "$as_awk_strverscmp" v1="$as_arg_v1" v2="$as_arg_v2" /dev/null case $? in #( 1) : PCRE_CONFIG=false ;; #( 0) : ;; #( 2) : ;; #( *) : ;; esac if test "${PCRE_CONFIG}" != false; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "the PCRE library version must be equal or greater than ${PCRE_MIN_VERSION}" "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "${PCRE_CONFIG} does not point to a script" "$LINENO" 5 fi ;; *) PCRE_CONFIG=false ;; esac if test -z "${enable_bundled_pcre}" && test -z "${PCRE_CONFIG}" -o "${PCRE_CONFIG}" = "false"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a system libpcre" >&5 $as_echo "$as_me: checking for a system libpcre" >&6;} # Extract the first word of "pcre-config", so it can be a program name with args. set dummy pcre-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PCRE_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PCRE_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PCRE_CONFIG="$PCRE_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PCRE_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PCRE_CONFIG=$ac_cv_path_PCRE_CONFIG if test -n "$PCRE_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PCRE_CONFIG" >&5 $as_echo "$PCRE_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test ! -z "${PCRE_CONFIG}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking checking pcre version equal or greater than ${PCRE_MIN_VERSION}" >&5 $as_echo_n "checking checking pcre version equal or greater than ${PCRE_MIN_VERSION}... " >&6; } PCRE_VERSION=$(${PCRE_CONFIG} --version) as_arg_v1="${PCRE_VERSION}" as_arg_v2="${PCRE_MIN_VERSION}" awk "$as_awk_strverscmp" v1="$as_arg_v1" v2="$as_arg_v2" /dev/null case $? in #( 1) : PCRE_CONFIG=false ;; #( 0) : ;; #( 2) : ;; #( *) : ;; esac if test "${PCRE_CONFIG}" != false; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else PCRE_CONFIG=false fi fi if test "${PCRE_CONFIG}" != false; then PCRE_PATH=$(${PCRE_CONFIG} --prefix) as_ac_Header=`$as_echo "ac_cv_header_"$PCRE_PATH/include/pcre.h"" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" ""$PCRE_PATH/include/pcre.h"" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : else PCRE_CONFIG=false fi fi if test "$PCRE_CONFIG" != "false"; then { $as_echo "$as_me:${as_lineno-$LINENO}: using system PCRE regular expressions library" >&5 $as_echo "$as_me: using system PCRE regular expressions library" >&6;} if test "x$CFLAGS" = "x"; then test "x$silent" != "xyes" && echo " setting CFLAGS to \"`$PCRE_CONFIG --cflags`\"" CFLAGS="`$PCRE_CONFIG --cflags`" else apr_addto_bugger="`$PCRE_CONFIG --cflags`" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $CFLAGS; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to CFLAGS" CFLAGS="$CFLAGS $i" fi done fi if test "x$LIBS" = "x"; then test "x$silent" != "xyes" && echo " setting LIBS to \"`$PCRE_CONFIG --libs`\"" LIBS="`$PCRE_CONFIG --libs`" else apr_addto_bugger="`$PCRE_CONFIG --libs`" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $LIBS; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to LIBS" LIBS="$LIBS $i" fi done fi else { $as_echo "$as_me:${as_lineno-$LINENO}: using bundled PCRE regular expressions library" >&5 $as_echo "$as_me: using bundled PCRE regular expressions library" >&6;} if test "x$INCLUDES" = "x"; then test "x$silent" != "xyes" && echo " setting INCLUDES to \"-Ipcre\"" INCLUDES="-Ipcre" else apr_addto_bugger="-Ipcre" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $INCLUDES; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to INCLUDES" INCLUDES="$INCLUDES $i" fi done fi if test "x$LDFLAGS" = "x"; then test "x$silent" != "xyes" && echo " setting LDFLAGS to \""-Lpcre/.libs"\"" LDFLAGS=""-Lpcre/.libs"" else apr_addto_bugger=""-Lpcre/.libs"" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $LDFLAGS; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to LDFLAGS" LDFLAGS="$LDFLAGS $i" fi done fi PCRE_DEP="pcre/.libs/libpcre.a" # save our work to this point; this allows the sub-package to use it cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache echo "configuring package in src/pcre now" ac_popdir=`pwd` apr_config_subdirs="src/pcre" test -d src/pcre || $mkdir_p src/pcre ac_abs_srcdir=`(cd $srcdir/src/pcre && pwd)` cd src/pcre # A "../" for each directory in /$config_subdirs. ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` # Make the cache file pathname absolute for the subdirs # required to correctly handle subdirs that might actually # be symlinks case "$cache_file" in /*) # already absolute ac_sub_cache_file=$cache_file ;; *) # Was relative path. ac_sub_cache_file="$ac_popdir/$cache_file" ;; esac apr_configure_args= apr_sep= for apr_configure_arg in $ac_configure_args do case "$apr_configure_arg" in --with-pcre=*|\'--with-pcre=*) continue ;; esac apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" apr_sep=" " done test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" apr_configure_args="--disable-option-checking $apr_configure_args" if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir then : echo "src/pcre configured properly" else echo "configure failed for src/pcre" exit 1 fi cd $ac_popdir # grab any updates from the sub-package if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use fnv hash library for non-sequential filenames" >&5 $as_echo_n "checking whether to use fnv hash library for non-sequential filenames... " >&6; } # Check whether --enable-libfnv was given. if test "${enable_libfnv+set}" = set; then : enableval=$enable_libfnv; given_libfnv=$enableval fi if test "$given_libfnv" != "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBFNV 1" >>confdefs.h if test "x$INCLUDES" = "x"; then test "x$silent" != "xyes" && echo " setting INCLUDES to \"-Ifnv\"" INCLUDES="-Ifnv" else apr_addto_bugger="-Ifnv" for i in $apr_addto_bugger; do apr_addto_duplicate="0" for j in $INCLUDES; do if test "x$i" = "x$j"; then apr_addto_duplicate="1" break fi done if test $apr_addto_duplicate = "0"; then test "x$silent" != "xyes" && echo " adding \"$i\" to INCLUDES" INCLUDES="$INCLUDES $i" fi done fi if test -n "src/fnv"; then if test "src/fnv" != "/usr/lib"; then if test -z "src/fnv" || echo "src/fnv" | grep '^/' >/dev/null ; then ai_p="src/fnv" else ep_dir="`echo src/fnv|sed 's%/*[^/][^/]*/*$%%'`" ep_realdir="`(cd \"$ep_dir\" && pwd)`" ai_p="$ep_realdir/`basename \"src/fnv\"`" fi unique=`echo $ai_p|sed 's/[^a-zA-Z0-9]/_/g'` cmd="echo $ac_n \"\$LIBPATH$unique$ac_c\"" if test -n "$unique" && test "`eval $cmd`" = "" ; then eval "LIBPATH$unique=set" LDFLAGS="$LDFLAGS -L$ai_p" fi fi fi EXTRA_LIBS="$EXTRA_LIBS -lfnv" FNV_DEP="fnv/libfnv.a" # save our work to this point; this allows the sub-package to use it cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache echo "configuring package in src/fnv now" ac_popdir=`pwd` apr_config_subdirs="src/fnv" test -d src/fnv || $mkdir_p src/fnv ac_abs_srcdir=`(cd $srcdir/src/fnv && pwd)` cd src/fnv # A "../" for each directory in /$config_subdirs. ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` # Make the cache file pathname absolute for the subdirs # required to correctly handle subdirs that might actually # be symlinks case "$cache_file" in /*) # already absolute ac_sub_cache_file=$cache_file ;; *) # Was relative path. ac_sub_cache_file="$ac_popdir/$cache_file" ;; esac apr_configure_args=$ac_configure_args test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" apr_configure_args="--disable-option-checking $apr_configure_args" if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir then : echo "src/fnv configured properly" else echo "configure failed for src/fnv" exit 1 fi cd $ac_popdir # grab any updates from the sub-package if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi fi USENSL=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr in -lsocket" >&5 $as_echo_n "checking for gethostbyaddr in -lsocket... " >&6; } if ${ac_cv_lib_socket_gethostbyaddr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyaddr (); int main () { return gethostbyaddr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_gethostbyaddr=yes else ac_cv_lib_socket_gethostbyaddr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyaddr" >&5 $as_echo "$ac_cv_lib_socket_gethostbyaddr" >&6; } if test "x$ac_cv_lib_socket_gethostbyaddr" = xyes; then : result=yes else result=no fi if test $result = yes; then LIBS="$LIBS -lsocket" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr in -lsocket" >&5 $as_echo_n "checking for gethostbyaddr in -lsocket... " >&6; } if ${ac_cv_lib_socket_gethostbyaddr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyaddr (); int main () { return gethostbyaddr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_gethostbyaddr=yes else ac_cv_lib_socket_gethostbyaddr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyaddr" >&5 $as_echo "$ac_cv_lib_socket_gethostbyaddr" >&6; } if test "x$ac_cv_lib_socket_gethostbyaddr" = xyes; then : result=yes else result=no fi if test $result = yes; then LIBS = "$LIBS -lsocket -lnsl" USENSL=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_addr in -lsocket" >&5 $as_echo_n "checking for inet_addr in -lsocket... " >&6; } if ${ac_cv_lib_socket_inet_addr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_addr (); int main () { return inet_addr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_inet_addr=yes else ac_cv_lib_socket_inet_addr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_inet_addr" >&5 $as_echo "$ac_cv_lib_socket_inet_addr" >&6; } if test "x$ac_cv_lib_socket_inet_addr" = xyes; then : result=yes else result=no fi if test $result = yes; then LIBS="$LIBS -lsocket" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_addr in -lsocket" >&5 $as_echo_n "checking for inet_addr in -lsocket... " >&6; } if ${ac_cv_lib_socket_inet_addr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket -lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_addr (); int main () { return inet_addr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_inet_addr=yes else ac_cv_lib_socket_inet_addr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_inet_addr" >&5 $as_echo "$ac_cv_lib_socket_inet_addr" >&6; } if test "x$ac_cv_lib_socket_inet_addr" = xyes; then : result=yes else result=no fi if test $result = yes; then LIBS="$LIBS -lsocket -lnsl" USENSL=yes fi fi fi fi if test $USENSL != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_addr in -lnsl" >&5 $as_echo_n "checking for inet_addr in -lnsl... " >&6; } if ${ac_cv_lib_nsl_inet_addr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_addr (); int main () { return inet_addr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_inet_addr=yes else ac_cv_lib_nsl_inet_addr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_inet_addr" >&5 $as_echo "$ac_cv_lib_nsl_inet_addr" >&6; } if test "x$ac_cv_lib_nsl_inet_addr" = xyes; then : result=yes else result=no fi if test $result = yes; then LIBS="$LIBS -lnsl" fi fi ac_config_files="$ac_config_files Makefile archive/Makefile docs/Makefile libcgi/Makefile src/Makefile tests/testhm src/defaults.h" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "archive/Makefile") CONFIG_FILES="$CONFIG_FILES archive/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "libcgi/Makefile") CONFIG_FILES="$CONFIG_FILES libcgi/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "tests/testhm") CONFIG_FILES="$CONFIG_FILES tests/testhm" ;; "src/defaults.h") CONFIG_FILES="$CONFIG_FILES src/defaults.h" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: configure.ac ================================================ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_REVISION($Revision: 1.2 $)dnl AC_INIT AC_CONFIG_SRCDIR([src/hypermail.c]) AC_CONFIG_HEADER(config.h) AC_PREFIX_DEFAULT(/usr/local) LDFLAGS="" LIBS="" EXTRA_LIBS="" INCLUDES="" CPPFLAGS="" GDBM_INCLUDE="" GDBM_LIB="" FNV_DEP="" TRIO_DEP="" PCRE_DEP="" PCRE_MIN_VERSION="8.39" dnl =========================================================================== dnl Get host, target and build variables filled with appropriate info. dnl =========================================================================== AC_CANONICAL_TARGET dnl =========================================================================== dnl Check to assure the cached information is valid. dnl =========================================================================== AC_MSG_CHECKING(cached information) hostcheck="$host" AC_CACHE_VAL(ac_cv_hostcheck, [ ac_cv_hostcheck="$hostcheck" ]) if test "$ac_cv_hostcheck" != "$hostcheck"; then AC_MSG_RESULT(changed) AC_MSG_WARN(config.cache exists!) AC_MSG_ERROR(you must do 'make clobber' first to compile for different host or different parameters.) else AC_MSG_RESULT(ok) fi dnl =========================================================================== dnl Checks for programs. dnl =========================================================================== AC_PROG_CC AC_PROG_CPP AC_PROG_YACC AC_CHECK_PROG(YACC_CHECK,$YACC,yes) AS_IF([test x"$YACC_CHECK" != x"yes"], [AC_MSG_ERROR([Please install either bison or yacc and run configure again])]) AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_CHECK_PROG(AR, ar, ar, echo) if test -z "$no_ranlib"; then AC_PROG_RANLIB else RANLIB=":" fi dnl =========================================================================== dnl Determine the host type and set compliation flags as needed dnl =========================================================================== INSTALL="install-sh" case "$host" in *-*-solaris*) # Solaris flags AC_DEFINE(NO_MACRO) ;; *-*-hpux*) # HPUX flags if test -z "$GCC"; then CFLAGS="$CFLAGS -Ae" fi ;; *-dec-osf*) # DEC OSF flags CFLAGS="$CFLAGS -mieee" INSTALL="install-sh" ;; esac export CFLAGS CC AC_SUBST(INSTALL) AC_MSG_CHECKING([that the compiler works]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ main(int ac, char **av) { return 0; } ]])],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) AC_MSG_ERROR(Could not compile and run even a trivial ANSI C program - check CC.)],[AC_MSG_ERROR(Could not compile and run even a trivial ANSI C program - check CC.)]) dnl =========================================================================== dnl Determine if building on a Cygwin system so that dnl etc/passwd checks are to be disabled. dnl =========================================================================== case "$build" in *-*-cygwin*) suffix=.exe AC_SUBST(suffix) ;; esac dnl =========================================================================== dnl Accepted arguments to ./configure... dnl =========================================================================== AC_MSG_CHECKING([whether to enable -Wall]) AC_ARG_ENABLE(warnings, [ --enable-warnings Enable -Wall if using gcc.], [ if test -n "$GCC"; then AC_MSG_RESULT(adding -Wall to CFLAGS.) CFLAGS="$CFLAGS -Wall" fi],AC_MSG_RESULT(no)) AC_ARG_WITH(httpddir, [ --with-httpddir=DIR webserver's root directory [/usr/local/apache]], httpddir=$with_httpddir, httpddir=/usr/local/apache) AC_SUBST(httpddir) AC_ARG_WITH(cgidir, [ --with-cgidir=DIR where to install CGI scripts ], cgidir=$with_cgidir, cgidir=$httpddir/cgi-bin) AC_SUBST(cgidir) AC_ARG_WITH(htmldir, [ --with-htmldir=DIR where to install Hypermail HTML pages ], htmldir=$with_htmldir, htmldir=$httpddir/htdocs/hypermail) AC_SUBST(htmldir) AC_ARG_WITH(language, [ --with-language=xx two character language indicator [en] ], language=$with_language, language=en) AC_SUBST(language) AC_ARG_WITH(htmlsuffix, [ --with-htmlsuffix=xx two character language indicator [html] ], htmlsuffix=$with_htmlsuffix, htmlsuffix=html) AC_SUBST(htmlsuffix) AC_ARG_ENABLE(defaultindex, [ --enable-defaultindex=type Default index page type [thread] ], [ defaultindex=$enableval ], [ defaultindex="thread" ]) AC_SUBST(defaultindex) AC_ARG_WITH(domainaddr, [ --with-domainaddr=YOURDOMAIN domain address of local domain ], domainaddr=$with_domainaddr, domainaddr=NONE) AC_SUBST(domainaddr) dnl =========================================================================== dnl Configure the subdirectories dnl dnl These are the subdirs that are compiled systematically dnl For subdirs that can be disabled thru configure options, dnl we configure them in a dedicated section near the test dnl =========================================================================== AC_DISABLE_OPTION_CHECKING dnl =========================================================================== dnl Checks headers dnl =========================================================================== AC_HEADER_STDC AC_CHECK_HEADERS(alloca.h arpa/inet.h ctype.h dirent.h errno.h \ fcntl.h locale.h malloc.h netdb.h netinet/in.h pwd.h stdarg.h \ stdio.h stdlib.h string.h sys/dir.h sys/param.h sys/socket.h \ sys/stat.h sys/time.h sys/types.h time.h unistd.h) AC_HEADER_STAT AC_HEADER_DIRENT AC_HEADER_TIME dnl =========================================================================== dnl Checks for library functions. dnl Check for typedefs, structures, and compiler characteristics. dnl =========================================================================== AC_STRUCT_TM AC_FUNC_STRFTIME AC_CHECK_FUNCS(mkdir strdup strstr strtol memcpy memset lstat strcasecmp \ strcasestr getpwuid getopt snprintf memmove strerror) AC_TYPE_SIZE_T if test $ac_cv_func_snprintf != no; then AC_DEFINE(HAVE_SNPRINTF) fi dnl gdbm checks AC_DEFUN([AC_TEMP_LDFLAGS],[ old_LDFLAGS="$LDFLAGS" LDFLAGS="$1 $LDFLAGS" $2 LDFLAGS="$old_LDFLAGS" ]) dnl dnl AC_HMAIL_ONCE(namespace, variable, code) dnl dnl execute code, if variable is not set in namespace dnl AC_DEFUN([AC_HMAIL_ONCE],[ changequote({,}) unique=`echo $2|sed 's/[^a-zA-Z0-9]/_/g'` changequote([,]) cmd="echo $ac_n \"\$$1$unique$ac_c\"" if test -n "$unique" && test "`eval $cmd`" = "" ; then eval "$1$unique=set" $3 fi ]) dnl dnl AC_EXPAND_PATH(path, variable) dnl dnl expands path to an absolute path and assigns it to variable dnl AC_DEFUN([AC_EXPAND_PATH],[ if test -z "$1" || echo "$1" | grep '^/' >/dev/null ; then $2="$1" else changequote({,}) ep_dir="`echo $1|sed 's%/*[^/][^/]*/*$%%'`" changequote([,]) ep_realdir="`(cd \"$ep_dir\" && pwd)`" $2="$ep_realdir/`basename \"$1\"`" fi ]) AC_DEFUN([AC_ADD_INCLUDE],[ if test "$1" != "/usr/include"; then AC_EXPAND_PATH($1, ai_p) AC_HMAIL_ONCE(INCLUDEPATH, $ai_p, [ INCLUDES="$INCLUDES -I$ai_p" ]) fi ]) dnl dnl AC_ADD_LIBPATH(path[, shared-libadd]) dnl dnl add a library to linkpath dnl AC_DEFUN([AC_ADD_LIBPATH],[ if test "$1" != "/usr/lib"; then AC_EXPAND_PATH($1, ai_p) AC_HMAIL_ONCE(LIBPATH, $ai_p, [ LDFLAGS="$LDFLAGS -L$ai_p" ]) fi ]) dnl dnl AC_ADD_LIBRARY_WITH_PATH(library, path[, shared-libadd]) dnl dnl add a library to the link line and path to linkpath/runpath. dnl if shared-libadd is not empty and $ext_shared is yes, dnl shared-libadd will be assigned the library information dnl AC_DEFUN([AC_ADD_LIBRARY_WITH_PATH],[ ifelse($3,,[ if test -n "$2"; then AC_ADD_LIBPATH($2) fi EXTRA_LIBS="$EXTRA_LIBS $1" ],[ AC_ADD_LIBRARY_WITH_PATH($1,$2) ]) ]) AC_ARG_WITH(gdbm, AS_HELP_STRING([--with-gdbm=[DIR]], [Include GDBM support]), [ given_gdbm=$withval]) if test "$given_gdbm" != "no"; then for i in /usr/local /usr $withval; do if test -f "$i/include/gdbm.h"; then GDBM_INCLUDE="$i/include" THIS_PREFIX="$i" fi done unset ac_cv_lib_gdbm_gdbm_open AC_TEMP_LDFLAGS(-L$THIS_PREFIX/lib,[ AC_CHECK_LIB(gdbm, gdbm_open, [GDBM_LIB="-lgdbm"]) ]) if test "$THIS_PREFIX" != "" && test "$THIS_PREFIX" != "/usr"; then THIS_LFLAGS="$THIS_PREFIX/lib" fi fi AC_MSG_CHECKING(for GDBM support) if test "$GDBM_LIB" = "" && test "$given_gdbm" != "no"; then AC_CHECK_LIB(gdbm, gdbm_open,[AC_DEFINE(GDBM,1, [Whether you have GDBM]) DBM_TYPE=gdbm; GDBM_LIB=-lgdbm], [DBM_TYPE=""]) AC_MSG_CHECKING([gdbm library]) if test "a$DBM_TYPE" = a; then AC_MSG_RESULT(none found) AC_MSG_WARN(No gdbm library found - will limit a few features) else AC_MSG_RESULT($DBM_TYPE found) fi else AC_MSG_RESULT(no) fi if test "$GDBM_LIB" = "-lgdbm" && test "$GDBM_INCLUDE" = ""; then AC_CHECK_HEADER(gdbm.h, [ GDBM_INCLUDE="" ], [ AC_MSG_RESULT(Try /usr/local/include/gdbm.h) AC_CHECK_HEADER(/usr/local/include/gdbm.h, [ GDBM_INCLUDE="-I/usr/local/include" ],[ AC_MSG_RESULT(Try /opt/local/include/gdbm.h) AC_CHECK_HEADER(/opt/local/include/gdbm.h, [ GDBM_INCLUDE="-I/opt/local/include" ],[ dnl if in /usr/pkg/include, do not add anything. See above. AC_MSG_RESULT(Try /usr/pkg/include/gdbm.h) AC_CHECK_HEADER(/usr/pkg/include/gdbm.h, [ GDBM_INCLUDE="" ],[ AC_MSG_RESULT([Giving up - You need to install gdbm.h somewhere]) exit ]) ]) ]) ]) fi if test -n "$GDBM_LIB"; then AC_ADD_INCLUDE($GDBM_INCLUDE) AC_DEFINE(HAVE_GDBM_H) EXTRA_LIBS="$EXTRA_LIBS $GDBM_LIB" fi dnl dnl iconv check dnl AC_ARG_ENABLE(i18n, [ --disable-i18n Disable I18N support], [given_iconv=$enableval]) if test "$given_iconv" = "no"; then echo "disabled I18N support." else AC_CHECK_FUNCS(iconv) AC_CHECK_HEADERS(iconv.h) fi dnl dnl libtrio: select whether to use the system or the bundled libtrio dnl dnl system libtrio AC_ARG_ENABLE([system_libtrio], AS_HELP_STRING([--enable-system-libtrio], [Use the system libtrio instead of compiling the bundled one])) if test "${enable_system_libtrio}" = yes; then AC_MSG_NOTICE(checking for system libtrio) AC_SEARCH_LIBS([trio_printf], [trio], [], [AC_MSG_ERROR([unable to find trio_copy() function]) ]) AC_CHECK_HEADER(trio.h, [], [AC_MSG_ERROR([unable to find trio.h header file (dev version not installed?)]) ]) else AC_MSG_NOTICE([using bundled libtrio]) APR_ADDTO(INCLUDES, "[-Itrio]") APR_ADDTO(LDFLAGS, "[-Ltrio]") APR_ADDTO(CPPFLAGS, "[-DTRIO_MINIMAL]") TRIO_DEP="trio/libtrio.a" APR_SUBDIR_CONFIG([src/trio], [CFLAGS=[-DTRIO_MINIMAL]], [--with-pcre=*|\'--with-pcre=*]) AC_SUBST([TRIO_DEP]) fi dnl dnl PCRE: select whether to use an external, the system, or the bundled PCRE lib dnl partially borrowed from Apache's configure.in dnl dnl bundled pcre lib AC_ARG_ENABLE(bundled_pcre, AS_HELP_STRING([--enable-bundled-pcre], [Force the use of the bundled PCRE library instead of the system one])) dnl external PCRE lib AC_ARG_WITH(external_pcre, AS_HELP_STRING([--with-external-pcre=PATH_TO_PCRE_DIR|PATH_TO_PCRE_CONFIG_SCRIPT], [Use an external PCRE library instead of the system or the bundled one])) AC_MSG_NOTICE(checking for PCRE regular expressions library) dnl if user selected the bundled one, give it priority over the bundled one if test ! -z ${enable_bundled_pcre}; then with_external_pcre="" fi case $with_external_pcre in /*) AC_MSG_NOTICE(--with-external-pcre => checking for an external libpcre) AC_MSG_CHECKING(for pcre-config) if test -d "$with_external_pcre" && test -x "$with_external_pcre/pcre-config"; then PCRE_CONFIG=$with_external_pcre/pcre-config elif test -x "$with_external_pcre"; then PCRE_CONFIG=$with_external_pcre else AC_MSG_RESULT(no) AC_MSG_ERROR(${PCRE_CONFIG} does not point to a directory or pcre-config) fi AC_MSG_RESULT(${PCRE_CONFIG}) AC_MSG_CHECKING(for pcre version equal or greater than ${PCRE_MIN_VERSION}) if test -f "${PCRE_CONFIG}" && test -x "${PCRE_CONFIG}"; then PCRE_VERSION=$(${PCRE_CONFIG} --version) AS_VERSION_COMPARE("${PCRE_VERSION}", "${PCRE_MIN_VERSION}", [PCRE_CONFIG=false], [], []) if test "${PCRE_CONFIG}" != false; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR(the PCRE library version must be equal or greater than ${PCRE_MIN_VERSION}) fi else AC_MSG_RESULT(no) AC_MSG_ERROR(${PCRE_CONFIG} does not point to a script) fi ;; *) PCRE_CONFIG=false ;; esac dnl nope; do we have a system PCRE lib? if test -z "${enable_bundled_pcre}" && test -z "${PCRE_CONFIG}" -o "${PCRE_CONFIG}" = "false"; then AC_MSG_NOTICE(checking for a system libpcre) AC_PATH_PROG([PCRE_CONFIG], [pcre-config], []) if test ! -z "${PCRE_CONFIG}"; then AC_MSG_CHECKING(checking pcre version equal or greater than ${PCRE_MIN_VERSION}) PCRE_VERSION=$(${PCRE_CONFIG} --version) AS_VERSION_COMPARE("${PCRE_VERSION}", "${PCRE_MIN_VERSION}", [PCRE_CONFIG=false], [], []) if test "${PCRE_CONFIG}" != false; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi else PCRE_CONFIG=false fi fi dnl found a library, do we have compilation headers? if test "${PCRE_CONFIG}" != false; then PCRE_PATH=$(${PCRE_CONFIG} --prefix) AC_CHECK_HEADER(["$PCRE_PATH/include/pcre.h"], [ ],[PCRE_CONFIG=false]) fi dnl PCRE conclusion if test "$PCRE_CONFIG" != "false"; then AC_MSG_NOTICE([using system PCRE regular expressions library]) APR_ADDTO(CFLAGS, [`$PCRE_CONFIG --cflags`]) APR_ADDTO(LIBS, [`$PCRE_CONFIG --libs`]) else AC_MSG_NOTICE([using bundled PCRE regular expressions library]) APR_ADDTO(INCLUDES, [-Ipcre]) APR_ADDTO(LDFLAGS, "[-Lpcre/.libs]") PCRE_DEP="pcre/.libs/libpcre.a" APR_SUBDIR_CONFIG([src/pcre], [], [--with-pcre=*|\'--with-pcre=*]) AC_SUBST([PCRE_DEP]) fi dnl dnl The FNV hash library used for the nonsequential filenames dnl AC_MSG_CHECKING([whether to use fnv hash library for non-sequential filenames]) AC_ARG_ENABLE(libfnv, [ AS_HELP_STRING([--enable-libfnv], [use the fnv hash library for generating non-sequential filenames [no]]) ], [ given_libfnv=$enableval ]) if test "$given_libfnv" != "yes"; then AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_LIBFNV]) APR_ADDTO(INCLUDES, [-Ifnv]) dnl APR_ADDTO(LDFLAGS, "[-Lfnv]") AC_ADD_LIBRARY_WITH_PATH([-lfnv],[src/fnv]) FNV_DEP="fnv/libfnv.a" APR_SUBDIR_CONFIG([src/fnv]) fi AC_SUBST(FNV_DEP) dnl =========================================================================== dnl Checks for libraries. dnl nsl socket lib? dnl =========================================================================== USENSL=no AC_CHECK_LIB(socket,gethostbyaddr,result=yes,result=no) if test $result = yes; then LIBS="$LIBS -lsocket" else AC_CHECK_LIB(socket,gethostbyaddr,result=yes,result=no,-lnsl) if test $result = yes; then LIBS = "$LIBS -lsocket -lnsl" USENSL=yes else AC_CHECK_LIB(socket,inet_addr,result=yes,result=no) if test $result = yes; then LIBS="$LIBS -lsocket" else AC_CHECK_LIB(socket,inet_addr,result=yes,result=no,-lnsl) if test $result = yes; then LIBS="$LIBS -lsocket -lnsl" USENSL=yes fi fi fi fi if test $USENSL != yes; then AC_CHECK_LIB(nsl,inet_addr,result=yes,result=no) if test $result = yes; then LIBS="$LIBS -lnsl" fi fi dnl =========================================================================== dnl Makefile variable substitution dnl =========================================================================== AC_SUBST(HAVE_MEMMOVE) AC_SUBST(HAVE_STRERROR) AC_SUBST(LDFLAGS) AC_SUBST(LIBS) AC_SUBST(EXTRA_LIBS) AC_SUBST(INCLUDES) AC_CONFIG_FILES([Makefile archive/Makefile docs/Makefile libcgi/Makefile src/Makefile tests/testhm src/defaults.h]) AC_OUTPUT ================================================ FILE: contrib/canonicalize.pl ================================================ #!/usr/bin/perl # # Author: Scott Rose # # $Id$ # # Comparing two archives is complicated by the fact that each message is # marked by the time at which it's archived. Attached is a script that # standardizes that date, if weakly, useful for such comparisons. # # NOTE: # - Must be in the html storage directory to use this. # - If your files are stored with a different suffix than .html # you will need to correct it below. # - If the date is really important to you, fix this script and # rebaseline it. # for $file (glob '[0-9][0-9][0-9][0-9].html') { open F, "$file" or die; @lines = ; close F; open F, ">$file" or die; $did = 0; for (@lines) { if(m#^: \w{3} \w{3}\s+\d{1,2} \d{4} - \d{2}:\d{2}:\d{2} \w{3}$#) { die 'oops' if($did); print F ": Sat Oct 16 1999 - 06:00:00 PDT\n"; $did++; } else { print F; } } die "Oops" unless($did); close F; print "$file\n" } ================================================ FILE: contrib/cron_hypermail ================================================ #!/usr/bin/perl =h1 This perl script is used for calling hypermail via cron. This script checks to see if an email has arrived in the mailbox. If so, hypermail is called on that mailbox. If not, that mailbox is not processed. It sends errors and reports to an email address. In my system, I have about 25 email broadcast lists, implemented with sendmail's aliases files. For every list, I created a user account named "ax" (for archive) prepended to the list name, e.g., axmylist. The account is in group "mail" so that sendmail can operate on it. In the file pointed to by the aliases file, there is an email address of axmylist@domain.com. In virtusertable, axmylist@domain.com is directed to axmylist, which ends up in /var/spool/mail/axmylist. hypermail is used with a configuration file. Anyone is welcome to use this script and modify it. It is not in a polished form, and it needs configuration and customizing. However, if it useful to anyone, they are welcome to use it. It is not copyrighted, and the original author is in no way responsible for whatever results you obtain from it. And the author remains anonymous. version 1.0 Feb 27, 2001 usage: cron will be told to call this script every hour owner: domainmail in group mail =cut use strict; # <>--------- CONFIGURE ---------<> my $do_it = 1; # 0 will not actually call hypermail -- for testing. 1 will call hypermail. my $webmaster = "me\@somewhere.net"; my $production_site = 'cron_hypermail domain'; my $cf_mail_directive = '/usr/lib/sendmail -oi -t'; my %list_info = ( 'list1'=>{'label'=>'My List','bdcast_list_page'=>'index'}, 'list2'=>{'label'=>'My Second List','bdcast_list_page'=>'list2'}, 'list3'=>{'label'=>'My Third List','bdcast_list_page'=>'list3'}, 'list4'=>{'label'=>'My Fourth List','bdcast_list_page'=>'list4'}, 'list5'=>{'label'=>'My Fifth List','bdcast_list_page'=>'list5'}, ); my $path_to_mailbox = '/var/spool/mail'; my $full_path_to_config_file = '/home/www/domain/members_only/email_archives/call_hypermail/hmrc.domain'; my $complete_text = ''; # will add the specific directory below, i.e., the mailbox name my $path_to_html_archive = '/home/www/domain/members_only/email_archives'; # <>--------- END CONFIGURE ---------<> BEGIN { $SIG{__DIE__} = \&Error_Message_die; $SIG{__WARN__} = \&Error_Message_warn; } if ($do_it) { $complete_text .= "EXECUTING THE HYPERMAIL COMMANDS, NOT IN TEST MODE\n"; } else { $complete_text .= "TEST MODE, NOT EXECUTING THE HYPERMAIL COMMANDS\n"; } # <>--------- GET MAILBOX NAME AND MODIFY VARIABLES ---------<> my $count = 0; foreach my $mboxname (keys %list_info) { # Has the mailbox received a message that needs to be archived? # Is the mailbox younger than the archive index page? # If so, run hypermail on that mailbox and archive $count++; $complete_text .= "______________________________\n********** $count. $mboxname **********\n"; $complete_text .= "\$path_to_mailbox/ax\$mboxname = $path_to_mailbox/ax$mboxname\n"; $complete_text .= "\$path_to_html_archive/\$mboxname/index.html = $path_to_html_archive/$mboxname/index.html\n"; $complete_text .= "M of mbox = "; $complete_text .= (-M "$path_to_mailbox/ax$mboxname"); $complete_text .= "\n"; $complete_text .= "M of htmlindex = "; $complete_text .= (-M "$path_to_html_archive/$mboxname/index.html"); $complete_text .= "\n"; # What if the mailbox does not exist? unless (-e "$path_to_mailbox/ax$mboxname") { $complete_text .= "mailbox does not exist, process next mbox name: $path_to_mailbox/ax$mboxname\n"; next; } # the mailbox exists # is the mailbox younger than its html index page? or an index.html does not yet exist if ( ( (-M "$path_to_mailbox/ax$mboxname") < (-M "$path_to_html_archive/$mboxname/index.html") ) or (!(-e "$path_to_html_archive/$mboxname/index.html")) ) { my $list_address = "$mboxname\@domain.com"; my $axmboxname = 'ax' . $mboxname; # check for debug mode if ($do_it) { # errors are normally sent to STDERR, and hence not captured by $x # so do the redirection, 2>&1 my $x = `/usr/local/bin/hypermail -m $path_to_mailbox/$axmboxname -c $full_path_to_config_file -d $path_to_html_archive/$mboxname -l "$list_info{$mboxname}{label}" -b "../../email_lists/$list_info{$mboxname}{bdcast_list_page}\.html" -n $list_address 2>&1`; # will be blank for successful operation $complete_text .= "\$x = $x\n"; } else { my $y = <&1 EOP ; $complete_text .= "\$y = $y\n"; } } # end of if -M < -M } # end of foreach mailbox # while running under cron, comment this out #print $complete_text; # send a report every time it runs (until you are confident it runs well) open(MAIL, "| $cf_mail_directive"); print MAIL "Subject: domain cron_hypermail ran\n"; print MAIL "From: domain cron_hypermail\n"; print MAIL "To: $webmaster\n\n"; print MAIL "The script to call hypermail ran \n\n"; print MAIL "$complete_text\n"; close(MAIL); exit; ############################################################# # Error_Message ############################################################# sub Error_Message_die { my $message = "@_"; open(MAIL, "| $cf_mail_directive"); print MAIL "Subject: RED ALERT! Runtime error at $production_site\n"; print MAIL "From: $production_site\n"; print MAIL "To: $webmaster\n\n"; print MAIL "Error at $production_site. This message was automatically produced by the program because the following error occured.\n\n$message\n\nComplete Debug Text:\n$complete_text"; close(MAIL); exit; } sub Error_Message_warn { my $message = "@_"; open(MAIL, "| $cf_mail_directive"); print MAIL "Subject: WARNING! Non-fatal error at $production_site\n"; print MAIL "From: $production_site\n"; print MAIL "To: $webmaster\n\n"; print MAIL "Error at $production_site. This message was automatically produced by the program because the following non-fatal error occured.\n\n$message\n\nComplete Debug Text:\n$complete_text"; close(MAIL); } ================================================ FILE: contrib/fixhtime.pl ================================================ #!/usr/bin/perl require 5.000; require Exporter; use Carp; # # This program is intended to modify the dates on files in a Hypermail # archive to be the times when the messages were sent rather than when # Hypermail last did something to them. # # The recommended usage is to cd to the archive directory and run: # fixhtime.pl [0-9]???.html # # If it doesn't do anything, first check that you have write permission on # the files. # # I've tested it under Linux. It should work on virtually any Unix system. # It might work on other operating systems. # # Send bug fixes or enhancements to pcm@rahul.net. # The latest version will probably be in the contrib/ directory of the latest # Hypermail distribution (http://sourceforge.net/projects/hypermail/ # or www.hypermail.org). # # This program is free software; you can redistribute it and/or modify it # under the same terms as Perl itself. # # Some code below is duplicated from Time::Local.pm. For some strange reason, # having it here rather than calling the Time::Local module avoids an infinite # loop on some systems (specifically, on a Linux box with Perl 5.005_03 # and a 2.0.25 kernel). # BEGIN { $SEC = 1; $MIN = 60 * $SEC; $HR = 60 * $MIN; $DAY = 24 * $HR; $epoch = (localtime(2*$DAY))[5]; # Allow for bugs near localtime == 0. $YearFix = ((gmtime(946684800))[5] == 100) ? 100 : 0; my $t = time; my @lt = localtime($t); my @gt = gmtime($t); $tzsec = ($gt[1] - $lt[1]) * $MIN + ($gt[2] - $lt[2]) * $HR; my($lday,$gday) = ($lt[7],$gt[7]); if($lt[5] > $gt[5]) { $tzsec -= $DAY; } elsif($gt[5] > $lt[5]) { $tzsec += $DAY; } else { $tzsec += ($gt[7] - $lt[7]) * $DAY; } $tzsec += $HR if($lt[8]); } sub timegm { $ym = pack(C2, @_[5,4]); $cheat = $cheat{$ym} || &cheat; return -1 if $cheat<0 and $^O ne 'VMS'; $cheat + $_[0] * $SEC + $_[1] * $MIN + $_[2] * $HR + ($_[3]-1) * $DAY; } sub timelocal { $time = &timegm + $tzsec; return -1 if $cheat<0 and $^O ne 'VMS'; @test = localtime($time); $time -= $HR if $test[2] != $_[2]; $time; } sub cheat { $year = $_[5]; $year -= 1900 if $year > 1900; $month = $_[4]; croak "Month '$month' out of range 0..11" if $month > 11 || $month < 0; croak "Day '$_[3]' out of range 1..31" if $_[3] > 31 || $_[3] < 1; croak "Hour '$_[2]' out of range 0..23" if $_[2] > 23 || $_[2] < 0; croak "Minute '$_[1]' out of range 0..59" if $_[1] > 59 || $_[1] < 0; croak "Second '$_[0]' out of range 0..59" if $_[0] > 59 || $_[0] < 0; $guess = $^T; @g = gmtime($guess); $year += $YearFix if $year < $epoch; $lastguess = ""; while ($diff = $year - $g[5]) { $guess += $diff * (363 * $DAY); @g = gmtime($guess); if (($thisguess = "@g") eq $lastguess){ return -1; #date beyond this machine's integer limit } $lastguess = $thisguess; } while ($diff = $month - $g[4]) { $guess += $diff * (27 * $DAY); @g = gmtime($guess); if (($thisguess = "@g") eq $lastguess){ return -1; #date beyond this machine's integer limit } $lastguess = $thisguess; } @gfake = gmtime($guess-1); #still being sceptic if ("@gfake" eq $lastguess){ return -1; #date beyond this machine's integer limit } $g[3]--; $guess -= $g[0] * $SEC + $g[1] * $MIN + $g[2] * $HR + $g[3] * $DAY; $cheat{$ym} = $guess; } $mon{"Jan"} = 0; $mon{"Feb"} = 1; $mon{"Mar"} = 2; $mon{"Apr"} = 3; $mon{"May"} = 4; $mon{"Jun"} = 5; $mon{"Jul"} = 6; $mon{"Aug"} = 7; $mon{"Sep"} = 8; $mon{"Oct"} = 9; $mon{"Nov"} = 10; $mon{"Dec"} = 11; foreach $file (@ARGV) { open(FD,$file) || warn("can't open $file"); while($line1 = ) { if($line1 =~ /^\<\!\-\- isosent\=\"(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/) { $year = $1; $month = $2 - 1; $day = $3; $hour = $4; $min = $5; $sec = $6; $date = timegm($sec,$min,$hour,$day,$month,$year); utime $date,$date,$file; print $line1; last; } if($line1 =~ /(\d+)\s+(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)[\s\"]+(\S+)/) { $day = $1; $monthname = $2; $year = $3; $hour = $4; $min = $5; $sec = $6; $tzone = $7; $date = timegm($sec,$min,$hour,$day,$mon{$monthname},$year); $tzone /= 100 if(abs($tzone) >= 100); $date -= $tzone*60*60; utime $date,$date,$file; last; } } } ================================================ FILE: contrib/hoaf-28/README ================================================ Date: Tue, 30 Nov 1999 02:18:32 -0600 From: Bernhard Reiter Subject: XML indexer, experimental, patch+python script Hello hypermailers, I know I shouldn't have done this, but I learned about python's XML handling in the process. This is my first attempt in XML file mangeling, so bear with me. I was always talking and thinking about how to get montly archives done and not only done, but the index files created, too: The problem: ------------ Hypermail in combination with the archive scripts, creates a bunch of directories for each year and each month when mails come in. a) How do you make a top page, linking all the scattered index files? b) Subproblem: If one mail comes in, do you really want to rebuild the complete index overviewfiles? Of course not. c) What if I want my top index page to have the number of mails grouped by week or so. :) (Hi egroups.) Solution: A python script strangles the problem. Part 1: I patched hypermail so that it creates an archive overview file complying with the haof.dtd in each directory it operates in. Oh, back to Part 0: Wrote a dtd for the Hypermail Archive Overview Format (hoaf). Part 2a: Wrote a little python module, which creates a HTML snipplet from this overviewfile and leaves it in the directory above. But only, if the overviewfile exists and is newer as the the snipplet. Part 2b: Wrote another python script, which runs through a directory, and checks each year and month and runs the module from 2a a couple of times. Results attached. Left for the interested reader: Beautify the output. Interesting research topics: * Only the mail references are missing in the hoaf, otherwise threading could be done on that level. * Well we could write this data into a little database. http://www.dbxml.org/ ? Or Postgres or MySql-GPL? Enjoy, Bernhard ps:This contribution to hypermail shall be free software under the GPL. I contribute it to hypermail as free software. My hopes are that hypermail stays under GPL, but I think I don't want to complicate things of you choose another free software license, so you have permission to publish it under this, too. ======================== Date: Tue, 7 Dec 1999 00:53:32 -0600 From: Bernhard Reiter To: hypermail@hypermail.org Subject: python index overview generator and xml patch Message-ID: <19991207005332.A1465@climate2.geog.uwm.edu> New Version of my nasty python script to create new archive overview files. Includes a hypermail to write a xml format file with the overview information. I run it from procmail, like: COLLECT_SNIPPLETS_SCRIPT=/usr/local/lib/site-python/collect_snipplets.py :0:.polis *X-Mailing-List: | polis-mail ; $COLLECT_SNIPPLETS_SCRIPT /var/www/mail-archive/polis polis-mail is the hypermail wrapper from archive/. Bernhard ================================================ FILE: contrib/hoaf-28/collect_snipplets.py ================================================ #!/usr/bin/env python """ Runs over the File system and builds a .html from snipplets. v%(version)s USAGE %(progname)s directory [ indexfilename ] The argument has to be a directory. The html will be left in the directory under index.html unless a second argument is given. The indexfilename is relative to the directory, "-" for stdout is recognised. directory has to contain top_html.hdr and footer_html.hdr. """ __version__=0.3 #29.11.1999 initial Bernhard Reiter # 6.12.1999 Bernhard # fix: table row not created, if no snipplet there # added: second argument #25.12.1999 Bernhard # cleanup: extracted code into new functions add_header(), add_footer() #20. 7.2002 Bernhard # finished the cleanup import sys import os import re import create_archive_snipplet topdirre= re.compile (r"^[12]\d{3,3}$") months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"] def add_header(outputfile,path): """ Read and dump header file use standard html header.""" fname=os.path.join(path,"top_html.hdr") if os.path.isfile(fname): f=open(fname,"r") outputfile.writelines(f.readlines()) f.close() else: outputfile.write("\n\n") def add_footer(outputfile,path): """ Read and dumb footer file or write standard html footer. """ fname=os.path.join(path,"footer_html.hdr") if os.path.isfile(fname): f=open(fname,"r") outputfile.writelines(f.readlines()) f.close() else: outputfile.write("\n\n") def main(argv): # check arguments if (not (len(argv)>=2 and len(argv)<=3)) or not os.path.isdir(argv[1]): sys.stderr.write(__doc__ % \ {"version": __version__, "progname": argv[0]} ) sys.exit(1) # set default outputfilename path=os.path.normpath(argv[1]) if len(argv)==3: outputfilename=argv[2] else: outputfilename="index.html" # use stdout for "-" if outputfilename=="-": outputfile=sys.stdout else: outputfilename=os.path.join(path,outputfilename) outputfile=open(outputfilename,"w") write=outputfile.write writelines=outputfile.writelines add_header(outputfile,path) # get the real work done dirlist=os.listdir(path) def iswantedDirin(x,path=path): """Check if is directory and looks like an archive name.""" return os.path.isdir(os.path.join(path,x)) and topdirre.match(x) directories=filter(iswantedDirin, dirlist) if not len(directories): sys.exit("Found no year directories to work on!\n") directories.sort() directories.reverse() for dir in directories: write("

%s

\n\n" % dir) write("\n") write("" + \ " " + \ ""+\ ""+\ "\n") subpath=os.path.join(path,dir) dirlist=os.listdir(subpath) months.reverse() for month in months: if month in dirlist and os.path.isdir(os.path.join(subpath,month)): monthdir = os.path.join(subpath,month) create_archive_snipplet.main((argv[0],monthdir,"2")) snippletfilename=os.path.join(subpath,month+"_html.blk") if os.path.isfile(snippletfilename): write("\n") f=open(snippletfilename,"r") writelines(f.readlines()) write("\n") write("
MonthIndex FilesMails
\n") add_footer(outputfile,path) if outputfile != sys.stdout: outputfile.close() if __name__ =="__main__": main(sys.argv) ================================================ FILE: contrib/hoaf-28/create_archive_snipplet.py ================================================ #!/usr/bin/env python """ Creates a html sniplet foor hypermail directories. v%(version)s Takes one directory name as argument, writes will create snipplet in current directory, only if the overviewfile has changed after the snipplet. USAGE %(progname)s directory_with_path number "number" speficies how many directory levels of the path should be left in the snipplet. 1 mean one and you can have more, if you want up to a limit. The snipplet will be left in one directory over the given one. This module requires the xml.sax module to be installed. Per default is also uses the validating parser of xmlproc, see code to disable that. Search for "xmlproc". In version 0.1 some code insite of this module is disabled. """ __version__=0.2 # 29.11.1999 initial Bernhard Reiter # 6.12.1999 Bernhard # added replacement for os.path.getmtime(), because debian's python package # is still 1.5.1 from xml.sax import saxexts, saxlib, saxutils from xml.sax.drivers import drv_xmlproc_val # for the xmlproc parsers import sys,urllib import os try: getmtime=os.path.getmtime except AttributeError, x: import stat def getmtime(file): statinfo=os.stat(file) return statinfo[stat.ST_MTIME] overviewfilename="archive_overview.haof" class Mail: """ Saves info about one mail message. """ def __init__(self): subject="" fromname="" fromemail="" date="" messageid="" filename="" class SimpleDocHandler(saxlib.DocumentHandler): def __init__(self): self.indices={} self.maillist=[] self.mode=0 self.current_name="" self.current_mail=None self.in_indices=0 def startElement(self, name, attrs): if name=="mail": self.current_mail=Mail() elif name=="indices": self.in_indices=1 self.current_name=name # sys.stdout.write( name + "starts.." ) # for attr in attrs: # print "A %s %s" %(attr,attrs[attr]) # print "("+name def endElement(self, name): #print name + "ends." if name=="mail": self.maillist.append(self.current_mail) if name=="indices": self.in_indices=0 def characters(self, ch, start,length): #print " found " + self.current_name + ": " + ch[start:start+length] if self.current_name=="subject": self.current_mail.subject=ch[start:start+length] elif self.current_name=="date": self.current_mail.date=ch[start:start+length] ##disable some of the next lines in v0.1 just for speed. # elif self.current_name=="fromname": # self.current_mail.fromname=ch[start:start+length] # elif self.current_name=="fromemail": # self.current_mail.fromemail=ch[start:start+length] # elif self.current_name=="message-id": # self.current_mail.messageid=ch[start:start+length] # elif self.current_name=="file": # self.current_mail.filename=ch[start:start+length] elif self.in_indices: self.indices[self.current_name]=ch[start:start+length] def main(argv): # test the arguments path=os.path.normpath(argv[1]) if len(argv)!=3 or not os.path.isdir(path) \ or int(argv[2]) not in range(1,10): sys.stderr.write(__doc__ % \ {"version": __version__, "progname": argv[0]} ) sys.exit(1) filename=os.path.join(path,overviewfilename) # which snipplet file are we talking about dirname,enddirname=os.path.split(path) snippletfilename=os.path.join(dirname,enddirname+"_html.blk") # do we have to work? if not os.path.isfile(filename) or (os.path.isfile(snippletfilename) \ and getmtime(snippletfilename) > getmtime(filename)): # nothing to be done # sys.stderr.write("Nothing to be done.") return 0 # check what filename, we have to leave in the URL predir=enddirname for t in range(1,int(argv[2]),1): dirname,head=os.path.split(dirname) predir=os.path.join(head,predir) # parse the overview file #p=saxexts.make_parser() # this is the normal parser coming with python p=drv_xmlproc_val.create_parser() # validating xmlproc parser dh=SimpleDocHandler() p.setErrorHandler(saxutils.ErrorPrinter()) p.setDocumentHandler(dh) p.parse(filename) # sys.stderr.write("the indices: " + repr(dh.indices) + "\n") # sys.stderr.write("found %d mails\n" % len(dh.maillist)) # write snipplet f=open(snippletfilename,"w") write=f.write def writetablefield(index,name,dh,write,predir): if dh.indices.has_key(index+"index"): write("
%s\n" \ %(predir,dh.indices[index+"index"],name)) else: write("\n") write(" %s\n" % (enddirname)) writetablefield("thread","Threads",dh,write,predir) writetablefield("date","Dates",dh,write,predir) writetablefield("subject","Subjects",dh,write,predir) writetablefield("author","Authors",dh,write,predir) write(" %d\n" % len(dh.maillist)) f.close() if __name__=="__main__": main(sys.argv) ================================================ FILE: contrib/hoaf-28/footer_html.hdr ================================================ ================================================ FILE: contrib/hoaf-28/haof-0.1.dtd ================================================ ================================================ FILE: contrib/hoaf-28/hypermail-2b28-2b28+.patch ================================================ diff -ru hypermail-2b28/patchlevel.h hypermail/patchlevel.h --- hypermail-2b28/patchlevel.h Mon Dec 6 17:22:27 1999 +++ hypermail/patchlevel.h Tue Nov 30 23:57:14 1999 @@ -1,2 +1,2 @@ -#define VERSION "2b28" +#define VERSION "2b28+" #define PATCHLEVEL "0" diff -ru hypermail-2b28/src/hypermail.c hypermail/src/hypermail.c --- hypermail-2b28/src/hypermail.c Mon Dec 6 17:22:28 1999 +++ hypermail/src/hypermail.c Tue Nov 30 23:57:14 1999 @@ -390,6 +390,11 @@ authname = setindex(set_defaultindex, "author", set_htmlsuffix); /* + * Set name of the overviewfile. FIXME, this is hardcoded + */ + overviewname = "archive_overview.haof" ; + + /* * General settings for mail command and rewriting. */ @@ -496,6 +501,7 @@ writethreads(amount_new); writesubjects(amount_new); writeauthors(amount_new); + writeoverview(amount_new); } else { printf("No mails to output!\n"); diff -ru hypermail-2b28/src/hypermail.h hypermail/src/hypermail.h --- hypermail-2b28/src/hypermail.h Mon Dec 6 17:22:28 1999 +++ hypermail/src/hypermail.h Tue Nov 30 23:57:14 1999 @@ -252,6 +252,7 @@ VAR char *datename; /* By date index file */ VAR char *subjname; /* By subject index file */ VAR char *thrdname; /* By thread index file */ +VAR char *overviewname; /* Easily parsable overview file */ VAR int use_mailcommand; VAR int use_mailto; diff -ru hypermail-2b28/src/print.c hypermail/src/print.c --- hypermail-2b28/src/print.c Mon Dec 6 17:22:28 1999 +++ hypermail/src/print.c Tue Nov 30 23:57:14 1999 @@ -366,6 +366,34 @@ } } +/* +** Pretty-prints the items for the overviewfile. +*/ + +void printoverviewitems(FILE *fp, struct header *hp) +{ + char *subj; + if (hp != NULL) { + struct emailinfo *em = hp->data; + printoverviewitems(fp, hp->left); + subj = convchars(em->subject); + fprintf(fp, + " \n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " \"%.4d.%s\"\n" + " \n\n" + ,subj, getdatestr(em->date), em->name, em->emailaddr, em->msgid, + em->msgnum, set_htmlsuffix); + + free(subj); + printoverviewitems(fp, hp->right); + } +} + int showheader(char *header) { return (inlist(set_show_headers, header) || inlist(set_show_headers, "*")); @@ -1482,6 +1510,67 @@ printfooter(fp, ihtmlfooterfile, set_label, set_dir, lang[MSG_BY_AUTHOR], authname); + + fclose(fp); + + if (newfile && chmod(filename, set_filemode) == -1) { + sprintf(errmsg, "%s \"%s\": %o.", + lang[MSG_CANNOT_CHMOD], filename, set_filemode); + progerr(errmsg); + } + + if (set_showprogress) + putchar('\n'); +} + +/* +** Write the overviewfile. Might be XML based. Should be easily parseble. +*/ + +void writeoverview(int amountmsgs) +{ + int newfile; + char filename[MAXFILELEN]; + FILE *fp; + + sprintf(filename, "%s%s%s", set_dir, + (set_dir[strlen(set_dir) - 1] == '/') ? "" : "/", overviewname); + + if (isfile(filename)) + newfile = 0; + else + newfile = 1; + + if ((fp = fopen(filename, "w")) == NULL) { + sprintf(errmsg, "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); + progerr(errmsg); + } + + if (set_showprogress) + printf("%s \"%s\"...", lang[MSG_WRITING_DATE_INDEX], filename); + + + fprintf(fp,"\n\n"); + fprintf(fp," \n\n" + ); + fprintf(fp," \n\n"); + + fprintf(fp," \n"); + fprintf(fp," %s\n",datename); + fprintf(fp," %s\n",thrdname); + fprintf(fp," %s\n",subjname); + fprintf(fp," %s\n",authname); + fprintf(fp," \n\n"); + + fprintf(fp," \n\n"); + printoverviewitems(fp,datelist); + fprintf(fp," \n"); + + + fprintf(fp," "); + fclose(fp); ================================================ FILE: contrib/hoaf-28/top_html.hdr ================================================ ================================================ FILE: contrib/hyperfeed.pl ================================================ #!/usr/bin/perl5 # # hyperfeed.pl # # Feed messages from an mbox into hypermail one at a time so as to test the # incremental mode of hypermail. # # -a call hypermail with these arguments instead of the default # -e stop feeding messages after the one with this index (1-based) # -f use this as the mbox to draw messages from # -h use this as hypermail instead of the default # -s start feeding messages with the one with this index (1-based) # # Notes: # # You can use this to extract a single contiguous range of messages from an # mbox by using a command line such as # # hyperfeed.pl -s 10 -e 20 -h /bin/cat -a '' -f mbox.all > mbox.some # # That command line will open an mbox named mbox.all and run separate # invocations of cat on messages 10 through 20-- eleven messages in all, # skipping the first nine. By using /bin/cat instead of hypermail, the # effect is to send the messages, still in mbox format, to the standard # output. Why you might care to do that is left as an excercise for the # reader. # # Author: Scott Rose, rose@cs.washington.edu. 19 Oct 1999. # She configures me... $default_args = '-uid .'; $default_mbox = 'mbox'; $default_prog = '/var/adm/sm.bin/hypermail'; # She configures me not! use Getopt::Std; getopts('f:h:a:s:e:v'); $| = 1; if(defined $opt_a) { $args = $opt_a; } else { $args = '-guid .'; } if(defined $opt_f) { $file = $opt_f; } else { $file = $default_mbox; } if(defined $opt_h) { $hypermail = $opt_h; } else { $hypermail = $default_prog; } open MBOX, $file or die "can't read the mbox."; $msg = 0; # Loop on lines in the mbox. while() { if(/^From / && defined @lines) { $msg++; exit if(defined $opt_e && $msg > $opt_e); # encountered the start of a new message with the content of the # previous one in @lines; emit it &h unless(defined $opt_s && $msg < $opt_s); undef @lines; } push @lines, $_; } $msg++; exit if(defined $opt_e && $msg > $opt_e); if(defined @lines) { &h unless((defined $opt_s && $msg < $opt_s) || (defined $opt_e && $msg > $opt_e)); } END { close MBOX or die "can't close mbox"; print "\n" if(defined $opt_v); } sub h { open HYPERMAIL, "|$hypermail $args" or die "can't pipe to hypermail."; print HYPERMAIL @lines; close HYPERMAIL or die "can't close hypermail"; print '.' if(defined $opt_v); } ================================================ FILE: contrib/hypetombox.pl ================================================ #!/usr/bin/perl # # Concept: # # Convert a hypermail archive to an mbox, weakly. # # Author: # # Scott Rose, rose@cs.[wisc,washington].edu. # # With modifications by Kent Landfield. # Further modifications by Peter McCluskey (pcm@rahul.net). # If it's broke, it's my fault. # For the very latest version, check the hypermail cvs repository: # http://cvs.hypermail.org/cgi-bin/cvsweb.cgi/hypermail/contrib/#hypetombox.pl # Or get the version in a recent hypermail distribution at # http://sourceforge.net/projects/hypermail/ or http://www.hypermail-project.org. # # A few more mods by Fyodor (fyodor@insecure.org) [9/24/00]: # * Added -H (additional header) option (useful for filtering messages) # * Extended the date formats accepted in "Received:" headers # * Added 'a' option to append to mailbox rather than clobbering it # * Updated usage info # # Usage: # # hypetombox.pl [-a] [-H ] [-m ] [-n ] [-S ] # -a means append to mailbox instead of clobbering it # -H adds the header(s) you specify. If more than one, put the three # characters %0A between them. # -R removes carriage returns (\r) from the end of lines; they sometimes get # added for reasons I haven't been able to explain. # -S defaults to 'html'. # # # $Header$ require 5.000; use Getopt::Std; use MIME::Base64; getopts('ad:H:m:n:RS:'); # This is a list of the fields in the comment header of each message. @fields = ('received', 'sent', 'name', 'email', 'subject', 'id', 'inreplyto'); # Get a list of the message files. $htmlsuffix = $opt_S || "html"; $fpat= "[0-9][0-9][0-9][0-9].$htmlsuffix"; $fpat = "$opt_d/$fpat" if(defined $opt_d); @msgs = sort glob($fpat); $to_address = $opt_n || 'bogus'; # Open the output file for write. $mbox_name = $opt_m || 'mbox'; if ($opt_H) { $opt_H =~ s/%0A/\n/g; chomp($opt_H); $opt_H .= "\n"; } $DIR_PREFIXER = "att-"; # should be same as DIR_PREFIXER in parse.h $PATH_SEPARATOR = '/'; if ($opt_a) { $openflag = ">>"; } else { $openflag = ">"; } (open MBOX, "$openflag$mbox_name") || die "can't open $mbox_name"; # Loop on the input files. # count the messages in the file $cntr = 0; $boguscntr = 0; foreach $msg (@msgs) { # Open the message file for read. # reset the header count for each message. # added by Erik Peterson 1/3/00. $header_count=0; $cntr += 1; $msgnum = int(substr($msg, length($opt_d) + ($opt_d ne ''), 99999)); $boundary = "=---------HYPETOMBOXCREATEDBOUNDARY$msgnum"; $attdir = sprintf("%s%s$DIR_PREFIXER%04d", $opt_d, $opt_d ne '' ? $PATH_SEPARATOR : '', $msgnum); @attfiles = glob("$attdir$PATH_SEPARATOR*"); undef %att_type; undef %att_desc; (open M, $msg) || die "can't open $msg"; # Loop on lines in the file $state = 'HeaderComments'; foreach $fld (@fields) { $$fld = ''; } my $line; my $msg_text; while($line = ) { # This is a header comment; save the value in a variable with the # same name. $line =~ s|\r(\n)$|\n| if($opt_R); if($state eq 'HeaderComments' && ($line =~ /^(\s*)$/)) { $key = $1; $value = $2; $value =~ s/&/&/g; $value =~ s/<//g; $$key = $value; ++$header_count; } elsif($header_count > 0) { if($state eq 'HeaderComments') { $state = 'LeadingGoo'; if($received =~ /^(\w{3} \w{3} {1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4})/) { $date = $1; } elsif($received =~ /^(\d{1,2} \w{3} {1,2}\d{2,4} \d{2}:\d{2}:\d{2} \w{3})/) { $date = $1; } elsif($received =~ /^(\w{3}), (\d{1,2}) (\w{3}) (\d{4}) (\d{2}:\d{2}:\d{2})/) { $date = sprintf("%s %s %.2d %s %s", $1, $3, $2, $5, $4); } else { $date = 'Bogus date'; $boguscntr += 1; warn("received $received, $line\n") if($boguscntr < 3); } $email = &unspamify($email); print MBOX "From $email $date\n"; print MBOX "Date: $sent\n"; $id = &unspamify($id); print MBOX "Message-Id: <$id>\n"; print MBOX "To: $to_address\n"; print MBOX "From: $email ($name)\n"; print MBOX "Subject: $subject\n"; if ($opt_H) { print MBOX $opt_H; } if ($inreplyto) { $inreplyto = &unspamify($inreplyto); print MBOX "In-Reply-To: <$inreplyto>\n"; } if (@attfiles) { print MBOX "Mime-Version: 1.0\n"; print MBOX "Content-Type: multipart/mixed; boundary=\"$boundary\"\n"; } print MBOX "\n"; if (@attfiles) { print MBOX "This is a multi-part message in MIME format.\n"; print MBOX "--$boundary\n"; print MBOX "Content-Type: text/plain; charset=us-ascii\n"; print MBOX "Content-Transfer-Encoding: 7bit\n"; } } if($line =~ m|^|) { my $attfilename = $2; my $part_no = $1; if($msg_text =~ s|
    \n
  • (\S+) attachment: ([^\n]+)\n
(\s*)$||s) { $att_type{$attfilename} = $1; $att_desc{$attfilename} = $2 if($2 ne 'stored'); } $msg_text =~ s|
\n$||s; $msg_text .= &get_att($attdir, $part_no, $attfilename); next; } $state = 'Body' if($line =~ /^/); $state = 'TrailingGoo' if(($line =~ /^/) || ($line =~ /^<([pP])>/)); next if(($line =~ /^ ... Besides making it much easier for removal or converter processes, standard incremental mailbox updates will be able to recognize that there are attachments and use the existing filenames or remove them prior to generating new ones. Attachment File Modes: ---------------------- For security reasons, all binary attachments written to disk get the same file permissions as the ordinary messages. They should never be to be executable, to any user. Controlling archiving of attachments ------------------------------------- The user can control the use of attachments by: 1. Indicating which mime types should not be stored at all. (i.e. vcard attachments) (see ignore_types) 2. Specifying a list with 'preferred' content-types when receiving/decoding mixed/alternative attachments (see prefered_types) 3. Indicating which content-types of images that is preferred to get in-lined - instead of . (see inline_types) 4. Use the 'attachmentlink' config file keyword to control how to "display" the attachment. You can for example use this to always display a warning page before the actual attachment is displayed or run by a client. Config file additions: ---------------------- # For each type to be ignored, put an ignore record for that # type. It is added to the list of ignored types when the config # file is read. # ignore_types = text/x-vcard ignore_types = application/x-msdownload # # ordered list, Do the first and if that is not present, # do the next and if that is not present ... # prefered_types = text/plain text/html ... # # Determine which image mime types should be inlined for # display in the message. instead of # inline_types = image/gif image/jpeg ... # # Format of the attachment links. # %p for the full path to the attachment # %f for the file name part only # %d for the directory name only # %n for the message number # %c for the content type string # attachmentlink = %p The readconfigs function is now able to look for more than one entry of certain types of variables. This can be on one line or on multiple lines. This type of parsing is only supported for ignore_types inline_types prefered_types ================================================ FILE: docs/customizing.html ================================================ Hypermail Documentation

   Customizing Hypermail Pages


Contents:


Hypermail Pages

You can customize hypermail generated pages to suit your local web site needs as well as the needs of the list. Hypermail generates three types of files:
  • HTML index pages,
  • HTML message pages,
  • MIME enclosure attactment files.

The attachment files are a copy of the attachment the user included and are not altered.

This version of hypermail allows you to customize both index and message pages separately as described below.


Definitions

In the examples below, the following terms are used.

label - the label passed in via the command line or specified in the list configuration file.

indextype - depends on the type of index being presented. It could be By Author, By Date, By Subject, or By Thread.

mailto-address - the MAILTO value compiled into hypermail, specified in the environment with the HM_MAILTO variable, or specified in the hm_mailto variable in the list specific configuration file.

subject-of-message - the contents of the message's RFC 2822 Subject: header.

HMURL - Used to contain a link to the Hypermail Development Center. Defined in hypermail.h.

PROGNAME - contains the name of the executable. Defined in hypermail.h.

VERSION - contains the version of the software that generated the page this appears on. Defined in src/hypermail.h.


Choosing the Default Look of Your Pages

There is no need to customize hypermail pages unless you have a specific need. There are two different default page layouts provided with hypermail, the Table Menu Display and the Standard Display.

Standard Page HTML

If you are not using the HTML template files described below then Hypermail generates headers and footers that look similar to the following. Note that you can substitute a <BODY> statement by either defining BODY in options.h or by using the hm_body variable in a list specific configuration file.

Index Page Headers

The default Index page headers used in hypermail look like:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<TITLE>labelindextype</TITLE>
<LINK REV="made" HREF="mailto:mailto-address">
<HEAD>
<BODY BGCOLOR="#ffffff" TEXT="#000000">
<H1 ALIGN=CENTER>label<BR>By indextype</H1>
<HR WIDTH=400>

Message Pages

The default Message page headers used in hypermail look like:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<TITLE>label:  subject-of-message</TITLE>
<LINK REV="made" HREF="mailto:mailto-address">
<HEAD>
<BODY BGCOLOR="#ffffff" TEXT="#000000"> <H1 ALIGN=CENTER>subject</H1>
<HR>

Page Footer

The default page footer shown below is used in hypermail on both the index and the message pages look like:

<HR>
<P>
<SMALL>
<EM>
This archive was generated by  <A HREF="HMURL">PROGNAME VERSION</A> on DATE and TIME
</EM>
</SMALL>
</BODY>
</HTML>

Table Menu Display

The table menu display generates pages that have a menu bar at the top and the bottom of the page that looks something like the following. If you have enabled the "About" and "Other Archives" links are displayed if you have enabled them in options.h, the environment variables or in the list configuration file. A example page:

TITLE HERE

Kent Landfield (kent@landfield.com)
Wed, 17 Jun 1998 22:28:29 -0500 (CDT)


BODY OF MESSAGE HERE


This archive was generated by hypermail 2.0x on Thu Jun 04 1998 - 10:05:34 CDT

If you do not want to use the table display then make sure that USETABLE is not defined in options.h and the hm_usetable is not enabled in the list configuration file. When you do so you will get the standard look and feel of the hypermail you have grown acustomed to.

Also note that New Message allows you to provide a means for someone to post a message to the list. This feature is currently only availabe on the Table Menu Display. It can be enabled or disabled by defining HMAIL in options.h or by setting the hm_hmail variable in the list specific configuration file.


Using Template Files to Customize Your Pages

You can customize your page headers and footers by specifying HTML template files. Hypermail reads template files and uses those in generating the header and footer sections of the index and message pages. Template files contain the actual HTML that you want used when generating the pages. Template files may also contain "Substitution Cookies".

Substitution Cookies

You can insert "substitution cookies" in the header and footer template files so the appropriate information is filled in at runtime.

Substitution cookies supported:

%%- '%' character
%~- Storage directory
%a- Other Archives URL
%b- About Archive URL
%e- Email address of message Author - Not valid on index pages
%g- Date and time archive generated
%h- HMURL
%i- Message-id - Not valid on index pages
%l- Archive label
%m- Mailto address
%p- PROGNAME
%s- Subject of message or Index Title
%v- VERSION
%u- Expanded version link (HMURL,PROGNAME,VERSION)
\n- newline character
\t- tab character

Additional cookies generate the complete HTML lines:

%A- Author META HTML - Not valid on index pages
%B- BODY HTML statement
%S- Subject META HTML

Specifying template file locations

You can specify the location of the template files either via environment variables or via entries in the list specific configuration file.

Using Environment Variables

If you wish to use environment variables, make sure they are exported and correctly available for hypermail to use. How to do this is dependent on the type of shell in use. See the appropriate man pages if you need more information.

  • HM_IHTMLHEADERFILE - the location of the INDEX header template.
  • HM_IHTMLFOOTERFILE - the location of the INDEX footer template.
  • HM_MHTMLHEADERFILE - the location of the MESSAGE header template.
  • HM_MHTMLFOOTERFILE - the location of the MESSAGE footer template.

Using Configuration File Entries

An easy way is to tell hypermail where the template files are is via a list specific configuration file. The following entries can be used.

  • hm_ihtmlheaderfile - the location of the INDEX header template.
  • hm_ihtmlfooterfile - the location of the INDEX footer template.
  • hm_mhtmlheaderfile - the location of the MESSAGE header template.
  • hm_mhtmlfooterfile - the location of the MESSAGE footer template.

Examples

It is acceptable to have a single configuration file listed in more than one entry. Suppose you want to have a common footer for all pages and separate headers. The following example shows that.

hm_ihtmlheaderfile = /lists/wu-ftpd/wu-ftpd-index.hyp
hm_mhtmlheaderfile = /lists/wu-ftpd/wu-ftpd-msg.hyp
hm_ihtmlfooterfile = /lists/wu-ftpd/wu-ftpd-msgfooter.hyp
hm_mhtmlfooterfile = /lists/wu-ftpd/wu-ftpd-msgfooter.hyp

If an entry is left blank and a location is not specified via an environment variable then the hypermail default headers are used.

hm_ihtmlheaderfile = /lists/wu-ftpd/wu-ftpd-index.hyp
hm_ihtmlfooterfile =
hm_mhtmlheaderfile = /lists/wu-ftpd/wu-ftpd-msg.hyp
hm_mhtmlfooterfile = /lists/wu-ftpd/wu-ftpd-msgfooter.hyp
The above example informs hypermail to use the template files listed for the Index header and the Message header and footer. The hypermail default page footer would be used on the index pages.

NOTE: While it is not necessary to provide absolute paths, it is a good idea to.

Message Pages

Each HTML file that is generated for a message contains (where applicable):

  • the subject of the article,
  • the name and email address of the sender,
  • the date the article was sent,
  • links to the next and previous messages in the archive,
  • a link to the message the article is in reply to, and
  • a link to the message next in the current thread.


Including Reference Links

Reference links such as the following

are normally included on each of the message pages. If this is not what you want you can disable them by using the SHOW_MESSAGE_LINKS define in options.h or the hm_show_msg_links in the list's configuration file.

Additionally, if you want to list all replies to a message such as the following,

you can do so by setting the SHOWREPLIES define in options.h or the hm_showreplies in the list's configuration file.


In-lining Images

It is possible to have images that are sent in email automatically displayed when the message is presented. To do this you need to set the hm_inline_types in the list configuration file.

For example, if you listed

hm_inline_types = image/gif image/jpeg
then both GIF files and JPEG files would be displayed as part of the message. Types that are not "in-lined" are linked as a simple attachment requiring the user to click on it to have it displayed.


Changing The HTML File Suffix

You may wish to have the pages generated use a different HTML file suffix other than the default ".html". To do this you need to either set the default define HTMLSUFFIX in options.h, set the environment variable HM_HTMLSUFFIX or set it in the list's configuration file by using the hm_htmlsuffix variable.

Note: Do not include a "." in the suffix; If you do you will end up with filenames that look like. "..html"


See Also

hypermail.(1),   hmrc.(4),   Hypermail   and   Hypermail List Configuration File. and Adding a Search Engines to your Hypermail Archive

Last updated April 10, 2003 ================================================ FILE: docs/hmrc.4 ================================================ .TH hmrc 4 "July 19, 2018" .SH NAME hmrc \- Hypermail configuration file .SH DESCRIPTION .B Hypermail can use a configuration file to allow you to customize the individual aspects of a list. In past versions of hypermail it was necessary for all hmrc variables to begin with 'hm_'. While still supported, it is not necessary to use the 'hm_' prefix any longer and this document reflects that. [This page may be out of date. See the hmrc.html file for complete and up to date info.] .RE .LP In the configuration file, blank lines and lines beginning with a hash mark .RB ( # ) are considered comments and are ignored. The format of the "options" need to be in lowercase and separated with an equals .RB ( = ) sign, such as: .LP .PD 0 .RS .B option = value .LP .B mbox = "/home/john/my_mailbox" .LP .B filemode = 0600 .PD .RE .LP You can specify which configuration file to use on the command line or, if not specified, Hypermail will use the one specified as .B CONFIGFILE in options.h. If the first character is "~", Hypermail will look for the file under the current user's home directory. .SH CONFIGURATION OPTIONS .TP Below is a list of variables that Hypermail understands. .LP Boolean numbers can have the value of .B 0 or .B 1. .TP .B language = two letter language specification This is a two-letter string specifying the default language to use, or a longer string specifying a language and locale. Set this the value of the language table you wish to use when running and generating archives. .in 10 .B Current supported languages: de (de_DE) - German en (en_US) - English es (es_ES) - Spanish fi (fi_FI) - Finnish fr (fr_FR) - French el (el) - Greek gr (el_GR) - Greek is (is_IS) - Icelandic no (no_NO) - Norwegian pl (pl_PL) - Polish pt (pt_BR) - Brazilian Portuguese ru (ru_RU) - Russian sv (sv_SE) - Swedish .nr The directory /usr/share/i18n/locales on many systems has the locale codes that are available on that system. .TP .B mbox = "filename" This is the mailbox to read messages in from. Set this with a value of .B "NONE" to read from standard input. .TP .B ietf_mbox = boolean_number Setting this variable to .B 1 will tell hypermail that the mbox is formatted according to the IETF mbox convention: all lines, except for the envelope, are prefixed with a .B > char. .TP .B linkquotes = [ 0 | 1 ] Set this to On to create fine-grained links from quoted text to the text where the quote originated. It also improves the threads index file by more accurately matching messages with replies. Note that this may be rather cpu intensive (see the searchbackmsgnum option to alter the performance). .TP .B eurodate = boolean_number Set this to .B 1 to display article received dates with days before months instead of months before days. .TP .B folder_by_date = strftime date format This string causes the messages to be put in subdirectories by date. The string will be passed to strftime(3) to generate subdirectory names based on message dates. Suggested values are "%y%m" or "%b%y" for monthly subdirectories, "%Y" for yearly, "%G/%V" for weekly. Do not alter this for an existing archive without removing the old html files. If you use this and update the archive incrementally (e.g. with -u), you must use the usegdbm option. .TP .B msgsperfolder = number Put messages in subdirectories with this many messages per directory. Do not use this and folder_by_date on the same archive. Do not alter this for an existing archive without removing the old html files. Deleted/expired messages ARE COUNTED for the purpose of deciding how many messages to put in a subdirectory. .TP .B increment = [ 0 | 1 | -1 ] Define as .B 1 to append all input messages to the end of existing archives. Define as .B 0 for it to read a mailbox that corresponds to the entire archive. (See the mbox_shortened option for an exception to the requirement that it be the entire archive). If there are any existing html messages, it will figure out which ones at the end of the mailbox are new, and add only those that haven't been converted yet. Define as .B -1 to have hypermail figure out whether the input is entirely new messages to be appended or whether it contains messages that are already in the archive. A value of -1 cannot be used with the mbox_shortened option or with the -i command line option or with mbox = NONE. .TP .B label = "label name" Define this as the label to put in archives. .TP .B dir = "directory" This is the directory that Hypermail will look for when creating and updating archives. If defined as .B "NONE" the directory will have the same name as the input mailbox. .LP .in 10 Using date substitution cookies, you can tell Hypermail to archive messages in directories by the date they were received. .LP .in 10 .B Substitution cookies supported %d - two digit day of month (1-28/30/31) %D - three letter day of the week %m - two digit month of year (1-12) %M - three letter month of year (Jan, ..., Dec) %y - four digit year (1990,..2001) .LP .in 10 For example, if you wished to have Hypermail archive files by year and month, you might use .LP .in 20 .B dir = /lists/somelist/%y/%M .LP .in 10 When a message was processed it would be put into a directory .B /lists/somelist/1998/Jun (if the message is processed in June of 1998). If the message arrives and there is no storage directory, Hypermail will automatically create it and store the message in the new directory. Note that the date that Hypermail was run will be used, not a date from the message (use the folder_by_date option to have Hypermail use dates from messages). .TP .B dateformat = strftime date format Format used in .B strftime(3) call for displaying dates. See .B strftime(3) for the valid conversion specifications. .TP .B stripsubject = "string" A string to be stripped from all subject lines. Helps unclutter mailing lists which add tags to subject lines. .TP .B archives = "URL" This will create a link in the archived index pages labeled .I "Other mail archives" to the specified URL. Set this to .B "NONE" to omit such a link. .TP .B custom_archives = HTML text If this variable is defined, a navigation entry will be created below the sorted_by_x list entry, with the text .I Other mail archives: followed by the value of this variable. Set it to .B NONE to ommit such an entry. .TP .B about = "URL" This will create a link in the archived index pages labeled .I "About this archive" to the specified URL. Set this to .B "NONE" to omit such a link. .TP .B usemeta = boolean_number This option allows you to use metadata to store the content type of a MIME attachment and, later on, when a user browses the attachment, send back this information in the HTTP Content-Type header. When set to .B 1, the Content-Type header of a MIME attachment will be stored in a metadata file. Let us say that the MIME attachments for a message are stored in directory .B att-num. The metadata for those attachments will then be stored in directory .B att-num/.meta. If a MIME attachment is stored in file .B att-file, its metadata will be stored in file .B att-file.meta. This convention is directly compatible with the Apache server handling of metada. .TP .B userobotmeta = boolean_number If a message has annotations for robots and .B usemeta is enabled, setting this option to .B 1 will associate the value of the annotations to each attachment using the experimental .B X-Robots-Tag HTTP header. For more information, browse https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag .TP .B indextable = boolean_number Setting this variable to .B 1 will tell Hypermail to generate an message index Subject/Author/Date listings using a table format. Set to .B 0 if you want the standard Hypermail index page look and feel. .TP .B reverse = boolean_number Setting this variable to .B 1 will reverse-sort the article entries in the date and thread index files by the date they were received. That is, the most recent messages will appear at the top of the index rather than the other way around. .TP .B showheaders = boolean_number Set this to .B 1 to show the article header lines in the archived HTML files. These lines typically include the .B "To:", "From:", and .B "Subject:" information found in most email messages. .TP .B showhtml = [ 0 | 1 | 2 ] Set this to .B 1 to show the articles in a proportionally-spaced font rather than a fixed-width (monospace) font. Set this to .B 2 for more complex conversion to html similar to that in .B txt2html.pl. Showhtml = 2 will normally produce nicer looking results than showhtml = 1, and showhtml = 0 will look pretty dull, but 1 and 2 run risks of altering the appearance in undesired ways. .TP .B showbr = boolean_number Set this to .B 1 to place .B
tags at the end of article lines. Otherwise, all non-quoted article lines will word wrap. This only takes effect if .B showhtml is enabled. .TP .B iquotes = boolean_number Set this to .B 1 to italicize quoted lines. .TP .B show_msg_links = boolean_number Set this to .B 1 to put the individual message links at the top of the individual message pages. Set this to .B 0 to produce pages without the Next, Previous, Reply, In-Reply-To, etc. links. .TP .B showreplies = boolean_number Set this to .B 1 to show all replies to a message as links in article files. .TP .B discard_dup_msgids = boolean_number Set this to .B 0 to accept messages with a Message-ID matching that of a message already in this archive. By default such messages are discarded. .TP .B require_msgids = boolean_number Set this to .B 0 to accept messages without a Message-ID header. Set this to .B 1 to discard messages without a Message-ID header. By default such messages are discarded. .TP .B fragment_prefix = "string" Put this string before the message number in each URI fragment. The defaul prefix is .B msg. .TP .B email_address_obfuscation = boolean_number Set to .B 1 to enable email address obfuscation using numeric character references. Option .B disabled by default. .TP .B i18n = boolean_number Enable I18N features, hypermail must be linked with .B libiconv. Option .B disabled by default. .TP .B i18n_body = boolean_number Translate message body into UTF-8. The .B i18n configuration option must be .B enabled. Option .B disabled by default. .TP .B htmlmessage_edited = "string" Set this to HTML markup you want to appear in the body of manually edited messages. Option .B disabled by default. .TP .B htmlmessage_deleted_other = "string" Set this to HTML markup you want to appear in the body of deleted messages (by reasons other than spam). Option .B disabled by default. .TP .B htmlmessage_deleted_spam = "string" Set this to HTML markup you want to appear in the body of deleted messages (by spam reasons). Option .B disabled by default. .TP .B spamprotect = boolean_number Set this to .B 1 to make hypermail not output real email addresses in the output HTML, but instead obfuscate them a little. By default email addresses are obfuscated. .TP .B antispam_at = "string" Set this to .B 1 make hypermail use something like "_at_" instead of the RFC 2822 @ address separator. .TP .B spamprotect_id = boolean_number Set this to .B 1 to make hypermail not output real email message ids in HTML comments (sometimes used internally by hypermail) but instead it will obfuscate them a little so they don't look like email addresses to spammers. .TP .B attachmentsindex = boolean_number Set this to .B 0 to make hypermail not output an index of articles with attachments. By default hypermail outputs this index. .TP .B mailto = "address" The address of the contact point that is put in the HTML header line .br Setting this to .B "NONE" disables header generation. .TP .B mailcommand = "command" This specifies the mail command to use when converting email addresses to links. The variables .B $TO, $SUBJECT, and .B $ID can be used in constructing the command string. .LP .in 10 .B $TO represents the address to send mail to, .LP .in 10 .B $SUBJECT represents the subject that is being replied to, and .LP .in 10 .B $ID represents the message ID of the article that is being replied to. .LP .in 10 If defined as .B "NONE", email addresses will not be converted to links in articles. A possible command one could use is .B "mailto:$TO?subject=$SUBJECT" and the Subject: would also be filled in. This can be changed to specify a CGI program such as .B "/cgi-bin/mail?to=$TO". A CGI mail program is included with the source which can be used for this purpose. .TP .B domainaddr = "domainname" Set this to the domainname you want added to a mail address appearing in the RFC822 field which lack a hostname. When the list resides on the same host as the user sending the message, it is often not required of the MTA to domain-ize these addresses for delivery. In such cases, Hypermail will add the DOMAINADDR to the email address. If defined as .B "NONE", this feature is turned off. .TP .B htmlsuffix = "suffix" Use this to specify the html file suffix to be used when Hypermail generates the html files. This is dependent on local needs. Do not put a '.' in the value. It would result in "file..html", probably not what you want. .TP .B describe_folder = "string describing folder" Controls the labels used in folders.html to describe the directories created by the folder_by_date or msgsperfolder options. For folder_by_date labels, the describe_folder string will be passed to strftime(3) the same as the folder_by_date string. For msgsperfolder: %d for the directory number (starts with 0) %D for the directory number (starts with 1) %m for the number of the first message in the directory %M for the number of the last message that can be put in the directory. .TP .B latest_folder = "string" If folder_by_date or msgsperfolder are in use, create a symbolic link by this name to the most recently created subdirectory. Note that many web servers are configured to not follow symbolic links for security reasons. The link will be created in the directory specified by the "dir" or "-d" option. .TP .B noindex_onindex = boolean_number Tells hypermail to add a .B noindex metadata to its generated message indexes (by author, etc.), to instruct robots to not index the indexes. See .B anontated for further discussion on the .B noindex metadata value. .TP .B base_url = "url" The url of the archive's main directory. This is needed when the latest_folder option is used and the folder_by_date makes directories more than one level deep (e.g. with '%y/%m'). .TP .B iso2022jp = boolean_number Set this to On to support ISO-2022-JP messages. .TP .B uselock = boolean_number Controls whether to use hypermail's built-in locking mechanism. By default, this option is set to .B 1. Set it to .B 0 if you have an external locking mechanism, like, for example, when using procmail or smartlist. .TP .B locktime = number-of-seconds Set this to the number of seconds that a lock should be honored when processing inbound messages. Defaults to 3600 seconds. .TP .B annotated = "list of headers" This is the list of headers that indicate that a message was annotated. Option .B disabled by default. In an annotated message, the values of the header specify the type of annotations. The header may have one or more comma-separated values. Order and case are not important. Hypermail recognizes two types of annotations: .B content and .B robot annotations. .B "Content annotations" give information to the reader about how an archive maintainer has operated on an original received message. This operation typically happens as a belated action, for example, when removing spam from an existing archive. Content annotations can have one, and only one, of the following values: .in 18 .I spam message deleted because it is spam; .br .in 18 .I deleted message deleted, other reasons; .br .in 18 .I edited original received message was manually edited. .in 14 If a message specifies more than one content annotation, only the first one will be taken into account. You can customize the markup that\'s shown for content annotations by means of the .I "htmlmessage_deleted_other," .I "htmlmessage_deleted_spam," and .I "htmlmessage_edited" directives. .B Robot annotations instruct a visiting web robot if the contents of a message should be indexed and/or if the outgoing links from the message should be followed, doing so thru a specific HTML meta tag. (browse http://www.robotstxt.org/ for further details). .B Robot annotations can have either one or both of the following values: .in 18 .I "nofollow" do not follow outgoing HTML links from this file; .br .in 18 .I "noindex" do not index the contents of this file. .in 14 You can use one or both values and combine them with the edited content annotation. Note that .I spam and .I deleted annotations have an implicit robot .I "noindex" annotation. In such case, user supplied robot annotations values will be silently ignored. Use .B userobotmeta for associating attachments with annotations for robots. NOTE: The list maintainer must be careful on whether to accept incoming messages containing the .B annotated header. If the policy is not to allow that header on incoming messages, it must be filtered out before the message is stored or acted upon by hypermail. .TP .B deleted = "list of headers" .B NOTE: this option has been deprecated by .B "annotated," but it will continue being parsed and honored for legacy reasons. This is the list of headers that indicate the message should not be displayed if the value of this header is 'yes'. The default is "X-Hypermail-Deleted X-No-Archive". .TP .B expires = "list of headers" This is the list of headers that indicate the message should not be displayed if the value of this header is a date in the past. The default value is "Expires". .TP .B delete_older = "date" Any message older than this date should not be displayed. Example: delete_older = "Wed, 14 Mar 2001 12:59:51 +0200" .TP .B delete_newer = "date" Any message newer than this date should not be displayed. .TP .B delete_msgnum = "list of message numbers" This is the list of message numbers that should be deleted from the html archive. The mbox is not changed. .TP .B delete_level = [ 0 | 1 | 2 | 3 ] 0 - remove deleted and expired files. Note that with this choice threading may be screwed up if there are replies to deleted or expired options and the archive is updated incrementally 1 - remove message body 2 - remove message body for deleted messages, leave expired messages 3 - leave all messages Deleted and expired messages are removed from the index files regardless of the delete_level selection. The default is 1. .TP .B delete_incremental = boolean_number If this option is enabled, hypermail will perform deletions on old messages when run in incremental mode (according to the other delete configuration options). Note that depending on your hypermail setup, the size of the archive, and the complexity of the markup, there may be memory and parsing issues, specifically when there are non-deleted replies to a deleted message. If this option is disabled, deleted messages will only be removed when rebuilding the whole archive. Option .B enabled by default. .TP .B txtsuffix = "suffix" If you want the original mail messages archived in individual files, set this to the extension that you want these messages to have (recommended value: txt). .TP .B filter_out = "list of patterns" Delete from the html archives any message having a header line which matches any of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions. .TP .B filter_require = "list of patterns" Delete from the html archives any message not having header lines which match each of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions. .TP .B filter_out_full_body = "list of patterns" Delete from the html archives any message having a line which matches any of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions. .TP .B filter_require_full_body = "list of patterns" Delete from the html archives any message not having lines which match each of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions. .TP .B save_alts = [ 0 | 1 | 2 ] This controls what happens to alternatives (other than the prefered alternative) for multipart/alternative messages. 0 - discard non-prefered alternatives 1 - show all alternatives inline 2 - put non-prefered alternatives in a separate file. .TP .B alts_text = "string" If save_alts is 1, this text is put between the alternatives. If save_alts is 2, this text is used to describe the link to each alternative file. .TP .B warn_suppressions = boolean_number Set this to On to get warnings (on stdout) about messages that are not converted because of they are missing a msgid (if require_msgids is On) or because one of the following options suppressed it: deleted expires delete_msgnum filter_out filter_require filter_out_full_body filter_require_full_body. .TP .B unsafe_chars = "characters" Any characters listed in this string are removed from user-specified attachment filenames. Those characters will be replaced by a "_" (which means that specifying "_" here won't have any effect). Note that many characters (including / and ) are removed by the safe_filename in parse.c regardless of what this option says. There might be some security problems that can be prevented if you specify "." here (e.g. if a web server is configured to enable server side includes on filenames ending in something other than .shtml), but that will prevent browsers from recognizing many file types. .TP .B files_by_thread = boolean_number Set this to On to generate (in addition to the usual files), a file for each thread that contains all the messages in that thread. .TP .B href_detection = boolean_number Set this to On to assume that any string on the body of the message that says , , and other statements that suit your local customized needs. .TP .B ihtmlfooterfile = path Define path as the path to a template file containing valid HTML formatting statements that you wish to included at the bottom of every index page. Hypermail will print this file as the trailer of the index so make sure it contains at a minimum a .B and .B statement. .TP .B mhtmlheaderfile = path Define path as the path to a template file containing valid HTML formatting statements that you wish to use at the top of every message page. Hypermail will print this file as the header of the message so make sure it contains .B , , and other statements that suit your local customized needs. .TP .B mhtmlfooterfile = path Define path as the path to a template file containing valid HTML formatting statements you wish to use at the bottom of every message page. Hypermail will print this file as the trailer of the message so make sure it contains at a minimum a .B and .B statement. .TP .B hmail = Mailing_List_Submission_Address Set this to the list's submission address. When enabled, this can be used to submit a new message to the list served by the hypermail archive. .B "NONE" means don't use it. .TP .B newmsg_command = "mailto:$TO" This specifies the mail command to use when converting the .B set_hmail address to links in replies. The variables .B $TO, .B $SUBJECT, and .B $ID can be used in constructing the command string. .TP .B replymsg_command = "mailto:$TO" This specifies the mail command to use when converting the set_hmail address to links in replies. The variables .B $TO, .B $SUBJECT, and .B $ID can be used in constructing the command string. The value from mailcommand will be used if this option is not specified. .TP .B inreplyto_command = "URL" This gives a URI template to a script that hypermail will link to if it's unable to find in the archive's messages the MID corresponding to an .B In-Reply-To header. The variable .B $ID is used to specify where the .B Message-Identifier value will appear in the link. A possible command one could use is .B http://example.org/mid-resolver/$ID. This option is .B disabled by default. .TP .B icss_url = "URL" This will link an external stylesheet found at the given URL to the index files. This will happen thru a .B LINK element in the index document's .B HEAD. By default this option is disabled. .TP .B mcss_url = "URL" This will link an external stylesheet found at the given URL to the message files. This will happen thru a .B LINK element in the message document's .B HEAD. By default this option is disabled. .TP .B show_headers = list_of_RFC_Headers_to_display This is the list of headers to be displayed if showheaders is set to 1 (TRUE). They can be listed comma or space separated all on a single line. If it contains the special character ``*'' .B hypermail will display all header lines. .TP .B format_flowed = boolean_number Set this option to 1 (TRUE) to support RFC 3676 format=flowed. When this option is enabled and a message says it is supporting format=flowed, hypermail will recreate a long-line that has been split into multiple lines as a single one. .TP .B format_flowed_disable_quoted = boolean_number Set this option to 1 (TRUE) if you want to disable RFC 3676 format=flowed processing on quoted line texts (the ones that begin with one or more '>' characters). This option is always disabled if .B format_flowed is not enabled. .TP .B readone = boolean_number Set this to .B 1 to specify there is only one message in the input. .TP .B inlinehtml = boolean_number This is used to make text/html parts to get inlined within the mail messages. If set to .B 0 , HTML-parts will be stored as separate files. .TP .B text_types = MIME types to be treated as text/plain. This is a list of MIME types that you want hypermail to treat exactly as if they were text/plain. This can be listed individually on multiple lines or comma or space separated on a single line. .TP .B prefered_types = which alternative types to use When mails using multipart/mixed types are scanned, this is the list of alternative MIME types that you want used. This can be listed individually on multiple lines or comma or space separated on a single line. Note: Order is important. .TP .B inline_types = which_image_types_should_be_inlined This is the list of MIME types that you want inlined as opposed to simply linked into the message. They can be listed individually on multiple lines or comma or space separated on a single line. .TP .B inline_addlink = boolean_number Enable add inline links to content that is stored in the attachments subdirectory. Option .B inline_types must also be enabled. This option is .B enabled by default. .TP .B ignore_types = types_of_MIME_attachments_to_ignore This is the list of MIME attachment types that you do not want to do anything with. They are quietly ignored. They can be listed individually on multiple lines or comma or space separated on a single line. .TP .B applemail_mimehack = [ 0 | 1] In a multipart/alternative message, Apple Mail (as of June/2018) is only adding attachments to the text/html related part. Set this option to .B On to force the display of all alternate parts when processing an Apple Mail message. If the message has only a text/plain and a text/html alternatives and the preference is for text/plain, the text/html alternative won't be displayed. This option won't be taken into account if your .B prefered type is text/html or if you enabled the .B save_alts option. .B Disabled by default. .TP .B searchbackmsgnum = postive integer If the linkquotes option is on and an incremental update is being done (-u option), this controls the tradeoff between speed and the reliability of finding the right source for quoted text. Try to set it to the largest number of messages between a message and the final direct reply to that message. .TP .B link_to_replies = [ string | NONE] If the linkquotes option is on, specifying a string here causes it to generate links from original quoted text the location(s) in replies which quote them. The string is used to display the link. .TP .B quote_hide_threshold = percent (integer) If the linkquotes option is on, setting this to an integer less than 100 will cause it to replace quoted text with one-line links if the percent of lines in the message body (exluding the signature) consisting of quoted text exceeds the number indicated by this option. .TP .B quote_link_string = [ string | NONE ] If the quote_hide_threshold option is being used, the quote_link_string will be used if available to display the link that replaces the quoted text. If no string is specified here, the first line of each section of quoted text will used. .TP .B monthly_index = [ 0 | 1 ] Set this to On to create additional index files broken up by month. A summary.html file will provide links to all the monthly indices. .TP .B yearly_index = [ 0 | 1 ] Set this to On to create additional index files broken up by year. A summary.html file will provide links to all the yearly indices. .TP .B thread_file_depth = [ 0 | 1 ] If nonzero, break the threads index file into multiple files, with the initial message of each thread in the main index file along with links to files containing the replies. Setting this to 1 creates one file for each thread that has replies, and is recommended for archives with over a few hundred messages. Setting this greater than 1 will produce multiple levels of files for each thread whose replies are nested by more than 1 level, but that is rarely useful. This option is currently disabled if the indextable option is turned on, and probably needs to be less than thrdlevels. .LP .SH HTML TEMPLATE FILE SUBSTITUTION COOKIES .LP You can insert "substitution cookies" in the header and footer HTML template files so appropriate information can be filled in at runtime. .LP .B Substitution cookies supported: .LP .nf %% - '%' character %~ - Storage directory %e - Email addres of message author - Not valid on index pages %h - HMURL %i - Message-id - Not valid on index pages %l - Archive label %m - Mailto address %p - PROGNAME %s - Subject of message or Index Title %v - VERSION %u - Expanded version link (HMURL,PROGNAME,VERSION) \\n - newline character \\t - tab character .nr .LP .B Additional cookies generate the complete META lines: .LP .nf %A - Author META TAG - Not valid on index pages %D - Date META TAG - Not valid on index pages %S - Subject META TAG .nr .TP ================================================ FILE: docs/hmrc.html ================================================ Hypermail - hmrc list configuration

   Hypermail List Configuration File


The hypermail list configuration file is used to specify list specific or user specific information to hypermail. Comments are denoted by the '#' character at the begining of the line. The file to use can be specified via the -c command line argument. The default file is .hmrc in the user's home directory.

Examples listed on this page are shown in this style. The default value is shown unless otherwise indicated. Off is equivalent to 0, and On is equivalent to 1 for options which are either on or off.

Options affecting both messages and index pages

Locale

language = [ two-or-more-letter-language-id ]
This is a two-letter string specifying the default language to use, or a longer string specifying a language and locale. Set this the value of the language table you wish to use when running and generating archives. See also iso2022jp and eurodate.

Current supported languages, with their default locales:

de (de_DE) - German
en (en_US) - English
es (es_ES) - Spanish
fi (fi_FI) - Finnish
fr (fr_FR) - French
el (el) - Greek
gr (el_GR) - Greek
is (is_IS) - Icelandic
no (no_NO) - Norwegian
pl (pl_PL) - Polish
pt (pt_BR) - Brazilian Portuguese
ru (ru_RU) - Russian
sv (sv_SE) - Swedish

The directory /usr/share/i18n/locales on many systems has the locale codes that are available on that system.

language = en
iso2022jp = [ 0 | 1 ]
Set this to On to support ISO-2022-JP messages.

iso2022jp = 0
i18n = [ 0 | 1 ]
Enable I18N features, hypermail must be linked with libiconv.

i18n = 1 (disabled by default)
eurodate = [ 0 | 1 ]
Set this to reflect how you want dates displayed in the index files.
Set as 1 to to use European date format "DD MM YYYY".
Define as 0 to to use American date format "MM DD YYYY".

eurodate = 0
dateformat = strftime-date-format
Format used in strftime(3) call for displaying dates.
See strftime(3) for the valid conversion specifications.

dateformat = "%D-%r Z" (disabled by default)
isodate = [ 0 | 1 ]
Set this to On to display article received dates in YYYY-MM-DD HH:MM:SS format. If used with the gmtime option, a Z will be inserted between the DD and HH.

isodate = 0
gmtime = [ 0 | 1 ]
Set this to On to display article received dates using Greenwich Mean Time (UTC) rather than local time.

gmtime = 0

Header options

label = [ Title | NONE ]
This is the default title you want to call your archives.
Set this to NONE to use the name of the input mailbox.

label = Hypermail Development List (default value is filename?????)
hmail = [ Mailing List Submission Address | NONE ]
Set this to the list's submission address. When enabled, this can be used to submit a new message to the list served by the hypermail archive. "NONE" means don't use it.

hmail = hypermail@hypermail.org (disabled by default)
newmsg_command = [ string ]
This specifies the mail command to use when converting the set_hmail address to links in replies. The variables $TO, $SUBJECT, and $ID can be used in constructing the command string.

newmsg_command=mailto:$TO
replymsg_command = [ string ]
This specifies the mail command to use when converting the set_hmail address to links in replies. The variables $TO, $SUBJECT, and $ID can be used in constructing the command string. The value from the mailcommand option will be used if this option is not specified.
There may be browsers that will benefit from adding something like
%26In-Reply-To=&lt;$ID&gt;
to the command, but I've heard no reports of this actually working.

replymsg_command=mailto:$TO?Subject=$SUBJECT
inreplyto_command = [ string ]
This specifies a URI template to a script that hypermail will link to if it's unable to find in the archive's messages the MID corresponding to an In-Reply-To header. The variable $ID is used to specify where the Message-Identifier value will appear in the link.

inreplyto_command = http://example.org/mid-resolver/$ID. (disabled by default)

Miscellaneous

stripsubject = [ string | NONE ]
A string to be stripped from all subject lines. Helps unclutter mailing lists which add tags to subject lines.

stripsubject = NONE
mailcommand = [ direct mailto | cgi-bin script path | NONE ]
This is the mail command that email links go to, for instance "mailto:$TO" or "/cgi-bin/mail?to=$TO&replyto=$ID&subject=$SUBJECT"
In constructing this command, you can specify variables:

$TO : the email address of the person you're sending mail to.
$ID : the ID of the message you're replying to.
$SUBJECT: the subject you're replying to.

NONE disables mailcommand usage.
There may be browsers that will benefit from adding something like
%26In-Reply-To=&lt;$ID&gt;
to the command, but I've heard no reports of this actually working.

mailcommand = mailto:$TO?Subject=$SUBJECT
mailto = [ email-address | NONE ]
The address of the contact point that is put in the HTML header line
<LINK REV=made HREF=mailto:mailto>

The <LINK...> header can be disabled by default by setting mailto to NONE.

mailto = webmaster@hypermail.org (disabled by default)
domainaddr = [ domainname | NONE ]
Domain-ize Addresses -- addresses appearing in the RFC2822 field which lack hostname can't be made into proper HREFs. Because the MTA resides on the same host as the list, it is often not required to domain-ize these addresses for delivery. In such cases, hypermail will add the DOMAINADDR to the email address.

domainaddr = hypermail.org (disabled by default)
use_sender_date = [ 0 | 1 ]
Set this to On to have it use the Date: header (created by the the system that sent the message) rather than the date/time the message was received, for purposes such as putting in folders or sorting. Details of which purposes this affects may change in the future.

use_sender_date = 0
fragment_prefix = [ preifx ]
Put this string before the message number in each URI fragment.

fragment_prefix = id (default is msg)
email_address_obfuscation = [ 0 | 1 ]
Set to 1 to enable email address obfuscation using numeric character references.

mail_address_obfuscationx = 1 (disabled by default)

Index page options

Index availability

folder_by_date = [ strftime-date-format ]
This string causes the messages to be put in subdirectories by date. The string will be passed to strftime(3) to generate subdirectory names based on message dates. Suggested values are "%y%m" or "%b%y" for monthly subdirectories, "%Y" for yearly, "%G/%V" for weekly. Do not alter this for an existing archive without removing the old html files. If you use this and update the archive incrementally (e.g. with -u), you must use the usegdbm option.

folder_by_date = %y%m (disabled by default)
monthly_index = [ 0 | 1 ]
Set this to On to create additional index files broken up by month. A summary.html file will provide links to all the monthly indices.

monthly_index = 0
msgsperfolder = integer
Put messages in subdirectories with this many messages per directory. Do not use this and folder_by_date on the same archive. Do not alter this for an existing archive without removing the old html files. Deleted/expired messages are counted for the purpose of deciding how many messages to put in a subdirectory.

msgsperfolder = 100 (disabled by default)
yearly_index = [ 0 | 1 ]
Set this to On to create additional index files broken up by year. A summary.html file will provide links to all the yearly indices.

yearly_index = 0
defaultindex = [ thread | date | subject | author | attachment ]
This indicates the default type of main index hypermail will generate. Users see this type of index when the archive is first accessed. When using the folder_by_date or msgsperfolder options, this option applies to subdirectories.

defaultindex = thread
default_top_index = [ folders | thread | date | subject | author | attachment ]
This specifies the default index that users can view when entering the top level of an archive that uses the folder_by_date or msgsperfolder option.

default_top_index = folders
avoid_indices = [ string ]
This is a list of index files to not generate. Valid types are date, thread, author, and subject. They can be listed individually on multiple lines or comma or space separated on a single line. When using the folder_by_date or msgsperfolder options, this option applies to subdirectories.

avoid_indices = subject author (disabled by default)
avoid_top_indices = [ string ]
This is a list of index files to not generate for the top directory of an archive using the folder_by_date or msgsperfolder option. Valid types are date, thread, author, subject, folders, and attachment.

avoid_top_indices = date thread author subject
attachmentsindex = [ 0 | 1 ]
Set this to Off to make hypermail not output an index of messages with attachments.

attachmentsindex = On
latest_folder = [ string ]
If folder_by_date or msgsperfolder are in use, create a symbolic link by this name to the most recently created subdirectory. Note that many web servers are configured to not follow symbolic links for security reasons. The link will be created in the directory specified by the "dir" or "-d" option.

latest_folder = current (disabled by default)
noindex_onindexes = [ 0 | 1 ]
Tells hypermail to add a noindex metadata to its generated message indexes (by author, etc.), to instruct robots to not index the indexes. See anontated for further discussion on noindex.

noindex_onindexes = 0

Index body style

indextable = [ 0 | 1 ]
Setting this variable to 1 will tell Hypermail to generate a message index Subject/Author/Date listings using a table format. Set to 0 if you want the standard Hypermail index page look and feel.

indextable = 0
reverse = [ 0 | 1 ]
Setting this variable to 1 will reverse-sort the article entries in the date and thread index files by the date they were received. That is, the most recent messages will appear at the top of the index rather than the other way around. Set to 0 if you want latest message on the bottom for date and thread indexes.

reverse = 0
reverse_folders = [ 0 | 1 ]
Setting this variable to On will reverse-sort the list of folders. That is, the most recent folders will appear at the top of the index rather than the other way around.

reverse_folders = 0
thrdlevels = number
This specifies the number of thread levels to outline in the thread index. For instance, if thrdlevels is 2, replies to messages will be indented once in the index, but replies to replies, etc., will only be indented once as well. The normal value is 4.

thrdlevels = 4
thread_file_depth = [ 0 | 1 ]
If nonzero, break the threads index file into multiple files, with the initial message of each thread in the main index file along with links to files containing the replies. Setting this to 1 creates one file for each thread that has replies, and is recommended for archives with over a few hundred messages. Setting this greater than 1 will produce multiple levels of files for each thread whose replies are nested by more than 1 level, but that is rarely useful. This option is currently disabled if the indextable option is turned on, and probably needs to be less than thrdlevels.

thread_file_depth = 0
icss_url= [ URL | NONE ]
This option let's you specify an external stylesheet that you would like to link to the index files. The stylesheet will be linked to thru a LINK element in the HEAD in the document's HEAD.
By default, this option is deactivated.

icss_url = http://www.w3.org/StyleSheets/Mail/public-messagelist.css
describe_folder = format string
Controls the labels used in folders.html to describe the directories created by the folder_by_date or msgsperfolder options. For folder_by_date labels, the describe_folder string will be passed to strftime(3) the same as the folder_by_date string.
For msgsperfolder:
%d for the directory number (starts with 0)
%D for the directory number (starts with 1)
%m for the number of the first message in the directory
%M for the number of the last message that can be put in the directory.
The default is the value of folder_by_date if that is selected, "%d" for msgsperfolder.

describe_folder = "%b %Y"

Index headers/footers

archives = [ URL | NONE ]
This creates a link in the archived index pages labeled "Other mail archives". Set this to NONE to omit such a link.

archives = NONE
custom_archives = [ HTML text | NONE ]
If this variable is defined, a navigation entry will be created below the sorted_by_x list entry, with the text "Other mail archives: " followed by the value of this variable. Set it to NONE to ommit such an entry.

custom_archives = NONE
about = [ URL | NONE ]
This creates a link in the archived index pages labeled "About this archive". Set this to NONE to omit such a link.

about = NONE
ihtmlheaderfile = [ path to index header template file | NONE ]
Set this to the path to the Index header template file. The template file contains HTML directives and substitution cookies for runtime expansion.

ihtmlheaderfile = /lists/hypermail-idxheader.hyp (disabled by default)
ihtmlfooterfile = [ path to index footer template file | NONE ]
Set this to the path to the Index footer template file. The template file contains HTML directives and substitution cookies for runtime expansion.

ihtmlfooterfile = /lists/hypermail-idxfooter.hyp (disabled by default)

Message page options

Body style

showhtml = [ 0 | 1 | 2 ]
Set this to 1 to show the articles in a proportionally-spaced font rather than a fixed-width (monospace) font. Setting this option to 1 also tells Hypermail to attempt to italicize quoted passages in articles.
Set this to 2 for more complex conversion to html similar to that in txt2html.pl.
Showhtml = 2 will normally produce nicer looking results than
showhtml = 1, and showhtml = 0 will look pretty dull, but
1 and 2 run risks of altering the appearance in undesired ways.

showhtml = 1
href_detection = [ 0 | 1 ]
Set this to 1 to assume that any string on the body of the message that says <A HREF=" ... </A> is a URL, together with its markup and treat it as such.

href_detection = 0
showbr = [ 0 | 1 ]
Set this to 1 if you want article lines to end with the <br> tag. Else set to 0 to have non-quoted lines word-wrap. Only takes effect if showhtml is set to 1.

showbr = 1
iquotes = [ 0 | 1 ]
Set this to 1 if you want quoted lines to be shown in italics. Only take effect if showhtml is set to 1.

iquotes = 1
i18n_body = [ 0 | 1 ]
Translate message body into UTF-8. The i18n configuration option must be enabled.

i18n_body = 1 (disabled by default)
mcss_url= [ URL | NONE ]
This option let's you specify an external stylesheet that you would like to link to the message files. The stylesheet will be linked to thru a LINK element in the HEAD in the document's HEAD. By default, this option is inactive.

mcss_url = http://www.w3.org/StyleSheets/Mail/public-message.css
quote_hide_threshold = percent (integer)
If the linkquotes option is on, setting this to an integer less than 100 will cause it to replace quoted text with one-line links if the percent of lines in the message body (exluding the signature) consisting of quoted text exceeds the number indicated by this option.

quote_hide_threshold = 100
files_by_thread = [ 0 | 1]
Set this to 1 to generate (in addition to the usual files), a file for each thread that contains all the messages in that thread. The first line in each thread of the thread index page links to this file instead of to a single message.

files_by_thread = 0

Message page links

linkquotes = [ 0 | 1 ]
Set this to On to create fine-grained links from quoted text to the text where the quote originated. It also improves the threads index file by more accurately matching messages with replies. Note that this may be rather cpu intensive (see the searchbackmsgnum option to alter the performance).

linkquotes = 0
searchbackmsgnum = postive integer
If the linkquotes option is on and an incremental update is being done (-u option), this controls the tradeoff between speed and the reliability of finding the right source for quoted text. Try to set it to the largest number of messages between a message and the final direct reply to that message.

searchbackmsgnum = 500
link_to_replies = [ string | NONE]
If the linkquotes option is on, specifying a string here causes it to generate links from original quoted text the location(s) in replies which quote them. The string is used to display the link.

link_to_replies = NONE
quote_link_string = [ string | NONE ]
If the quote_hide_threshold option is being used, the quote_link_string will be used if available to display the link that replaces the quoted text. If no string is specified here, the first line of each section of quoted text will used.

quote_link_string = NONE
spamprotect = [ 0 | 1 ]
Set this to On to make hypermail not output real email addresses in the output HTML but instead it will obfuscate them a little. You can control the obfuscation with antispamdomain.

spamprotect = On
antispamdomain = string with invalid domain
By default the spamprotect option only does a small amount of massaging of email addresses. Use this to completely replace the domain from which a message originates (everything after the @) with some string to confuse screen-scraping programs. It is probably wise to make this an invalid mail domain.

antispamdomain = "email.domain.hidden" (disabled by default)
spamprotect_id = [ 0 | 1 ]
Set this to On to make hypermail not output real email message ids in HTML comments (sometimes used internally by hypermail) but instead it will obfuscate them a little so they don't look like email addresses to spammers.

spamprotect_id = On

Message page headers/footers

showreplies = [ 0 | 1 ]
Set to 1 to show all replies to a message as links in article files. If this is set to 0 no reply links are generated.

showreplies = 1
show_msg_links = [ 0 | 1 | 3 | 4 ]
Set this to 1 if you want links to Next, Prev, Next thread, Reply to, etc. displayed on the article pages. Setting this to 0 disables these links from appearing on the generated pages. Set it to 3 to produce those links only at the top of the message pages, or 4 to produce those links only at the bottom of the message.

show_msg_links = 1
show_index_links = [ 0 | 1 | 3 | 4 ]
Set this to 1 to show links to index pages from the top and bottom of each message file. Set it to 0 to avoid those links. Set it to 3 to show the links only at the top of the message pages, or 4 to produce those links only at the bottom of the message.

show_index_links = 1
showheaders = [ 0 | 1 ]
Set this to 1 to show the RFC 2822 message headers To:, From:, and Subject: information found in the email messages. Set to 0 if you want to hide mail headers in articles.

showheaders = 0
show_headers = List of RFC 2822 Headers to display
This is the list of headers to be displayed if showheaders is set to 1 (TRUE) They can be listed comman or space separated all on a single line such as
      show_headers = From,Subject,Date,Message-ID

or they can be listed individually or any combination of.

      show_headers = From
      show_headers = Subject
      show_headers = Date
      show_headers = Message-ID

If show_headers contains the special character ``*'', then hypermail will display all header lines.
NOTE: Do not put the ':' at the end of the headers.

show_headers = From,Subject,Date,Message-ID (disabled by default)
format_flowed [ 0 | 1 ] (EXPERIMENTAL)
Enable this option to support RFC 3676 format=flowed. When this option is enabled and a message says it is supporting format=flowed, hypermail will recreate a long-line that has been split into multiple lines as a single one.

format_flowed = 1 (disabled by default)
format_flowed_disable_quoted [ 0 | 1 ]
Use this option if you want to disable support for format=flowed inside quoted text (the lines starting with one or more '>' characters). This option is always disabled if format_flowed is not enabled.

format_flowed_disable_quoted = 1 (disabled by default)
mhtmlheaderfile = [ path to message header template file | NONE ]
Set this to the path to the Message header template file. The template file contains HTML directives and substitution cookies for runtime expansion.

mhtmlheaderfile = /lists/hypermail-msgheader.hyp (disabled by default)
mhtmlfooterfile = [ path to message footer template file | NONE ]
Set this to the path to the Message footer template file. The template file contains HTML directives and substitution cookies for runtime expansion.

mhtmlfooterfile = /lists/hypermail-msgfooter.hyp (disabled by default)

Attachments

inlinehtml [ 0 | 1 ]
Define to On to make text/html parts to get inlined with the mails. If set to Off, HTML-parts will be stored as separate files. A "Content-Disposition: attachment;" line in the mail will cause an HTML-part to be stored as a separate file even if this option is On.

inlinehtml = 1
usemeta [ 0 | 1 ]
This option allows you to use metadata to store the content type of a MIME attachments and, later on, when a user browses the attachment, send back this information in the HTTP Content-Type header. When set to 1, the Content-Type header of a MIME attachment will be stored in a metadata file.
Let us say that the MIME attachments for a message are stored in directory att-num. The metadata for those attachments will then be stored in directory att-num/.meta. If a MIME attachment is stored in file att-file, its metadata will be stored in file att-file.meta. This convention is directly compatible with the Apache server handling of metadata.

usemeta = 0
userobotmeta [ 0 | 1 ]
If a message has annotations for robots and usemeta is enabled, setting this option to 1 will associate the value of the annotations to each attachment using the experimental X-Robots-Tag HTTP header. For more information, browse Google's Robots Meta Tag documentation.

userobotmeta = 0
text_types = list of types to be the same as text/plain
This is a list of MIME types that you want hypermail to treat exactly as if they were text/plain. They can be listed individually on multiple lines or comma or space separated on a single line.

text_types = text, text/plain, message/rfc2822 (disabled by default)
inline_types = indicate data types data to be inlined
This is the list of MIME types that you want inlined as opposed to simply linked into the message. They can be listed individually on multiple lines or comma or space separated on a single line.

      inline_types = image/gif image/jpeg
or
      inline_types = image/gif
      inline_types = image/jpeg

inline_types = image/gif image/jpeg
inline_addlink = [ 0 | 1 ]
Set to On to add inline links to content that is stored in the\ attachments subdirectory. inline_types must be enabled.

inline_addlink = 1 (enabled by default)
prefered_types = multipart/mixed types to present
When mails using multipart/mixed or multipart/alternative types are scanned, this list of MIME types defines which part you want presented in the result.

prefered_types = text/plain, text/html
ignore_types = indicate types of attachments to ignore
This is the list of MIME attachment types that you do not want to do anything with. They are quietly ignored and are not processed. They can be listed individually on multiple lines or comma or space separated on a single line.

Two special types may be used here:
$BINARY - ignore all types that would be stored as separate files.
$NONPLAIN - ignore all types not treated as text/plain, and all $BINARY types.
Note: the behavior of these may be affected by the inlinehtml option.


      ignore_types = text/x-vcard application/x-msdownload
or
      ignore_types = text/x-vcard
      ignore_types = application/x-msdownload

ignore_types = text/x-vcard
ignore_types = application/x-msdownload

attachmentlink = attachment-link-format
Format of the attachment links.

%p for the full path to the attachment
%f for the file name part only
%d for the directory name only
%n for the message number
%c for the content type string

attachmentlink = "%p"
applemail_mimehack [ 0 | 1 ]
In a multipart/alternative message, Apple Mail (as of June/2018) is only adding attachments to the text/html related part. Set this option to On to force the display of all alternate parts when processing an Apple Mail message. If the message has only a text/plain and a text/html alternatives and the preference is for text/plain, the text/html alternative won't be displayed. This option won't be taken into account if your prefered type is text/html or if you enabled the save_alts option.
applemail_mimehack = 0 (disabled by default)
unsafe_chars = list of chars to prohibit
Any characters listed in this string are removed from user-specified attachment filenames. Those characters will be replaced by a "_" (which means that specifying "_" here won't have any effect). Note that many characters (including / and \) are removed by the safe_filename in parse.c regardless of what this option says. There might be some security problems that can be prevented if you specify "." here (e.g. if a web server is configured to enable server side includes on filenames ending in something other than .shtml), but that will prevent browsers from recognizing many file types.

unsafe_chars = "." (disabled by default)
save_alts = [ 0 | 1 | 2 ]
This controls what happens to alternatives (other than the prefered alternative) for multipart/alternative messages.
0 - discard non-prefered alternatives
1 - show all alternatives inline
2 - put non-prefered alternatives in a separate file.

save_alts = 0
alts_text = descriptive text
If save_alts is 1, this text is put between the alternatives.
If save_alts is 2, this text is used to describe the link to each alternative file.

alts_text = "alternate version of message" (the default if save_alts = 2)
alts_text = "<hr>" (the default if save_alts = 1)

System administration

Message input

increment = [ -1 | 0 | 1 ]

Define as 1 to append all input messages to the end of existing archives.
Define as 0 for it to read a mailbox that corresponds to the entire archive. (See the mbox_shortened option for an exception to the requirement that it be the entire archive). If there are any existing html messages, it will figure out which ones at the end of the mailbox are new, and add only those that haven't been converted yet.
Define as -1 to have hypermail figure out whether the input is entirely new messages to be appended or whether it contains messages that are already in the archive. A value of -1 cannot be used with the mbox_shortened option or with the -i command line option or with mbox = NONE.

increment = 0
readone = [ 0 | 1 ]
Set this to 1 to specify there is only one message in the input.

readone = 0
mbox = [ filename | NONE ]
This is the default mailbox to read messages in from. Set this with a value of NONE to read from standard input as the default.

mbox = NONE
mbox_shortened = [ 0 | 1 ]
Set this to 1 to enable use of mbox that has had some of its initial messages deleted. Requires usegdbm = 1 and increment = 0. The first message in the shortened mbox must have a Message-Id header. If discard_dup_msgids is 0, the first message in the shortened mbox may not have the same Message-Id as a message that was deleted. The mbox may not be altered in any way other than deleting from beginning of the mbox or appending new messages to the end (unless you rebuild the archive from scratch using a complete mbox).

mbox_shortened = 0
ietf_mbox = [ 0 | 1 ]
Setting this variable to 1 will tell hypermail that the mbox is formatted according to the IETF mbox convention: all lines, except for the envelope, are prefixed with a > char.

ietf_mbox = 0
discard_dup_msgids = [ 0 | 1 ]
Set this to 0 to accept messages with a Message-ID matching that of a message already in this archive. By default such messages are discarded.

discard_dup_msgids = 1
require_msgids = [ 0 | 1 ]
Set this to 0 to accept messages without a Message-ID header.
Set this to 1 to discard messages without a Message-ID header.
By default such messages are discarded.

require_msgids = 1

Message Filtering

Regular expression support is provided by the PCRE  library package, which is open source software, written by Philip Hazel, and copyright by the University of Cambridge, England.

The full body searches can be slow, and do not match multi-line strings in message bodies. A string that spans multiple lines of a header can be matched.

filter_out = expression
Delete from the html archives any message having a header line which matches any of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions.

The following examples should reject messages Cc'd to more than 3 addresses or from any address at spammers.com. This option is disabled by default.

filter_out=Cc:([^,]*,){3}
filter_out=From:.+@spammers.com

filter_require = expression
Delete from the html archives any message not having header lines which match each of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions.

filter_require =
filter_out_full_body = expression
Delete from the html archives any message having a line which matches any of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions.

filter_out_full_body =
filter_require_full_body = expression
Delete from the html archives any message not having lines which match each of these expressions. Uses the same rules for deletion as the expires option. The expressions use the same syntax as Perl regular expressions.

filter_require_full_body =

Filesystem output

dir = [ directory path | NONE ]
This is the default directory that Hypermail uses when creating and updating archives. If set to NONE, the directory will have the same name as the input mailbox.
Note that the date that Hypermail was run will be used, not a date from the message (use the folder_by_date option to have Hypermail use dates from messages).

dir = NONE
overwrite = [ 0 | 1 ]
Set to 1 to make Hypermail rewrite all messages.
Set to 0 to rewrite as few messages as possible.
Rewriting all messages is slower, but if you change the options that control the appearance of the messages you may want to rewrite all the messages to make the appearance consistent throughout the archive. (This defaulted to 1 for most versions 2.0 through 2.1.3, presumably to encourage archives that upgraded to have a single style. The default was changed back to 0 after 2.1.3).

overwrite = 0
htmlsuffix = [ html | htm | shtml ... ]
Use this to specify the html file suffix to be used when Hypermail generates the html files. This is dependent on local needs. Do not put a '.' in the value. It would result in "file..html", probably not what you want.

htmlsuffix = shtml
dirmode = octal number
This is an octal number representing the rwx modes that new directories are set to when they are created. If the archives will be made publically available, it's a good idea to define this as 0755. This must be an octal number.

dirmode = 0755
filemode = octal number
This is an octal number representing the permission modes that new files are set to when they are created. If the archives will be made publically available, it's a good idea to define this as 0644. This must be an octal number.

filemode = 0644
filename_base = [ string ]
This option overrides the normal rules for creating attachment file names, and creates file names from the string that this option is set to plus a file name extension if one can be found in the name supplied by the message. This option is mainly for languages that use different character sets from English.

filename_base = attachment (disabled by default)

System miscellaneous

usegdbm = [ 0 | 1 ]
Set this to 1 to use gdbm to implement a header cache. This will speed up hypermail, especially if your filesystem is slow. It will not provide any speedup with the linkquotes option.

usegdbm = 0
writehaof = [ 0 | 1 ]
Set this to On to let hypermail write an XML archive overview file in each directory. The filename is archive_overview.haof.

writehaof = 0
append = [ 0 | 1 ]
Set this to On to maintain a parallel mbox archive. The file name defaults to mbox in the directory specified by -d or dir.

append = 1
append_filename = [ string ]
Specifies the filename to be used by the append option. $DIR may be used to specify a name relative to the directory specified in the -d or dir option. The string will be passed to strftime(3) to allow splitting the mailbox into yearly or monthy files, such as "%Y-%m.mbox".

append_filename = $DIR/INBOX
txtsuffix = [ string ]
If you want the original mail messages archived in individual files, set this to the extension that you want these messages to have (recommended value: txt).

txtsuffix = txt (off by default)
annotated = list of headers used to indicate deletion
This is the list of headers that indicate that a message contains an annotation. Options disabled by default.

In an annotated message, the values of the header specify the type of annotations. The header may have one or more comma-separated values. Order and case are not important. Hypermail recognizes two types of annotations: content and robot annotations.

Content annotations give information to the reader about how an archive maintainer has operated on an original received message. This operation typically happens as a belated action, for example, when removing spam from an existing archive. Content annotations can have one, and only one, of the following values:
spam
message deleted because it is spam;
deleted
message deleted, other reasons;
edited
original received message was manually edited.

If a message specifies more than one content annotation, only the first one will be taken into account. You can customize the markup that\'s shown for content annotations by means of the htmlmessage_deleted_other, htmlmessage_deleted_spam, and htmlmessage_edited directives. See also the delete_level option for more info about what happens to a deleted message.

Robot annotations instruct a visiting web robot if a the contents of a message should be indexed and/or if the outgoing links from the message should be followed, doing so thru a specific HTML meta tag (browse About the Robots <META> tag for further details).
Robot annotations can have either one or both of the following values:
nofollow
don't follow outgoing HTML links from this file;
noindex
don't index this message.

You can use one or both robot annotation values and combine them with the edited content annotation. Note that spam and deleted annotations have an implicit robot noindex annotation. In such case, user supplied robot annotations values will be silently ignored.

Use userobotmeta for associating attachments with annotations for robots.

Note that the list maintainer must be careful on whether to accept incoming messages containing the annotated header. If the policy is not to allow that header on incoming messages, it must be filtered out before the message is stored or acted upon by hypermail.

In an hmrc file:
annotated = X-Hypermail-Annotated (off by default)
In a message:
X-Hypermail-Annotated: edited, noindex
deleted = list of headers used to indicate deletion [DEPRECATED]
This is the list of headers that indicate the message should not be displayed if the value of this header is 'yes'. See the delete_level option for more info about what happens to the message.
NOTE: This option has been deprecated if favor of annotated. However, it will still be parsed and honored to take into account legacy archives.

deleted = X-Hypermail-Deleted X-No-Archive
expires = list of headers used to indicate expiration
This is the list of headers that indicate the message should not be displayed if the value of this header is a date in the past. See the delete_level option for more info about what happens to the message.

expires = Expires
delete_older = date/time string
Any message older than this date should not be displayed. See the delete_level option for more info about what happens to the message. Any date format that works in the Date: header line of an email message should work here.

delete_older = "Wed, 14 Mar 2001 12:59:51 +0200" (off by default)
delete_newer = date/time string
Any message newer than this date should not be displayed. See the delete_level option for more info about what happens to the message. Any date format that works in the Date: header line of an email message should work here.

delete_newer = "Wed, 28 Mar 2001 12:59:51 +0200" (off by default)
delete_msgnum = list of message numbers
This is the list of message numbers that should be deleted from the html archive. The mbox is not changed. See the delete_level option for more info about what happens to the message.

delete_msgnum = 42 666 (off by default)
delete_level = [ 0 | 1 | 2 | 3 ]

0 - remove deleted and expired files. Note that with this choice threading may be screwed up if there are replies to deleted or expired options and the archive is updated incrementally
1 - remove message body
2 - remove message body for deleted messages, leave expired messages
3 - leave all messages
Deleted and expired messages are removed from the index files regardless of the delete_level selection.

delete_level = 1
delete_incremental = [ 0 | 1 ]

If this option is enabled, hypermail will perform deletions on old messages when run in incremental mode (according to the other delete configuration options). Note that depending on your hypermail setup, the size of the archive, and the complexity of the markup, there may be memory and parsing issues, specifically when there are non-deleted replies to a deleted message. If this option is disabled, deleted messages will only be removed when rebuilding the whole archive.

delete_incremental = 0 (enabled by default)
htmlmessage_edited = [HTML markup string]

Custom markup to use in the body of manually edited message when delete_level is equal or superior to 2.

htmlmessage_edited = <div class="edited"><img src="http://example.org/Mail/edited.png" alt="original message edited" /> <p class="editedmmes">The originally received message was edited by the archive maintainer.</p><p class="spamfooter">The editing of this email is consistent with <a href="http://example.org/Mail/">example.org's Mailing List and Archive Usage Policy.</a></p></div> (disabled by default)
htmlmessage_deleted_other = [HTML markup string]

Custom markup to use in the body of deleted messages (by reasons other than spam) when delete_level is equal or superior to 2.

htmlmessage_deleted_spam = <div class="deleted"><img src="http://example.org/Mail/deleted.png" alt="email removed" /> <p class="deletedmmes">This message was removed from our mail archives by the archive maintainer.</p><p class="deletedfooter">The removal of this email is consistent with <a href="http://example.org/Mail/">example.org's Mailing List and Archive Usage Policy.</a></p></div> (disabled by default)
htmlmessage_deleted_spam = [HTML markup string]

Custom markup to use in the body of deleted messages (by spam reasons) when delete_level is equal or superior to 2.

htmlmessage_deleted_spam = <div class="spam"><img src="http://example.org/Mail/noUCE.png" alt="unsolicited bulk email removed" /> <p class="spammes">This message was determined to be unsolicited bulk email and has been removed from our archives.</p><p class="spamfooter">The removal of this email is consistent with <a href="http://example.org/Mail/">example.org's Mailing List and Archive Usage Policy.</a></p></div> (disabled by default)
progress = [ 0 | 1 | 2 ]
Set to 1 or 2 to show progress as Hypermail works. Set to 0 for silent operation. Output goes to standard output. Set to 1, progress information relating to attachments creation is overwritten for each new attachment. Set to 2, attachment creation information is listed individually with the number of the message the attachments relates to.

progress = 0
warn_suppressions = [ 0 | 1 ]
Set this to 1 to get warnings (on stdout) about messages that are not converted because of they are missing a msgid (if require_msgids is On) or because one of the following options suppressed it: deleted expires delete_msgnum filter_out filter_require filter_out_full_body filter_require_full_body.

warn_suppressions = 1
uselock = [ 0 | 1 ]
Controls whether to use hypermail's built-in locking mechanism. By default, this option is set to 1. Set it to 0 if you have an external locking mechanism, like, for example, when using procmail or smartlist.

uselock = 0
locktime = number-of-seconds
The number of seconds that a lock should be honored when processing inbound messages before it is overridden.

locktime = 3600
base_url = url-of-main-archive-directory
The url of the archive's main directory. This is needed when the latest_folder option is used and the folder_by_date makes directories more than one level deep (e.g. with '%y/%m').

base_url = http://www.hypermail-project.org/archive/
report_new_folder = [ 0 | 1 ]
Set this to On to have it print (on stdout) the names of any new directories created pursuant to the folder_by_date or msgsperfolder option, or the initial creation of the archive. It will print the full path if that is what you use to specify the archive directory. Does not print anything when attachment or metadata directories are created.

report_new_folder = 0
report_new_file = [ 0 | 1 ]
Set this to On to have it print (on stdout) the names of any new files created for new messages. It will print the full path if that is what you use to specify the archive directory.
report_new_file = 0

See Also
hypermail(1),   hmrc(4),   Hypermail   and   Customizing Hypermail Pages and Adding a Search Engines to your Hypermail Archive
Last updated February 6, 2013
================================================ FILE: docs/hypermail-faq.html ================================================ Hypermail Frequently Asked Questions

Hypermail Frequently Asked Questions

----

This is the beginning of the Hypermail FAQ. Don't dispair that there is little here. That will change shortly.

Table of Contents

  1. Why is the License Different ?
  2. Will hypermail run on my system ?
  3. What Happened to EIT ?
  4. Where in the World is Kevin Hughes ?
  5. What is the latest version of Hypermail ?
  6. Where can I get the latest version of Hypermail ?
  7. How can I split the archives into months ?
  8. How do I change the font on the pages ?
  9. What is HM_MAILTO used for ?
  10. Can I send a message to the list from the web archive ?
  11. Can I build and run this on Windows 98/2000/NT ?
  12. How can I remove a listserver subject prefix ?
  13. Which configuration file should I use ?
  14. Why is the downloaded file name different when I download hypermail.tar.gz ?
  15. Can I throttle hypermail's CPU usage ?
  16. How can I make my archive searchable ?
  17. How does hypermail decide whether messages are in the same thread?
  18. How can I have multiple mailboxes produce one archive?
  19. I have received an email with attachment that needs octet-stream. What should I do?
  20. Why is Hypermail ignoring some messages?
  21. Bogus dates are causing some emails to be put in a strange folder. Is there an easy way around this?

----

1. Why is the License Different ?

Hewlett-Packard (who is now the legal owner of Hypermail, since EIT was bought by VeriFone, which was bought by Hewlett-Packard) has put it under the GNU license, a widely used "free software" license. This means that you can use and modify the source code as long as you make your changes publically available and do not charge for their use (although, under GNU, you can charge for their distribution). More details are available at http://www.fsf.org/ and http://www.fsf.org/copyleft/gpl.html.

----

2. Will hypermail run on my system ?

Hypermail can compile and run as-is on most of the more popular UNIX systems today. If you're not sure if hypermail will run on your UNIX system, try compiling it and see!

Hypermail has been reported to work on MacOSX (X.2.6), with the advice to use --disable-shared and manually execute make in src/pcre.

People have indeed ported hypermail to DOS, Windows 95, and Windows NT (but not Java ...yet). Installation advice for some Windows systems is available at win32.html.

----

3. What Happened to EIT ?

A very old and established government contractor company called Electronic Instrumentation and Technology Inc. made legal moves to obtain the eit.com domain. Since VeriFone/HP had no interest in keeping EIT, they dissolved it completely some months ago. This company had a trademark on EIT so the domain name was given to them. (Thank you InterNic...)

----

4. Where in the World is Kevin Hughes ?

Kevin has not dropped off the face of the earth but is extremely busy these days as a Hypermedia Engineer at Veo Systems.

Kevin Hughes
kev@kevcom.com
kevinh@veosys.com
(650) 858-7710 (office number)
(650) 858-4925 (fax)
www.veosystems.com

----

5. What is the latest version of Hypermail ?

The latest stable version of Hypermail is Version 2.1.9. It is available from http://www.hypermail-project.org

----

6. Where can I get the latest version of Hypermail ?

The latest version of Hypermail is available from the Hypermail Development Center at SourceForge and/or at

http://www.hypermail-project.org/

It and past versions are also available via FTP from

ftp://ftp.hypermail.org/hypermail/

The cvs server at :pserver:cvs@cvs.hypermail.org:/CVS usually has a more recent but less tested version.

----

7. How can I split the archives into months ?

I have a fat archive that I'd like to split up by month, like I see so many others doing. Is there a description somewhere of a procedure to follow, or will I just have to think it through?

If you are using version 2.1.0 or later and either have gdbm or don't do incremental updates, see the folder_by_date option. The simple way to use this is to add these to your .hmrc:

folder_by_date="%y%m"
usegdbm = 1
and regenerate your archive from its mbox file.

An older alternative is a set of scripts in a directory named archive/ that has tools to do just what you want to do.

If you want index files split by month but don't need to split the archive into multiple directories, try adding "monthly_index=1" in your config file (usually ~/.hmrc) (available in version 2.1). A summary.html file will provide links to all the monthly indices. This is probably appropriate for archives with a few thousand messages, but for larger archives I recommend splitting into multiple directories.

There's a script at http://users.netrus.net/troc/perl.html called mms (monthly mail splitter) which has also been reported useful.

----

8. How do I change the font on the pages ?

What I'd like to do is change the font of the archives pages. I tried doing this by adding a <FONT FACE=...> tag in the header.hyp file and a <FONT> tag in the footer file, but it didn't work. Is there something in the program itself that's preventing me from making this change?

Yes and no. Let me guess... You have hm_usetable = 1. The code for tables is not inheriting the FONT values and that they need to be set in the <TH..> tags. If tables are not used it works as expected.

To test it put a

<FONT SIZE="1" FACE="GENEVA,ARIAL,HELVETICA">
in the test-index.hyp and test-msg.hyp. In test-footer.hyp put
</FONT>

With hm_usetable = 1 in the test.rc file, then ran "hypermail -c test.rc -m testmail" and everything between the "menus" was the right FONT but the menus were not.

Then edit the test.rc file and set hm_usetable = 0. Next remove the existing testdir and rerun hypermail again. This time the FONT works as expected.

Is this what is happening to you ? If so the code will need to be modified.

----

9. What is HM_MAILTO used for ?

I've enabled this option in .hyprc (the configuration file to which the pipe script for my archive points). Unlike the other options, this one does not create a link to mailto:admin@domain.com as I would expect. Any ideas?

HM_MAILTO has a couple different uses. One is to trigger the insertion of the <LINK REV=made HREF=mailto:...> header in the HTML sources. This is most useable with ascii browsers such as lynx.

hm_mailto = [ email-address | NONE ]
#
# The address of the contact point that is put in the HTML header line
# <LINK REV=made HREF=mailto:hm_mailto>
#
# The <LINK...> header can be disabled by default by setting
# mailto to NONE.

It can also be used in a hypermail page template file since it resolves to %m.

For example, your footer file might look like...

<P ALIGN=CENTER><IMG SRC="/images/bar.png" WIDTH="400" HEIGHT="4" ALT="---------"></P>
<ADDRESS>
<EM>
<SMALL>
This archive was generated by %u on %g
<P ALIGN=CENTER>
Send administrative comments to<A HREF="mailto:%m">%m</A>
</P>
</SMALL>
</EM>
</ADDRESS>
</BODY>
</HTML>

In this case the %m is expanded to admin@domain.com.

----

10. Can I send a message to the list from the web archive ?

I would like to add a link to the menu that says "Send a Message to the List." I read through the documentation on your website, and I think I know what I have to do. However, I cannot find an example of what a .hyp template file should look like.

That's what "Respond" on the menubar does. It allows a person to reply to the existing message, with the reply sent to the list address. And "mail a new topic" on the menubar allows a user to send a new message to the list.

To enable this feature set


hm_hmail = listaddr@your-site.domain

----

Can I build and run this on Windows 98/2000/NT ?

I would like to use Hypermail on my Windows box. Can I ? If so how do I build the latest version ?

There is a complete description on how to build hypermail on a Windows system at win32.html. This was written by Bob Crispen <bob.crispen@boeing.com>. (Thanks Bob!)

----

How can I remove a listserver subject prefix ?

The Subject index page does not seem to do the right sorting. My list has a "subject prefix" so people can filter their inbound mail better. Is that confusing the sorting ?

Yes. Hypermail functions that deal with replies look for the Re: and return a pointer to the subject line after the "Re: ". The listserver software is prefixing the subject line contents with [subject-prefix]. For example:

Initial message:

Subject: [subject-prefix] the subject of the message

Replies:

Subject: [subject-prefix] Re: the subject of the message

The best solution is to use the directive

stripsubject = [subject-prefix]
in the config file for that list. Then [subject-prefix] is stripped before the Reply processing occurs and the proper things happen. This is the proper fix since hypermail would need to know to strip the [subject-prefix] from the initial messages to get it right.

----

Which configuration file should I use ?

Which configuration file should I use ?. Is it the hypermail.rc file in the Configs directory? I'm trying to edit the appearance of pages created by hypermail, but I think I'm trying to edit the wrong config file.

With one of the later versions you can use the -v option to generate a config file that you can use. There is not just one config file. What are included are examples.

$ hypermail -v > some-file.rc
Edit the some-file.rc and set the values to what you want.

Then run hypermail using the config file by:

$ hypermail -c some-file.rc.

----

Why is the downloaded file name different when I download hypermail.tar.gz ?

The source is available from

www.hypermail.org/hypermail.tar.gz
However: When downloading though IE v4 browser on an NT PC, you get a file called hypermail_tar.tar.

Depending on your browser MIME type setup and support applications, the filename downloaded might be hypermail.tar, hypermail.tar.gz, etc. In any case, you will be informed as to the filename when you actually download it onto a Windows/NT PC. Use that name from that point forward.

----

Can I throttle hypermail's CPU usage ?

I'm looking for a good way to throttle hypermail. When it runs it is taking over both CPU's on my system. Is there a way to have it limit itself?

There is currently no "nice" call in hypermail to limit itself. Maybe we can consider it in the future. You might run it as a subcommand to nice. For example in an aliases file:

"|nice someval 'hypermail command line'"
I've NEVER tried this so... ;)

You might also be looking at a very large archive with lots of messages being the cause. If so then try breaking it up into smaller archives such as monthly archives. Tools are available for that in the latest release.

And if the list is a high traffic list, consider not running it from a sendmail alias and instead, run it from cron. (To assure it does not run unnecessarily, consider using 'make' to check dependencies on the inbound mailbox and the archive itself. If the mailbox is newer, then run the hypermail command. If not, then no new message have been received so don't bother running it.

If the you are using the linkquotes option and incremental update (-u option), add a searchbackmsgnum line to your config file. It controls the tradeoff between speed and the reliability of finding the right source for quoted text. Try to set it to the largest number of messages between a message and the final direct reply to that message.

----

How can I make my archive searchable ?

Where can I find a program that provides an easy way of adding a "search this archive" feature to my hypermail archive?

These seem to be the most popular choices:

Swish-E comes with a script (index_hypermail.pl) that is customized for indexing Hypermail archives. index_hypermail.txt has a description of how to use it.

You can also use search engines by putting text such as this on your web page (although this search produces results from an entire site, not just the email archive):
<form action=http://www.google.com/search>
<input type=text name=as_q>
<input type=hidden name=as_sitesearch value=hypermail-project.org>
<input type=submit value="Search Hypermail">
</form>

You can probably get more complete (but apparently not recent) info at: Search Engine Software For Your Web Site.

----

How does hypermail decide whether messages are in the same thread?

It uses the In-Reply-To: header if that is available. If not, it uses the References: header if that is available. If these are not available, it looks for previous messages with the same subject header. Matches based on the subject are listed as "maybe" replies.

If the linkquotes option is used, it will also search the message bodies of the previous searchbackmsgnum (default = 500) messages for text that looks like it is being quoted in the current message. If it finds one or more prior messages with such text matches, it will treat the one with the longest match as the message being replied to. The exact algorithms for deciding what is quoted text are a bit complex. These matches override the In-Reply-To: and References: info (this rule may deserve further thought).

----

How can I have multiple mailboxes produce one archive?

One simple way is to combine them into one mailbox, and send that to hypermail. Something like

"cat file1 file2 file3 > combined"
should do that.

Another way is to invoke hypermail several times, using the -u flag for any mailboxes that you want added after the html archive has been started:

 hypermail -m file1
 hypermail -u -m file2
 hypermail -u -m file3

Do not try to send hypermail more than one mailbox at a time, or send it a second mailbox without using the -u flag or the increment=1 or increment=-1 option.

----

I have received an email with attachment that needs octet-stream. What should I do?

No attachment "needs" octet-stream. octet-stream is a label that describes the attachment as being "a stream of octets". What is that you say? Well, the application didn't know any more specifics and thus it identified it as good as possible. It knows it is a stream of octets, nothing else.

So, an attachment coming as "octet-stream" can be pretty much ANYTHING. You have no idea, and neither does anyone else. The only way to figure out is to download the file and see for yourself, ask the person who mailed it or to hope that the mail it came with describes what the attachment was about.

"octet-stream" could just as well be named "I haven't got the slightest idea what this is, but I know it is built up with a series of bytes".

----

Why is Hypermail ignoring some messages?

One possibility is that those messages have a header saying

X-No-Archive: yes
which seems to indicate that the author doesn't want them included in any archive. This is controlled by a configure option which defaults to:
deleted = "X-Hypermail-Deleted X-No-Archive"
To get Hypermail to treat these as normal messages, add this to your config file (which is ~/.hmrc by default) or alter the "deleted" line in your existing config file to:
deleted = "X-Hypermail-Deleted"

----

Bogus dates are causing some emails to be put in a strange folder. Is there an easy way around this?

If the bad dates were caused by a computer with the date set absurdly, try running mailbox_date_trimmer.py, available in the Hypermail's contrib directory.

If the bad dates are in a format that Hypermail doesn't understand, then you will probably need to edit them manually.

----


Do you have a Hypermail related question you'd like to see listed here ? If so send mail to the Hypermail mailing list hypermail@hypermail-project.org   (preferably with the answers). In order to minimize spam on the list, you must subscribe to the list (at least temporarily) in order to send mail to it. You may subscribe to the list by sending a message with the word "subscribe" in the Subject: field to hypermail-request@hypermail-project.org.

 

================================================ FILE: docs/hypermail.1 ================================================ .TH HYPERMAIL 1 "June 24, 2000" .SH NAME hypermail \- convert mail archives in UNIX box format to HTML pages .SH SYNOPSIS .BR "hypermail " [ \-AgiMptTuvVxX1 ] .RB [ \-m .IR "mailbox" ] .RB [ \-d .IR "directory" ] .RB [ \-l .IR "label" ] .RB [ \-L .IR "language" ] .RB [ \-a .IR "URL" ] .RB [ \-b .IR "URL" ] .RB [ \-c .IR "file" ] .RB [ \-n .IR "listaddress" ] .RB [ \-o .IR "keyword=value" ] .RB [ \-s .IR "htmlsuffix" ] .RB [ \-0 .IR "number" ] .RB [ "mailbox" ] .SH DESCRIPTION .B hypermail is a program that takes a file of mail messages in UNIX mailbox format and generates a set of cross-referenced HTML documents. Each file that is created represents a separate message in the mail archive and contains links to other articles, so that the entire archive can be browsed in a number of ways by following links. Archives generated by Hypermail can be incrementally updated, and Hypermail is set by default to only update archives when changes are detected. .LP Each HTML file that is generated for a message contains (where applicable): the subject of the article, the name and email address of the sender, the date the article was sent, links to the next and previous messages in the archive, a link to the message the article is in reply to, and a link to the message next in the current thread. .LP In addition, Hypermail will convert references in each message to email addresses and URLs to hyperlinks so they can be selected. Email addresses will be converted to .B mailto: URLs, or links to a CGI mail program. .LP To complement each set of HTML messages, four .I index files are created which sort the articles by date received, thread, subject, and author. Each entry in these index files are links to the individual articles and provide a bird's-eye view of every archived message: .TP .B date.html The index of articles sorted by the date they were received by the mail daemon. .TP .B thread.html The index of articles sorted by thread first, then the date they were received. .TP .B subject.html The index of articles sorted by subject. Any .B "Re:" prefixes in front of subjects will have been stripped out. .TP .B author.html is the index of articles sorted by the first word of the author's name. If the author's name can't be determined, their email address will be substituted. .LP One of the index files will be called .B index.html and is the default index that users can go to when entering the archive. In the specified directory, articles will be read out in the order that they were read from a mailbox or standard input. Filenames start at zero and increase in this fashion: .B 0000.html, 0001.html, 0002.html, etc. .SH OPTIONS .TP .BI \-a " URL" This option includes a link labelled .B "Other mail archives" in the index pages to the specified URL. This way users who are looking at the Hypermail archive have the opportunity to go to pointers to other mail archives. By default, this is a link to the parent directory which holds the archive files. .TP .BI \-A Use this to maintain a parallel mbox archive. The file name defaults to mbox in the directory specified by -d or dir. .TP .BI \-b " URL" This option includes a link labelled .B "About this archive" in the index pages to the specified URL. This way users who are looking at the Hypermail archive have the opportunity to go to information about the archive. .TP .BI \-c " file" This option specifies a configuration file to read settings from. By default, Hypermail will look for a file called .B .hmrc in the user's home directory. .TP .BI \-d " directory" Specifies the directory to put the HTML files and index files that are created. If the directory doesn't exist, a new one will be created with the name that is specified. If the .B \-d option isn't used, Hypermail will look for a directory with the same name as the input mailbox or will create one if needed. .TP .B \-g Use this to use gdbm to implement a header cache. This will speed up hypermail, especially if your filesystem is slow. It will probably not provide any speedup if you use the linkquotes option. .TP .B \-i Reads in articles from standard input. .TP .BI \-l " label" This option tells Hypermail what to call the archive \- the name that is specified will be in the title of the index pages so users know what sort of messages are being archived. .TP .BI \-L " language" This is a two-letter string specifying the default language to use, or a longer string specifying a language and locale. Set this the value of the language table you wish to use when running and generating archives. See also the iso2022jp and eurodate config file options. Current supported languages, with their default locales: de (de_DE) - German en (en_US) - English es (es_ES) - Spanish fi (fi_FI) - Finnish fr (fr_FR) - French el (el) - Greek gr (el_GR) - Greek is (is_IS) - Icelandic no (no_NO) - Norwegian pl (pl_PL) - Polish pt (pt_BR) - Brazilian Portuguese ru (ru_RU) - Russian sv (sv_SE) - Swedish .TP .BI \-m " mailbox" Specifies the mailbox to read articles in from. By default, Hypermail will look for a file called .B mbox. .TP .B \-M This option allows you to use metadata to store the content type of a MIME attachments and, later on, when a user browses the attachment, send back this information in the HTTP Content-Type header. When used, the Content-Type header of a MIME attachment will be stored in a metadata file. .TP .BI \-n " submission-address" This is the list\'s submission address. In this manner people will be able to submit new messages to the list the hypermail archive serves. .TP .BI \-o " keyword=value" This is a means of setting any variable that can be specified in a config file. .TP .B \-p This shows a progress report as Hypermail reads in and writes out messages \- the number of files that Hypermail is reading and writing and the file names of the directory and files created are shown. .TP .B \-s htmlsuffix Use this to specify the html file suffix to be used when Hypermail generates the html files. This is dependent on local needs. Do not put a '.' in the value. It would result in "file..html", probably not what you want. .TP .B \-t This will tell Hypermail to generate an index menu at the top and bottom of each page in a table format. .TP .B \-T This will tell Hypermail to generate a message index Subject/Author/Date listings using a table format. .TP .B \-u This option tells Hypermail to add message(s) to the end of the existing HTML file archive and integrate them into it by links and cross-references. All archive index files will be regenerated to include the new message. Hypermail used to require that you only send it one message at a time when using the -u option, but it should now work reasonably when given mailboxes containing multiple messages. When using the -u option, don't send any messages that Hypermail has already processed. If you want Hypermail to recognize that some messages are old messages that shouldn't be added to the archive again, send it a mailbox with a complete set of messages and avoid the -u option. .TP .B \-v This shows a the variables and their values that Hypermail will use when. .TP .B \-V This shows the version information for the executing Hypermail. Once displayed, Hypermail exits without doing any processing. .TP .B \-x This tells Hypermail to explicitly overwrite any previous HTML files that may exist. Use this option only when it is desirable to completely rewrite the entire archive. .TP .B \-X Use this to let hypermail write an XML archive overview file in each directory. The filename is archive_overview.haof. .TP .B \-0 number This is a message number that should be deleted from the html archive. The mbox is not changed. See the delete_level config file option for more info about what happens to the message. .TP .B \-1 Use this to specify there is only one message in the input. .LP .SS GENERAL EXECUTION NOTES .LP .B Note: No matter what options are specified, the index files are always rewritten. The date when Hypermail was last run is included in index pages, so it's easy to tell when the archive was last updated. .LP .B Note: The .B \-i and .B \-m options cannot be used together. Only archives in UNIX mailbox format can be read in - mailboxes of this kind are usually appended RFC2822-compliant articles separated by lines such as "\\nFrom person@site Mon Jan 10 12:34:56 1994". .LP .B Note: If the mailbox that is being read from is an archive that new messages are always being added to, don't use the .B \-u option. Hypermail will then read in all the messages given it but will only write new messages that have been appended to the mailbox. .LP .SS CONFIGURATION OPTIONS .LP The following settings can be read in as environment variables or from the specified configuration file. Environment settings are in uppercase. For instance, in the C shell, variables can be set as: .LP .PD 0 .RS .B setenv HM_MBOX "/home/john/my_mailbox" .LP .B setenv HM_FILEMODE 0600 .PD .RE .LP In the configuration file, blank lines and lines beginning with a hash mark .RB ( # ) are ignored. Variables must be in lowercase and separated by values with an equals .RB ( = ) sign, such as: .LP .PD 0 .RS .B mbox = "/home/john/my_mailbox" .LP .B filemode = 0600 .PD .RE .LP Settings are read in this order: from the program's hard-wired internal defaults, from environment variables, from the configuration file, from command-line options. .LP See .B hmrc.4 for more information on configuration file usage. .LP Below is a partial list of variables that Hypermail understands. A full list is available in the file hmrc.html, or you can also look in setup.c. Boolean numbers can have the value of .B 0 or .B 1. .TP .B HM_CONFIGFILE "filename" This is the default configuration file to read settings in from. This can only be specified as an environment variable. If the first character is "~", Hypermail will look for the file under the current user's home directory. .TP .B HM_MBOX "filename" This is the default mailbox to read messages in from. Define this with a value of .B "NONE" to read from standard input as the default. .TP .B HM_ARCHIVES "URL" This will create a link in the archived index pages labelled .I "Other mail archives" to the specified URL. Define as .B "NONE" to omit such a link. .TP .B HM_ABOUT "URL" This will create a link in the archived index pages labelled .I "About this archive" to the specified URL. Define as .B "NONE" to omit such a link. .TP .B HM_REVERSE boolean_number Defining this variable as .B 1 will reverse-sort the article entries in the date and thread index files by the date they were received. That is, the most recent messages will appear at the top of the index rather than the other way around. .TP .B HM_SHOWHEADERS boolean_number Define this as .B 1 to show the article header lines in the archived HTML files. These lines typically include the .BR "To:" , " From: " and " Subject:" information found in most email messages. .TP .B HM_SHOWHTML 0, 1, or 2 Define as .B 1 to show the articles in a proportionally-spaced font rather than a fixed-width (monospace) font. Setting this option to 1 also tells Hypermail to attempt to italicize quoted passages in articles. Define as .B 2 for more complex conversion to html similar to that in txt2html.pl. Showhtml = 2 will normally produce nicer looking results than showhtml = 1, and showhtml = 0 will look pretty dull, but 1 and 2 run risks of altering the appearance in undesired ways. .TP .B HM_SHOWBR boolean_number Define as .B 1 to place .B
tags at the end of article lines. Otherwise, all non-quoted article lines will word wrap. This only takes effect if .B HM_SHOWHTML is defined. .TP .B HM_IQUOTES boolean_number Define as .B 1 to italicize quoted lines. .TP .B HM_SHOW_MSG_LINKS boolean_number Define as .B 1 to put the individual message links at the top of the individual message pages. Define as .B 0 to produce pages without the Next, Previous, Reply, In reply to, etc. links. .TP .B HM_EURODATE boolean_number Define as .B 1 to display article received dates with days before months instead of months before days. .TP .B HM_SHOWREPLIES boolean_number Define as .B 1 to show all replies to a message as links in article files. .TP .B HM_MAILTO "address" The address of the contact point that is put in the HTML header line The header can be disabled by default by setting HM_MAILTO to "NONE". .TP .B HM_MAILCOMMAND "command" This specifies the mail command to use when converting email addresses to links. The variables .B $TO, $SUBJECT, and .B $ID can be used in constructing the command string. .B $TO represents the address to send mail to, .B $SUBJECT represents the subject that is being replied to, and .B $ID represents the message ID of the article that is being replied to. If defined as .B "NONE", email addresses will not be converted to links in articles. A possible command one could use is .B "mailto:$TO", but this could easily be changed to specify a CGI program such as .B "/cgi-bin/mail?to=$TO". A CGI mail program is included with the source which can be used for this purpose. .TP .B HM_DOMAINADDR "domainname" Set this to the domainname you want added to a mail address appearing in the RFC2822 field which lack a hostname. When the list resides on the same host as the user sending the message, it is often not required of the MTA to domain-ize these addresses for delivery. In such cases, Hypermail will add the DOMAINADDR to the email address. If defined as .B "NONE", this feature is turned off. .TP .B HM_LABEL "label name" Define this as the default label to put in archives. .TP .B HM_DIR "directory" This is the default directory that Hypermail will look for when creating and updating archives. If defined as .B "NONE" the directory will have the same name as the input mailbox. .TP .B HM_DIRMODE octal_number This is an octal number that new directories are set to when they are created. If the archives will be made publically available, it's a good idea to define this as .B 0755. If files will be updated incrementally with sendmail, this will have to be .B 0777. .TP .B HM_FILEMODE octal_number This is an octal number that new files are set to when they are created. If the archives will be made publically available, it's a good idea to define this as .B 0644. .TP .B HM_OVERWRITE boolean_number Define as .B 1 to make Hypermail overwrite existing archives by default. .TP .B HM_INCREMENT 0, 1, or -1 Define as .B 1 to append all input messages to the end of existing archives. Define as .B 0 for it to read a mailbox that corresponds to the entire archive. (See the mbox_shortened option for an exception to the requirement that it be the entire archive). If there are any existing html messages, it will figure out which ones at the end of the mailbox are new, and add only those that haven't been converted yet. Define as .B -1 to have hypermail figure out whether the input is entirely new messages to be appended or whether it contains messages that are already in the archive. A value of -1 cannot be used with the mbox_shortened option or with the -i command line option or with mbox = NONE. .TP .B HM_PROGRESS boolean_number Define as .B 1 or as .B 2 to always show a progress report as Hypermail works. Defined as 2 shows more information about the attachment files created. This is written to stdout. .TP .B HM_THRDLEVELS number This specifies the number of thread levels to outline in the thread index. For instance, if .B HM_THRDLEVELS is .B 2, replies to messages will be indented once in the index, but replies to replies, etc., will only be indented once as well. .TP .B HM_DEFAULTINDEX type This specifies the default index that users can view when entering the archive. Valid types are .B "date," .B "thread," .B "author," and .B "subject." .TP .BI HM_HMAIL " submission-address" This is the email address used to send a new message to a hypermail archive. "NONE" means don't use it. Since this is different for each hypermail archive, you should probably leave it set to "NONE" here, and let it be specified at runtime by command-line parameters in the list specific configfile. .TP .B HM_IHTMLHEADERFILE path Define path as the path to a file containing valid HTML formatting statements that you wish to included at the top of every index page. Hypermail will print this file as the header of the index so make sure it contains .B , , and other statements that suit your local customized needs. .TP .B HM_IHTMLFOOTERFILE path Define path as the path to a file containing valid HTML formatting statements that you wish to included at the bottom of every index page. Hypermail will print this file as the trailer of the index so make sure it contains at a minimum a .B and .B statement. .TP .B HM_MHTMLHEADERFILE path Define path as the path to a file containing valid HTML formatting statements that you wish to included at the top of every message page. Hypermail will print this file as the header of the message so make sure it contains .B , , and other statements that suit your local customized needs. .TP .B HM_MHTMLFOOTERFILE path Define path as the path to a file containing valid HTML formatting statements that you wish to included at the bottom of every message page. Hypermail will print this file as the trailer of the message so make sure it contains at a minimum a .B and .B statement. .TP .B HM_SHOW_HEADERS list of headers to display Define the list of headers to be displayed if the variable HM_SHOWHEADERS is set to 1 (ON). This is a comma or space separated all on a single line such as show_headers = From,Subject,Date,Message-ID or they can be listed individually or any combination of. .nf show_headers = From show_headers = Subject show_headers = Date show_headers = Message-ID .nr As a special case you can use the identifier ``*'' as header to tell .B hypermail to display all header lines. .TP .B HM_INLINE_TYPES image data types to inline This is the list of MIME types that you want inlined as opposed to simply linked into the message. They can be listed individually on multiple lines or comma or space separated on a single line. .nf inline_types = image/gif image/jpeg or inline_types = image/gif inline_types = image/jpeg .nr .TP .B HM_IGNORE_TYPES indicate attachment types to ignore This is the list of MIME attachment types that you do not want to do anything with. They are quietly ignored. They can be listed individually on multiple lines or comma or space separated on a single line. .nf ignore_types = text/x-vcard application/x-msdownload or ignore_types = text/x-vcard ignore_types = application/x-msdownload .nr .TP .B HM_LINKQUOTES boolean_number Set this to On to create fine-grained links from quoted text to the text where the quote originated. It also improves the threads index file by more accurately matching messages with replies. Note that this may be rather cpu intensive (see the searchbackmsgnum option to alter the performance). .TP .B HM_SEARCHBACKMSGNUM postive integer If the linkquotes option is on and an incremental update is being done (-u option), this controls the tradeoff between speed and the reliability of finding the right source for quoted text. Try to set it to the largest number of messages between a message and the final direct reply to that message. .TP .B HM_LINK_TO_REPLIES "text used to indicate links to replies" If the linkquotes option is on, specifying a string here causes it to generate links from original quoted text the location(s) in replies which quote them. The string is used to display the link. .TP .B HM_QUOTE_HIDE_THRESHOLD percent (integer) If the linkquotes option is on, setting this to an integer less than 100 will cause it to replace quoted text with one-line links if the percent of lines in the message body (exluding the signature) consisting of quoted text exceeds the number indicated by this option. .TP .B HM_QUOTE_LINK_STRING "text to appear in place of quoted text" If the quote_hide_threshold option is being used, the quote_link_string will be used if available to display the link that replaces the quoted text. If no string is specified here, the first line of each section of quoted text will used. .TP .B HM_MONTHLY_INDEX = boolean_number Set this to On to create additional index files broken up by month. A summary.html file will provide links to all the monthly indices. .TP .B HM_YEARLY_INDEX = boolean_number Set this to On to create additional index files broken up by year. A summary.html file will provide links to all the yearly indices. .TP .B HM_THREAD_FILE_DEPTH = 0 or 1 If nonzero, break the threads index file into multiple files, with the initial message of each thread in the main index file along with links to files containing the replies. Setting this to 1 creates one file for each thread that has replies, and is recommended for archives with over a few hundred messages. Setting this greater than 1 will produce multiple levels of files for each thread whose replies are nested by more than 1 level, but that is rarely useful. This option is currently disabled if the indextable option is turned on, and probably needs to be less than thrdlevels. .SH BUGS .LP .B Sorting: In the date and thread index files, note that these lists are sorted by the date the articles were received by the system's mail daemon, not by the date they were written on. The order of articles in the date index may not necessarily match the order in which the article files are written and linked together. Because of this, it is a good idea to make sure the mailbox is sorted by date with the most recent messages towards the bottom. .LP Forwarded messages with bad headers may be incorrectly handled. .LP .SH AUTHORS .LP .B Hypermail was originally designed and developed by Tom Gruber .RI for Enterprise Integration Technologies (EIT) in Common Lisp. It was later rewritten in C by Kevin Hughes .RI while at EIT. Kevin passed on\-going development and support for Hypermail to Kent Landfield .RI . .LP The latest documentation can usually be found at .B http://www.hypermail.org/ but you might also want to check the cvs repository which is the first place that changes become available: .B http://cvs.hypermail.org/cgi-bin/cvsweb.cgi/hypermail/docs/ .LP .SH CREDITS .LP .LP I'd like to thank the members of the Hypermail Development list for their continued encouragement, ideas, bug fixes and participation. Additionally, following people should be noted for their work and contributions to the hypermail development. This list is far from complete ... .LP .nf Bob Crispen Ashley M. Kirchner Darci Chapman Byron C. Darrah Dave Kopper Daniel Stenberg I.Ioannou Elliot Lee Martin Schulze Jay Soffian Jared Reisinger Peter C. McCluskey Roy T. Fielding Roy Tennant Jose Kahan Bjarni R. Einarsson Francisco Iacobelli Nicolas Noble Scott Rose Greg Shenaut W. Tasin Darryl Lee Paul Haldane Andreas Fuchs David D Kilzer Tim Witham Jyrki Kuoppala Bernhard Reiter Hisashi Gotoh David Eisner Andy Yoder Peter Karlsson Moritz Willers David Bau Brian Kirkby William King .nr .TP ================================================ FILE: docs/hypermail.html ================================================ Hypermail Documentation

  Hypermail


Contents:


What is Hypermail?

Hypermail is a program that takes a file of mail messages in UNIX mailbox format and generates a set of cross-referenced HTML documents. Each file that is created represents a separate message in the mail archive and contains links to other articles, so that the entire archive can be browsed in a number of ways by following links. Archives generated by Hypermail can be incrementally updated, and Hypermail is set by default to only update archives when changes are detected.

Each HTML file that is generated for a message contains (where applicable):

  • the subject of the article,
  • the name and email address of the sender,
  • the date the article was sent,
  • links to the next and previous messages in the archive,
  • a link to the message the article is in reply to, and
  • a link to the message next in the current thread.

In addition, Hypermail will convert references in each message to email addresses and URLs to hyperlinks so they can be selected. Email addresses can be converted to mailto: URLs or links to a CGI mail program.

To complement each set of HTML messages, four index files are created which sort the articles by date received, thread, subject, and author. Each entry in these index files are links to the individual articles and provide a bird's-eye view of every archived message.

Hypermail was originally developed and designed by Tom Gruber for Enterprise Integration Technologies (EIT) in Common Lisp. It was later rewritten in C by Kevin Hughes while at EIT. Hypermail is now being maintained by Peter McCluskey <pcm@rahul.net>.

To see what Hypermail can do, take a look at these Hypermail-produced archives:


Usage

Usage: hypermail [options]

Options:
  -a URL        : URL to other archives
  -A            : Maintain an mbox archive
  -b URL        : URL to archive information
  -c file       : Configuration file to read in
  -d dir        : The directory to save HTML files in
  -g            : Build a GDBM header cache
  -i            : Read messages from standard input
  -l label      : What to name the output archive
  -m mbox       : Mail archive to read in
  -M            : Use metadata
  -n listaddr   : The submission address of the list
  -o keyword=val: Set config item
  -p            : Show progress
  -s htmlsuffix : HTML file suffix (.html, .htm, ..)
  -t            : Use Tables
  -T            : Use index tables
  -u            : Append all input messages
  -v            : Show configuration variables only
  -V            : Show version information and exit
  -x            : Overwrite previous messages
  -X            : Write haof XML files
  -0 number     : Delete messages
  -1            : Read only one mail from input
  -L lang       : Specify language to use (de en es fi fr is pl pt sv no el gr ru it )

Using the flags -h, or -? with Hypermail will display this usage summary.


Command-Line Options

Input and Output Options:
-i,
-m  "mailbox",
-d  "directory",
-c  "file"

To tell Hypermail what mailbox to read in, use the -m option. If articles will be sent to Hypermail through standard input, use the -i option. Note that the -m and -i options can't be used together! By default, Hypermail will look for a file called mbox to read its articles in from.

The -d option specifies the directory to put the HTML files and index files that are created into. If the directory doesn't exist, a new one will be created with the name that is specified. If the -d option isn't used, Hypermail will look for a directory with the same name as the mailbox or will create one if needed.

   example 1: hypermail -m "wu-ftpd" -d "/wu-ftpd"
   example 2: cat "/var/spool/mail/wu-ftpd" | hypermail -i

  1. This example reads the articles in wu-ftpd and will save the output in the /wu-ftpd directory.

  2. This reads the file /var/spool/mail/wu-ftpd from standard input and will save the output in a directory called archive in the same directory Hypermail was run from.

Note that Hypermail can only read messages in the UNIX mailbox format! Such archives are typically RFC 2822 mail messages appended to each other that look similar to this:

   From john@foo.com  Mon Jan  1 00:01:30 1994
   Date: Mon, 1 Jan 1994 00:01:15 PDT
   From: john@foo.com
   To: everyone@foo.com
   Subject: Hello, world!

   Hi, everyone, just saying hello!

   From someone.else@foo.com  Mon Jan  1 00:02:00 1994
   Date: Mon, 1 Jan 1994 00:01:45 PDT
   ...

The messages are typically separated by lines in this format:

   From wu-ftpd@wugate.wustl.edu  Fri Jul  1 00:18:20 1994

The -c option tells Hypermail to read in settings from a configuration file. By default, the program will attempt to read settings from a file called .hmrc in the user's home directory if it exists.

In the configuration file, variables are set in the following manner:

variable = number
variable = "string"
The complete set of variables that Hypermail recognizes is described in the Configuration Options page.

Archive Interface Options:

-l  "label",
-b  "About URL",
-a  "Other Archives URL"

The -l option tells Hypermail what to call the archive - the name that is specified will be in the title of the index pages so users know what sort of messages are being archived.

The -a option includes a link labelled "Other mail archives" in the index pages to any specified URL. This way users who are looking at the archive have the opportunity to go to pointers to other mail archives. By default, this will be a pointer to the parent directory in which the archive files reside.

The -b option includes a link labelled "About this archive" in the index pages to any specified URL. This way users who are looking at the archive have the opportunity to go to information about the archive.

   example: hypermail -l "WU-FTPD Development Archives"
            -a "http://www.landfield.com/wu-ftpd/"
            -b "http://www.landfield.com/wu-ftpd/mail-archive/"

In the index files for the archive, the above setting will produce something like this:

(top of page)

WU-FTPD Archives

(list of indexed articles below)

Updating Options:

-x,
-u

The -x option tells Hypermail to explicitly overwrite any previous HTML files that may exist. Use this option only when it is desirable to completely rewrite the entire archive.

The -u option tells Hypermail to add message(s) to the end of the existing HTML file archive and integrate them into it by links and cross-references. All archive index files will be regenerated to include the new message.

Hypermail used to require that you only send it one message at a time when using the -u option, but it should now work reasonably when given mailboxes containing multiple messages.

When using the -u option, don't send any messages that Hypermail has already processed. If you want Hypermail to recognize that some messages are old messages that shouldn't be added to the archive again, send it a mailbox with a complete set of messages and avoid the -u option.

   example 1: cat "one.letter" | hypermail -i -u -d "/wu-ftpd/mail-archives"
   example 2: hypermail -u -m "one.letter" -d "/wu-ftpd/mail-archives"
   example 3: hypermail -m "mailbox" -d "/wu-ftpd/mail-archives" -x
   example 4: hypermail -m "mailbox" -d "/wu-ftpd/mail-archives"

  1. This tells Hypermail to take the article it receives from standard input and integrate it with the archive under the wu-ftpd/mail-archives directory. If no archive exists, a new one will be created with the specified letter as the first file of the archive.

  2. This does the same thing, except that the letter is read in from a file that contains only that letter.

  3. With these options, Hypermail will read in the articles from mailbox and write over any existing files in the wu-ftpd/mail-archives directory if they exist. If no archive exists, a new one will be created.

  4. With these options, Hypermail will read in the articles from mailbox and only write new articles - it will not overwrite any existing archive files.

Note that no matter what options are specified, the index files are always rewritten. The date when Hypermail was last run is included in index pages, so it's easy to tell when the archive was last updated.

Miscellaneous Options

-p
-v
-V

The -p option shows a progress report as Hypermail reads in and writes out messages - the number of files that Hypermail is reading and writing and the file names of the directory and files created are shown. This information is written to standard output.

The -v option shows the configuration variables and their values that Hypermail would use if it was run with the same configuration file and command line options. This is useful when starting up a new list or modifying a list configuration file. Once the information is displayed, Hypermail terminates and no actual processing occurs.

The -V option prints the Hypermail version information. Once the information is displayed, Hypermail terminates and not actual processing occurs.

The -0 option list message numbers that should be deleted from the html archive. The mbox is not changed. It is equivalent to the delete_msgnum option.


Configuration Options

Hypermail has many variables that can be set as environment variables or as variables in the specified configuration file. For instance, using the C shell, one could define variables in this manner:

   setenv HM_MBOX /home/john/my_mailbox
   setenv HM_FILEMODE 0600

In the configuration file, variables must be in lowercase and separated by their values with an equals (=) sign. Blank lines and lines beginning with the # character are skipped:

   mbox = "/home/john/my_mailbox"
   filemode = 0600
While the example uses quotes ("), they is not required when used in the configuration file.

Below is a list of the more important configuration variables. For a complete list, see hmrc.html.

HM_LABEL "label name"
Define this as the default label to put in archives.

HM_ARCHIVES "URL"
This will create a link in the archived index pages to the specified URL. Define as "NONE" to omit such a link. See also custom_archives.

HM_HMAIL "list submission address"
This is the email address used to send a new message to a hypermail archive. "NONE" means don't use it. Since this is different for each hypermail archive, you should probably leave it set to "NONE" here, and let it be specified at runtime by command-line parameters in the list specific configfile.
See also newmsg_command and replymsg_command.

HM_DIR "directory"
This is the default directory that Hypermail will look for when creating and updating archives. If defined as "NONE", the directory name will be the same name as the mailbox read in.

HM_MBOX "filename"
This is the default mailbox to read messages in from. Define this with a value of "NONE" to read from standard input as the default.

HM_STRIPSUBJECT "text"
A string to be stripped from all subject lines. Helps unclutter mailing lists which add tags to subject lines.

HM_FOLDER_BY_DATE = "strftime-date-format"
This string causes the messages to be put in subdirectories by date. The string will be passed to strftime(3) to generate subdirectory names based on message dates. Suggested values are "%y%m" or "%b%y" for monthly subdirectories, "%Y" for yearly, "%G/%V" for weekly. Do not alter this for an existing archive without removing the old html files. If you use this and update the archive incrementally (e.g. with -u), you must use the usegdbm option.
See also monthly_index.

HM_ISODATE boolean_number
Set this to On to display article received dates in YYYY-MM-DD HH:MM:SS format. If used with the gmtime option, a Z will be inserted between the DD and HH.
See also eurodate and dateformat.

HM_LANGUAGE "language-id"
This is a two-letter string specifying the default language to use, or a longer string specifying a language and locale. Set this the value of the language table you wish to use when running and generating archives. See also iso2022jp and eurodate.

Current supported languages, with their default locales:
de (de_DE) - German
en (en_US) - English
es (es_ES) - Spanish
fi (fi_FI) - Finnish
fr (fr_FR) - French
el (el) - Greek
gr (el_GR) - Greek
is (is_IS) - Icelandic
no (no_NO) - Norwegian
pl (pl_PL) - Polish
pt (pt_BR) - Brazilian Portuguese
ru (ru_RU) - Russian
sv (sv_SE) - Swedish
The directory /usr/share/i18n/locales on many systems has the locale codes that are available on that system.

HM_INCREMENT -1, 0, or 1
Define as 1 to append all input messages to the end of existing archives.
Define as 0 for it to read a mailbox that corresponds to the entire archive. If there are any existing html messages, it will figure out which ones at the end of the mailbox are new, and add only those that haven't been converted yet.
Define as -1 to have hypermail figure out whether the input is entirely new messages to be appended or whether it contains messages that are already in the archive. A value of -1 cannot be used with the mbox_shortened option or with the -i command line option or with mbox = NONE.

HM_APPEND boolean_number
Set this to On to maintain a parallel mbox archive. The file name defaults to mbox in the directory specified by -d or dir.
See also append_filename and txtsuffix.

HM_SHOWHTML 0, 1, or 2
Define as 1 to show the articles in a proportionally-spaced font rather than a fixed-width (monospace) font. Setting this option to 1 also tells Hypermail to attempt to italicize quoted passages in articles.

Define as 2 for more complex conversion to html similar to that in txt2html.pl. Showhtml = 2 will normally produce nicer looking results than showhtml = 1, and showhtml = 0 will look pretty dull, but 1 and 2 run risks of altering the appearance in undesired ways.

HM_LINKQUOTES boolean_number
Set this to On to create fine-grained links from quoted text to the text where the quote originated. It also improves the threads index file by more accurately matching messages with replies. Note that this may be rather cpu intensive (see the searchbackmsgnum option to alter the performance).

HM_ABOUT "URL"
This will create a link in the archived index pages to the specified URL. Define as "NONE" to omit such a link.

HM_MAILTO address
The address of the contact point that is put in the HTML header line
<LINK REV=made HREF=mailto:MAILTO>
The <LINK...> header can be disabled by default by setting HM_MAILTO to "NONE".

HM_INDEXTABLE boolean_number
Setting this variable to 1 will tell Hypermail to generate a message index Subject/Author/Date listings using a table format. Set to 0 if you want the standard Hypermail index page look and feel.

HM_FILTER_OUT expression Delete messages with headers matching regular expressions (PCRE syntax). See also filter_require, filter_out_full_body, and filter_require_full_body.

HM_DOMAINADDR "domainname"
Set this to the domainname you want added to a mail address appearing in the RFC2822 field which lack a hostname. When the list resides on the same host as the user sending the message, it is often not required of the MTA to domain-ize these addresses for delivery. In such cases, Hypermail will add the DOMAINADDR to the email address. If defined as NONE, this feature is turned off.

HM_USEMETA [ 0 | 1 ]
This option allows you to use metadata to store the content type of a MIME attachments and, later on, when a user browses the attachment, send back this information in the HTTP Content-Type header. When set to 1, the Content-Type header of a MIME attachment will be stored in a metadata file. Let us say that the MIME attachments for a message are stored in directory att-num. The metadata for those attachments will then be stored in directory att-num/.meta. If a MIME attachment is stored in file att-file, its metadata will be stored in file att-file.meta. This convention is directly compatible with the Apache server handling of metadata.

HM_REVERSE boolean_number
Defining this variable as 1 will reverse-sort the article entries in the date and thread index files by the date they were received. That is, the most recent messages will appear at the top of the index rather than the other way around.

HM_MHTMLHEADERFILE "path"
Define path as the path to a file containing valid HTML formatting statements that you wish to included at the top of every message page. Hypermail will print this file as the header of the message so make sure it contains <HTML>, <HEAD>, and <BODY> and other statements that suit your local customized needs.
See also ihtmlheaderfile, ihtmlfooterfile, and mhtmlfooterfile.

HM_CONFIGFILE "filename"
This is the default configuration file to read settings in from. This can only be specified as an environment variable. If the first character is "~", Hypermail will look for the file under the current user's home directory.


Order of Options Processing

Settings are processed in this order:

  1. From the program's hard-wired internal defaults (specified in options.h),
  2. From runtime environment variables,
  3. From the configuration file,
  4. From command-line options.

Early versions of Hypermail read the command line before reading the configuration file.


Other Things

Filenames: In the specified directory, articles will be read out in the order that they were read in from a mailbox or standard input. Filenames start at zero and increase in this fashion: 0000.html, 0001.html, 0002.html, etc. In the same directory:

  • date.html is the index of articles sorted by the date they were received by the system's mail daemon.
  • thread.html is the index of articles sorted by thread first, then the date they were received.
  • subject.html is the index of articles sorted by subject. Any "Re:" prefixes in front of subjects will have been stripped out.
  • author.html is the index of articles sorted by the first word of the author's name. If the author's name can't be determined, their email address will be substituted.
  • One of the above files will be called index.html and is the default index that users can go to when entering the archive.

Sorting: In the date and thread index files, note that these lists are sorted by the date the articles were received by the system's mail daemon, not by the date they were written on. The order of articles in the date index may not necessarily match the order in which the article files are written and linked together. Because of this, it is a good idea to make sure the mailbox is sorted by date with the most recent messages towards the bottom.

Running Hypermail automatically: All that's needed to start archiving email messages is to set up Hypermail to do incremental updates in your /etc/aliases file (assuming that you use sendmail or something that works like it to deliver mail). Here's what an entry might look like (the last line is one unbroken line):

#
# WU-FTPD Mailing List Archives
#
wulist: "|/usr/local/bin/hypermail -i -u -d /wu-ftpd/mail-archive -l \"WU-FTPD Mailing List Archive\""
After adding the entry, make sure newaliases is run to update the mail aliases. This entry will run Hypermail and update/create the archive whenever a new message is received. Hypermail also works well as a cron job. Because sendmail may run Hypermail as different users, you will want to make sure that archive directories and files are made readable and writeable by a trusted sendmail user (or read/writable by everyone if you can't do that) when they are created. This will ensure that there will be no problems incrementally updating the archive.

If you use qmail instead of sendmail, you probably want to create a file /var/qmail/alias/.qmail-<mylistemailaddress> containing something like this:

|/usr/local/bin/hypermail -i -u -d /wu-ftpd/mail-archive -l \"WU-FTPD Mailing List Archive\"

If you are running Linux kernel version 2.4 or higher, dnotify looks like it provides another way to automate Hypermail.

Including HTML in messages: One can include formatted HTML in message bodies by enclosing the HTML with the <HTML> tag (in either uppercase or lowercase). This tag must be on a line by itself:

   This text will not be parsed...
   <html>
   this text will be parsed as HTML.
   </html>
   This text will not be parsed...

There is no limit to how often the <HTML> tag can be used in an article.


Getting Help With Hypermail

If you are are looking for more information on Hypermail and its features and developmental status, check out SourceForge: Project Info - hypermail and hypermail-project.org. Additional documentation and the hypermail development list archives are available there.


Getting Hypermail Software

Hypermail is available free of charge under GNU Public License. More details about the GPL are available at http://www.fsf.org/copyleft/gpl.html.

Currently, SourceForge: Project Info - hypermail has the most recent version.

The Hypermail Development Center also has beta development versions of hypermail available from time to time.


Credits

I would like to thank Tom Gruber, who originally designed and developed Hypermail in Common Lisp, for the basis of a GREAT tool.

I'd also like to thank Kevin Hughes for developing the initial C version of Hypermail. Kevin also provided a great deal of assistance with restarting the current hypermail development.

There are a great deal of people that also contributed to Hypermail's development. The Hypermail Development Center Credits page is an attempt to let you know just who they are.

Hypermail development is currently being fostered by <Peter McCluskey>.


See Also

hypermail(1),   hmrc(4),   Hypermail List Configuration File.   and   Customizing Hypermail Pages and Adding a Search Engines to your Hypermail Archive

Please send any feature requests, bug fixes, and comments on Hypermail to <hypermail@hypermail-project.org>. In order to minimize spam on the list, you must subscribe to the list (at least temporarily) in order to send mail to it. You may subscribe to the list by sending a message with the word "subscribe" in the Subject: field to hypermail-request@hypermail-project.org.

Last updated Sep 2, 2006 ================================================ FILE: docs/index_hypermail.txt ================================================ From Bill Moseley: I noticed this page on indexing with Swish-e: http://hypermail.org/source/docs/archive_search.html Here's another way if using Perl. The Swish-e (http://swish-e.org) package comes with a script for indexing hypermail archives and includes instructions on usage. Below I've included part of the documentation. That script is in use here: http://swish-e.org/Discussion/archive/ The search results page is not that pretty, but it's just using the default templates. I'm often frustrated when searching archives that I can't limit by date or author. So besides being able to just search by name, email, title, etc., you can do a search like: hypermail name=moseley to find posts with "hypermail" in either the title or body, and also only messages from moseley. Here's the (un-proof read) instructions: NAME index_hypermail.pl - Parse Hypermail archive for indexing with Swish-e SYNOPSIS Using an example data structure like this: hypermail/ archive/ search/ Create the hypermail archive: $ cd hypermail $ hypermail -i -d archive < messages.mbox Create a swish-e config file: $ cd search $ cat swish.conf # config for indexing hypermail v2.1.8 archives IndexDir ./index_hypermail.pl SwishProgParameters ../archive MetaNames swishtitle name email PropertyNames name email IndexContents HTML* .html StoreDescription HTML* 100000 UndefinedMetaTags ignore Copy index_hypermail.pl to the current directory. Swish-e installs index_hypermail.pl in the $prefix/share/doc/swish-e/examples/prog-bin directory, where $prefix is typically "/usr/local" or simply "/usr" on some distributions. $ cp /usr/local/share/doc/swish-e/example/prog-bin/index_hypermail . Then Index the documents: $ swish-e -c swish.conf -S prog Now create the search interface: $ cp /usr/local/lib/swish-e/swish.cgi . $ cat .swishcgi.conf $ENV{TZ} = 'UTC'; # display dates in UTC format return { title => "Search the Foo List Archive", display_props => [qw/ name email swishlastmodified /], sorts => [qw/swishrank swishtitle email swishlastmodified/], metanames => [qw/swishdefault swishtitle name email/], name_labels => { swishrank => 'Rank', swishtitle => 'Subject Only', name => "Poster's Name", email => "Poster's Email", swishlastmodified => 'Message Date', swishdefault => 'Subject & Body', }, highlight => { package => 'SWISH::PhraseHighlight', xhighlight_on => '', xhighlight_off => '', meta_to_prop_map => { # this maps search metatags to display properties swishdefault => [ qw/swishtitle swishdescription/ ], swishtitle => [ qw/swishtitle/ ], email => [ qw/email/ ], name => [ qw/name/ ], swishdocpath => [ qw/swishdocpath/ ], }, }, }; Setup web server (OS/web server dependent): /var/www # ln -s /path/to/hypermail/search /var/www # ln -s /path/to/hypermail/archive and maybe tell apache to run the script: $ cat .htaccess Deny from all Allow from all SetHandler cgi-script Options +ExecCGI ================================================ FILE: install-sh ================================================ #! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 ================================================ FILE: lcc/README.txt ================================================ A. COMPILING HYPERMAIL USING LCC-Win32 1. Install LCC-Win32 in c:\lcc (the default installation directory) 2. Put the Hypermail directory tree in c:\lcc\projects\hypermail 3. Bring up wedit, select "Project" and "Create" 4. Name the project "hypermail" 5. Make the path to the project's working directory c:\lcc\projects\hypermail\lcc 6. Check to see that the Output Directory is c:\lcc\projects\hypermail\lcc\lcc 7. Click on "Create". 8. On the "Do you want to use the wizard to generate the application skeleton?" dialog, click "No". 9. On the "Add source files to project" dialog, click "Cancel" 10. On the "Source files for project" dialog, click "Read file list from a text file" 11. Select "hypermail_files.txt" 12. Click on "OK" 13. On the "Compiler settings dialog", click "Next" 14. On the "Linker settings" dialog type "gdbm.lib" in the "Additional files to be included in the link" space, then click "Next". 15. On the "Debugger settings" dialog, make any changes you'd like to use to begin your debugging session and click "Finish". 16. At this point you should see a lot of text file windows open and a dialog labeles "Building makefile for hypermail" with a progress bar which moves to the end. 17. Select "Compiler" and "Make". Observe some fairly meaningless error messages and observe the linker return code is "0" (success). B. TIPS, BUGS, AND LIMITATIONS ON HYPERMAIL FOR WINDOWS 1. Hypermail gives a warning message when it attempts to set a locale on Windows 98 (and probably 95 and ME). I believe this is due to a limitation in the Windows 9x family of operating systems. It should work OK on NT family operating systems. 2. LCC version 3.3's standard library gives a blank output for date and time when the "%D" format string is specified. Since "%D" is deprecated anyway, I recommend using "%c" instead, which will give the same result on U.S. systems. 3. Don't build hypermail archives in directories that are shortcuts to other directories. 4. The "latest_folder" configuration option is turned off in Windows. 5. By default, we're building PCRE as an 8-bit library. If you want to build it instead as an 16-bit or 32-bit library, change the pcre file names in hypermail_files.txt to use the pcre16 or pcre32 prefix for the following files: pcrenn_maketables.c, pcrenn_study.c, pcrenn_get.c, where nn should be 16 or 32. 6. If you have problems comping the newer pcre library, check the NON-AUTOTOOLS-BUILD file for more info and send feedback so that we can updat these instructions. Bob Crispen revbob@crispen.org ================================================ FILE: lcc/defaults.h ================================================ #ifndef __DEFAULTS_H #define __DEFAULTS_H /* ALERT! ALERT! ALERT! ALERT! ALERT! ALERT! ALERT! ALERT! * * The #defines following here ARE NOT intended to be modified locally * before you compile hypermail. They're here to set internal defaults * and they are set during the configure process. To alter these settings * for use during runtime, modify your config file! */ #define CONFIGFILE "~/.hmrc" #define INLINE_TYPES "image/gif image/jpeg image/png" #define SHOW_HEADERS "From Subject Date Message-ID" #define MAILCOMMAND "mailto:$TO?Subject=$SUBJECT" #define PROGRESS 0 #define RECOGNIZE_SUPERCITE_QUOTES 1 #define LANGUAGE "@language@" #define HTMLSUFFIX "@htmlsuffix@" #define DEFAULTINDEX "@defaultindex@" #define DOMAINADDR "@domainaddr@" #define ANTISPAM_AT "_at_" #endif ================================================ FILE: lcc/dirent.c ================================================ /* Implementation of POSIX directory browsing functions and types for Win32. Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) History: Created March 1997. Updated February 2003. Rights: See end of file. */ #include "dirent.h" #include #include /* _findfirst and _findnext set errno iff they return -1 */ #include #include struct DIR { long handle; /* -1 for failed rewind */ struct _finddata_t info; struct dirent result; /* d_name null iff first time */ char *name; /* null-terminated char string */ }; DIR *opendir(const char *name) { DIR *dir = 0; if(name && name[0]) { size_t base_length = strlen(name); const char *all = /* search pattern must end with suitable wildcard */ strchr("/\\", name[base_length - 1]) ? "*" : "/*"; if((dir = (DIR *) malloc(sizeof *dir)) != 0 && (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) { strcat(strcpy(dir->name, name), all); if((dir->handle = _findfirst(dir->name, &dir->info)) != -1) { dir->result.d_name = 0; } else /* rollback */ { free(dir->name); free(dir); dir = 0; } } else /* rollback */ { free(dir); dir = 0; errno = ENOMEM; } } else { errno = EINVAL; } return dir; } int closedir(DIR *dir) { int result = -1; if(dir) { if(dir->handle != -1) { result = _findclose(dir->handle); } free(dir->name); free(dir); } if(result == -1) /* map all errors to EBADF */ { errno = EBADF; } return result; } struct dirent *readdir(DIR *dir) { struct dirent *result = 0; if(dir && dir->handle != -1) { if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) { result = &dir->result; result->d_name = dir->info.name; } } else { errno = EBADF; } return result; } void rewinddir(DIR *dir) { if(dir && dir->handle != -1) { _findclose(dir->handle); dir->handle = _findfirst(dir->name, &dir->info); dir->result.d_name = 0; } else { errno = EBADF; } } /* Copyright Kevlin Henney, 1997, 2003. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives. This software is supplied "as is" without express or implied warranty. But that said, if there are any problems please get in touch. */ ================================================ FILE: lcc/dirent.h ================================================ #ifndef DIRENT_INCLUDED #define DIRENT_INCLUDED /* Declaration of POSIX directory browsing functions and types for Win32. Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com) History: Created March 1997. Updated February 2003. Rights: See end of file. */ typedef struct DIR DIR; struct dirent { char *d_name; }; DIR *opendir(const char *); int closedir(DIR *); struct dirent *readdir(DIR *); void rewinddir(DIR *); /* Copyright Kevlin Henney, 1997, 2003. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives. This software is supplied "as is" without express or implied warranty. But that said, if there are any problems please get in touch. */ #endif ================================================ FILE: lcc/getdate.c ================================================ /* A Bison parser, made from getdate.y by GNU bison 1.35. */ #define YYBISON 1 /* Identify Bison output. */ # define tAGO 257 # define tDAY 258 # define tDAY_UNIT 259 # define tDAYZONE 260 # define tDST 261 # define tHOUR_UNIT 262 # define tID 263 # define tMERIDIAN 264 # define tMINUTE_UNIT 265 # define tMONTH 266 # define tMONTH_UNIT 267 # define tSEC_UNIT 268 # define tSNUMBER 269 # define tUNUMBER 270 # define tYEAR_UNIT 271 # define tZONE 272 #line 1 "getdate.y" /* ** Originally written by Steven M. Bellovin while ** at the University of North Carolina at Chapel Hill. Later tweaked by ** a couple of people on Usenet. Completely overhauled by Rich $alz ** and Jim Berets in August, 1990; ** ** This grammar has 13 shift/reduce conflicts. ** ** This code is in the public domain and has no copyright. */ #include "config.h" #include "../src/setup.h" #ifdef HAVE_CONFIG_H # ifdef FORCE_ALLOCA_H # include # endif #endif /* Since the code of getdate.y is not included in the Emacs executable itself, there is no need to #define static in this file. Even if the code were included in the Emacs executable, it probably wouldn't do any harm to #undef it here; this will only cause problems if we try to write to a static variable, which I don't think this code needs to do. */ #ifdef emacs # undef static #endif #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #ifdef HAVE_STRING_H #include #endif #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) # define IN_CTYPE_DOMAIN(c) 1 #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) #define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) /* ISDIGIT differs from ISDIGIT_LOCALE, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. - It's typically faster. Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless it's important to use the locale's definition of `digit' even when the host does not conform to Posix. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #include "../src/getdate.h" #if defined (STDC_HEADERS) || defined (USG) # include #endif /* Some old versions of bison generate parsers that use bcopy. That loses on systems that don't provide the function, so we have to redefine it here. */ #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy) # define bcopy(from, to, len) memcpy ((to), (from), (len)) #endif /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), as well as gratuitiously global symbol names, so we can have multiple yacc generated parsers in the same program. Note that these are only the variables produced by yacc. If other parser generators (bison, byacc, etc) produce additional global names that conflict at link time, then those parser generators need to be fixed instead of adding those names to this list. */ #define yymaxdepth gd_maxdepth #define yyparse gd_parse #define yylex gd_lex #define yyerror gd_error #define yylval gd_lval #define yychar gd_char #define yydebug gd_debug #define yypact gd_pact #define yyr1 gd_r1 #define yyr2 gd_r2 #define yydef gd_def #define yychk gd_chk #define yypgo gd_pgo #define yyact gd_act #define yyexca gd_exca #define yyerrflag gd_errflag #define yynerrs gd_nerrs #define yyps gd_ps #define yypv gd_pv #define yys gd_s #define yy_yys gd_yys #define yystate gd_state #define yytmp gd_tmp #define yyv gd_v #define yy_yyv gd_yyv #define yyval gd_val #define yylloc gd_lloc #define yyreds gd_reds /* With YYDEBUG defined */ #define yytoks gd_toks /* With YYDEBUG defined */ #define yylhs gd_yylhs #define yylen gd_yylen #define yydefred gd_yydefred #define yydgoto gd_yydgoto #define yysindex gd_yysindex #define yyrindex gd_yyrindex #define yygindex gd_yygindex #define yytable gd_yytable #define yycheck gd_yycheck static int yylex (void); static int yyerror (char *s); extern int yyparse (void); #define EPOCH 1970 #define HOUR(x) ((x) * 60) #define MAX_BUFF_LEN 128 /* size of buffer to read the date into */ /* ** An entry in the lexical lookup table. */ typedef struct _TABLE { const char *name; int type; int value; } TABLE; /* ** Meridian: am, pm, or 24-hour style. */ typedef enum _MERIDIAN { MERam, MERpm, MER24 } MERIDIAN; /* ** Global variables. We could get rid of most of these by using a good ** union as the yacc stack. (This routine was originally written before ** yacc had the %union construct.) Maybe someday; right now we only use ** the %union very rarely. */ static const char *yyInput; static int yyDayOrdinal; static int yyDayNumber; static int yyHaveDate; static int yyHaveDay; static int yyHaveRel; static int yyHaveTime; static int yyHaveZone; static int yyTimezone; static int yyDay; static int yyHour; static int yyMinutes; static int yyMonth; static int yySeconds; static int yyYear; static MERIDIAN yyMeridian; static int yyRelDay; static int yyRelHour; static int yyRelMinutes; static int yyRelMonth; static int yyRelSeconds; static int yyRelYear; #line 183 "getdate.y" #ifndef YYSTYPE typedef union { int Number; enum _MERIDIAN Meridian; } yystype; # define YYSTYPE yystype # define YYSTYPE_IS_TRIVIAL 1 #endif #ifndef YYDEBUG # define YYDEBUG 0 #endif #define YYFINAL 61 #define YYFLAG -32768 #define YYNTBASE 22 /* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ #define YYTRANSLATE(x) ((unsigned)(x) <= 272 ? yytranslate[x] : 32) /* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ static const char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 20, 2, 2, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }; #if YYDEBUG static const short yyprhs[] = { 0, 0, 1, 4, 6, 8, 10, 12, 14, 16, 19, 24, 29, 36, 43, 45, 47, 50, 52, 55, 58, 62, 68, 72, 76, 79, 84, 87, 91, 94, 96, 99, 102, 104, 107, 110, 112, 115, 118, 120, 123, 126, 128, 131, 134, 136, 139, 142, 144, 146, 147 }; static const short yyrhs[] = { -1, 22, 23, 0, 24, 0, 25, 0, 27, 0, 26, 0, 28, 0, 30, 0, 16, 10, 0, 16, 19, 16, 31, 0, 16, 19, 16, 15, 0, 16, 19, 16, 19, 16, 31, 0, 16, 19, 16, 19, 16, 15, 0, 18, 0, 6, 0, 18, 7, 0, 4, 0, 4, 20, 0, 16, 4, 0, 16, 21, 16, 0, 16, 21, 16, 21, 16, 0, 16, 15, 15, 0, 16, 12, 15, 0, 12, 16, 0, 12, 16, 20, 16, 0, 16, 12, 0, 16, 12, 16, 0, 29, 3, 0, 29, 0, 16, 17, 0, 15, 17, 0, 17, 0, 16, 13, 0, 15, 13, 0, 13, 0, 16, 5, 0, 15, 5, 0, 5, 0, 16, 8, 0, 15, 8, 0, 8, 0, 16, 11, 0, 15, 11, 0, 11, 0, 16, 14, 0, 15, 14, 0, 14, 0, 16, 0, 0, 10, 0 }; #endif #if YYDEBUG /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const short yyrline[] = { 0, 199, 200, 203, 206, 209, 212, 215, 218, 221, 227, 233, 242, 248, 260, 263, 266, 272, 276, 280, 286, 290, 308, 314, 320, 324, 329, 333, 340, 348, 351, 354, 357, 360, 363, 366, 369, 372, 375, 378, 381, 384, 387, 390, 393, 396, 399, 402, 407, 440, 444 }; #endif #if (YYDEBUG) || defined YYERROR_VERBOSE /* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ static const char *const yytname[] = { "$", "error", "$undefined.", "tAGO", "tDAY", "tDAY_UNIT", "tDAYZONE", "tDST", "tHOUR_UNIT", "tID", "tMERIDIAN", "tMINUTE_UNIT", "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tSNUMBER", "tUNUMBER", "tYEAR_UNIT", "tZONE", "':'", "','", "'/'", "spec", "item", "time", "zone", "day", "date", "rel", "relunit", "number", "o_merid", 0 }; #endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const short yyr1[] = { 0, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 31, 31 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const short yyr2[] = { 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 4, 4, 6, 6, 1, 1, 2, 1, 2, 2, 3, 5, 3, 3, 2, 4, 2, 3, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 1, 0, 1 }; /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const short yydefact[] = { 1, 0, 17, 38, 15, 41, 44, 0, 35, 47, 0, 48, 32, 14, 2, 3, 4, 6, 5, 7, 29, 8, 18, 24, 37, 40, 43, 34, 46, 31, 19, 36, 39, 9, 42, 26, 33, 45, 0, 30, 0, 0, 16, 28, 0, 23, 27, 22, 49, 20, 25, 50, 11, 0, 10, 0, 49, 21, 13, 12, 0, 0 }; static const short yydefgoto[] = { 1, 14, 15, 16, 17, 18, 19, 20, 21, 54 }; static const short yypact[] = { -32768, 0, -19,-32768,-32768,-32768,-32768, -13,-32768,-32768, 30, 15,-32768, 14,-32768,-32768,-32768,-32768,-32768,-32768, 19,-32768,-32768, 4,-32768,-32768,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768, -6,-32768,-32768, 16,-32768, 17, 23,-32768,-32768, 24,-32768,-32768,-32768, 27, 28, -32768,-32768,-32768, 29,-32768, 32, -8,-32768,-32768,-32768, 50,-32768 }; static const short yypgoto[] = { -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -5 }; #define YYLAST 51 static const short yytable[] = { 60, 22, 51, 23, 2, 3, 4, 58, 5, 45, 46, 6, 7, 8, 9, 10, 11, 12, 13, 30, 31, 42, 43, 32, 44, 33, 34, 35, 36, 37, 38, 47, 39, 48, 40, 24, 41, 51, 25, 49, 50, 26, 52, 27, 28, 56, 53, 29, 57, 55, 61, 59 }; static const short yycheck[] = { 0, 20, 10, 16, 4, 5, 6, 15, 8, 15, 16, 11, 12, 13, 14, 15, 16, 17, 18, 4, 5, 7, 3, 8, 20, 10, 11, 12, 13, 14, 15, 15, 17, 16, 19, 5, 21, 10, 8, 16, 16, 11, 15, 13, 14, 16, 19, 17, 16, 21, 0, 56 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "/usr/share/bison/bison.simple" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ #if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) /* The parser invokes alloca or malloc; define the necessary symbols. */ # if YYSTACK_USE_ALLOCA # define YYSTACK_ALLOC alloca # else # ifndef YYSTACK_USE_ALLOCA # if defined (alloca) || defined (_ALLOCA_H) # define YYSTACK_ALLOC alloca # else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # else # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif # define YYSTACK_ALLOC malloc # define YYSTACK_FREE free # endif #endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { short yyss; YYSTYPE yyvs; # if YYLSP_NEEDED YYLTYPE yyls; # endif }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # if YYLSP_NEEDED # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAX) # else # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAX) # endif /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) # define YYSIZE_T __SIZE_TYPE__ #endif #if ! defined (YYSIZE_T) && defined (size_t) # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif #endif #if ! defined (YYSIZE_T) # define YYSIZE_T unsigned int #endif #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ yyerror ("syntax error: cannot back up"); \ YYERROR; \ } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Compute the default location (before the actions are run). When YYLLOC_DEFAULT is run, CURRENT is set the location of the first token. By default, to implement support for ranges, extend its range to the last symbol. */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ Current.last_line = Rhs[N].last_line; \ Current.last_column = Rhs[N].last_column; #endif /* YYLEX -- calling `yylex' with the right arguments. */ #if YYPURE # if YYLSP_NEEDED # ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) # else # define YYLEX yylex (&yylval, &yylloc) # endif # else /* !YYLSP_NEEDED */ # ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) # else # define YYLEX yylex (&yylval) # endif # endif /* !YYLSP_NEEDED */ #else /* !YYPURE */ # define YYLEX yylex () #endif /* !YYPURE */ /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #if YYMAXDEPTH == 0 # undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #ifdef YYERROR_VERBOSE # ifndef yystrlen # if defined (__GLIBC__) && defined (_STRING_H) # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T # if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) # else yystrlen (yystr) const char *yystr; # endif { register const char *yys = yystr; while (*yys++ != '\0') continue; return yys - yystr - 1; } # endif # endif # ifndef yystpcpy # if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * # if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) # else yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; # endif { register char *yyd = yydest; register const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif #endif #line 315 "/usr/share/bison/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. It should actually point to an object. Grammar actions can access the variable by casting it to the proper pointer type. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) # define YYPARSE_PARAM_ARG void *YYPARSE_PARAM # define YYPARSE_PARAM_DECL # else # define YYPARSE_PARAM_ARG YYPARSE_PARAM # define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; # endif #else /* !YYPARSE_PARAM */ # define YYPARSE_PARAM_ARG # define YYPARSE_PARAM_DECL #endif /* !YYPARSE_PARAM */ /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ # ifdef YYPARSE_PARAM int yyparse (void *); # else int yyparse (void); # endif #endif /* YY_DECL_VARIABLES -- depending whether we use a pure parser, variables are global, or local to YYPARSE. */ #define YY_DECL_NON_LSP_VARIABLES \ /* The lookahead symbol. */ \ int yychar; \ \ /* The semantic value of the lookahead symbol. */ \ YYSTYPE yylval; \ \ /* Number of parse errors so far. */ \ int yynerrs; #if YYLSP_NEEDED # define YY_DECL_VARIABLES \ YY_DECL_NON_LSP_VARIABLES \ \ /* Location data for the lookahead symbol. */ \ YYLTYPE yylloc; #else # define YY_DECL_VARIABLES \ YY_DECL_NON_LSP_VARIABLES #endif /* If nonreentrant, generate the variables here. */ #if !YYPURE YY_DECL_VARIABLES #endif /* !YYPURE */ int yyparse (YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { /* If reentrant, generate the variables here. */ #if YYPURE YY_DECL_VARIABLES #endif /* !YYPURE */ register int yystate; register int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Lookahead token as an internal (translated) token number. */ int yychar1 = 0; /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ short yyssa[YYINITDEPTH]; short *yyss = yyssa; register short *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; #if YYLSP_NEEDED /* The location stack. */ YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; #endif #if YYLSP_NEEDED # define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else # define YYPOPSTACK (yyvsp--, yyssp--) #endif YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYLSP_NEEDED YYLTYPE yyloc; #endif /* When reducing, the number of symbols on the RHS of the reduced rule. */ int yylen; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; #if YYLSP_NEEDED yylsp = yyls; #endif goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ # if YYLSP_NEEDED YYLTYPE *yyls1 = yyls; /* This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yyls1, yysize * sizeof (*yylsp), &yystacksize); yyls = yyls1; # else yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); # endif yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyoverflowlab; # else /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) goto yyoverflowlab; yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; { short *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyoverflowlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # if YYLSP_NEEDED YYSTACK_RELOCATE (yyls); # endif # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; #if YYLSP_NEEDED yylsp = yyls + yysize - 1; #endif YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyssp >= yyss + yystacksize - 1) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yychar1 = YYTRANSLATE (yychar); #if YYDEBUG /* We have to keep this `#if YYDEBUG', since we use variables which are defined only if `YYDEBUG' is set. */ if (yydebug) { YYFPRINTF (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ # ifdef YYPRINT YYPRINT (stderr, yychar, yylval); # endif YYFPRINTF (stderr, ")\n"); } #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ YYDPRINTF ((stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #if YYLSP_NEEDED *++yylsp = yylloc; #endif /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to the semantic value of the lookahead token. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; #if YYLSP_NEEDED /* Similarly for the default location. Let the user run additional commands if for instance locations are ranges. */ yyloc = yylsp[1-yylen]; YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); #endif #if YYDEBUG /* We have to keep this `#if YYDEBUG', since we use variables which are defined only if `YYDEBUG' is set. */ if (yydebug) { int yyi; YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif switch (yyn) { case 3: #line 203 "getdate.y" { yyHaveTime++; } break; case 4: #line 206 "getdate.y" { yyHaveZone++; } break; case 5: #line 209 "getdate.y" { yyHaveDate++; } break; case 6: #line 212 "getdate.y" { yyHaveDay++; } break; case 7: #line 215 "getdate.y" { yyHaveRel++; } break; case 9: #line 221 "getdate.y" { yyHour = yyvsp[-1].Number; yyMinutes = 0; yySeconds = 0; yyMeridian = yyvsp[0].Meridian; } break; case 10: #line 227 "getdate.y" { yyHour = yyvsp[-3].Number; yyMinutes = yyvsp[-1].Number; yySeconds = 0; yyMeridian = yyvsp[0].Meridian; } break; case 11: #line 233 "getdate.y" { yyHour = yyvsp[-3].Number; yyMinutes = yyvsp[-1].Number; yyMeridian = MER24; yyHaveZone++; yyTimezone = (yyvsp[0].Number < 0 ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); } break; case 12: #line 242 "getdate.y" { yyHour = yyvsp[-5].Number; yyMinutes = yyvsp[-3].Number; yySeconds = yyvsp[-1].Number; yyMeridian = yyvsp[0].Meridian; } break; case 13: #line 248 "getdate.y" { yyHour = yyvsp[-5].Number; yyMinutes = yyvsp[-3].Number; yySeconds = yyvsp[-1].Number; yyMeridian = MER24; yyHaveZone++; yyTimezone = (yyvsp[0].Number < 0 ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); } break; case 14: #line 260 "getdate.y" { yyTimezone = yyvsp[0].Number; } break; case 15: #line 263 "getdate.y" { yyTimezone = yyvsp[0].Number - 60; } break; case 16: #line 267 "getdate.y" { yyTimezone = yyvsp[-1].Number - 60; } break; case 17: #line 272 "getdate.y" { yyDayOrdinal = 1; yyDayNumber = yyvsp[0].Number; } break; case 18: #line 276 "getdate.y" { yyDayOrdinal = 1; yyDayNumber = yyvsp[-1].Number; } break; case 19: #line 280 "getdate.y" { yyDayOrdinal = yyvsp[-1].Number; yyDayNumber = yyvsp[0].Number; } break; case 20: #line 286 "getdate.y" { yyMonth = yyvsp[-2].Number; yyDay = yyvsp[0].Number; } break; case 21: #line 290 "getdate.y" { /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. The goal in recognizing YYYY/MM/DD is solely to support legacy machine-generated dates like those in an RCS log listing. If you want portability, use the ISO 8601 format. */ if (yyvsp[-4].Number >= 1000) { yyYear = yyvsp[-4].Number; yyMonth = yyvsp[-2].Number; yyDay = yyvsp[0].Number; } else { yyMonth = yyvsp[-4].Number; yyDay = yyvsp[-2].Number; yyYear = yyvsp[0].Number; } } break; case 22: #line 308 "getdate.y" { /* ISO 8601 format. yyyy-mm-dd. */ yyYear = yyvsp[-2].Number; yyMonth = -yyvsp[-1].Number; yyDay = -yyvsp[0].Number; } break; case 23: #line 314 "getdate.y" { /* e.g. 17-JUN-1992. */ yyDay = yyvsp[-2].Number; yyMonth = yyvsp[-1].Number; yyYear = -yyvsp[0].Number; } break; case 24: #line 320 "getdate.y" { yyMonth = yyvsp[-1].Number; yyDay = yyvsp[0].Number; } break; case 25: #line 324 "getdate.y" { yyMonth = yyvsp[-3].Number; yyDay = yyvsp[-2].Number; yyYear = yyvsp[0].Number; } break; case 26: #line 329 "getdate.y" { yyMonth = yyvsp[0].Number; yyDay = yyvsp[-1].Number; } break; case 27: #line 333 "getdate.y" { yyMonth = yyvsp[-1].Number; yyDay = yyvsp[-2].Number; yyYear = yyvsp[0].Number; } break; case 28: #line 340 "getdate.y" { yyRelSeconds = -yyRelSeconds; yyRelMinutes = -yyRelMinutes; yyRelHour = -yyRelHour; yyRelDay = -yyRelDay; yyRelMonth = -yyRelMonth; yyRelYear = -yyRelYear; } break; case 30: #line 351 "getdate.y" { yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; } break; case 31: #line 354 "getdate.y" { yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; } break; case 32: #line 357 "getdate.y" { yyRelYear++; } break; case 33: #line 360 "getdate.y" { yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; } break; case 34: #line 363 "getdate.y" { yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; } break; case 35: #line 366 "getdate.y" { yyRelMonth++; } break; case 36: #line 369 "getdate.y" { yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; } break; case 37: #line 372 "getdate.y" { yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; } break; case 38: #line 375 "getdate.y" { yyRelDay++; } break; case 39: #line 378 "getdate.y" { yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; } break; case 40: #line 381 "getdate.y" { yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; } break; case 41: #line 384 "getdate.y" { yyRelHour++; } break; case 42: #line 387 "getdate.y" { yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; } break; case 43: #line 390 "getdate.y" { yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; } break; case 44: #line 393 "getdate.y" { yyRelMinutes++; } break; case 45: #line 396 "getdate.y" { yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; } break; case 46: #line 399 "getdate.y" { yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; } break; case 47: #line 402 "getdate.y" { yyRelSeconds++; } break; case 48: #line 408 "getdate.y" { if (yyHaveTime && yyHaveDate && !yyHaveRel) yyYear = yyvsp[0].Number; else { if (yyvsp[0].Number>10000) { yyHaveDate++; yyDay= (yyvsp[0].Number)%100; yyMonth= (yyvsp[0].Number/100)%100; yyYear = yyvsp[0].Number/10000; } else { yyHaveTime++; if (yyvsp[0].Number < 100) { yyHour = yyvsp[0].Number; yyMinutes = 0; } else { yyHour = yyvsp[0].Number / 100; yyMinutes = yyvsp[0].Number % 100; } yySeconds = 0; yyMeridian = MER24; } } } break; case 49: #line 441 "getdate.y" { yyval.Meridian = MER24; } break; case 50: #line 445 "getdate.y" { yyval.Meridian = yyvsp[0].Meridian; } break; } #line 705 "/usr/share/bison/bison.simple" yyvsp -= yylen; yyssp -= yylen; #if YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG if (yydebug) { short *yyssp1 = yyss - 1; YYFPRINTF (stderr, "state stack now"); while (yyssp1 != yyssp) YYFPRINTF (stderr, " %d", *++yyssp1); YYFPRINTF (stderr, "\n"); } #endif *++yyvsp = yyval; #if YYLSP_NEEDED *++yylsp = yyloc; #endif /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { YYSIZE_T yysize = 0; char *yymsg; int yyx, yycount; yycount = 0; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ for (yyx = yyn < 0 ? -yyn : 0; yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) if (yycheck[yyx + yyn] == yyx) yysize += yystrlen (yytname[yyx]) + 15, yycount++; yysize += yystrlen ("parse error, unexpected ") + 1; yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { char *yyp = yystpcpy (yymsg, "parse error, unexpected "); yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); if (yycount < 5) { yycount = 0; for (yyx = yyn < 0 ? -yyn : 0; yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) if (yycheck[yyx + yyn] == yyx) { const char *yyq = ! yycount ? ", expecting " : " or "; yyp = yystpcpy (yyp, yyq); yyp = yystpcpy (yyp, yytname[yyx]); yycount++; } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else yyerror ("parse error; also virtual memory exhausted"); } else #endif /* defined (YYERROR_VERBOSE) */ yyerror ("parse error"); } goto yyerrlab1; /*--------------------------------------------------. | yyerrlab1 -- error raised explicitly by an action | `--------------------------------------------------*/ yyerrlab1: if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; YYDPRINTF ((stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1])); yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; /*-------------------------------------------------------------------. | yyerrdefault -- current state does not do anything special for the | | error token. | `-------------------------------------------------------------------*/ yyerrdefault: #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ /* If its default is to accept any token, ok. Otherwise pop it. */ yyn = yydefact[yystate]; if (yyn) goto yydefault; #endif /*---------------------------------------------------------------. | yyerrpop -- pop the current state because it cannot handle the | | error token | `---------------------------------------------------------------*/ yyerrpop: if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #if YYLSP_NEEDED yylsp--; #endif #if YYDEBUG if (yydebug) { short *yyssp1 = yyss - 1; YYFPRINTF (stderr, "Error: state stack now"); while (yyssp1 != yyssp) YYFPRINTF (stderr, " %d", *++yyssp1); YYFPRINTF (stderr, "\n"); } #endif /*--------------. | yyerrhandle. | `--------------*/ yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; #if YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; /*---------------------------------------------. | yyoverflowab -- parser overflow comes here. | `---------------------------------------------*/ yyoverflowlab: yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ yyreturn: #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } #line 450 "getdate.y" /* Month and day table. */ static TABLE const MonthDayTable[] = { { "january", tMONTH, 1 }, { "february", tMONTH, 2 }, { "march", tMONTH, 3 }, { "april", tMONTH, 4 }, { "may", tMONTH, 5 }, { "june", tMONTH, 6 }, { "july", tMONTH, 7 }, { "august", tMONTH, 8 }, { "september", tMONTH, 9 }, { "sept", tMONTH, 9 }, { "october", tMONTH, 10 }, { "november", tMONTH, 11 }, { "december", tMONTH, 12 }, { "sunday", tDAY, 0 }, { "monday", tDAY, 1 }, { "tuesday", tDAY, 2 }, { "tues", tDAY, 2 }, { "wednesday", tDAY, 3 }, { "wednes", tDAY, 3 }, { "thursday", tDAY, 4 }, { "thur", tDAY, 4 }, { "thurs", tDAY, 4 }, { "friday", tDAY, 5 }, { "saturday", tDAY, 6 }, { NULL } }; /* Time units table. */ static TABLE const UnitsTable[] = { { "year", tYEAR_UNIT, 1 }, { "month", tMONTH_UNIT, 1 }, { "fortnight", tDAY_UNIT, 14 }, { "week", tDAY_UNIT, 7 }, { "day", tDAY_UNIT, 1 }, { "hour", tHOUR_UNIT, 1 }, { "minute", tMINUTE_UNIT, 1 }, { "min", tMINUTE_UNIT, 1 }, { "second", tSEC_UNIT, 1 }, { "sec", tSEC_UNIT, 1 }, { NULL } }; /* Assorted relative-time words. */ static TABLE const OtherTable[] = { { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, { "today", tMINUTE_UNIT, 0 }, { "now", tMINUTE_UNIT, 0 }, { "last", tUNUMBER, -1 }, { "this", tMINUTE_UNIT, 0 }, { "next", tUNUMBER, 2 }, { "first", tUNUMBER, 1 }, /* { "second", tUNUMBER, 2 }, */ { "third", tUNUMBER, 3 }, { "fourth", tUNUMBER, 4 }, { "fifth", tUNUMBER, 5 }, { "sixth", tUNUMBER, 6 }, { "seventh", tUNUMBER, 7 }, { "eighth", tUNUMBER, 8 }, { "ninth", tUNUMBER, 9 }, { "tenth", tUNUMBER, 10 }, { "eleventh", tUNUMBER, 11 }, { "twelfth", tUNUMBER, 12 }, { "ago", tAGO, 1 }, { NULL } }; /* The timezone table. */ static TABLE const TimezoneTable[] = { { "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */ { "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ { "utc", tZONE, HOUR ( 0) }, { "wet", tZONE, HOUR ( 0) }, /* Western European */ { "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */ { "wat", tZONE, HOUR ( 1) }, /* West Africa */ { "at", tZONE, HOUR ( 2) }, /* Azores */ #if 0 /* For completeness. BST is also British Summer, and GST is * also Guam Standard. */ { "bst", tZONE, HOUR ( 3) }, /* Brazil Standard */ { "gst", tZONE, HOUR ( 3) }, /* Greenland Standard */ #endif #if 0 { "nft", tZONE, HOUR (3.5) }, /* Newfoundland */ { "nst", tZONE, HOUR (3.5) }, /* Newfoundland Standard */ { "ndt", tDAYZONE, HOUR (3.5) }, /* Newfoundland Daylight */ #endif { "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */ { "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */ { "est", tZONE, HOUR ( 5) }, /* Eastern Standard */ { "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */ { "cst", tZONE, HOUR ( 6) }, /* Central Standard */ { "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */ { "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */ { "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */ { "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */ { "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */ { "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */ { "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */ { "hst", tZONE, HOUR (10) }, /* Hawaii Standard */ { "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */ { "cat", tZONE, HOUR (10) }, /* Central Alaska */ { "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */ { "nt", tZONE, HOUR (11) }, /* Nome */ { "idlw", tZONE, HOUR (12) }, /* International Date Line West */ { "cet", tZONE, -HOUR (1) }, /* Central European */ { "met", tZONE, -HOUR (1) }, /* Middle European */ { "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */ { "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ { "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ { "swt", tZONE, -HOUR (1) }, /* Swedish Winter */ { "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */ { "fwt", tZONE, -HOUR (1) }, /* French Winter */ { "fst", tDAYZONE, -HOUR (1) }, /* French Summer */ { "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */ { "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */ #if 0 { "it", tZONE, -HOUR (3.5) },/* Iran */ #endif { "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */ { "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */ #if 0 { "ist", tZONE, -HOUR (5.5) },/* Indian Standard */ #endif { "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */ #if 0 /* For completeness. NST is also Newfoundland Standard, and SST is * also Swedish Summer. */ { "nst", tZONE, -HOUR (6.5) },/* North Sumatra */ { "sst", tZONE, -HOUR (7) }, /* South Sumatra, USSR Zone 6 */ #endif /* 0 */ { "wast", tZONE, -HOUR (7) }, /* West Australian Standard */ { "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */ #if 0 { "jt", tZONE, -HOUR (7.5) },/* Java (3pm in Cronusland!) */ #endif { "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */ { "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */ #if 0 { "cast", tZONE, -HOUR (9.5) },/* Central Australian Standard */ { "cadt", tDAYZONE, -HOUR (9.5) },/* Central Australian Daylight */ #endif { "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */ { "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */ { "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */ { "nzt", tZONE, -HOUR (12) }, /* New Zealand */ { "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */ { "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */ { "idle", tZONE, -HOUR (12) }, /* International Date Line East */ { NULL } }; /* Military timezone table. */ static TABLE const MilitaryTable[] = { { "a", tZONE, HOUR ( 1) }, { "b", tZONE, HOUR ( 2) }, { "c", tZONE, HOUR ( 3) }, { "d", tZONE, HOUR ( 4) }, { "e", tZONE, HOUR ( 5) }, { "f", tZONE, HOUR ( 6) }, { "g", tZONE, HOUR ( 7) }, { "h", tZONE, HOUR ( 8) }, { "i", tZONE, HOUR ( 9) }, { "k", tZONE, HOUR ( 10) }, { "l", tZONE, HOUR ( 11) }, { "m", tZONE, HOUR ( 12) }, { "n", tZONE, HOUR (- 1) }, { "o", tZONE, HOUR (- 2) }, { "p", tZONE, HOUR (- 3) }, { "q", tZONE, HOUR (- 4) }, { "r", tZONE, HOUR (- 5) }, { "s", tZONE, HOUR (- 6) }, { "t", tZONE, HOUR (- 7) }, { "u", tZONE, HOUR (- 8) }, { "v", tZONE, HOUR (- 9) }, { "w", tZONE, HOUR (-10) }, { "x", tZONE, HOUR (-11) }, { "y", tZONE, HOUR (-12) }, { "z", tZONE, HOUR ( 0) }, { NULL } }; /* ARGSUSED */ static int yyerror (char *s) { return 0; } static int ToHour (int Hours, MERIDIAN Meridian) { switch (Meridian) { case MER24: if (Hours < 0 || Hours > 23) return -1; return Hours; case MERam: if (Hours < 1 || Hours > 12) return -1; if (Hours == 12) Hours = 0; return Hours; case MERpm: if (Hours < 1 || Hours > 12) return -1; if (Hours == 12) Hours = 0; return Hours + 12; default: abort (); } /* NOTREACHED */ } static int ToYear (int Year) { if (Year < 0) Year = -Year; /* XPG4 suggests that years 00-68 map to 2000-2068, and years 69-99 map to 1969-1999. */ if (Year < 69) Year += 2000; else if (Year < 100) Year += 1900; return Year; } static int LookupWord (char *buff) { register char *p; register char *q; register const TABLE *tp; int i; int abbrev; /* Make it lowercase. */ for (p = buff; *p; p++) if (ISUPPER (*p)) *p = tolower (*p); if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) { yylval.Meridian = MERam; return tMERIDIAN; } if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) { yylval.Meridian = MERpm; return tMERIDIAN; } /* See if we have an abbreviation for a month. */ if (strlen (buff) == 3) abbrev = 1; else if (strlen (buff) == 4 && buff[3] == '.') { abbrev = 1; buff[3] = '\0'; } else abbrev = 0; for (tp = MonthDayTable; tp->name; tp++) { if (abbrev) { if (strncmp (buff, tp->name, 3) == 0) { yylval.Number = tp->value; return tp->type; } } else if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } } for (tp = TimezoneTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } if (strcmp (buff, "dst") == 0) return tDST; for (tp = UnitsTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } /* Strip off any plural and try the units table again. */ i = strlen (buff) - 1; if (buff[i] == 's') { buff[i] = '\0'; for (tp = UnitsTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } buff[i] = 's'; /* Put back for "this" in OtherTable. */ } for (tp = OtherTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } /* Military timezones. */ if (buff[1] == '\0' && ISALPHA (*buff)) { for (tp = MilitaryTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } } /* Drop out any periods and try the timezone table again. */ for (i = 0, p = q = buff; *q; q++) if (*q != '.') *p++ = *q; else i++; *p = '\0'; if (i) for (tp = TimezoneTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } return tID; } static int yylex (void) { register char c; register char *p; char buff[20]; int Count; int sign; for (;;) { while (ISSPACE (*yyInput)) yyInput++; if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') { if (c == '-' || c == '+') { sign = c == '-' ? -1 : 1; if (!ISDIGIT (*++yyInput)) /* skip the '-' sign */ continue; } else sign = 0; for (yylval.Number = 0; ISDIGIT (c = *yyInput++);) yylval.Number = 10 * yylval.Number + c - '0'; yyInput--; if (sign < 0) yylval.Number = -yylval.Number; return sign ? tSNUMBER : tUNUMBER; } if (ISALPHA (c)) { for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';) if (p < &buff[sizeof buff - 1]) *p++ = c; *p = '\0'; yyInput--; return LookupWord (buff); } if (c != '(') return *yyInput++; Count = 0; do { c = *yyInput++; if (c == '\0') return c; if (c == '(') Count++; else if (c == ')') Count--; } while (Count > 0); } } #define TM_YEAR_ORIGIN 1900 /* Yield A - B, measured in seconds. */ static long difftm (struct tm *a, struct tm *b) { int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); int by = b->tm_year + (TM_YEAR_ORIGIN - 1); long days = ( /* difference in day of year */ a->tm_yday - b->tm_yday /* + intervening leap days */ + ((ay >> 2) - (by >> 2)) - (ay / 100 - by / 100) + ((ay / 100 >> 2) - (by / 100 >> 2)) /* + difference in years * 365 */ + (long) (ay - by) * 365 ); return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + (a->tm_min - b->tm_min)) + (a->tm_sec - b->tm_sec)); } time_t get_date (const char *p, const time_t *now) { struct tm tm, tm0, *tmp; time_t Start; yyInput = p; Start = now ? *now : time ((time_t *) NULL); tmp = (set_gmtime ? gmtime(&Start) : localtime (&Start)); yyYear = tmp->tm_year + TM_YEAR_ORIGIN; yyMonth = tmp->tm_mon + 1; yyDay = tmp->tm_mday; yyHour = tmp->tm_hour; yyMinutes = tmp->tm_min; yySeconds = tmp->tm_sec; yyMeridian = MER24; yyRelSeconds = 0; yyRelMinutes = 0; yyRelHour = 0; yyRelDay = 0; yyRelMonth = 0; yyRelYear = 0; yyHaveDate = 0; yyHaveDay = 0; yyHaveRel = 0; yyHaveTime = 0; yyHaveZone = 0; if (yyparse () || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) return -1; tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear; tm.tm_mon = yyMonth - 1 + yyRelMonth; tm.tm_mday = yyDay + yyRelDay; if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) { tm.tm_hour = ToHour (yyHour, yyMeridian); if (tm.tm_hour < 0) return -1; tm.tm_min = yyMinutes; tm.tm_sec = yySeconds; } else { tm.tm_hour = tm.tm_min = tm.tm_sec = 0; } tm.tm_hour += yyRelHour; tm.tm_min += yyRelMinutes; tm.tm_sec += yyRelSeconds; tm.tm_isdst = -1; tm0 = tm; Start = mktime (&tm); if (Start == (time_t) -1) { /* Guard against falsely reporting errors near the time_t boundaries when parsing times in other time zones. For example, if the min time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead of UTC, then the min localtime value is 1970-01-01 08:00:00; if we apply mktime to 1970-01-01 00:00:00 we will get an error, so we apply mktime to 1970-01-02 08:00:00 instead and adjust the time zone by 24 hours to compensate. This algorithm assumes that there is no DST transition within a day of the time_t boundaries. */ if (yyHaveZone) { tm = tm0; if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) { tm.tm_mday++; yyTimezone -= 24 * 60; } else { tm.tm_mday--; yyTimezone += 24 * 60; } Start = mktime (&tm); } if (Start == (time_t) -1) return Start; } if (yyHaveDay && !yyHaveDate) { tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7 + 7 * (yyDayOrdinal - (0 < yyDayOrdinal))); Start = mktime (&tm); if (Start == (time_t) -1) return Start; } if (yyHaveZone) { long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start)); if ((Start + delta < Start) != (delta < 0)) return -1; /* time_t overflow */ Start += delta; } return Start; } #if defined (TEST) /* ARGSUSED */ int main (int ac, char *av[]) { char buff[MAX_BUFF_LEN + 1]; time_t d; (void) printf ("Enter date, or blank line to exit.\n\t> "); (void) fflush (stdout); buff[MAX_BUFF_LEN] = 0; while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) { d = get_date (buff, (time_t *) NULL); if (d == -1) (void) printf ("Bad format - couldn't convert.\n"); else (void) printf ("%s", ctime (&d)); (void) printf ("\t> "); (void) fflush (stdout); } exit (0); /* NOTREACHED */ } #endif /* defined (TEST) */ ================================================ FILE: lcc/hypermail_files.txt ================================================ lcc_extras.c getdate.c dirent.c ..\src\uudecode.c ..\src\txt2html.c ..\src\trio\triostr.c ..\src\trio\trionan.c ..\src\trio\trio.c ..\src\threadprint.c ..\src\struct.c ..\src\string.c ..\src\setup.c ..\src\search.c ..\src\quotes.c ..\src\printfile.c ..\src\print.c ..\src\pcre\pcre_study.c ..\src\pcre\pcreposix.c ..\src\pcre\pcre.c ..\src\pcre\pcre_maketables.c ..\src\pcre\pcre_get.c ..\src\parse.c ..\src\mem.c ..\src\lock.c ..\src\lang.c ..\src\hypermail.c ..\src\getname.c ..\src\finelink.c ..\src\file.c ..\src\domains.c ..\src\dmatch.c ..\src\date.c ..\src\base64.c ================================================ FILE: lcc/lcc_extras.c ================================================ /* stat and fstat are defined in lcc, but not lstat */ #include /* * The way we're handling this now is to assume that we'll never try this * on a symlink */ int lstat(const char *file_name, struct stat *buf) { return stat(file_name, buf); } ================================================ FILE: lcc/lcc_extras.h ================================================ /* stat and fstat are defined in lcc, but not lstat */ int lstat(const char *file_name, struct stat *buf); ================================================ FILE: lcc/pcre.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is the public header file for the PCRE library, to be #included by applications that call the PCRE functions. Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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 _PCRE_H #define _PCRE_H /* The current PCRE version information. */ #define PCRE_MAJOR 8 #define PCRE_MINOR 32 #define PCRE_PRERELEASE #define PCRE_DATE 2012-11-30 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate export setting is defined in pcre_internal.h, which includes this file. So we don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ #if defined(_WIN32) && !defined(PCRE_STATIC) # ifndef PCRE_EXP_DECL # define PCRE_EXP_DECL extern __declspec(dllimport) # endif # ifdef __cplusplus # ifndef PCRECPP_EXP_DECL # define PCRECPP_EXP_DECL extern __declspec(dllimport) # endif # ifndef PCRECPP_EXP_DEFN # define PCRECPP_EXP_DEFN __declspec(dllimport) # endif # endif #endif /* By default, we use the standard "extern" declarations. */ #ifndef PCRE_EXP_DECL # ifdef __cplusplus # define PCRE_EXP_DECL extern "C" # else # define PCRE_EXP_DECL extern # endif #endif #ifdef __cplusplus # ifndef PCRECPP_EXP_DECL # define PCRECPP_EXP_DECL extern # endif # ifndef PCRECPP_EXP_DEFN # define PCRECPP_EXP_DEFN # endif #endif /* Have to include stdlib.h in order to ensure that size_t is defined; it is needed here for malloc. */ #include /* Allow for C++ users */ #ifdef __cplusplus extern "C" { #endif /* Public options. Some are compile-time only, some are run-time only, and some are both, so we keep them all distinct. However, almost all the bits in the options word are now used. In the long run, we may have to re-use some of the compile-time only bits for runtime options, or vice versa. Any of the compile-time options may be inspected during studying (and therefore JIT compiling). Some options for pcre_compile() change its behaviour but do not affect the behaviour of the execution functions. Other options are passed through to the execution functions and affect their behaviour, with or without affecting the behaviour of pcre_compile(). Options that can be passed to pcre_compile() are tagged Cx below, with these variants: C1 Affects compile only C2 Does not affect compile; affects exec, dfa_exec C3 Affects compile, exec, dfa_exec C4 Affects compile, exec, dfa_exec, study C5 Affects compile, exec, study Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with E and D, respectively. They take precedence over C3, C4, and C5 settings passed from pcre_compile(). Those that are compatible with JIT execution are flagged with J. */ #define PCRE_CASELESS 0x00000001 /* C1 */ #define PCRE_MULTILINE 0x00000002 /* C1 */ #define PCRE_DOTALL 0x00000004 /* C1 */ #define PCRE_EXTENDED 0x00000008 /* C1 */ #define PCRE_ANCHORED 0x00000010 /* C4 E D */ #define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */ #define PCRE_EXTRA 0x00000040 /* C1 */ #define PCRE_NOTBOL 0x00000080 /* E D J */ #define PCRE_NOTEOL 0x00000100 /* E D J */ #define PCRE_UNGREEDY 0x00000200 /* C1 */ #define PCRE_NOTEMPTY 0x00000400 /* E D J */ #define PCRE_UTF8 0x00000800 /* C4 ) */ #define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */ #define PCRE_UTF32 0x00000800 /* C4 ) */ #define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */ #define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */ #define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */ #define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */ #define PCRE_PARTIAL 0x00008000 /* E D J ) */ #define PCRE_DFA_SHORTEST 0x00010000 /* D */ #define PCRE_DFA_RESTART 0x00020000 /* D */ #define PCRE_FIRSTLINE 0x00040000 /* C3 */ #define PCRE_DUPNAMES 0x00080000 /* C1 */ #define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */ #define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */ #define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */ #define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */ #define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */ #define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */ #define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */ #define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */ #define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */ #define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */ #define PCRE_PARTIAL_HARD 0x08000000 /* E D J */ #define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */ #define PCRE_UCP 0x20000000 /* C3 */ /* Exec-time and get/set-time error codes */ #define PCRE_ERROR_NOMATCH (-1) #define PCRE_ERROR_NULL (-2) #define PCRE_ERROR_BADOPTION (-3) #define PCRE_ERROR_BADMAGIC (-4) #define PCRE_ERROR_UNKNOWN_OPCODE (-5) #define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */ #define PCRE_ERROR_NOMEMORY (-6) #define PCRE_ERROR_NOSUBSTRING (-7) #define PCRE_ERROR_MATCHLIMIT (-8) #define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ #define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_PARTIAL (-12) #define PCRE_ERROR_BADPARTIAL (-13) #define PCRE_ERROR_INTERNAL (-14) #define PCRE_ERROR_BADCOUNT (-15) #define PCRE_ERROR_DFA_UITEM (-16) #define PCRE_ERROR_DFA_UCOND (-17) #define PCRE_ERROR_DFA_UMLIMIT (-18) #define PCRE_ERROR_DFA_WSSIZE (-19) #define PCRE_ERROR_DFA_RECURSE (-20) #define PCRE_ERROR_RECURSIONLIMIT (-21) #define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */ #define PCRE_ERROR_BADNEWLINE (-23) #define PCRE_ERROR_BADOFFSET (-24) #define PCRE_ERROR_SHORTUTF8 (-25) #define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */ #define PCRE_ERROR_RECURSELOOP (-26) #define PCRE_ERROR_JIT_STACKLIMIT (-27) #define PCRE_ERROR_BADMODE (-28) #define PCRE_ERROR_BADENDIANNESS (-29) #define PCRE_ERROR_DFA_BADRESTART (-30) #define PCRE_ERROR_JIT_BADOPTION (-31) #define PCRE_ERROR_BADLENGTH (-32) /* Specific error codes for UTF-8 validity checks */ #define PCRE_UTF8_ERR0 0 #define PCRE_UTF8_ERR1 1 #define PCRE_UTF8_ERR2 2 #define PCRE_UTF8_ERR3 3 #define PCRE_UTF8_ERR4 4 #define PCRE_UTF8_ERR5 5 #define PCRE_UTF8_ERR6 6 #define PCRE_UTF8_ERR7 7 #define PCRE_UTF8_ERR8 8 #define PCRE_UTF8_ERR9 9 #define PCRE_UTF8_ERR10 10 #define PCRE_UTF8_ERR11 11 #define PCRE_UTF8_ERR12 12 #define PCRE_UTF8_ERR13 13 #define PCRE_UTF8_ERR14 14 #define PCRE_UTF8_ERR15 15 #define PCRE_UTF8_ERR16 16 #define PCRE_UTF8_ERR17 17 #define PCRE_UTF8_ERR18 18 #define PCRE_UTF8_ERR19 19 #define PCRE_UTF8_ERR20 20 #define PCRE_UTF8_ERR21 21 #define PCRE_UTF8_ERR22 22 /* Specific error codes for UTF-16 validity checks */ #define PCRE_UTF16_ERR0 0 #define PCRE_UTF16_ERR1 1 #define PCRE_UTF16_ERR2 2 #define PCRE_UTF16_ERR3 3 #define PCRE_UTF16_ERR4 4 /* Specific error codes for UTF-32 validity checks */ #define PCRE_UTF32_ERR0 0 #define PCRE_UTF32_ERR1 1 #define PCRE_UTF32_ERR2 2 #define PCRE_UTF32_ERR3 3 /* Request types for pcre_fullinfo() */ #define PCRE_INFO_OPTIONS 0 #define PCRE_INFO_SIZE 1 #define PCRE_INFO_CAPTURECOUNT 2 #define PCRE_INFO_BACKREFMAX 3 #define PCRE_INFO_FIRSTBYTE 4 #define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ #define PCRE_INFO_FIRSTTABLE 5 #define PCRE_INFO_LASTLITERAL 6 #define PCRE_INFO_NAMEENTRYSIZE 7 #define PCRE_INFO_NAMECOUNT 8 #define PCRE_INFO_NAMETABLE 9 #define PCRE_INFO_STUDYSIZE 10 #define PCRE_INFO_DEFAULT_TABLES 11 #define PCRE_INFO_OKPARTIAL 12 #define PCRE_INFO_JCHANGED 13 #define PCRE_INFO_HASCRORLF 14 #define PCRE_INFO_MINLENGTH 15 #define PCRE_INFO_JIT 16 #define PCRE_INFO_JITSIZE 17 #define PCRE_INFO_MAXLOOKBEHIND 18 #define PCRE_INFO_FIRSTCHARACTER 19 #define PCRE_INFO_FIRSTCHARACTERFLAGS 20 #define PCRE_INFO_REQUIREDCHAR 21 #define PCRE_INFO_REQUIREDCHARFLAGS 22 /* Request types for pcre_config(). Do not re-arrange, in order to remain compatible. */ #define PCRE_CONFIG_UTF8 0 #define PCRE_CONFIG_NEWLINE 1 #define PCRE_CONFIG_LINK_SIZE 2 #define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 #define PCRE_CONFIG_MATCH_LIMIT 4 #define PCRE_CONFIG_STACKRECURSE 5 #define PCRE_CONFIG_UNICODE_PROPERTIES 6 #define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7 #define PCRE_CONFIG_BSR 8 #define PCRE_CONFIG_JIT 9 #define PCRE_CONFIG_UTF16 10 #define PCRE_CONFIG_JITTARGET 11 #define PCRE_CONFIG_UTF32 12 /* Request types for pcre_study(). Do not re-arrange, in order to remain compatible. */ #define PCRE_STUDY_JIT_COMPILE 0x0001 #define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002 #define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004 #define PCRE_STUDY_EXTRA_NEEDED 0x0008 /* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine these bits, just add new ones on the end, in order to remain compatible. */ #define PCRE_EXTRA_STUDY_DATA 0x0001 #define PCRE_EXTRA_MATCH_LIMIT 0x0002 #define PCRE_EXTRA_CALLOUT_DATA 0x0004 #define PCRE_EXTRA_TABLES 0x0008 #define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010 #define PCRE_EXTRA_MARK 0x0020 #define PCRE_EXTRA_EXECUTABLE_JIT 0x0040 /* Types */ struct real_pcre; /* declaration; the definition is private */ typedef struct real_pcre pcre; struct real_pcre16; /* declaration; the definition is private */ typedef struct real_pcre16 pcre16; struct real_pcre32; /* declaration; the definition is private */ typedef struct real_pcre32 pcre32; struct real_pcre_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre_jit_stack pcre_jit_stack; struct real_pcre16_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre16_jit_stack pcre16_jit_stack; struct real_pcre32_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre32_jit_stack pcre32_jit_stack; /* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain a 16 bit wide signed data type. Otherwise it can be a dummy data type since pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */ #ifndef PCRE_UCHAR16 #define PCRE_UCHAR16 unsigned short #endif #ifndef PCRE_SPTR16 #define PCRE_SPTR16 const PCRE_UCHAR16 * #endif /* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain a 32 bit wide signed data type. Otherwise it can be a dummy data type since pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */ #ifndef PCRE_UCHAR32 #define PCRE_UCHAR32 unsigned int #endif #ifndef PCRE_SPTR32 #define PCRE_SPTR32 const PCRE_UCHAR32 * #endif /* When PCRE is compiled as a C++ library, the subject pointer type can be replaced with a custom type. For conventional use, the public interface is a const char *. */ #ifndef PCRE_SPTR #define PCRE_SPTR const char * #endif /* The structure for passing additional data to pcre_exec(). This is defined in such as way as to be extensible. Always add new fields at the end, in order to remain compatible. */ typedef struct pcre_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ unsigned char **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre_extra; /* Same structure as above, but with 16 bit char pointers. */ typedef struct pcre16_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre16_extra; /* Same structure as above, but with 32 bit char pointers. */ typedef struct pcre32_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ PCRE_UCHAR32 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre32_extra; /* The structure for passing out data via the pcre_callout_function. We use a structure so that new fields can be added on the end in future versions, without changing the API of the function, thereby allowing old clients to work without modification. */ typedef struct pcre_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const unsigned char *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre_callout_block; /* Same structure as above, but with 16 bit char pointers. */ typedef struct pcre16_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR16 subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre16_callout_block; /* Same structure as above, but with 32 bit char pointers. */ typedef struct pcre32_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR32 subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre32_callout_block; /* Indirection for store get and free functions. These can be set to alternative malloc/free functions if required. Special ones are used in the non-recursive case for "frames". There is also an optional callout function that is triggered by the (?) regex item. For Virtual Pascal, these definitions have to take another form. */ #ifndef VPCOMPAT PCRE_EXP_DECL void *(*pcre_malloc)(size_t); PCRE_EXP_DECL void (*pcre_free)(void *); PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre_stack_free)(void *); PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *); PCRE_EXP_DECL void *(*pcre16_malloc)(size_t); PCRE_EXP_DECL void (*pcre16_free)(void *); PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre16_stack_free)(void *); PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *); PCRE_EXP_DECL void *(*pcre32_malloc)(size_t); PCRE_EXP_DECL void (*pcre32_free)(void *); PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre32_stack_free)(void *); PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *); #else /* VPCOMPAT */ PCRE_EXP_DECL void *pcre_malloc(size_t); PCRE_EXP_DECL void pcre_free(void *); PCRE_EXP_DECL void *pcre_stack_malloc(size_t); PCRE_EXP_DECL void pcre_stack_free(void *); PCRE_EXP_DECL int pcre_callout(pcre_callout_block *); PCRE_EXP_DECL void *pcre16_malloc(size_t); PCRE_EXP_DECL void pcre16_free(void *); PCRE_EXP_DECL void *pcre16_stack_malloc(size_t); PCRE_EXP_DECL void pcre16_stack_free(void *); PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *); PCRE_EXP_DECL void *pcre32_malloc(size_t); PCRE_EXP_DECL void pcre32_free(void *); PCRE_EXP_DECL void *pcre32_stack_malloc(size_t); PCRE_EXP_DECL void pcre32_stack_free(void *); PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *); #endif /* VPCOMPAT */ /* User defined callback which provides a stack just before the match starts. */ typedef pcre_jit_stack *(*pcre_jit_callback)(void *); typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *); typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *); /* Exported PCRE functions */ PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL int pcre_config(int, void *); PCRE_EXP_DECL int pcre16_config(int, void *); PCRE_EXP_DECL int pcre32_config(int, void *); PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, int *, int, const char *, char *, int); PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32, int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int); PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, char *, int); PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int, PCRE_UCHAR32 *, int); PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int); PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int); PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int); PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int, pcre_jit_stack *); PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int, pcre16_jit_stack *); PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int, pcre32_jit_stack *); PCRE_EXP_DECL void pcre_free_substring(const char *); PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16); PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32); PCRE_EXP_DECL void pcre_free_substring_list(const char **); PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *); PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *); PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int, void *); PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int, void *); PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, int *, int, const char *, const char **); PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16, int *, int, PCRE_SPTR16, PCRE_SPTR16 *); PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32, int *, int, PCRE_SPTR32, PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32); PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, char **, char **); PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16, PCRE_UCHAR16 **, PCRE_UCHAR16 **); PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32, PCRE_UCHAR32 **, PCRE_UCHAR32 **); PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, const char **); PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, PCRE_SPTR16 *); PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int, PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, const char ***); PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int, PCRE_SPTR16 **); PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int, PCRE_SPTR32 **); PCRE_EXP_DECL const unsigned char *pcre_maketables(void); PCRE_EXP_DECL const unsigned char *pcre16_maketables(void); PCRE_EXP_DECL const unsigned char *pcre32_maketables(void); PCRE_EXP_DECL int pcre_refcount(pcre *, int); PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int); PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int); PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **); PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **); PCRE_EXP_DECL void pcre_free_study(pcre_extra *); PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *); PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *); PCRE_EXP_DECL const char *pcre_version(void); PCRE_EXP_DECL const char *pcre16_version(void); PCRE_EXP_DECL const char *pcre32_version(void); /* Utility functions for byte order swaps. */ PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, const unsigned char *); PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, PCRE_SPTR16, int, int *, int); PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *, PCRE_SPTR32, int, int *, int); /* JIT compiler related functions. */ PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int); PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *); PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *); PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *); PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, pcre_jit_callback, void *); PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *, pcre16_jit_callback, void *); PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *, pcre32_jit_callback, void *); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* End of pcre.h */ ================================================ FILE: lcc/pcre_chartables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This file contains character tables that are used when no external tables are passed to PCRE by the application that calls it. The tables are used only for characters whose code values are less than 256. This is a default version of the tables that assumes ASCII encoding. A program called dftables (which is distributed with PCRE) can be used to build alternative versions of this file. This is necessary if you are running in an EBCDIC environment, or if you want to default to a different encoding, for example ISO-8859-1. When dftables is run, it creates these tables in the current locale. If PCRE is configured with --enable-rebuild-chartables, this happens automatically. The following #includes are present because without them gcc 4.x may remove the array definition from the final binary if PCRE is built into a static library and dead code stripping is activated. This leads to link errors. Pulling in the header ensures that the array gets flagged as "someone outside this compilation unit might reference this" and so it will always be supplied to the linker. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" const pcre_uint8 PRIV(default_tables)[] = { /* This table is a lower casing table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table is a case flipping table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table contains bit maps for various character classes. Each map is 32 bytes long and the bits run from the least significant end of each byte. The classes that have their own maps are: space, xdigit, digit, upper, lower, word, graph, print, punct, and cntrl. Other classes are built from combinations. */ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* This table identifies various classes of character by individual bits: 0x01 white space character 0x02 letter 0x04 decimal digit 0x08 hexadecimal digit 0x10 alphanumeric or '_' 0x80 regular expression metacharacter or binary zero */ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ 0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ /* End of pcre_chartables.c */ ================================================ FILE: lcc/pcre_config.h ================================================ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* PCRE is written in Standard C, but there are a few non-standard things it can cope with, allowing it to run on SunOS4 and other "close to standard" systems. In environments that support the facilities, config.h.in is converted by "configure", or config-cmake.h.in is converted by CMake, into config.h. If you are going to build PCRE "by hand" without using "configure" or CMake, you should copy the distributed config.h.generic to config.h, and then edit the macro definitions to be the way you need them. You must then add -DHAVE_CONFIG_H to all of your compile commands, so that config.h is included at the start of every source. Alternatively, you can avoid editing by using -D on the compiler command line to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H. PCRE uses memmove() if HAVE_MEMMOVE is set to 1; otherwise it uses bcopy() if HAVE_BCOPY is set to 1. If your system has neither bcopy() nor memmove(), set them both to 0; an emulation function will be used. */ /* By default, the \R escape sequence matches any Unicode line ending character or sequence of characters. If BSR_ANYCRLF is defined (to any value), this is changed so that backslash-R matches only CR, LF, or CRLF. The build-time default can be overridden by the user of PCRE at runtime. */ /* #undef BSR_ANYCRLF */ /* If you are compiling for a system that uses EBCDIC instead of ASCII character codes, define this macro to any value. You must also edit the NEWLINE macro below to set a suitable EBCDIC newline, commonly 21 (0x15). On systems that can use "configure" or CMake to set EBCDIC, NEWLINE is automatically adjusted. When EBCDIC is set, PCRE assumes that all input strings are in EBCDIC. If you do not define this macro, PCRE will assume input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build a version of PCRE that supports both EBCDIC and UTF-8/16/32. */ /* #undef EBCDIC */ /* In an EBCDIC environment, define this macro to any value to arrange for the NL character to be 0x25 instead of the default 0x15. NL plays the role that LF does in an ASCII/Unicode environment. The value must also be set in the NEWLINE macro below. On systems that can use "configure" or CMake to set EBCDIC_NL25, the adjustment of NEWLINE is automatic. */ /* #undef EBCDIC_NL25 */ /* Define to 1 if you have the `bcopy' function. */ #ifndef HAVE_BCOPY #define HAVE_BCOPY 1 #endif /* Define to 1 if you have the header file. */ /* #undef HAVE_BITS_TYPE_TRAITS_H */ /* Define to 1 if you have the header file. */ #ifndef HAVE_BZLIB_H #define HAVE_BZLIB_H 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_DIRENT_H #define HAVE_DIRENT_H 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_DLFCN_H #define HAVE_DLFCN_H 1 #endif /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDIT_READLINE_READLINE_H */ /* Define to 1 if you have the header file. */ #ifndef HAVE_INTTYPES_H #define HAVE_INTTYPES_H 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_LIMITS_H #define HAVE_LIMITS_H 1 #endif /* Define to 1 if the system has the type `long long'. */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG 1 #endif /* Define to 1 if you have the `memmove' function. */ #ifndef HAVE_MEMMOVE #define HAVE_MEMMOVE 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_MEMORY_H #define HAVE_MEMORY_H 1 #endif /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Have PTHREAD_PRIO_INHERIT. */ /* #undef HAVE_PTHREAD_PRIO_INHERIT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_READLINE_H */ /* Define to 1 if you have the header file. */ #ifndef HAVE_STDINT_H #define HAVE_STDINT_H 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_STDLIB_H #define HAVE_STDLIB_H 1 #endif /* Define to 1 if you have the `strerror' function. */ #ifndef HAVE_STRERROR #define HAVE_STRERROR 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_STRING #define HAVE_STRING 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_STRINGS_H #define HAVE_STRINGS_H 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_STRING_H #define HAVE_STRING_H 1 #endif /* Define to 1 if you have `strtoimax'. */ /* #undef HAVE_STRTOIMAX */ /* Define to 1 if you have `strtoll'. */ /* #undef HAVE_STRTOLL */ /* Define to 1 if you have `strtoq'. */ #ifndef HAVE_STRTOQ #define HAVE_STRTOQ 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_SYS_STAT_H #define HAVE_SYS_STAT_H 1 #endif /* Define to 1 if you have the header file. */ #ifndef HAVE_SYS_TYPES_H #define HAVE_SYS_TYPES_H 1 #endif /* Define to 1 if you have the header file. */ /* #undef HAVE_TYPE_TRAITS_H */ /* Define to 1 if you have the header file. */ #ifndef HAVE_UNISTD_H #define HAVE_UNISTD_H 1 #endif /* Define to 1 if the system has the type `unsigned long long'. */ #ifndef HAVE_UNSIGNED_LONG_LONG #define HAVE_UNSIGNED_LONG_LONG 1 #endif /* Define to 1 or 0, depending whether the compiler supports simple visibility declarations. */ #ifndef HAVE_VISIBILITY #define HAVE_VISIBILITY 1 #endif /* Define to 1 if you have the header file. */ /* #undef HAVE_WINDOWS_H */ /* Define to 1 if you have the header file. */ #ifndef HAVE_ZLIB_H #define HAVE_ZLIB_H 1 #endif /* Define to 1 if you have `_strtoi64'. */ /* #undef HAVE__STRTOI64 */ /* The value of LINK_SIZE determines the number of bytes used to store links as offsets within the compiled regex. The default is 2, which allows for compiled patterns up to 64K long. This covers the vast majority of cases. However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows for longer patterns in extreme cases. */ #ifndef LINK_SIZE #define LINK_SIZE 2 #endif /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #ifndef LT_OBJDIR #define LT_OBJDIR ".libs/" #endif /* The value of MATCH_LIMIT determines the default number of times the internal match() function can be called during a single execution of pcre_exec(). There is a runtime interface for setting a different limit. The limit exists in order to catch runaway regular expressions that take for ever to determine that they do not match. The default is set very large so that it does not accidentally catch legitimate cases. */ #ifndef MATCH_LIMIT #define MATCH_LIMIT 10000000 #endif /* The above limit applies to all calls of match(), whether or not they increase the recursion depth. In some environments it is desirable to limit the depth of recursive calls of match() more strictly, in order to restrict the maximum amount of stack (or heap, if NO_RECURSE is defined) that is used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of match(). To have any useful effect, it must be less than the value of MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is a runtime method for setting a different limit. */ #ifndef MATCH_LIMIT_RECURSION #define MATCH_LIMIT_RECURSION MATCH_LIMIT #endif /* This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #ifndef MAX_NAME_COUNT #define MAX_NAME_COUNT 10000 #endif /* This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #ifndef MAX_NAME_SIZE #define MAX_NAME_SIZE 32 #endif /* The value of NEWLINE determines the default newline character sequence. PCRE client programs can override this by selecting other values at run time. In ASCII environments, the value can be 10 (LF), 13 (CR), or 3338 (CRLF); in EBCDIC environments the value can be 21 or 37 (LF), 13 (CR), or 3349 or 3365 (CRLF) because there are two alternative codepoints (0x15 and 0x25) that are used as the NL line terminator that is equivalent to ASCII LF. In both ASCII and EBCDIC environments the value can also be -1 (ANY), or -2 (ANYCRLF). */ #ifndef NEWLINE #define NEWLINE 10 #endif /* Define to 1 if your C compiler doesn't accept -c and -o together. */ /* #undef NO_MINUS_C_MINUS_O */ /* PCRE uses recursive function calls to handle backtracking while matching. This can sometimes be a problem on systems that have stacks of limited size. Define NO_RECURSE to any value to get a version that doesn't use recursion in the match() function; instead it creates its own stack by steam using pcre_recurse_malloc() to obtain memory from the heap. For more detail, see the comments and other stuff just above the match() function. */ /* #undef NO_RECURSE */ /* Name of package */ #define PACKAGE "pcre" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "PCRE" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "PCRE 8.32" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "8.32" /* The value of PCREGREP_BUFSIZE determines the size of buffer used by pcregrep to hold parts of the file it is searching. This is also the minimum value. The actual amount of memory used by pcregrep is three times this number, because it allows for the buffering of "before" and "after" lines. */ #ifndef PCREGREP_BUFSIZE #define PCREGREP_BUFSIZE 20480 #endif /* If you are compiling for a system other than a Unix-like system or Win32, and it needs some magic to be inserted before the definition of a function that is exported by the library, define this macro to contain the relevant magic. If you do not define this macro, a suitable __declspec value is used for Windows systems; in other environments "extern" is used for a C compiler and "extern C" for a C++ compiler. This macro apears at the start of every exported function that is part of the external API. It does not appear on functions that are "external" in the C sense, but which are internal to the library. */ /* #undef PCRE_EXP_DEFN */ /* Define to any value if linking statically (TODO: make nice with Libtool) */ /* #undef PCRE_STATIC */ /* When calling PCRE via the POSIX interface, additional working storage is required for holding the pointers to capturing substrings because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using malloc() for each call. The threshold above which the stack is no longer used is defined by POSIX_MALLOC_THRESHOLD. */ #ifndef POSIX_MALLOC_THRESHOLD #define POSIX_MALLOC_THRESHOLD 10 #endif /* Define to necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* Define to 1 if you have the ANSI C header files. */ #ifndef STDC_HEADERS #define STDC_HEADERS 1 #endif /* Define to allow pcretest and pcregrep to be linked with gcov, so that they are able to generate code coverage reports. */ /* #undef SUPPORT_GCOV */ /* Define to any value to enable support for Just-In-Time compiling. */ /* #undef SUPPORT_JIT */ /* Define to any value to allow pcregrep to be linked with libbz2, so that it is able to handle .bz2 files. */ /* #undef SUPPORT_LIBBZ2 */ /* Define to any value to allow pcretest to be linked with libedit. */ /* #undef SUPPORT_LIBEDIT */ /* Define to any value to allow pcretest to be linked with libreadline. */ /* #undef SUPPORT_LIBREADLINE */ /* Define to any value to allow pcregrep to be linked with libz, so that it is able to handle .gz files. */ /* #undef SUPPORT_LIBZ */ /* Define to any value to enable the 16 bit PCRE library. */ /* #undef SUPPORT_PCRE16 */ /* Define to any value to enable the 32 bit PCRE library. */ /* #undef SUPPORT_PCRE32 */ /* Define to any value to enable the 8 bit PCRE library. */ #ifndef SUPPORT_PCRE8 #define SUPPORT_PCRE8 /**/ #endif /* Define to any value to enable JIT support in pcregrep. */ /* #undef SUPPORT_PCREGREP_JIT */ /* Define to any value to enable support for Unicode properties. */ /* #undef SUPPORT_UCP */ /* Define to any value to enable support for the UTF-8/16/32 Unicode encoding. This will work even in an EBCDIC environment, but it is incompatible with the EBCDIC macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16/32, but not both at once. */ /* #undef SUPPORT_UTF */ /* Valgrind support to find invalid memory reads. */ /* #undef SUPPORT_VALGRIND */ /* Version number of package */ #ifndef VERSION #define VERSION "8.32" #endif /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef int64_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ ================================================ FILE: libcgi/.indent.pro ================================================ -nbad -bap -nbbo -nbc -br -brs -c33 -cd33 -ncdb -nce -ci4 -cp33 -ncs -d0 -di1 -nfc1 -nfca -hnl -i4 -ip0 -l75 -lp -npcs -npsl -nsc -nsob -nss -Tform_entry -Tcgi_info -TFILE ================================================ FILE: libcgi/Makefile.in ================================================ # CGI virdoc library makefile #WNOERROR=-Werror #WARNINGS=$(WNOERROR) -ansi -pedantic -Wall -Wtraditional -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Dlint # You shouldn't have to edit anything else. CC=@CC@ $(WARNINGS) INSTALL=@INSTALL@ AUX_LIBS= RANLIB=@RANLIB@ RM=rm LINT=lint SRCS=form_ent.c get_cgi_info.c main.c syn_mime.c syn_url.c mcode.c\ form_tags.c strops.c html.c .c.o: $(CC) -c $(CFLAGS) $(AUX_CFLAGS) $(INF_INCS) $< ALL = libcgi.a %.o: %.c $(CC) -c $(CFLAGS) $(AUX_CFLAGS) $(INF_INCS) $< all: $(ALL) libcgi.a: form_ent.o get_cgi_info.o main.o syn_mime.o syn_url.o mcode.o\ form_tags.o strops.o html.o ar r $@ $? ${RANLIB} $@ install: $(ALL) clean: -$(RM) -f *.o *~ *.a clobber: clean distclean: clean insight: clean $(MAKE) CC="insight" lint: $(LINT) $(LINTFLAGS) $(SRCS) 2>&1 | tee lint.out ================================================ FILE: libcgi/cgi.h ================================================ /** ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA **/ /** ** This file is part of the LIBCGI library ** */ #ifndef CGI_H #define CGI_H #include #include #include #include #include "../config.h" #ifdef NO_MACRO #undef isspace #undef isdigit #undef isalpha #undef isupper #undef islower #undef isxdigit #undef isalnum #undef ispunct #undef isprint #undef isgraph #undef iscntrl #undef isascii #endif #define MCODE_GET 1 #define MCODE_POST 2 #define MCODE_PUT 3 #define MCODE_HEAD 4 typedef struct { char *server_software; char *server_name; char *gateway_interface; char *server_protocol; char *server_port; char *request_method; char *http_accept; char *path_info; char *path_translated; char *script_name; char *query_string; char *remote_host; char *remote_addr; char *remote_user; char *auth_type; char *remote_ident; char *content_type; int content_length; } cgi_info; typedef struct festruct { char *name; char *val; struct festruct *next; } form_entry; /* Prototypes */ /* ---------- */ int get_cgi_info(cgi_info *); int syn_base_url(char *, cgi_info *); int syn_mimeheader(char *, char *); int mcode(cgi_info *); char *trim(char *); char *strmaxcpy(char *, char *, int); char *sanitize(char *, char *); char *parmval(form_entry *, char *); int print_base_url(cgi_info *); int print_mimeheader(const char *); void print_doc_begin(char *); void print_doc_end(char *); void print_logo(void); void print_sel_list(char *, char **, char *); void print_submit(char *); void print_input_blank(char *, unsigned int, unsigned int, char *); form_entry *get_form_entries(cgi_info *); void free_form_entries(form_entry *); form_entry *get_fes_from_string(char *); form_entry *get_fes_from_stream(int, FILE *); unsigned char dd2c(char, char); void dump_cgi_info(cgi_info *); #ifdef lint extern int isspace(int); extern int isalnum(int); extern int strcasecmp(const char *, const char *); extern int strncasecmp(const char *, const char *, size_t); #endif #endif ================================================ FILE: libcgi/form_ent.c ================================================ /** ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" #define LF 10 #define CR 13 #define STARTSIZE 8 form_entry *get_form_entries(cgi_info *ci) { if (ci && ci->request_method && !strncasecmp(ci->request_method, "POST", 4) && ci->content_type && !strncasecmp(ci->content_type, "application/x-www-form-urlencoded", 33)) return get_fes_from_stream(ci->content_length, stdin); else if (ci && ci->request_method && !strncasecmp(ci->request_method, "GET", 3)) return get_fes_from_string(ci->query_string); else return NULL; } void free_form_entries(form_entry *fe) { form_entry *tempfe; while (fe) { if (fe->name) free(fe->name); if (fe->val) free(fe->val); tempfe = fe->next; free(fe); fe = tempfe; } } char *parmval(form_entry *fe, char *s) { while (fe) { if (!strcasecmp(fe->name, s)) return fe->val; else fe = fe->next; } return NULL; } form_entry *get_fes_from_string(char *s) { form_entry *fe; int asize; int i; if (s == NULL) return NULL; while (isspace(*s) || *s == '&') s++; /* some cases that shouldn't happen */ if (*s == '\0') return NULL; fe = (form_entry *)malloc(sizeof(form_entry)); if (fe == NULL) return NULL; fe->name = malloc((asize = STARTSIZE * sizeof(char))); if (fe->name == NULL) { free(fe); return NULL; } /* get form field name */ for (i = 0; *s && *s != '&' && *s != '='; s++, i++) { switch (*s) { case '+': fe->name[i] = ' '; break; case '%': fe->name[i] = dd2c(s[1], s[2]); s += 2; break; default: fe->name[i] = *s; } if (i + 1 >= asize) { /* try to double the buffer */ fe->name = realloc(fe->name, (asize *= 2)); if (fe->name == NULL) return NULL; } } fe->name[i] = '\0'; switch (*s++) { case '&': fe->val = NULL; break; case '=': fe->val = malloc((asize = STARTSIZE * sizeof(char))); if (fe->val == NULL) break; for (i = 0; *s && *s != '&'; s++, i++) { switch (*s) { case '+': fe->val[i] = ' '; break; case '%': fe->val[i] = dd2c(s[1], s[2]); s += 2; break; default: fe->val[i] = *s; } if (i + 1 >= asize) { /* try to double the buffer */ fe->val = realloc(fe->val, (asize *= 2)); if (fe->val == NULL) return NULL; } } fe->val[i] = '\0'; switch (*s++) { case '&': fe->next = get_fes_from_string(s); break; case '\0': default: fe->next = NULL; } break; case '\0': default: fe->val = NULL; fe->next = NULL; } return fe; } #define getccl(s, l) (l-- ? getc(s) : EOF) form_entry *get_fes_from_stream(int length, FILE *stream) { form_entry *fe; int asize; int i; int c; int c1, c2; while (isspace(c = getccl(stream, length)) || c == '&'); if (c == EOF) return NULL; fe = (form_entry *)malloc(sizeof(form_entry)); if (fe == NULL) return NULL; fe->name = malloc((asize = STARTSIZE * sizeof(char))); if (fe->name == NULL) { free(fe); return NULL; } /* get form field name */ for (i = 0; c != EOF && c != '&' && c != '='; c = getccl(stream, length), i++) { switch (c) { case '+': fe->name[i] = ' '; break; case '%': c1 = getccl(stream, length); c2 = getccl(stream, length); fe->name[i] = dd2c(c1, c2); break; default: fe->name[i] = c; } if (i + 1 >= asize) { /* try to double the buffer */ fe->name = realloc(fe->name, (asize *= 2)); if (fe->name == NULL) return NULL; } } fe->name[i] = '\0'; if (c == EOF) { fe->val = NULL; fe->next = NULL; } else switch (c) { case '&': fe->val = NULL; break; case '=': fe->val = malloc((asize = STARTSIZE * sizeof(char))); for (i = 0, c = getccl(stream, length); c != EOF && c != '&'; c = getccl(stream, length), i++) { switch (c) { case '+': fe->val[i] = ' '; break; case '%': c1 = getccl(stream, length); c2 = getccl(stream, length); fe->val[i] = dd2c(c1, c2); break; default: fe->val[i] = c; } if (i + 1 >= asize) { /* try to double the buffer */ fe->val = realloc(fe->val, (asize *= 2)); if (fe->val == NULL) return NULL; } } fe->val[i] = '\0'; if (c == '&') { fe->next = get_fes_from_stream(length, stream); } else fe->next = NULL; } return fe; } unsigned char dd2c(char d1, char d2) { register unsigned char digit; digit = (d1 >= 'A' ? ((d1 & 0xdf) - 'A') + 10 : (d1 - '0')); digit *= 16; digit += (d2 >= 'A' ? ((d2 & 0xdf) - 'A') + 10 : (d2 - '0')); return (digit); } void dump_cgi_info(cgi_info *ci) { printf("CONTENT_LENGTH: %d\n", ci->content_length); if (ci->content_type != NULL) printf("
CONTENT_TYPE: %s\n", ci->content_type); if (ci->server_name != NULL) printf("
SERVER_NAME: %s\n", ci->server_name); if (ci->server_software != NULL) printf("
SERVER_SOFTWARE: %s\n", ci->server_software); if (ci->gateway_interface != NULL) printf("
GATEWAY_INTERFACE: %s\n", ci->gateway_interface); if (ci->server_protocol != NULL) printf("
SERVER_PROTOCOL: %s\n", ci->server_protocol); if (ci->server_port != NULL) printf("
SERVER_PORT: %s\n", ci->server_port); if (ci->request_method != NULL) printf("
REQUEST_METHOD: %s\n", ci->request_method); if (ci->http_accept != NULL) printf("
HTTP_ACCEPT: %s\n", ci->http_accept); if (ci->path_info != NULL) printf("
PATH_INFO: %s\n", ci->path_info); if (ci->path_translated != NULL) printf("
PATH_TRANSLATED: %s\n", ci->path_translated); if (ci->script_name != NULL) printf("
SCRIPT_NAME: %s\n", ci->script_name); if (ci->query_string != NULL) printf("
QUERY_STRING: %s\n", ci->query_string); if (ci->remote_host != NULL) printf("
REMOTE_HOST: %s\n", ci->remote_host); if (ci->remote_addr != NULL) printf("
REMOTE_ADDR: %s\n", ci->remote_addr); if (ci->auth_type != NULL) printf("
AUTH_TYPE: %s\n", ci->auth_type); if (ci->remote_user != NULL) printf("
REMOTE_USER: %s\n", ci->remote_user); if (ci->remote_ident != NULL) printf("
REMOTE_IDENT: %s\n", ci->remote_ident); return; } ================================================ FILE: libcgi/form_tags.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" void print_sel_list(char *tname, char **opts, char *init) { printf("", stdout); } void print_input_blank(char *tname, unsigned int size, unsigned int maxlength, char *init) { printf("", stdout); } void print_submit(char *label) { printf("", stdout); } ================================================ FILE: libcgi/get_cgi_info.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" int get_cgi_info(cgi_info *ci) { char *s; ci->content_length = (s = getenv("CONTENT_LENGTH")) ? atoi(s) : 0; ci->content_type = getenv("CONTENT_TYPE"); ci->server_software = getenv("SERVER_SOFTWARE"); ci->gateway_interface = getenv("GATEWAY_INTERFACE"); ci->server_protocol = getenv("SERVER_PROTOCOL"); ci->server_port = getenv("SERVER_PORT"); ci->request_method = getenv("REQUEST_METHOD"); ci->http_accept = getenv("HTTP_ACCEPT"); ci->path_info = getenv("PATH_INFO"); ci->path_translated = getenv("PATH_TRANSLATED"); ci->script_name = getenv("SCRIPT_NAME"); ci->query_string = getenv("QUERY_STRING"); ci->remote_host = getenv("REMOTE_HOST"); ci->remote_addr = getenv("REMOTE_ADDR"); ci->remote_user = getenv("REMOTE_USER"); ci->auth_type = getenv("AUTH_TYPE"); ci->remote_user = getenv("REMOTE_USER"); ci->remote_ident = getenv("REMOTE_IDENT"); return (ci->server_name = getenv("SERVER_NAME")) != NULL; } ================================================ FILE: libcgi/html.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" void print_doc_begin(char *title) { printf("%s\n", title); printf("

%s

\n\"\"
", title); } void print_doc_end(char *text) { char *w; puts("


"); if (text && *text) puts(text); else if ((w = getenv("WEBMASTER"))) printf("
%s
\n", w); } void print_logo(void) { printf("\"HYPERMAIL\""); } ================================================ FILE: libcgi/libcgi.html ================================================ Hypermail's CGI Library

Hypermail.ORG
CGI Library

These functions help you write virtual document (CGI) programs using C. Look at the template.c file for an illustrative example. Feel free to download the latest distributions from ftp.hypermail.org.


Synopsis

#include "libcgi/cgi.h"
main()
cgi_main(cgi_info *ci)

Description

libcgi contains a simple stub of a main program, which merely calls cgi_main() with a struct filled with all the CGI vars. Thus cgi_main is actually the entry point for your CGI-processing code. It is this way to be upwardly-compatible with a scheme for virtual document "daemons" that we're hatching.

Synopsis

#include "libcgi/cgi.h"
int get_cgi_info(cgi_info *)

Description

This routine paws through the environment and fills up the struct provided, which must already be allocated.

This function is called by main, and the result passed to cgi_main.

Returns

0 if there is a problem.

Synopsis

#include "libcgi/cgi.h"
form_entry *get_form_entries(cgi_info *)
void free_form_entries(cgi_info *)
char *parmval(form_entry *, char *)

Description

get_form_entries parses any form inputs information into a linked-list of name/value pairs, returning the head pointer of that list. It does all plus-to-space and hex code translations.

free_form_entries reclaims all the memory from the provided linked-list.

parmval return the value corresponding to the name in the second argument (a caseless string compar) by a linear search through the list in the first argument.

Returns

get_form_enties returns the head pointer, or NULL if there is a problem or no form input information was available. parmval returns the corresponding value string or NULL if there is a problem or no matching name.

Synopsis

#include "libcgi/cgi.h"
int syn_mimeheader(char *, char *)
int print_mimeheader(char *)

Description

syn_mimeheader creates a MIME header based on the MIME type in the second string and writes it into the first string buffer (including trailing double-newline).

print_mimeheader creates the same MIME header based on the MIME type in its sole argument, and prints it to stdout

Returns

both return 0 if there is a problem

Synopsis

#include "libcgi/cgi.h"
int syn_base_url(char *, cgi_info *)
int print_base_url(cgi_info *)

Description

syn_base_url reconstructs the virtual document's URL given the cgi_info, minus any query string, and fills the provided char buffer.

print_base_url does the same but prints to stdout instead

Returns

both return 0 if there is a problem

Synopsis

#include "libcgi/cgi.h"
int mcode(cgi_info *)

Description

This function examines the request_method in the cgi information and returns an integer code. These codes are defined in cgi.h.

Returns

0 if it doesn't recognize the method name, otherwise the code as defined in cgi.h

Synopsis

#include "libcgi/cgi.h"
void print_sel_list(char *tname, char **opts, char *init)

Description

Prints an HTML+ selection list construct to stdout. The name of the SELECT tag is given by tname, and the NULL-terminated string array opts is turned into separate OPTION tags with values corresponding to entries in opts. If any of these entries are a caseless match with init, then that OPTION tag is the default selection.

Synopsis

#include "libcgi/cgi.h"
void print_input_blank(char *tname, unsigned size, char *init)

Description

Prints an HTML+ INPUT tag (of type text) to stdout. The tag's name is tname, its size is size, and initial value is init.

Synopsis

#include "libcgi/cgi.h"
void print_submit(char *label)

Description

Prints an HTML+ INPUT tag of type submit to stdout. The submit button will be labelled by label if non-NULL.

Synopsis

#include "libcgi/cgi.h"
char *trim(char *s)

Description

Changes the string from blank-padded to NULL-padded

Returns

its argument

Synopsis

#include "libcgi/cgi.h"
char *sanitize(char *to, char *from)

Description

Prepares the string for inclusion in a URL. That is, the from string is copied to the to buffer except that blanks are turned into '+' characters and non-alphanumerics are turned into 3-character sequences of a '%' followed by two hex digits corresponding to the ascii code.

Returns

the to string

Synopsis

#include "libcgi/cgi.h"
char *strmaxcpy(char *s1, char *s2, int n)

Description

copies at most n-1 characters from s2 into s1, and then null-terminates. Handy for truncating while copying.

Returns

s1 as long as n > 0, NULL otherwise


hypermail@hypermail.org
================================================ FILE: libcgi/main.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" void cgi_main(cgi_info *ci); int main(void) { cgi_info ci; get_cgi_info(&ci); cgi_main(&ci); return (0); } ================================================ FILE: libcgi/mcode.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" int mcode(cgi_info *ci) { if (ci->request_method == NULL) return 0; else if (!strncasecmp(ci->request_method, "GET", 3)) return MCODE_GET; else if (!strncasecmp(ci->request_method, "POST", 4)) return MCODE_POST; else if (!strncasecmp(ci->request_method, "PUT", 3)) return MCODE_PUT; else if (!strncasecmp(ci->request_method, "HEAD", 4)) return MCODE_HEAD; else return 0; } ================================================ FILE: libcgi/strops.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* ** This file is part of the LIBCGI library ** */ #include "cgi.h" char *trim(char *s) { char *t = s; while (*t) t++; while (t > s && *--t == ' ') *t = 0; return s; } #if 0 char *sanitize(char *buf, char *s) { char *t; for (t = buf; *s; s++) if (*s == ' ') *t++ = '+'; else if (isalnum(*s)) *t++ = *s; else { sprintf(t, "%%%2X", *s); t += 3; } *t = '\0'; return buf; } #endif char *strmaxcpy(char *dest, char *src, int n) { char *d = dest; if (n < 1) return NULL; while (--n && *src) *d++ = *src++; *d = 0; return dest; } ================================================ FILE: libcgi/syn_mime.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" #if 0 int syn_mimeheader(char *buf, char *ct) { int x; if (buf && ct) { x = (int)sprintf(buf, "Content-Type: %s\n\n", ct); return (x && x != EOF); } else return 0; } #endif int print_mimeheader(const char *ct) { return (ct && (printf("Content-Type: %s\n\n", ct) != EOF)); } ================================================ FILE: libcgi/syn_url.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" #if 0 int syn_base_url(char *buf, cgi_info *ci) { int x; if (ci && buf) { x = (int)sprintf(buf, "http://%s:%s%s", ci->server_name, ci->server_port, ci->script_name); return (x && x != EOF); } else return 0; } #endif int print_base_url(cgi_info *ci) { return (ci && (printf("http://%s:%s%s", ci->server_name, ci->server_port, ci->script_name) != EOF)); } ================================================ FILE: libcgi/template.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* * This file is part of the LIBCGI library * */ #include "cgi.h" void cgi_main(cgi_info *ci) { char *parmval(); form_entry *parms, *p; form_entry *get_form_entries(); char *foo, *bar; print_mimeheader("text/html"); puts("Your Title Here"); puts("

Your heading here

"); parms = get_form_entries(ci); if (parms) { /* extract specific form parameters */ for (p = parms; p; p = p->next) { if (strcasecmp(p->name, "foo")) foo = p->val; else if (strcasecmp(p->name, "bar")) bar = p->val; } } switch (mcode(ci)) { case MCODE_HEAD: return; case MCODE_GET: puts("Your GET response here"); printf("based on foo=%s and bar=%s.\n", foo, bar); break; case MCODE_POST: puts("Your POST response here"); printf("based on foo=%s and bar=%s.\n", foo, bar); break; default: printf("Unrecognized method '%s'.\n", ci->request_method); } free_form_entries(parms); } ================================================ FILE: ltmain.sh ================================================ # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" # Parse our command line options once, thoroughly. while test $# -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" exit 0 ;; --config) sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 exit 0 ;; --debug) echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then case $nonopt in *cc | *++ | gcc* | *-gcc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= prev= lastarg= srcfile="$nonopt" suppress_output= user_target=no for arg do case $prev in "") ;; xcompiler) # Aesthetically quote the previous argument. prev= lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac # Accept any command-line options. case $arg in -o) if test "$user_target" != "no"; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi user_target=next ;; -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; -Xcompiler) prev=xcompiler continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac case $user_target in next) # The next one is the -o target name user_target=yes continue ;; yes) # We got the output file user_target=set libobj="$arg" continue ;; esac # Accept the current argument as the source file. lastarg="$srcfile" srcfile="$arg" # Aesthetically quote the previous argument. # Backslashify any backslashes, double quotes, and dollar signs. # These are the only characters that are still specially # interpreted inside of double-quoted scrings. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $lastarg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi done case $user_target in set) ;; no) # Get the name of the library object. libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; *) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSfmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $libobj" else removelist="$libobj" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test $pic_mode = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" else # Don't build PIC code command="$base_compile $srcfile" fi if test "$build_old_libs" = yes; then lo_libobj="$libobj" dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$libobj"; then dir="$objdir" else dir="$dir/$objdir" fi libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` if test -d "$dir"; then $show "$rm $libobj" $run $rm $libobj else $show "$mkdir $dir" $run $mkdir $dir status=$? if test $status -ne 0 && test ! -d $dir; then exit $status fi fi fi if test "$compiler_o_lo" = yes; then output_obj="$libobj" command="$command -o $output_obj" elif test "$compiler_c_o" = yes; then output_obj="$obj" command="$command -o $output_obj" fi $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test x"$output_obj" != x"$libobj"; then $show "$mv $output_obj $libobj" if $run $mv $output_obj $libobj; then : else error=$? $run $rm $removelist exit $error fi fi # If we have no pic_flag, then copy the object into place and finish. if (test -z "$pic_flag" || test "$pic_mode" != default) && test "$build_old_libs" = yes; then # Rename the .lo from within objdir to obj if test -f $obj; then $show $rm $obj $run $rm $obj fi $show "$mv $libobj $obj" if $run $mv $libobj $obj; then : else error=$? $run $rm $removelist exit $error fi xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` # Now arrange that obj and lo_libobj become the same file $show "(cd $xdir && $LN_S $baseobj $libobj)" if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 else error=$? $run $rm $removelist exit $error fi fi # Allow error messages only from the first compilation. suppress_output=' >/dev/null 2>&1' fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $srcfile" else # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" output_obj="$obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test x"$output_obj" != x"$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Create an invalid libtool object if no PIC, so that we do not # accidentally link it into a program. if test "$build_libtool_libs" != yes; then $show "echo timestamp > $libobj" $run eval "echo timestamp > \$libobj" || exit $? else # Move the .lo from within objdir $show "$mv $libobj $lo_libobj" if $run $mv $libobj $lo_libobj; then : else error=$? $run $rm $removelist exit $error fi fi fi # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 ;; # libtool link mode link | relink) modename="$modename: link" case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invokation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args="$nonopt" compile_command="$nonopt" finalize_command="$nonopt" compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= # We need to know -static, to get the right output filenames. for arg do case $arg in -all-static | -static) if test "X$arg" = "X-all-static"; then if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test $# -gt 0; do arg="$1" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n $prev prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | no/*-*-nonstopux*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 exit 1 fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-mingw* | *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.lo | *.$objext) # A library or standard object. if test "$prev" = dlfiles; then # This file was specified with -dlopen. if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $arg" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` prev= else case $arg in *.lo) libobjs="$libobjs $arg" ;; *) objs="$objs $arg" ;; esac fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d $output_objdir; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test $status -ne 0 && test ! -d $output_objdir; then exit $status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit 1 ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test $linkmode = prog; then # Determine which files to process case $pass in dlopen) libs="$dlfiles" save_deplibs="$deplibs" # Collect dlpreopened libraries deplibs= ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi for deplib in $libs; do lib= found=no case $deplib in -l*) if test $linkmode = oldlib && test $linkmode = obj; then $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 continue fi if test $pass = conv; then deplibs="$deplib $deplibs" continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do # Search the libtool library lib="$searchdir/lib${name}.la" if test -f "$lib"; then found=yes break fi done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test $pass = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi if test $pass = scan; then deplibs="$deplib $deplibs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test $pass = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) if test "$deplibs_check_method" != pass_all; then echo echo "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not used here." else echo echo "*** Warning: Linking the shared library $output against the" echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test $pass != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test $found = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 exit 1 fi # Check to see that this really is a libtool archive. if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variable installed. installed=yes # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test $linkmode = oldlib && test $linkmode = obj; }; then # Add dl[pre]opened files of deplib test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test $pass = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test $linkmode != prog && test $linkmode != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit 1 fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # This library was specified with -dlopen. if test $pass = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit 1 fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. dlprefiles="$dlprefiles $lib" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test $pass = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit 1 fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test $linkmode = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" fi continue fi if test $linkmode = prog && test $pass != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test $linkalldeplibs = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... link_static=no # Whether the deplib will be linked statically if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # Link against this shared library if test "$linkmode,$pass" = "prog,link" || { test $linkmode = lib && test $hardcode_into_libs = yes; }; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac if test $linkmode = prog; then # We need to hardcode the library path if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi fi fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`echo $soroot | sed -e 's/^.*\///'` newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$extract_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$old_archive_from_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n $old_archive_from_expsyms_cmds if test $linkmode = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test $linkmode = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test $linkmode = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" add="-l$name" fi if test $linkmode = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test $linkmode = prog; then if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi # Try to link the static library # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo echo "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test $linkmode = lib; then if test -n "$dependency_libs" && { test $hardcode_into_libs != yes || test $build_old_libs = yes || test $link_static = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test $link_all_deplibs != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="-L$absdir/$objdir" else eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="-L$absdir" fi ;; *) continue ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$deplibs $path" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test $pass = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test $pass != dlopen; then test $pass != scan && dependency_libs="$newdependency_libs" if test $pass != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do case $deplib in -L*) new_libs="$deplib $new_libs" ;; *) case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi if test "$pass" = "conv" && { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then libs="$deplibs" # reset libs deplibs= fi done # for pass if test $linkmode = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit 1 else echo echo "*** Warning: Linking the shared library $output against the non-libtool" echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test $# -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. libext=al oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi current="$2" revision="$3" age="$4" # Check that each of the things are valid numbers. case $current in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $revision in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $age in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test $age -gt $current; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" major=`expr $current - $age + 1` # Add in all the interfaces that we are compatible with. loop=$revision while test $loop != 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test $loop != 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= verstring="0.0" case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring="" ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs. $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'` deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'` dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test $hardcode_into_libs != yes || test $build_old_libs = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. ;; *) # Add libc to deplibs on all other systems if necessary. if test $build_libtool_need_lc = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behaviour. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | sed 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | sed 10q \ | egrep "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then echo "*** with $libname but no candidates were found. (...for file magic test)" else echo "*** with $libname and none of the candidates passed a file format test" echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check below in file_magic test if eval echo \"$potent_lib\" 2>/dev/null \ | sed 10q \ | egrep "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then echo "*** with $libname but no candidates were found. (...for regex pattern test)" else echo "*** with $libname and none of the candidates passed a file format test" echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | grep . >/dev/null; then echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" echo "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test $allow_undefined = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test $hardcode_into_libs = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi test -z "$dlname" && dlname=$soname lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Ensure that we have .o objects for linkers which dislike .lo # (e.g. aix) in case we are running --disable-static for obj in $libobjs; do xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` if test ! -f $xdir/$oldobj; then $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? fi done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? exit 0 fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. $show "echo timestamp > $libobj" $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" else # Just create a symlink. $show $rm $libobj $run $rm $libobj xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$libobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` $show "(cd $xdir && $LN_S $oldobj $baseobj)" $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; prog) case $host in *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`echo "$arg" | sed -e 's%^.*/%%'` $run eval 'echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test $need_relink = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit 0 fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case $0 in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`echo $output|sed 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe ;; *) exeext= ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # win32 systems need to use the prog path for dll # lookup to work *-*-cygwin* | *-*-pw32*) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ # Export the path to the program. PATH=\"\$progdir:\$PATH\" export PATH exec \$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else # Ensure that we have .o objects in place in case we decided # not to build a shared library, and have fallen back to building # static libs even though --disable-static was passed! for oldobj in $oldobjs; do if test ! -f $oldobj; then xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$oldobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` $show "(cd $xdir && ${LN_S} $obj $baseobj)" $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? fi done eval cmds=\"$old_archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test $need_relink = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case $arg in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test $# -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 continue fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test $# -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`echo $file | sed -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (sed -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $wrapper ;; *) . ./$wrapper ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit 1 fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $wrapper ;; *) . ./$wrapper ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir="$tmpdir/libtool-$$" if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyways case $install_prog,$host in /usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`echo $destfile | sed -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $0 --finish$current_libdirs' else exit 0 fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = ":" && exit 0 echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do echo " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" echo "more information, such as the ld(1) and ld.so(8) manual pages." echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved enviroment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi rmdirs= for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$objdir" else objdir="$dir/$objdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test $mode = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test $mode = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" if test $mode = uninstall; then if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi fi ;; *.lo) if test "$build_old_libs" = yes; then oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` rmfiles="$rmfiles $dir/$oldobj" fi ;; *) # Do a test to see if this is a libtool program. if test $mode = clean && (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$file rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit 1 fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE." exit 0 ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: ================================================ FILE: maketgz ================================================ #! /bin/sh # Script to build release-archives with # echo "Version number ?" read version echo "Patchlevel ?" read patchlevel HEADER="patchlevel.h" # Replace version number in header file: sed -e 's/#define VERSION.*/#define VERSION "'$version'"/g' \ -e 's/#define PATCHLEVEL.*/#define PATCHLEVEL "'$patchlevel'"/g' $HEADER >$HEADER.new # Save old header file cp -p $HEADER $HEADER.old # Make new header: mv $HEADER.new $HEADER # get current dir dir=`pwd` # Get basename orig=`basename $dir` # Get the left part of the dash (-) new=`echo $orig | cut -d- -f1` # Build new directory name n=$new-$version; # Tell the world what we're doing echo "creates $n.tar.gz"; if [ -r $n ]; then echo "Directory already exists!" exit fi # Create the new dir mkdir $n # Copy all relevant files, with path and permissions! tar -cf - `cat FILES | grep -v \#` | (cd $n; tar -xBpf -) # Make a tar archive of it all tar -cvf $n.tar $n # gzip the archive gzip $n.tar # Make it world readable chmod a+r $n.tar.gz ; # Delete the temp dir rm -rf $n ================================================ FILE: patchlevel.h ================================================ #define VERSION "2.4.0" #define PATCHLEVEL "0" ================================================ FILE: src/.indent.pro ================================================ -nbad -bap -nbbo -nbc -br -brs -ncdb -nce -ci4 -cp33 -ncs -d0 -di1 -nfc1 -nfca -hnl -i4 -ip0 -l75 -lp -npcs -npsl -nsc -nsob -nss -Tform_entry -Tcgi_info -TFILE -Ttime_t -Tva_stack_t -Tpattern ================================================ FILE: src/.splintrc ================================================ # # Standard mode of checking. # -weak #-standard #-checks #-strict # # MEMORY/NULL/SECURITY +nullterminated +bounds +boundsread +boundswrite +fcnpost +redundantconstraints +checkpost +implictconstraint +orconstraint +nullterminated +showconstraintparens +boundscompacterrormessages +showconstraintlocation +debugfcnconstraint +deparrays +charindex +enumindex +mustfreefresh +mustfreeonly +mustfree +compdestroy +strictdestroy +null +nullderef +nullpass +nullret +nullstate +nullassign +bufferoverflow +bufferoverflowhigh +implementationoptional +multithreaded +portability +superuser +toctou +unixstandard +its4mostrisky +its4veryrisky +its4risky +its4moderate +its4low # # Others # # #-abstract #-badflag #-boolops #-booltype #-branchstate #-casebreak #+charintliteral #-compdef #-compdestroy #-compmempass #-dependenttrans #-evalorder #-exitarg #-exportlocal #-formatconst #-formattype #-fullinitblock #-globstate #-globuse #-ifempty +ignoresigns #-immediatetrans #-incondefs #-infloops #-initallelements #-kepttrans #-likelybool #-macroredef +matchanyintegral #-mayaliasunique #-modobserver #-mustfreefresh #-mustfreeonly #-noret #-nullassign #-nullderef #-nullpass #-nullret #-nullstate #-observertrans #-onlytrans #-paramuse #-posix-lib #-predboolint #-predboolothers #+ptrnegate #-realcompare #-redef #-retvalint -retvalother #-shadow #-shiftimplementation #-shiftnegative #+showscan #-showsummary #-statictrans #+stats #-temptrans #-type #-uniondef #-unqualifiedtrans #-unreachable -unrecog #-unrecogcomments #-usedef #-usereleased -usevarargs #-varuse #-warnlintcomments -warnposixheaders ================================================ FILE: src/Makefile.in ================================================ # # Makefile for Hypermail # @SET_MAKE@ prefix=@prefix@ datarootdir = @datarootdir@ datadir = @datadir@ exec_prefix=@exec_prefix@ # This is where you want hypermail to be installed bindir=@bindir@ # This is where the man page goes mandir=@mandir@ # This is where your CGI programs live cgidir=@cgidir@ # Executable program suffix (.exe for windows, null for Unix systems) SUFFIX=@suffix@ # Compiler to use CC=@CC@ # Installation program to use INSTALL_PROG=@INSTALL@ SPLINTFLAGS=@INCLUDES@ PCRE_DEP=@PCRE_DEP@ TRIO_DEP=@TRIO_DEP@ FNV_DEP=@FNV_DEP@ #WNOERROR=-Werror #WARNINGS=$(WNOERROR) -ansi -pedantic -Wall -Wtraditional -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Dlint CFLAGS=@CFLAGS@ $(WARNINGS) CPPFLAGS=@CPPFLAGS@ @INCLUDES@ YACC=@YACC@ NETLIBS=@LIBS@ LDFLAGS=@LDFLAGS@ MISC_LIBS= -lpcre -ltrio -lm OPT_LIBS=@EXTRA_LIBS@ INCS= domains.h hypermail.h lang.h proto.h \ ../config.h ../patchlevel.h dsprintf.h threadprint.h \ getdate.h getname.h finelink.h txt2html.h search.h SRCS= base64.c date.c domains.c file.c hypermail.c lang.c lock.c \ mem.c parse.c print.c printfile.c string.c struct.c uudecode.c\ dmatch.c setup.c threadprint.c getdate.c getname.c\ finelink.c txt2html.c search.c quotes.c OBJS= base64.o date.o domains.o file.o hypermail.o lang.o lock.o \ mem.o parse.o print.o printfile.o string.o struct.o uudecode.o\ dmatch.o setup.o threadprint.o getdate.o getname.o\ finelink.o txt2html.o search.o quotes.o MAILOBJS= mail.o ../libcgi/libcgi.a .c.o: $(CC) -c $(CFLAGS) $(CPPFLAGS) $< all: @PCRE_DEP@ @TRIO_DEP@ @FNV_DEP@ hypermail$(SUFFIX) mail$(SUFFIX) lang$(SUFFIX) pcre/.libs/libpcre.a: @cd pcre; $(MAKE) CC="$(CC)" ; rm -f .libs/lib*.so* trio/libtrio.a: @cd trio; $(MAKE) CC="$(CC)" fnv/libfnv.a: @cd fnv; $(MAKE) libfnv.a CC="$(CC)" CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" hypermail$(SUFFIX): $(OBJS) $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(OBJS) $(OPT_LIBS) $(MISC_LIBS) chmod 0755 $@ mail$(SUFFIX): $(MAILOBJS) $(CC) -o $@ $(CFLAGS) $(MAILOBJS) $(NETLIBS) -lm chmod 0755 $@ lang$(SUFFIX): lang.c lang.h $(CC) -DLANG_PROG $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ lang.c $(MISC_LIBS) ../libcgi/libcgi.a: @cd ../libcgi; $(MAKE) all CC="$(CC)" CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" getdate.c: getdate.y getdate.h @echo "Expect 13 shift/reduce conflicts." $(YACC) getdate.y @mv -f y.tab.c getdate.c install: all @if [ ! -d $(bindir) ]; then mkdir -p $(bindir); fi $(INSTALL_PROG) -s -c -m 0755 hypermail$(SUFFIX) $(bindir) mail.install: @if [ ! -d $(cgidir) ]; then mkdir -p $(cgidir); fi $(INSTALL_PROG) -s -c -m 0755 mail$(SUFFIX) $(cgidir) uninstall: rm -f $(bindir)/hypermail$(SUFFIX) rm -f $(cgidir)/mail$(SUFFIX) insight: $(MAKE) CC="insight" pure: $(MAKE) CFLAGS="-g" $(OBJS) purify $(CC) -o hypermail -g $(CFLAGS) $(CPPFLAGS) $(OBJS) quant: $(MAKE) CFLAGS="-g" $(OBJS) quantify $(CC) -o hypermail -g $(CFLAGS) $(CPPFLAGS) $(OBJS) splint: splint $(SPLINTFLAGS) $(SRCS) 2>&1 | tee splint.out lint: lint $(SRCS) 2>&1 | tee lint.out lint_mail: lint mail.c 2>&1 | tee lint.out @(cd ../libcgi; $(MAKE) lint 2>&1 | tee -a ../lint.out) clean: rm -f hypermail$(SUFFIX) mail$(SUFFIX) lang$(SUFFIX) rm -f *.o .pure *qx *qv *.ln core rm -f .inslog tca.map lint.out splint.out rm -f getdate.c @(if test "$(PCRE_DEP)" != "" ; then cd pcre; $(MAKE) clean; fi) @(if test "$(TRIO_DEP)" != "" ; then cd trio; $(MAKE) clean; fi) @(if test "$(FNV_DEP)" != "" ; then cd fnv; $(MAKE) clean; fi) @cd ../libcgi; $(MAKE) clean clobber: clean @(if test "$(PCRE_DEP)" != "" ; then cd pcre; rm -f *.lock; fi) @(if test "$(TRIO_DEP)" != ""; then cd trio; rm -f *.lock; fi) @(if test "$(FNV_DEP)" != "" ; then cd fnv; $(MAKE) clobber; fi) @cd ../libcgi; $(MAKE) clobber distclean: clobber @(if test "$(PCRE_DEP)" != "" ; then cd pcre; $(MAKE) distclean; fi) @(if test "$(TRIO_DEP)" != ""; then cd trio; $(MAKE) clean; fi) @(if test "$(FNV_DEP)" != "" ; then cd fnv; $(MAKE) distclean; fi) @cd ../libcgi; $(MAKE) distclean # # Regenerate this dependency list with gcc -MM *.c: # base64.o: base64.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ base64.h date.o: date.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h dmatch.o: dmatch.c dmatch.h ../config.h domains.o: domains.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h domains.h file.o: file.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h struct.h finelink.o: finelink.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h finelink.h setup.h print.h struct.h search.h getname.o: getname.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h getname.h setup.h hypermail.o: hypermail.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h defaults.h setup.h parse.h print.h finelink.h search.h struct.h lang.o: lang.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h lock.o: lock.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h mail.o: mail.c ../libcgi/cgi.h ../libcgi/../config.h ../config.h mem.o: mem.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h parse.o: parse.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h struct.h uudecode.h base64.h search.h getname.h parse.h print.h print.o: print.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h struct.h printfile.h print.h parse.h txt2html.h finelink.h \ threadprint.h printfile.o: printfile.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h setup.h print.h printfile.h struct.h quotes.o: quotes.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h search.o: search.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h struct.h print.h search.h setup.o: setup.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ defaults.h setup.h struct.h print.h string.o: string.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ setup.h parse.h uconvert.h struct.o: struct.c hypermail.h ../config.h ../patchlevel.h proto.h lang.h \ dmatch.h setup.h struct.h parse.h getname.h threadprint.o: threadprint.c hypermail.h ../config.h ../patchlevel.h \ proto.h lang.h setup.h struct.h threadprint.h printfile.h print.h txt2html.o: txt2html.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h setup.h print.h finelink.h txt2html.h uudecode.o: uudecode.c hypermail.h ../config.h ../patchlevel.h proto.h \ lang.h setup.h uudecode.h ================================================ FILE: src/base64.c ================================================ /* ** Author: Daniel Stenberg ** Version: 0.1 ** ** This is a Base64 encoder as defined in RFC 2045. If the output is gonna be ** used in a mail body: "The encoded output stream must be represented in ** lines of no more than 76 characters each." ** ** CHANGES by Daniel Stenberg. May 11, 1998: ** ** - Encoded strings that ended with more than one = caused the decode ** function+ to generate 3 extra zero bytes at the end of the output. */ #include "hypermail.h" #include "base64.h" void base64Decode(char *intext, char *out, int *length) { unsigned char ibuf[4]; unsigned char obuf[3]; char ignore; char endtext = FALSE; char ch; int lindex = 0; *length = 0; memset(ibuf, 0, sizeof(ibuf)); while (*intext) { ch = *intext; ignore = FALSE; if ((ch >= 'A') && (ch <= 'Z')) ch = ch - 'A'; else if ((ch >= 'a') && (ch <= 'z')) ch = ch - 'a' + 26; else if ((ch >= '0') && (ch <= '9')) ch = ch - '0' + 52; else if (ch == '+') ch = 62; else if (ch == '=') { /* end of text */ if (endtext) break; endtext = TRUE; lindex--; if (lindex < 0) lindex = 3; } else if (ch == '/') ch = 63; else if (endtext) break; else ignore = TRUE; if (!ignore) { if (!endtext) { ibuf[lindex] = ch; lindex++; lindex &= 3; /* use bit arithmetic instead of remainder */ } if ((0 == lindex) || endtext) { obuf[0] = (ibuf[0] << 2) | ((ibuf[1] & 0x30) >> 4); obuf[1] = ((ibuf[1] & 0x0F) << 4) | ((ibuf[2] & 0x3C) >> 2); obuf[2] = ((ibuf[2] & 0x03) << 6) | (ibuf[3] & 0x3F); switch (lindex) { case 1: sprintf(out, "%c", obuf[0]); out++; (*length)++; break; case 2: sprintf(out, "%c%c", obuf[0], obuf[1]); out += 2; (*length) += 2; break; default: sprintf(out, "%c%c%c", obuf[0], obuf[1], obuf[2]); out += 3; (*length) += 3; break; } memset(ibuf, 0, sizeof(ibuf)); } } intext++; } *out = 0; } ================================================ FILE: src/base64.h ================================================ /* ** MIME Decode - base64.c */ void base64Decode(char *, char *, int *); ================================================ FILE: src/date.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* ** Move to wrappers calling standard functions - perhaps slower ** but easier to maintain */ #include "hypermail.h" #include "setup.h" /* ** Given a long date string, it returns the number of seconds ** since BASEYEAR. (Y2K ok) */ extern time_t get_date(const char *, const time_t *); static time_t ydhms_tm_diff(int, int, int, int, int, const struct tm *); static time_t my_mktime(struct tm *); time_t convtoyearsecs(char *date) { time_t yearsecs; char *p, *s = date; /* the (non-standard) timezone specs GMT0 and BST-1 * confuse the get_date routines (GMT0 sets the year to 0). * Rather than altering the standard routine, we try to * put them into a standard format here. */ if ((p = strstr(date, "GMT0")) != NULL) { s = malloc(strlen(date) + 1); strcpy(s, date); *(s + (p - date) + 3) = '\0'; } else if ((p = strstr(date, "BST-1")) != NULL) { s = malloc(strlen(date) + 1); strcpy(s, date); strcpy(s + (p - date), "-1"); } yearsecs = get_date(s, (time_t *)NULL); if (s != date) { free(s); } /* if we can't parse the date string, the calling * routine needs to know as it may have another * way of getting the date. */ return yearsecs; } /* ** Gets the local time and returns it formatted. */ char *getlocaltime(void) { static char s[DATESTRLEN + 5]; time_t tp; struct tm *tmptr; time(&tp); tmptr = (set_gmtime ? gmtime(&tp) : localtime(&tp)); s[0] = '\0'; if (set_dateformat != NULL) { strftime(s, DATESTRLEN, set_dateformat, tmptr); /* * Need to check if the timezone %Z was specified. * If so do not print it out automatically. */ if (strstr(set_dateformat, "%Z") == NULL) sprintf(s, "%s %s", s, timezonestr); } else { if (set_eurodate) strftime(s, DATESTRLEN, "%a %d %b %Y - %H:%M:%S", tmptr); else if (set_isodate) { if (set_gmtime) strftime(s, DATESTRLEN, "%Y-%m-%dZ%H:%M:%S", tmptr); else strftime(s, DATESTRLEN, "%Y-%m-%d %H:%M:%S", tmptr); } else strftime(s, DATESTRLEN, "%a %b %d %Y - %H:%M:%S", tmptr); sprintf(s, "%s %s", s, timezonestr); } return s; } /* ** Gets the local time zone. */ void gettimezone(void) { time_t tp; time(&tp); strftime(timezonestr, TIMEZONELEN, "%Z", set_gmtime ? gmtime(&tp) : localtime(&tp)); } /* ** Gets the current year. */ void getthisyear(void) { time_t tp; time(&tp); strftime(thisyear, YEARLEN, "%Y", set_gmtime ? gmtime(&tp) : localtime(&tp)); } int year_of_datenum(time_t t) { struct tm *tptr = (set_gmtime ? gmtime(&t) : localtime(&t)); return tptr->tm_year + 1900; } int month_of_datenum(time_t t) { struct tm *tptr = (set_gmtime ? gmtime(&t) : localtime(&t)); return tptr->tm_mon; } /* ** From the number of seconds since BASEYEAR, this pretty-prints ** a date for you. */ char *getdatestr(time_t yearsecs) { static char date[DATESTRLEN]; struct tm *tmptr = (set_gmtime ? gmtime(&yearsecs) : localtime(&yearsecs)); if (set_dateformat != NULL) { strftime(date, DATESTRLEN, set_dateformat, tmptr); } else { if (set_eurodate) strftime(date, DATESTRLEN, "%a %d %b %Y - %H:%M:%S %Z", tmptr); else if (set_isodate) { if (set_gmtime) strftime(date, DATESTRLEN, "%Y-%m-%dZ%H:%M:%S", tmptr); else strftime(date, DATESTRLEN, "%Y-%m-%d %H:%M:%S", tmptr); } else strftime(date, DATESTRLEN, "%a %b %d %Y - %H:%M:%S %Z", tmptr); } return date; } /* ** This function calls getdatestr, but with an alternate date format ** that is used for showing dates in the indexs */ char *getindexdatestr(time_t yearsecs) { char *previous_dateformat; char *date; /* store the previous dateformat */ previous_dateformat = set_dateformat; /* if there's an index date format, we use it, otherwise use the standard dateformat */ if (set_indexdateformat) set_dateformat = set_indexdateformat; date = getdatestr (yearsecs); /* restore the previous dateformat */ set_dateformat = previous_dateformat; return date; } /* ** This function calls getdatestr, but with a fixed alternate ** date format that we use for comparing two dates minus the hour. */ char *getdateindexdatestr(time_t yearsecs) { char *previous_dateformat; char *date; /* store the previous dateformat */ previous_dateformat = set_dateformat; set_dateformat = "%A, %e %B %Y"; date = getdatestr (yearsecs); /* restore the previous dateformat */ set_dateformat = previous_dateformat; return date; } char *secs_to_iso(time_t t) { /* is passed time_t variable * holding number of seconds since EPOCH * returns pointer to string holding date in format * YYYYMMDDHHMMSS * This buffer will be overwritten by next call to secs_to_iso. */ static char s[15]; struct tm *tm; tm = gmtime(&t); sprintf(s, "%4.4d%02.2d%02.2d%02.2d%02.2d%02.2d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return s; } char *secs_to_iso_meta(time_t t) { /* is passed time_t variable * holding number of seconds since EPOCH * returns pointer to string holding date in format * YYYY-MM-DD * This buffer will be overwritten by next call to secs_to_iso_meta. */ static char s[11]; struct tm *tm; tm = localtime(&t); sprintf(s, "%4.4d-%02.2d-%02.2d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); return s; } time_t iso_to_secs(char *isodate) { /* is passed string holding date in format * YYYYMMDDHHMMSS * returns number of seconds since EPOCH */ struct tm t; char s[15]; strncpy(s, isodate, 14); s[14] = '\0'; t.tm_isdst = 0; t.tm_yday = 0; t.tm_wday = 0; t.tm_sec = atoi(s + 12); *(s + 12) = '\0'; t.tm_min = atoi(s + 10); *(s + 10) = '\0'; t.tm_hour = atoi(s + 8); *(s + 8) = '\0'; t.tm_mday = atoi(s + 6); *(s + 6) = '\0'; t.tm_mon = atoi(s + 4) - 1; *(s + 4) = '\0'; t.tm_year = atoi(s) - 1900; return my_mktime(&t); } /* Based on mktime.c from the GNU C library (glibc-2.0.6) * simplified to ignore timezones completely for use by hypermail when * converting from iso string representation of time to seconds since * epoch (interpreting given time as UTC). * * Paul Haldane */ #define TM_YEAR_BASE 1900 #define EPOCH_YEAR 1970 #ifndef __isleap /* Nonzero if YEAR is a leap year (every 4 years, except every 100th isn't, and every 400th is). */ # define __isleap(year) \ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) #endif /* How many days come before each month (0-12). */ const unsigned short int __mon_yday[2][13] = { /* Normal years. */ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, /* Leap years. */ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} }; /* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP), measured in seconds, ignoring leap seconds. YEAR uses the same numbering as TM->tm_year. All values are in range, except possibly YEAR. If overflow occurs, yield the low order bits of the correct answer. */ static time_t ydhms_tm_diff(int year, int yday, int hour, int min, int sec, const struct tm *tp) { /* Compute intervening leap days correctly even if year is negative. Take care to avoid int overflow. time_t overflow is OK, since only the low order bits of the correct time_t answer are needed. Don't convert to time_t until after all divisions are done, since time_t might be unsigned. */ int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - !(year & 3); int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - !(tp->tm_year & 3); int a100 = a4 / 25 - (a4 % 25 < 0); int b100 = b4 / 25 - (b4 % 25 < 0); int a400 = a100 >> 2; int b400 = b100 >> 2; int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); time_t years = year - (time_t)tp->tm_year; time_t ddays = (365 * years + intervening_leap_days + (yday - tp->tm_yday)); return (60 * (60 * (24 * ddays + (hour - tp->tm_hour)) + (min - tp->tm_min)) + (sec - tp->tm_sec)); } /* Convert *TP to a time_t value */ static time_t my_mktime(struct tm *tp) { time_t t0; struct tm tm; /* Time requested. Copy it in case CONVERT modifies *TP; this can occur if TP is localtime's returned value and CONVERT is localtime. */ int sec = tp->tm_sec; int min = tp->tm_min; int hour = tp->tm_hour; int mday = tp->tm_mday; int mon = tp->tm_mon; int year_requested = tp->tm_year; /* Ensure that mon is in range, and set year accordingly. */ int mon_remainder = mon % 12; int negative_mon_remainder = mon_remainder < 0; int mon_years = mon / 12 - negative_mon_remainder; int year = year_requested + mon_years; /* The other values need not be in range: the remaining code handles minor overflows correctly, assuming int and time_t arithmetic wraps around. Major overflows are caught at the end. */ /* Calculate day of year from year, month, and day of month. The result need not be in range. */ int yday = ((__mon_yday[__isleap(year + TM_YEAR_BASE)] [mon_remainder + 12 * negative_mon_remainder]) + mday - 1); tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE; tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0; t0 = ydhms_tm_diff(year, yday, hour, min, sec, &tm); return t0; } ================================================ FILE: src/defaults.h.in ================================================ #ifndef __DEFAULTS_H #define __DEFAULTS_H /* ALERT! ALERT! ALERT! ALERT! ALERT! ALERT! ALERT! ALERT! * * The #defines following here ARE NOT intended to be modified locally * before you compile hypermail. They're here to set internal defaults * and they are set during the configure process. To alter these settings * for use during runtime, modify your config file! */ #define CONFIGFILE "~/.hmrc" #define INLINE_TYPES "image/gif image/jpeg image/png" #define SHOW_HEADERS "From Subject Date Message-ID" #define MAILCOMMAND "mailto:$TO?Subject=$SUBJECT" #define PROGRESS 0 #define RECOGNIZE_SUPERCITE_QUOTES 1 #define LANGUAGE "@language@" #define HTMLSUFFIX "@htmlsuffix@" #define DEFAULTINDEX "@defaultindex@" #define DOMAINADDR "@domainaddr@" #define ANTISPAM_AT "_at_" #define APPLE_MAIL_UA "Apple iPhone iPad" #endif ================================================ FILE: src/dmatch.c ================================================ /* The shortest ever? 88 characters... m(char*s,char*t){return*t-'*'?*s?*t=='?'|*s==*t&&m(s+1,t+1):!*t:m(s,t+1)||*s&&m(s+1,t);} Written by Staffan Ulfberg What follows below is a rewrite of the above into readable C and a small patch to prevent really deep recursiveness on patterns featuring a long sequence of '*'. Done by Daniel Stenberg */ #include "dmatch.h" #ifdef __LCC__ #include "../lcc/config.h" #else #include "../config.h" #endif #ifdef HAVE_CTYPE_H #include #endif #undef FALSE #define FALSE 0 #undef TRUE #define TRUE 1 char Match(char *string, char *pattern) { for (; '*'^*pattern; ++pattern, ++string) { if (!*string) return (!*pattern); if (toupper(*string) ^ toupper(*pattern) && '?'^*pattern) return (FALSE); } /* two-line patch to prevent *too* much recursiveness: */ while ('*' == pattern[1]) pattern ++; do { if (Match(string, pattern +1)) return (TRUE); } while (*string++); return (FALSE); } ================================================ FILE: src/dmatch.h ================================================ char Match(char *, char *); ================================================ FILE: src/domains.c ================================================ #include "hypermail.h" #include "domains.h" struct co_code *ccptr; int valid_root_domain(char *eaddr) { char *name_to_check; /* First check to see if it has a '.' in it. ** Not invalid if there is no '.'. */ if ((name_to_check = strrchr(eaddr, '.')) == NULL) return (0); ++name_to_check; if (!*name_to_check) return (0); /* DNS has evolved and we have now a variety of new domains, hard to track and that are not covered by this function. While temporary waiting to see if we evolve this function to be user configurable, we're going to return 1 (valid) all the time. 19/06/2020 -JK */ return (1); for (ccptr = domain_codes; ccptr->domain != NULL; ccptr++) { if (strcasecmp(name_to_check, ccptr->domain) == 0) return (1); } return (0); } ================================================ FILE: src/domains.h ================================================ /* ** @(#)domains.h 1.17 03/09/03 - Kent Landfield */ /* ** Domain Address COUNTRY Abbreviations ** Domain codes ** ** Thanks to Olivier Crepin-Leblond for the basis of ** this file. For more timely information, check out ** ** http://www.nsrc.org/codes/country-codes.html ** http://www.faqs.org/faqs/mail/country-codes/ ** */ struct co_code { char *domain; char *country; }; struct co_code domain_codes[] = { { "ARPA", "Arpanet" }, { "AERO", "Air Transport Industry" }, { "BIZ", "Businesses" }, { "COOP", "Non-profit cooperatives" }, { "COM", "Commercial Entity" }, { "EDU", "Educational Institution" }, { "GOV", "Government Office" }, { "INFO", "Informational" }, { "INT", "International Organization" }, { "MIL", "US Military" }, { "MUSEUM", "Museum" }, { "NAME", "Personal Name" }, { "NET", "Network Service Provider" }, { "PRO", "Accountants, lawyers and physicians" }, { "ORG", "Organizations" }, { "AC", "Ascension Island" }, { "AD", "Andorra" }, { "AE", "United Arab Emirates" }, { "AF", "Afghanistan" }, { "AG", "Antigua and Barbuda" }, { "AI", "Anguilla" }, { "AL", "Albania" }, { "AM", "Armenia" }, { "AN", "Netherlands Antilles" }, { "AO", "Republic of Angola" }, { "AQ", "Antarctica" }, { "AR", "Argentina" }, { "AS", "American Samoa" }, { "AT", "Austria" }, { "AU", "Australia" }, { "AW", "Aruba" }, { "AZ", "Azerbaijan" }, { "BA", "Bosnia-Herzegovina" }, { "BB", "Barbados" }, { "BD", "Bangladesh" }, { "BE", "Belgium" }, { "BF", "Burkina Faso" }, { "BG", "Bulgaria" }, { "BH", "Bahrain" }, { "BI", "Burundi" }, { "BJ", "Benin" }, { "BM", "Bermuda" }, { "BN", "Brunei Darussalam" }, { "BO", "Bolivia" }, { "BR", "Brazil" }, { "BS", "Bahamas" }, { "BT", "Bhutan" }, { "BV", "Bouvet Island" }, { "BW", "Botswana" }, { "BY", "Belarus" }, { "BZ", "Belize" }, { "CA", "Canada" }, { "CC", "Cocos (Keeling) Islands" }, { "CD", "Democratic Republic of Congo", }, { "CF", "Central African Republic" }, { "CG", "Congo, Republic of" }, { "CH", "Switzerland" }, { "CI", "Cote D'Ivoire (Ivory Coast)" }, { "CK", "Cook Islands" }, { "CL", "Chile" }, { "CM", "Cameroon" }, { "CN", "China" }, { "CO", "Colombia" }, { "CR", "Costa Rica" }, { "CU", "Cuba" }, { "CV", "Cape Verde" }, { "CX", "Christmas Island" }, { "CY", "Cyprus" }, { "CZ", "Czech Republic" }, { "DE", "Germany" }, { "DJ", "Djibouti" }, { "DK", "Denmark" }, { "DM", "Dominica" }, { "DO", "Dominican Republic" }, { "DZ", "Algeria" }, { "EC", "Ecuador" }, { "EE", "Estonia" }, { "EG", "Egypt" }, { "EH", "Western Sahara" }, { "ER", "Eritrea" }, { "ES", "Spain" }, { "ET", "Ethiopia" }, { "FI", "Finland" }, { "FJ", "Fiji" }, { "FK", "Falkland Islands (Malvinas)" }, { "FM", "Micronesia, Federal State of" }, { "FO", "Faroe Islands" }, { "FR", "France" }, { "GA", "Gabon" }, { "GB", "Great Britian" }, { "GD", "Grenada" }, { "GE", "Georgia" }, { "GF", "French Guiana" }, { "GG", "Guernsey" }, { "GH", "Ghana" }, { "GI", "Gibraltar" }, { "GL", "Greenland" }, { "GM", "Gambia" }, { "GN", "Guinea" }, { "GP", "Guadeloupe" }, { "GQ", "Equatorial Guinea" }, { "GR", "Greece" }, { "GS", "S.Georgia & S.Sandwich Islands." }, { "GT", "Guatemala" }, { "GU", "Guam (US)" }, { "GW", "Guinea-Bissau" }, { "GY", "Guyana" }, { "HK", "Hong Kong" }, { "HM", "Heard and McDonald Islands" }, { "HN", "Honduras" }, { "HR", "Croatia/Hrvatska" }, { "HT", "Haiti" }, { "HU", "Hungary" }, { "ID", "Indonesia" }, { "IE", "Ireland" }, { "IL", "Israel" }, { "IM", "Isle of Man" }, { "IN", "India" }, { "IO", "British Indian Ocean Territory." }, { "IQ", "Iraq" }, { "IR", "Iran (Islamic Republic of)" }, { "IS", "Iceland" }, { "IT", "Italy" }, { "JE", "Jersey" }, { "JM", "Jamaica" }, { "JO", "Jordan" }, { "JP", "Japan" }, { "KE", "Kenya" }, { "KG", "Kyrgyzstan" }, { "KH", "Cambodia" }, { "KI", "Kiribati" }, { "KM", "Comoros" }, { "KN", "Saint Kitts and Nevis" }, { "KP", "Korea (North)" }, { "KR", "Korea (South)" }, { "KW", "Kuwait" }, { "KY", "Cayman Islands" }, { "KZ", "Kazakhstan" }, { "LA", "Laos" }, { "LB", "Lebanon" }, { "LC", "Saint Lucia" }, { "LI", "Liechtenstein" }, { "LK", "Sri Lanka" }, { "LR", "Liberia" }, { "LS", "Lesotho" }, { "LT", "Lithuania" }, { "LU", "Luxembourg" }, { "LV", "Latvia" }, { "LY", "Libya" }, { "MA", "Morocco" }, { "MC", "Monaco" }, { "MD", "Moldova (Republic of)" }, { "MG", "Madagascar" }, { "MH", "Marshall Islands" }, { "MK", "Macedonia" }, { "ML", "Mali" }, { "MM", "Myanmar" }, { "MN", "Mongolia" }, { "MO", "Macau" }, { "MP", "Northern Mariana Islands" }, { "MQ", "Martinique" }, { "MR", "Mauritania" }, { "MS", "Montserrat" }, { "MT", "Malta" }, { "MU", "Mauritius" }, { "MV", "Maldives" }, { "MW", "Malawi" }, { "MX", "Mexico" }, { "MY", "Malaysia" }, { "MZ", "Mozambique" }, { "NA", "Namibia" }, { "NC", "New Caledonia" }, { "NE", "Niger" }, { "NF", "Norfolk Island" }, { "NG", "Nigeria" }, { "NI", "Nicaragua" }, { "NL", "Netherlands" }, { "NO", "Norway" }, { "NP", "Nepal" }, { "NR", "Nauru" }, { "NU", "Niue" }, { "NZ", "New Zealand" }, { "OM", "Oman" }, { "PA", "Panama" }, { "PE", "Peru" }, { "PF", "French Polynesia" }, { "PG", "Papua New Guinea" }, { "PH", "Philippines" }, { "PK", "Pakistan" }, { "PL", "Poland" }, { "PM", "St. Pierre and Miquelon" }, { "PN", "Pitcairn Island" }, { "PR", "Puerto Rico" }, { "PT", "Portugal" }, { "PW", "Palau" }, { "PY", "Paraguay" }, { "QA", "Qatar" }, { "RE", "Reunion Island" }, { "RO", "Romania" }, { "RU", "Russian Federation" }, { "RW", "Rwanda" }, { "SA", "Saudi Arabia" }, { "SB", "Solomon Islands" }, { "SC", "Seychelles" }, { "SD", "Sudan" }, { "SE", "Sweden" }, { "SG", "Singapore" }, { "SH", "St. Helena" }, { "SI", "Slovenia" }, { "SJ", "Svalbard and Jan Mayen Islands." }, { "SK", "Slovak Republic" }, { "SL", "Sierra Leone" }, { "SM", "San Marino" }, { "SN", "Senegal" }, { "SO", "Somalia" }, { "SR", "Suriname" }, { "ST", "Sao Tome and Principe" }, { "SU", "Soviet Union" }, /* NOTLISTED */ { "SV", "El Salvador" }, { "SY", "Syrian Arab Republic" }, { "SZ", "Swaziland" }, { "TC", "Turks and Caicos Islands" }, { "TD", "Chad" }, { "TF", "French Southern Territories" }, { "TG", "Togo" }, { "TH", "Thailand" }, { "TJ", "Tajikistan" }, { "TK", "Tokelau" }, { "TM", "Turkmenistan" }, { "TN", "Tunisia" }, { "TO", "Tonga" }, { "TP", "East Timor" }, { "TR", "Turkey" }, { "TT", "Trinidad and Tobago" }, { "TV", "Tuvalu" }, { "TW", "Taiwan" }, { "TZ", "Tanzania" }, { "UA", "Ukraine" }, { "UG", "Uganda" }, { "UK", "United Kingdom" }, { "UM", "US Minor Outlying Islands" }, { "US", "United States" }, { "UY", "Uruguay" }, { "UZ", "Uzbekistan" }, { "VA", "Vatican City State (Holy See)" }, { "VC", "Saint Vincent & The Grenadines" }, { "VE", "Venezuela" }, { "VG", "Virgin Islands (British)" }, { "VI", "Virgin Islands (USA)" }, { "VN", "Vietnam" }, { "VU", "Vanuatu" }, { "WF", "Wallis and Futuna Islands" }, { "WS", "Western Samoa" }, { "YE", "Yemen" }, { "YT", "Mayotte" }, { "YU", "Yugoslavia" }, { "ZA", "South Africa" }, { "ZM", "Zambia" }, { "ZW", "Zimbabwe" }, { NULL, NULL }, }; #define num_root_domains (sizeof (domain_codes) / sizeof (struct co_code)) #define MIN_DOMAIN_LEN 2 ================================================ FILE: src/file.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include "hypermail.h" #include "setup.h" #include "struct.h" #include "parse.h" #ifdef HAVE_DIRENT_H #ifdef __LCC__ #include "../lcc/dirent.h" #include #else #include #endif #else #include #endif #ifdef GDBM #include "gdbm.h" #endif #ifdef HAVE_LIBFNV /* ** Since LCC won't use configure which moves fnv.h to this directory, ** include it in its original location. */ #ifdef __LCC__ #include "fnv/fnv.h" #else #include "fnv.h" #endif #endif /* HAVE_LIBFNV */ /* ** Does a file exist? */ int isfile(char *path) { struct stat stbuf; if (stat(path, &stbuf)) return 0; return ((stbuf.st_mode & S_IFMT) == S_IFREG) ? 1 : 0; } /* ** Does a directory exist? */ int isdir(char *path) { struct stat stbuf; if (stat(path, &stbuf)) return 0; return ((stbuf.st_mode & S_IFMT) == S_IFDIR) ? 1 : 0; } /* ** This tries to create and chmod a directory. */ void check1dir(char *dir) { struct stat sbuf; if (stat(dir, &sbuf)) { /* ** LCC only has the short mkdir(). Fortunately, we do a chmod ** immediately afterward, so it's a don't care. */ #ifdef __LCC__ if (errno != ENOENT || mkdir(dir) < 0) { #else if (errno != ENOENT || mkdir(dir, set_dirmode) < 0) { #endif if (errno != EEXIST) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_CANNOT_CREATE_DIRECTORY], dir); progerr(errmsg); } } if (set_showprogress) printf(" %s \"%s\", %s %o.\n", lang[MSG_CREATING_DIRECTORY], dir, lang[MSG_MODE], set_dirmode); if (chmod(dir, set_dirmode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\" to %o.", lang[MSG_CANNOT_CHMOD], dir, set_dirmode); progerr(errmsg); } } } /* ** This tries to create and chmod a path to a directory. */ void checkdir(char *dir) { register char *p; struct stat sbuf; int ch; p = dir; if (*p && *p == '/') /* get off root */ p++; for (;; ++p) { if (!*p || *p == '/') { ch = *p; *p = '\0'; if (stat(dir, &sbuf)) { /* See comment in check1dir */ #ifdef __LCC__ if (errno != ENOENT || mkdir(dir) < 0) { #else if (errno != ENOENT || mkdir(dir, set_dirmode) < 0) { #endif if (errno != EEXIST) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_CANNOT_CREATE_DIRECTORY], dir); progerr(errmsg); } } if (set_report_new_folder) { printf("%s\n", dir); } if (set_showprogress) printf(" %s \"%s\", %s %o.\n", lang[MSG_CREATING_DIRECTORY], dir, lang[MSG_MODE], set_dirmode); if (chmod(dir, set_dirmode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\" to %o.", lang[MSG_CANNOT_CHMOD], dir, set_dirmode); progerr(errmsg); } } *p = ch; if (!*p) break; } } } char *getfilecontents(char *filename) { FILE *infile; struct stat finfo; char *retval; if ((infile = fopen(filename, "r")) == NULL) return (NULL); if (fstat(fileno(infile), &finfo) != 0) { (void)fclose(infile); return (NULL); } if (finfo.st_size == 0) { (void)fclose(infile); return (NULL); } else { if (!(retval = (char *)malloc((unsigned)finfo.st_size + 1))) { (void)fclose(infile); return (NULL); } if (!fread(retval, (size_t) finfo.st_size, 1, infile)) { (void)fclose(infile); free(retval); return (NULL); } *(retval + finfo.st_size) = '\0'; } (void)fclose(infile); return (retval); } /* ** expand_path - fill in values substituting for magic cookies ** ** Substitution cookies supported ** ** %d - two digit day of month (1-28/30/31) ** %D - three letter day of the week ** %m - two digit month of year (1-12) ** %M - three letter month of year (Jan, Feb, ..., Dec) ** %y - four digit year (1990,..2001) ** ** Returns: expanded path string */ char *dirpath(char *frmptr) { register char *aptr; char dtstr[DATESTRLEN]; char c; struct tm *now; time_t clk; struct Push buff; INIT_PUSH(buff); clk = time((time_t *)0); now = localtime(&clk); aptr = frmptr; while ((c = *aptr++)) { if (c == '%') { switch (*aptr++) { case '%': /* Add the % character */ PushByte(&buff, '%'); continue; case 'd': /* two digit day of month (1-31) */ sprintf(dtstr, "%.2d", now->tm_mday); PushString(&buff, dtstr); continue; case 'D': /* three letter day of week */ PushString(&buff, days[now->tm_wday]); continue; case 'j': /* julian date */ sprintf(dtstr, "%.3d", now->tm_yday); PushString(&buff, dtstr); continue; case 'm': /* two digit month of year (1-12) */ sprintf(dtstr, "%.2d", now->tm_mon + 1); PushString(&buff, dtstr); continue; case 'M': /* three letter month of year */ PushString(&buff, months[now->tm_mon]); continue; case 'y': /* 4 digit year */ sprintf(dtstr, "%.4d", now->tm_year + 1900); PushString(&buff, dtstr); continue; default: PushString(&buff, "%?"); continue; } /* end switch */ } PushByte(&buff, c); } /* end while */ RETURN_PUSH(buff); } /* ** Reads a configuration file if it exists and puts all the right ** values into the right variables. */ void readconfigs(char *path, int cmd_show_variables) { if (path && path[0] == '~') { char *ep; char tmppath[MAXFILELEN]; /*AUDIT biege: pathname + filename is more then 4KB long on linux */ struct passwd *pp; #ifndef __LCC__ /* ** Getting password data from /etc/passwd is pretty silly in ** Win9x systems since nearly everybody builds this file after ** they set up $HOME. Just skip this try at finding a default ** location for the config file and go on to try $HOME. */ if ((pp = getpwuid(getuid())) != NULL) { snprintf(tmppath, sizeof(tmppath), "%s%s", pp->pw_dir, path + 1); /* AUDIT biege: who gurantees that path+1 contains data? */ ConfigInit(tmppath); } else #endif if ((ep = getenv("HOME")) != NULL) { /* AUDIT biege: possible BOF.. but it's not setuid.. so why to care? */ snprintf(tmppath, sizeof(tmppath), "%s%s", ep, path + 1); /* AUDIT biege: who gurantees that path+1 contains data? */ ConfigInit(tmppath); } /* * So what happens here if the above two conditions fail ???? * Simply use the compiled in defaults ? */ } else { ConfigInit(path); if (set_showprogress && !cmd_show_variables) printf("%s: %s\n", lang[MSG_PATH], path); } } void symlink_latest() { /* ** Symlinks work so differently in Windows that I think we'll just ** skip that whole thing and ignore that option. */ #ifdef __LCC__ snprintf(errmsg, sizeof(errmsg), "WARNING: latest_folder not supported in Win32 environment.\n"); fprintf(stderr, "%s", errmsg); #else char filename[MAXFILELEN]; struct stat stbuf; if (!latest_folder_path) return; /* haven't created new folder this time? */ trio_snprintf(filename, MAXFILELEN, "%s%s", set_dir, set_latest_folder); if (!stat(filename, &stbuf) && unlink(filename)) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\" (latest_folder option).", lang[MSG_CANNOT_UNLINK], filename); progerr(errmsg); return; } if (symlink(latest_folder_path, filename)) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\" (latest_folder option).", lang[MSG_CANNOT_CREATE_SYMLINK], filename); progerr(errmsg); return; } #endif } int find_max_msgnum() { DIR *dir; #ifdef HAVE_DIRENT_H struct dirent *entry; #else struct direct *entry; #endif int max_num = -1; int num; char *s_dir = strsav(set_dir); int len = (int)strlen(s_dir); if (len > 0 && s_dir[len - 1] == PATH_SEPARATOR) s_dir[len - 1] = 0; dir = opendir(s_dir); if (dir == NULL) return -1; #ifdef GDBM if (set_folder_by_date && set_usegdbm) { return loadoldheadersfromGDBMindex(set_dir, 1) - 1; } #endif if (set_msgsperfolder) { int max_folder = -1; char *tmpptr; while ((entry = readdir(dir))) { const char *p = entry->d_name; while (isdigit(*p)) ++p; if (!*p && p > entry->d_name) { num = atoi(entry->d_name); if (num > max_folder) { char *full_path; trio_asprintf(&full_path, "%s%d", set_dir, num); if (isdir(full_path)) max_folder = num; free(full_path); } } } closedir(dir); trio_asprintf(&tmpptr, "%s%d", set_dir, max_folder); free(s_dir); s_dir = tmpptr; if (max_folder == -1) return -1; dir = opendir(s_dir); if (dir == NULL) { snprintf(errmsg, sizeof(errmsg), "internal error find_max_msgnum opening \"%s\".", s_dir); progerr(errmsg); } } while ((entry = readdir(dir))) { const char *p = entry->d_name; while (isdigit(*p)) ++p; if (*p == '.' && p >= entry->d_name + 4) { ++p; if (!strcmp(p, set_htmlsuffix)) { num = atoi(entry->d_name); if (num > max_num) max_num = num; } } } closedir(dir); free(s_dir); return max_num; } /* ** Returns a buffer with the name of the message index name file. ** The caller has to free this buffer. */ char *messageindex_name(void) { char *buf; trio_asprintf(&buf, "%s%s", set_dir, "msgindex"); return (buf); } /* ** Returns the corresponding message number from the messageindex file. */ int find_max_msgnum_id() { int max_num = -1; FILE *fp; char line[MAXLINE]; int maxnum; int startnum; char *buf; /* open the index file */ buf = messageindex_name(); fp = fopen(buf, "r"); free(buf); if (fp) { fgets(line, sizeof(line), fp); if (2 == sscanf(line, "%04d %04d", &startnum, &maxnum)) max_num = maxnum; fclose(fp); } return max_num; } /* ** Get a list of msgid corresponding to hypermail msg numbers */ char **read_msgnum_id_table(int max_num) { char **table; int read_msgs; FILE *fp; char line[MAXLINE]; char *buf; if (max_num == -1) return NULL; table = (char **)calloc(sizeof(char *), max_num + 1); /* open the index file */ buf = messageindex_name(); fp = fopen(buf, "r"); free(buf); /* skip the max_msgnum (first) line */ fgets(line, sizeof(line), fp); read_msgs = 0; while (fgets(line, sizeof(line), fp) && read_msgs <= max_num) { char *msgid; int num; msgid = malloc(strlen(line) + 1); sscanf(line, "%d %s\n", &num, msgid); /* was the message skipped? */ if (read_msgs < num) { while (read_msgs < num) { table[read_msgs] = NULL; read_msgs++; } } table[read_msgs] = msgid; read_msgs++; } fclose(fp); return table; } /* ** Frees the table used to store the msgnum id correspondance */ void free_msgnum_id_table(char *table[], int max_num) { int i; if (!table) return; for (i = 0; i < max_num; i++) if (table[i]) free(table[i]); free(table); } int is_empty_archive() { DIR *dir; #ifdef HAVE_DIRENT_H struct dirent *entry; #else struct direct *entry; #endif int num_files = 0; char *s_dir = strsav(set_dir); int len = (int)strlen(s_dir); if (len > 0 && s_dir[len - 1] == PATH_SEPARATOR) s_dir[len - 1] = 0; dir = opendir(s_dir); if (dir == NULL) return 1; while ((entry = readdir(dir))) { const char *p = entry->d_name; if (*p != '.') { ++num_files; break; } } closedir(dir); free(s_dir); return num_files == 0; } static char *msgsperfolder_label(char *frmptr, int subdir_no) { register char *aptr; char dtstr[DATESTRLEN]; char c; struct Push buff; INIT_PUSH(buff); aptr = frmptr; while ((c = *aptr++)) { if (c == '%') { switch (*aptr++) { case '%': /* Add the % character */ PushByte(&buff, '%'); continue; case 'd': /* directory number, starting at 0 */ sprintf(dtstr, "%d", subdir_no); PushString(&buff, dtstr); continue; case 'D': /* directory number, starting with 1 */ sprintf(dtstr, "%d", subdir_no + 1); PushString(&buff, dtstr); continue; case 'm': /* number of first message in directory */ sprintf(dtstr, "%d", set_msgsperfolder * subdir_no); PushString(&buff, dtstr); continue; case 'M': /* number of last message possible */ sprintf(dtstr, "%d", set_msgsperfolder * (subdir_no + 1) - 1); PushString(&buff, dtstr); continue; default: PushString(&buff, "%?"); continue; } /* end switch */ } PushByte(&buff, c); } /* end while */ RETURN_PUSH(buff); } struct emailsubdir *msg_subdir(int msgnum, time_t date) { static struct emailsubdir *last_subdir; static struct emailsubdir *subdir; char s[DATESTRLEN]; char desc_buf[DATESTRLEN]; char *desc = NULL; char *fmt = set_describe_folder; if (set_msgsperfolder > 0) { int subdir_no = msgnum / set_msgsperfolder; trio_snprintf(s, DATESTRLEN, "%d/", subdir_no); if (!fmt) fmt = "%d"; desc = msgsperfolder_label(fmt, subdir_no); } else if (set_folder_by_date) { strftime(s, DATESTRLEN - 1, set_folder_by_date, localtime(&date)); if (!fmt) fmt = set_folder_by_date; strftime(desc_buf, DATESTRLEN, fmt, localtime(&date)); desc = strsav(desc_buf); if (s[0] && s[strlen(s) - 1] != '/') strcat(s, "/"); } else return NULL; subdir = last_subdir; if (!last_subdir || strcmp(s, last_subdir->subdir)) { subdir = new_subdir(s, last_subdir, desc, date); if (set_increment != -1) last_subdir = subdir; } if (desc) free(desc); return subdir; } /* ** Returns the filename we want to use. According to the convention, this ** can be the msgnumber, the msgid, or some other kind of name. */ char *message_name (struct emailinfo *email) { static char buffer[8 + sizeof (time_t) * 2 + 1]; #ifdef HAVE_LIBFNV if (set_nonsequential && email->msgid) { /* Call the FNV msg hash library */ Fnv32_t hash_val; hash_val = fnv_32_buf(email->msgid, strlen (email->msgid), FNV1_32_INIT); /* the line below is what we used before when the hash included the fromdate string, and we didn't concatenate the mail date. However, we changed strategies to avoid collisions. */ /* hash_val = fnv_32_str(email->fromdatestr, hash_val); */ sprintf (buffer, "%08x%08x", hash_val, email->fromdate); return buffer; } else { #endif /* HAVE_LIBFNV */ sprintf (buffer, "%.4d", email->msgnum); return buffer; #ifdef HAVE_LIBFNV } #endif /* HAVE_LIBFNV */ } /* * returns "" that links to to_email from the directory of * from_email, or from the set_dir directory if email is NULL. */ char *msg_href(struct emailinfo *to_email, struct emailinfo *from_email, bool generate_markup) /* note: you probably have to make a copy of * the buffer returned before the next call to this function. */ { static char buffer[MAXFILELEN + 11]; char *ptr; ptr = msg_relpath(to_email, from_email); if (generate_markup) trio_snprintf(buffer, MAXFILELEN + 11, "", ptr); else trio_snprintf(buffer, MAXFILELEN + 11, "%s", ptr); return buffer; } char *msg_relpath(struct emailinfo *to_email, struct emailinfo *from_email) /* called by msg_href() : note: you probably have to make a copy of * the buffer returned before the next call to this function. */ { static char buffer[MAXFILELEN]; char *name; name = message_name(to_email); if (!from_email && to_email->subdir) trio_snprintf(buffer, MAXFILELEN, "%s%s.%s", to_email->subdir->subdir, name, set_htmlsuffix); else if (!to_email->subdir || to_email->subdir == from_email->subdir) trio_snprintf(buffer, MAXFILELEN, "%s.%s", name, set_htmlsuffix); else trio_snprintf(buffer, MAXFILELEN, "%s%s%s.%s", to_email->subdir->rel_path_to_top, to_email->subdir->subdir, name, set_htmlsuffix); return buffer; } char *articlehtmlfilename(struct emailinfo *email) { char *buf; char *name; name = message_name(email); trio_asprintf(&buf, "%s%s.%s", email->subdir ? email->subdir->full_path : set_dir, name, set_htmlsuffix); return buf; } char *htmlfilename(const char *file, struct emailinfo *email, const char *suffix) { char *buf; trio_asprintf(&buf, "%s%s%s%s", email && email->subdir ? email->subdir->full_path : set_dir, file, *suffix ? "." : "", suffix); return buf; } char *haofname(struct emailinfo *email) { char *buf; trio_asprintf(&buf, "%s%s", email && email->subdir ? email->subdir->full_path : set_dir, HAOF_NAME); return buf; } /* matches_existing returns 0 if it finds a file with the same msgnum as argument eptr but different contents. A return value of 1 does not guarantee that they match, it only says a difference wasn't found (which can mean that no file was found). */ int matches_existing(int msgnum) { struct emailinfo *eptr; if (hashnumlookup(msgnum, &eptr) == NULL) return -1; #ifdef GDBM if (set_usegdbm) { char *indexname; GDBM_FILE gp; int num; trio_asprintf(&indexname, "%s%s", set_dir, GDBM_INDEX_NAME); if ((gp = gdbm_open(indexname, 0, GDBM_READER, 0, 0))) { /* we _can_ read the index */ datum content; datum key; int max_num; key.dptr = (char *)# key.dsize = (int)sizeof(num); num = -1; content = gdbm_fetch(gp, key); if (!content.dptr) max_num = -1; else max_num = atoi(content.dptr); if (eptr->msgnum <= max_num) { char *dp, *dp_end; char *name = NULL; char *email = NULL; char *date = NULL; char *msgid = NULL; char *fromdate = NULL; num = eptr->msgnum; key.dptr = (char *)# key.dsize = (int)sizeof(num); content = gdbm_fetch(gp, key); if (!(dp = content.dptr)) { return 1; } dp_end = dp + content.dsize; fromdate = dp; dp += strlen(dp) + 1; date = dp; dp += strlen(dp) + 1; name = dp; dp += strlen(dp) + 1; email = dp; dp += strlen(dp) + 1; dp += strlen(dp) + 1; msgid = dp; if (strcmp(msgid, eptr->msgid)) return 0; } gdbm_close(gp); } /* end case of able to read gdbm index */ free(indexname); } #endif if (!set_usegdbm) { int msgids_are_same; msgids_are_same = parse_old_html(msgnum, eptr, 0, 0, NULL, 1); return msgids_are_same != 0; } return 1; } ================================================ FILE: src/finelink.c ================================================ /* ** Copyright (C) 1997, Peter McCluskey (pcm@rahul.net) ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "hypermail.h" #include "finelink.h" #include "print.h" #include "struct.h" #include "search.h" #include "setup.h" #include "proto.h" #include #include static int str_similar_str(const char *str1, const char *str2); static char *stripwhitespace(const char *line); static int new_reply_to = -1; static int found_quote = 0; static char *get_path(struct emailinfo *ep, struct emailinfo *ep2) { char *path = ""; if (ep2->subdir && ep2->subdir != ep->subdir) trio_asprintf(&path, "%s%s", ep2->subdir->rel_path_to_top, ep2->subdir->subdir); return path; } static struct body *place_anchor(const String_Match * match_info, struct body *bp, char *buffer, FILE *fp2, char **ptr, const char *anchor) { if (match_info) { int index; char token[MAXLINE]; char *tptr; char *ptr1 = buffer; char *last_ptr0 = *ptr; char *penultimate_ptr0 = last_ptr0; char *last_ptr = ptr1; char *penultimate_ptr = ptr1; if (!bp) return FALSE; while ((bp = tokenize_body(bp, token, ptr, &index, TRUE)) != NULL) { if (*ptr == match_info->start_match) { strcpy(token, last_ptr); *last_ptr = 0; fprintf(fp2, "%s", buffer, anchor); strcpy(buffer, token); *ptr = last_ptr0; return bp; } penultimate_ptr = ptr1; last_ptr = penultimate_ptr; last_ptr0 = penultimate_ptr0; penultimate_ptr0 = *ptr; if (!(tptr = strstr(ptr1, *ptr))) { int len = (4 * strlen(*ptr)) / 5; char *temp1 = (char *)emalloc(len + 1); strncpy(temp1, *ptr, len); temp1[len] = 0; tptr = strstr(ptr1, temp1); free(temp1); if (!tptr) break; } ptr1 = tptr; while (ispunct(*ptr1) && *ptr1 != '<') ++ptr1; } if (0) printf("No match found %s; %s", anchor, buffer); } fprintf(fp2, "", anchor); return bp; } static int place_a_end(const String_Match * match_info, struct body **bp, char *buffer, FILE *fp2, char **ptr) { int index; char token[MAXLINE]; char *ptr1 = buffer; char *last_ptr = ptr1; char *tptr; if (!*bp) return FALSE; while ((*bp = tokenize_body(*bp, token, ptr, &index, TRUE)) != NULL) { if (*ptr == match_info->stop_match) { strcpy(token, ptr1); *ptr1 = 0; fprintf(fp2, "%s%s", buffer, token); return TRUE; } last_ptr = ptr1; if (!(tptr = strstr(ptr1, *ptr))) { int len = (4 * strlen(*ptr)) / 5; char *temp1 = (char *)emalloc(len + 1); strncpy(temp1, *ptr, len); temp1[len] = 0; tptr = strstr(ptr1, temp1); free(temp1); if (!tptr) return FALSE; } ptr1 = tptr; while (ispunct(*ptr1) && *ptr1 != '<') ++ptr1; } return FALSE; } /* ** Alter the message being quoted to add an anchor specifying the quoted text */ static int add_anchor(int msgnum, int quoting_msgnum, int quote_num, const char *anchor, char *line, int find_substr, int count_quoted_lines, const String_Match * match_info) { char *filename; char *tmpfilename; char buffer[MAXLINE]; FILE *fp1, *fp2; int matches = 0; int in_body = FALSE; int cmp_len = strlen(line); struct emailinfo *ep; struct body *bp = hashnumlookup(msgnum, &ep); char *ptr; char *tmpptr; while (bp && (!strncmp(bp->line, "Date:", 5) || !strncmp(bp->line, "From:", 5) || !strncmp(bp->line, "From:", 5) || !strncasecmp(bp->line, "Message-Id:", 11) || !strncmp(bp->line, "Subject:", 8) || !strncasecmp(bp->line, "In-Reply-To:", 12) || !strncasecmp(bp->line, "References:", 11) || !strncmp(bp->line, "To:", 3))) bp = bp->next; /* skip over header info */ ptr = bp ? bp->line : NULL; while (ptr && !*ptr) { bp = bp->next; if (!bp) break; ptr = bp->line; } filename = articlehtmlfilename(ep); if ((fp1 = fopen(filename, "r")) == NULL) { free(filename); if (msgnum > quoting_msgnum) return 0; /* just a forward ref */ if (set_showprogress) fprintf(stderr, "Couldn't read message number %d (linked from %d). " "May mean message deleted with delete_level = 0.\n", msgnum, quoting_msgnum); return -1; } tmpfilename = htmlfilename("tmp", ep, "tmp"); /* AUDIT biege: where is the tmp-file created? cwd? what about checking the return-value */ if ((fp2 = fopen(tmpfilename, "w")) == NULL) { snprintf(errmsg, sizeof(errmsg), "Couldn't write \"%s\".", tmpfilename); progerr(errmsg); } while (fgets(buffer, sizeof(buffer), fp1)) { if ((find_substr && str_similar_str(buffer, line)) || (!find_substr && !strncmp(buffer, line, cmp_len))) { int wrote_a_end = FALSE; ++matches; bp = place_anchor(match_info, bp, buffer, fp2, &ptr, anchor); if (set_link_to_replies) { struct emailinfo *ep2; if (hashnumlookup(quoting_msgnum, &ep2)) { char *path = get_path(ep, ep2); fprintf(fp2, "%s", path, quoting_msgnum, set_htmlsuffix, quote_num, set_link_to_replies); if (*path) free(path); } } /* Now find end of quoted text: */ do { if (!strcmp(buffer, "\n")) { count_quoted_lines = -1; break; /* reply quoted more lines than exist? */ } if (match_info && place_a_end(match_info, &bp, buffer, fp2, &ptr)) { wrote_a_end = TRUE; count_quoted_lines = 0; if (bp) bp = bp->next; if (bp) ptr = bp->line; break; } fputs(buffer, fp2); /* suppress decrement for lines inserted by html conversion: */ if (!strcasecmp(buffer, "

\n")) ++count_quoted_lines; else { char *tptr = remove_hypermail_tags(buffer); if (tptr) free(tptr); else ++count_quoted_lines; } } while (--count_quoted_lines > 0 && fgets(buffer, sizeof(buffer), fp1)); if (!wrote_a_end) fputs("", fp2); if (count_quoted_lines > 0) /* got eof? */ break; /* avoid last fputs */ else if (count_quoted_lines == 0 && !fgets(buffer, sizeof(buffer), fp1)) break; } else if (in_body && bp && (tmpptr = remove_hypermail_tags(buffer))) { char *tmpptr2 = unconvchars(tmpptr); if (tmpptr2 && str_similar_str(tmpptr, bp->line)) bp = bp->next; if (bp) ptr = bp->line; if (tmpptr2) free(tmpptr2); free(tmpptr); } else if (!in_body && !strcmp(buffer, "\n")) in_body = TRUE; fputs(buffer, fp2); } fclose(fp1); fclose(fp2); if (matches != 1) remove(tmpfilename); else { if (rename(tmpfilename, filename) == -1) { snprintf(errmsg, sizeof(errmsg), "Couldn't rename \"%s\" to %s.", tmpfilename, filename); progerr(errmsg); } if (chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "Couldn't chmod \"%s\" to %o.", filename, set_filemode); progerr(errmsg); } } free(filename); free(tmpfilename); return matches == 1; } static char *unquote_and_strip(char *line) { char *p = unquote(line); char *p2; char *cvtd_line; while (*p && isspace(*p)) ++p; cvtd_line = (char *)emalloc(strlen(p) + 1); strcpy(cvtd_line, p); p2 = cvtd_line + strlen(cvtd_line); if (p2 > cvtd_line && p2[-1] == '\n') *--p2 = 0; if (p2 > cvtd_line && *--p2 == '-') *p2 = 0; /* don't demand trailing '-' in searches; may have been unhyphenated */ return cvtd_line; } /* ** Find URL of the message this line of quoted text was taken from */ static char *url_replying_to(struct emailinfo *email, char *line1, /* first line of quoted text, with html */ const char *line2, /* first line of quoted text, w/o html */ const struct body *bp, int quote_num, int *quoting_msgnum, int count_quoted_lines, int maybe_reply) { String_Match match_info; char *p; int subjmatch = 0; char *anchor; struct emailinfo *ep; int statusnum = hashreplynumlookup(*quoting_msgnum, email->inreplyto, email->subject, &subjmatch); hashnumlookup(*quoting_msgnum, &ep); trio_asprintf(&anchor, "%.4dqlink%d", *quoting_msgnum, quote_num); if (statusnum != -1) { struct emailinfo *ep2; hashnumlookup(statusnum, &ep2); if (add_anchor(statusnum, *quoting_msgnum, quote_num, anchor, line1, 0, count_quoted_lines, NULL)) { char *path = get_path(ep, ep2); char *buf; trio_asprintf(&buf, "%s%.4d.%s#%s", path, statusnum, set_htmlsuffix, anchor); if (maybe_reply) set_new_reply_to(statusnum, strlen(line2)); if (*path) free(path); free(anchor); return buf; } if (strlen(line2) > 6 && (p = strstr(line2, "..."))) { char *parsed; char *tptr = (char *)emalloc(p - line2 + 1 + strlen(p + 3)); /* AUDIT biege: IOF unlikely */ strncpy(tptr, line2, p - line2); strcpy(tptr + (p - line2), p + 3); parsed = ConvURLsString(tptr, email->msgid, email->subject, email->charset); free(tptr); tptr = stripwhitespace(parsed ? parsed : ""); if (parsed) free(parsed); if (add_anchor(statusnum, *quoting_msgnum, quote_num, anchor, tptr, 1, count_quoted_lines, NULL)) { char *path = get_path(ep, ep2); char *buf; trio_asprintf(&buf, "%s%.4d.%s#%s", path, statusnum, set_htmlsuffix, anchor); free(tptr); if (maybe_reply) set_new_reply_to(statusnum, strlen(buf)); if (*path) free(path); free(anchor); return buf; } free(tptr); } } { int i; struct Push full_line; struct Push exact_line; INIT_PUSH(full_line); INIT_PUSH(exact_line); PushString(&full_line, p = stripwhitespace(line2)); free(p); PushString(&exact_line, line2); for (i = 1; i < count_quoted_lines && (bp = bp->next); ++i) { char *stripped = unquote_and_strip(bp->line); PushByte(&full_line, '\n'); PushString(&full_line, p = stripwhitespace(stripped)); free(p); free(stripped); PushString(&exact_line, unquote(bp->line)); } search_for_quote(PUSH_STRING(full_line), PUSH_STRING(exact_line), *quoting_msgnum, &match_info); free(PUSH_STRING(full_line)); free(PUSH_STRING(exact_line)); } if (match_info.msgnum >= 0) { char *parsed = ConvURLsString(match_info.last_matched_string, email->msgid, email->subject, email->charset); if (parsed) { char *parsed2 = stripwhitespace(parsed); free(parsed); if (add_anchor(match_info.msgnum, *quoting_msgnum, quote_num, anchor, parsed2, 1, count_quoted_lines, &match_info)) { struct emailinfo *ep2; char *path; char *buf; hashnumlookup(match_info.msgnum, &ep2); path = get_path(ep, ep2); trio_asprintf(&buf, "%s%.4d.%s#%s", path, match_info.msgnum, set_htmlsuffix, anchor); set_new_reply_to(match_info.msgnum, match_info.match_len_bytes); free(parsed2); if (*path) free(path); free(anchor); return buf; } free(parsed2); } if (match_info.last_matched_string) free(match_info.last_matched_string); } if (count_quoted_lines < 3 && strcmp(get_quote_prefix(), ">") && strcmp(get_quote_prefix(), " >")) /* was quote_prefix guess shaky? */ *quoting_msgnum = -1; /* msg probably doesn't have any quotes */ free(anchor); return NULL; } /* ** handles everything we do for a single line that is a quote ** of another message */ int handle_quoted_text(FILE *fp, struct emailinfo *email, const struct body *bp, char *line, int inquote, int quote_num, bool replace_quoted, int maybe_reply) { char *url1; int quoting_msgnum = email->msgnum; const struct body *last_quoted_line = bp; int count_quoted_lines = 0; char *fmt2; char *cvtd_line = ConvURLsString(unquote(line), email->msgid, email->subject, email->charset); char *buffer1; trio_asprintf(&fmt2, set_iquotes ? "%%s
" : "%%s
", find_quote_class(line)); trio_asprintf(&buffer1, fmt2, cvtd_line ? cvtd_line : ""); if (cvtd_line) free(cvtd_line); found_quote = (quote_num > 0); while (last_quoted_line && isquote(last_quoted_line->line)) { ++count_quoted_lines; last_quoted_line = last_quoted_line->next; } cvtd_line = unquote_and_strip(line); if (strlen(cvtd_line) < 5 && (!replace_quoted || !inquote)) { char *parsed = ConvURLsString(line, email->msgid, email->subject, email->charset); if (parsed) { fprintf(fp, fmt2, parsed); free(parsed); } } else if ((!inquote || !found_quote) && (url1 = url_replying_to(email, buffer1, cvtd_line, bp, ++quote_num, "ing_msgnum, count_quoted_lines, maybe_reply))) { static const char *fmt1 = "%s%s
\n"; char *tmpline; char *p2; bool replacing = replace_quoted && set_quote_link_string && set_quote_link_string[0]; char *part2 = strcasestr(line, "", quote_num); p2 = ConvURLsString(part2, email->msgid, email->subject, email->charset); if (replacing) fprintf(fp, fmt1, url1, set_quote_link_string, p2 ? p2 : ""); else { char *tmpptr = convchars(tmpline, email->charset); if (tmpptr) { fprintf(fp, fmt1, url1, tmpptr, p2 ? p2 : ""); free(tmpptr); } } free(url1); free(tmpline); if (p2) free(p2); free(cvtd_line); free(buffer1); free(fmt2); return 1; } else if (!replace_quoted || !inquote) { char *parsed = ConvURLsString(bp->line, email->msgid, email->subject, email->charset); if (parsed) { fprintf(fp, quoting_msgnum >= 0 ? fmt2 : "%s
\n", parsed); free(parsed); } } free(cvtd_line); free(buffer1); free(fmt2); return 0; } /* ** Update guess about which message the current message is replying to; ** do nothing if set_new_reply_to has been called more for another msgnum since ** starting this message or if another msgnum had longer match_len. */ void set_new_reply_to(int msgnum, int match_len) { static int alt_msgnum = -1; static int count_alt = 0; static int count_last = 0; static int best_match_len = -1; if (new_reply_to == -1 || msgnum == -1) { new_reply_to = msgnum; count_last = 1; count_alt = 0; alt_msgnum = -1; best_match_len = match_len; } else if (msgnum == new_reply_to) { ++count_last; } else { if (msgnum == alt_msgnum || alt_msgnum == -1) { if (++count_alt > count_last || (count_alt == count_last && match_len > best_match_len)) { count_last = count_alt; new_reply_to = msgnum; if (match_len > best_match_len) best_match_len = match_len; } } else count_alt = 0; alt_msgnum = msgnum; } } int get_new_reply_to() { return new_reply_to; } /* * Update a message to change "maybe in reply to"'s to a single definite * "In reply to" */ void replace_maybe_replies(const char *filename, struct emailinfo *ep, int new_reply_to) { char tmpfilename[MAXFILELEN]; char buffer[MAXLINE]; FILE *fp1, *fp2; struct emailinfo *ep2; int in_body = 0; char *ptr; static const char *prev_patt0 = ".html\">[ Previous ]"; if (!hashnumlookup(new_reply_to, &ep2)) return; snprintf(tmpfilename, sizeof(tmpfilename), "%s/aaaa.tmp", set_dir); /* AUDIT biege: poss. BOF. */ if ((fp1 = fopen(filename, "r")) == NULL) { snprintf(errmsg, sizeof(errmsg), "Couldn't read \"%s\".", filename); progerr(errmsg); } if ((fp2 = fopen(tmpfilename, "w")) == NULL) { snprintf(errmsg, sizeof(errmsg), "Couldn't write \"%s\".", tmpfilename); progerr(errmsg); } while (fgets(buffer, sizeof(buffer), fp1)) { if (strstr(buffer, "\n")) in_body = 0; if (!strcmp(buffer, "\n")) in_body = 1; if (!in_body) { if (!strcmp(buffer, "\n")) { char *tmpptr = convchars(ep2->subject, ep2->charset); if (tmpptr) { char *path = get_path(ep, ep2); fprintf(fp2,"[ %s ]\n", path, new_reply_to, set_htmlsuffix, lang[MSG_LTITLE_IN_REPLY_TO], ep2->name, tmpptr ? tmpptr : ""); free(tmpptr); } } else if (!strcmp(buffer, "\n")) { char *tmpptr = convchars(ep2->subject, ep2->charset); if (tmpptr) { char *path = get_path(ep, ep2); fprintf(fp2, "

  • %s " "%s: \"%s\"
  • \n", lang[MSG_IN_REPLY_TO], path, new_reply_to, set_htmlsuffix, lang[MSG_LTITLE_IN_REPLY_TO], ep2->name, tmpptr ? tmpptr : ""); free(tmpptr); } } else if (!strcmp(buffer, "\n")) { char *tmpptr = convchars(ep2->subject, ep2->charset); if (tmpptr) { char *path = get_path(ep, ep2); fprintf(fp2, "
  • %s: " "%s: \"%s\"\n", lang[MSG_IN_REPLY_TO], path, new_reply_to, set_htmlsuffix, ep2->name, tmpptr ? tmpptr : ""); free(tmpptr); } } else { static const char *patts[] = { "Maybe in reply to:", "%s:", "In reply to:", "%s:", "
  • Previous message: %s: %s: %s: %s: = 0 && isspace(buffer[--i])) buffer[i] = '\0'; return buffer; } ================================================ FILE: src/finelink.h ================================================ #ifndef __FINELINK_H #define __FINELINK_H #include "hypermail.h" #include "setup.h" /* for bool */ int handle_quoted_text(FILE *fp, struct emailinfo *, const struct body *, char *line, int inquote, int quote_num, bool replace_quoted, int maybe_reply); void replace_maybe_replies(const char *, struct emailinfo *, int); void set_new_reply_to(int msgnum, int match_len); int get_new_reply_to(void); #endif ================================================ FILE: src/fnv/Makefile.in ================================================ # Makefile.in for Fowler / Noll / Vo (FNV) Hash Tools library # # Prepared for the autoconf tools from the original Makefile # by Jose KAHAN (jose.kahan@w3.org). # # ------------------------------------------------------------- # Original comments # ------------------------------------------------------------ # # @(#) $Revision: 1.2 $ # @(#) $Id: Makefile.in,v 1.2 2013-04-11 13:48:18 kahan Exp $ # @(#) $Source: /sources/public/hypermess/hypermail/src/fnv/Makefile.in,v $ # # See: # http://www.isthe.com/chongo/tech/comp/fnv/index.html # # for the most up to date copy of this code and the FNV hash home page. # # Please do not copyright this code. This code is in the public domain. # # LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO # EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF # USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. # # By: # chongo /\oo/\ # http://www.isthe.com/chongo/ # # Share and Enjoy! :-) #---------------------------------------------------------------------------# # To build mingw32 DLL uncomment the next two lines. This addition for # # mingw32 was contributed by . I (Philip # # Hazel) don't know anything about it! There are some additional targets at # # the bottom of this Makefile. # #---------------------------------------------------------------------------# # # include dll.mk # DLL_LDFLAGS=-s #---------------------------------------------------------------------------# # The next few lines are modified by "configure" to insert data that it is # # given in its arguments, or which it finds out for itself. # #---------------------------------------------------------------------------# # BINDIR is the directory in which the fnv command is installed. # INCDIR is the directory in which the public header file fnv.h is installed. # LIBDIR is the directory in which the libraries are installed. # MANDIR is the directory in which the man pages are installed. prefix = @prefix@ exec_prefix = @exec_prefix@ BINDIR = @bindir@ LIBDIR = @libdir@ INCDIR = @includedir@ MANDIR = @mandir@ CC = @CC@ CFLAGS = @CFLAGS@ RANLIB = @RANLIB@ UTF8 = @UTF8@ # LIBTOOL defaults to "./libtool", which enables the building of shared # libraries. If "configure" is called with --disable-shared-libraries, LIBTOOL # is set to "", which stops shared libraries from being built, and LIBSUFFIX # is set to "a" instead of "la", which causes the shared libraries not to be # installed. LIBTOOL = @LIBTOOL@ LIBSUFFIX = @LIBSUFFIX@ # These are the version numbers for the shared libraries FNVLIBVERSION = @FNV_LIB_VERSION@ FNVPOSIXLIBVERSION = @FNV_POSIXLIB_VERSION@ #---------------------------------------------------------------------------# # For almost all systems, the command to create a library is "ar cq", but # # there is at least one where it is different, so this command must be # # configurable. However, I haven't got round to learning how to make # # "configure" find this out for itself. It is necessary to use a command # # such as "make AR='ar -rc'" if you need to vary this. The setting of AR is # # *not* passed over to ./ltconfig, because it does its own setting up. # #---------------------------------------------------------------------------# AR = ar cq # make tools # SHELL= /bin/sh TAR= tar EGREP= egrep GZIP_BIN= gzip INSTALL= install DESTBIN= /usr/local/bin DESTLIB= /usr/local/lib DESTINC= /usr/local/include # NOTE: Lines with WWW in them are removed from the shipped Makefile WWW= /web/isthe/chroot/html/chongo/src/fnv # what to build # SRC= hash_32.c hash_64.c \ fnv32.c fnv64.c \ have_ulong64.c HSRC= fnv.h \ longlong.h ALL= ${SRC} ${HSRC} \ README Makefile PROGS= fnv032 fnv064 fnv0_32 fnv0_64 fnv132 fnv164 fnv1_32 fnv1_64 LIBS= libfnv.$(LIBSUFFIX) LIBOBJ= hash_32.o hash_64.o OTHEROBJ= fnv32.o fnv64.o TARGETS= ${LIBOBJ} ${LIBS} ${PROGS} # default rule # all: libtool ${TARGETS} # things to build libtool: config.guess config.sub ltconfig ltmain.sh @if test "$(LIBTOOL)" = "./libtool"; then \ echo '--- Building libtool ---'; \ CC=$(CC) CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)' ./ltconfig ./ltmain.sh; \ echo '--- Built libtool ---'; fi hash_32.o: hash_32.c longlong.h fnv.h ${CC} ${CFLAGS} hash_32.c -c hash_64.o: hash_64.c longlong.h fnv.h ${CC} ${CFLAGS} hash_64.c -c libfnv.la: $(OBJ) @echo ' ' @echo '--- Building shared library: libfnv' @echo ' ' -rm -f libpcre.la ./libtool $(CC) -version-info '$(FNVLIBVERSION)' -o libfnv.la -rpath $(LIBDIR) $(LOBJ) libfnv.a: ${LIBOBJ} @echo ' ' @echo '--- Building static library: libfnv' @echo ' ' rm -f $@ ${AR} $@ ${LIBOBJ} ${RANLIB} $@ fnv32.o: fnv32.c longlong.h fnv.h ${CC} ${CFLAGS} fnv32.c -c fnv032: fnv32.o libfnv.a ${CC} fnv32.o libfnv.a -o fnv032 fnv64.o: fnv64.c longlong.h fnv.h ${CC} ${CFLAGS} fnv64.c -c fnv064: fnv64.o libfnv.a ${CC} fnv64.o libfnv.a -o fnv064 fnv0_32: fnv032 -rm -f $@ -cp -f $? $@ fnv0_64: fnv064 -rm -f $@ -cp -f $? $@ fnv132: fnv032 -rm -f $@ -cp -f $? $@ fnv164: fnv064 -rm -f $@ -cp -f $? $@ fnv1_32: fnv032 -rm -f $@ -cp -f $? $@ fnv1_64: fnv064 -rm -f $@ -cp -f $? $@ longlong.h: have_ulong64.c Makefile -@rm -f have_ulong64 have_ulong64.o ll_tmp longlong.h @echo 'forming longlong.h' @echo '/*' > longlong.h @echo ' * DO NOT EDIT -- generated by the Makefile' >> longlong.h @echo ' */' >> longlong.h @echo '' >> longlong.h @echo '#if !defined(__LONGLONG_H__)' >> longlong.h @echo '#define __LONGLONG_H__' >> longlong.h @echo '' >> longlong.h @echo '/* do we have/want to use a long long type? */' >> longlong.h -@rm -f have_ulong64.o have_ulong64 -@${CC} ${CFLAGS} have_ulong64.c -c 2>/dev/null; true -@${CC} ${CFLAGS} have_ulong64.o -o have_ulong64 2>/dev/null; true -@${SHELL} -c "./have_ulong64 > ll_tmp 2>/dev/null" \ >/dev/null 2>&1; true -@if [ -s ll_tmp ]; then \ cat ll_tmp >> longlong.h; \ else \ echo '#undef HAVE_64BIT_LONG_LONG /* no */' >> longlong.h; \ fi @echo '' >> longlong.h @echo '#endif /* !__LONGLONG_H__ */' >> longlong.h -@rm -f have_ulong64 have_ulong64.o ll_tmp @echo 'longlong.h formed' # utilities # install: all -@if [ -d "${DESTBIN}" ]; then \ echo " mkdir -p ${DESTBIN}"; \ mkdir -p ${DESTBIN}; \ fi -@if [ -d "${DESTLIB}" ]; then \ echo " mkdir -p ${DESTLIB}"; \ mkdir -p ${DESTLIB}; \ fi -@if [ -d "${DESTINC}" ]; then \ echo " mkdir -p ${DESTINC}"; \ mkdir -p ${DESTINC}; \ fi ${INSTALL} -m 0755 ${PROGS} ${DESTBIN} ${INSTALL} -m 0644 ${LIBS} ${DESTLIB} ${RANLIB} ${DESTLIB}/libfnv.a ${INSTALL} -m 0644 ${HSRC} ${DESTINC} @# NOTE: Lines with WWW in them are removed from the shipped Makefile -@if [ -d ${WWW} ]; then \ echo "rm -f Makefile.ship"; : WWW; \ rm -f Makefile.ship; : WWW; \ echo "${EGREP} -v WWW Makefile > Makefile.ship"; : WWW; \ ${EGREP} -v WWW Makefile > Makefile.ship; : WWW; \ echo "rm -f Makefile.save"; : WWW; \ rm -f Makefile.save; : WWW; \ echo "ln Makefile Makefile.save"; : WWW; \ ln Makefile Makefile.save; : WWW; \ echo "cp -f Makefile.ship Makefile"; : WWW; \ cp -f Makefile.ship Makefile; : WWW; \ echo "${TAR} -cf - ${ALL} | ${GZIP_BIN} --best > fnv_hash.tar.gz";: WWW; \ ${TAR} -cf - ${ALL} | ${GZIP_BIN} --best > fnv_hash.tar.gz;: WWW; \ echo "${INSTALL} -m 0644 fnv_hash.tar.gz ${ALL} ${WWW}"; \ ${INSTALL} -m 0644 fnv_hash.tar.gz ${ALL} ${WWW}; \ echo "mv -f Makefile.save Makefile"; : WWW; \ mv -f Makefile.save Makefile; : WWW; \ echo "rm -f fnv_hash.tar.gz Makefile.ship"; : WWW; \ rm -f fnv_hash.tar.gz Makefile.ship; : WWW; \ fi; : WWW clean: -rm -f have_ulong64 have_ulong64.o ll_tmp ll_tmp2 longlong.h -rm -f ${LIBOBJ} -rm -f ${OTHEROBJ} -rm -rf *.lo *.la .libs -rm -f *.a -rm -f fnv_hash.tar.gz Makefile.ship # WWW clobber: clean -rm -f ${TARGETS} distclean: clobber -rm -f Makefile libtool config.h config.status config.log config.cache check: all @echo @echo " These tests should not print an un-indented hash value:" @echo @echo " fnv0_32 -s hi == 0x6800a3d1" -@./fnv0_32 -s hi | ${EGREP} -v 0x6800a3d1; /bin/true @echo " fnv0_32 -s hello == 0xec6d6be8" -@./fnv0_32 -s hello | ${EGREP} -v 0xec6d6be8; /bin/true @echo " fnv0_32 -s curds and whey == 0x4a83403b" -@./fnv0_32 -s curds and whey | ${EGREP} -v 0x4a83403b; /bin/true @echo " fnv0_64 -s hi == 0x000068000000b0d1" -@./fnv0_64 -s hi | ${EGREP} -v 0x000068000000b0d1; /bin/true @echo " fnv0_64 -s hello == 0x3fa86e63bc7d03c8" -@./fnv0_64 -s hello | ${EGREP} -v 0x3fa86e63bc7d03c8; /bin/true @echo " fnv0_64 -s curds and whey == 0x09d2b4132bd1333b" -@./fnv0_64 -s curds and whey | ${EGREP} -v 0x09d2b4132bd1333b;/bin/true -@rm -f ll_tmp ll_tmp2 -@echo line 1 > ll_tmp -@echo line 2 >> ll_tmp -@echo line 3 >> ll_tmp @echo ' echo "line 1\\nline 2\\nline 3" > ll_tmp' @echo " dd if=/dev/zero bs=1024k count=4 of=ll_tmp2 >/dev/null 2>&1" -@dd if=/dev/zero bs=1024k count=4 of=ll_tmp2 >/dev/null 2>&1 @echo " fnv0_32 < ll_tmp == 0x1fad81d0" -@./fnv0_32 < ll_tmp | ${EGREP} -v 0x1fad81d0; /bin/true @echo " fnv0_64 < ll_tmp == 0xa8cf5b7784759250" -@./fnv0_64 < ll_tmp | ${EGREP} -v 0xa8cf5b7784759250; /bin/true @echo " fnv0_32 < ll_tmp2 == 0x00000000" -@./fnv0_32 < ll_tmp2 | ${EGREP} -v 0x00000000; /bin/true @echo " fnv0_64 < ll_tmp2 == 0x0000000000000000" -@./fnv0_64 < ll_tmp2 | ${EGREP} -v 0x0000000000000000; /bin/true @echo " fnv0_32 ll_tmp == 0x1fad81d0" -@./fnv0_32 ll_tmp | ${EGREP} -v 0x1fad81d0; /bin/true @echo " fnv0_64 ll_tmp == 0xa8cf5b7784759250" -@./fnv0_64 ll_tmp | ${EGREP} -v 0xa8cf5b7784759250; /bin/true @echo " fnv0_32 ll_tmp2 == 0x00000000" -@./fnv0_32 ll_tmp2 | ${EGREP} -v 0x00000000; /bin/true @echo " fnv0_64 ll_tmp2 == 0x0000000000000000" -@./fnv0_64 ll_tmp2 | ${EGREP} -v 0x0000000000000000; /bin/true @echo " fnv0_32 ll_tmp ll_tmp == 0xc500fd20" -@./fnv0_32 ll_tmp ll_tmp | ${EGREP} -v 0xc500fd20; /bin/true @echo " fnv0_64 ll_tmp ll_tmp == 0x3c8b9c3715fc1920" -@./fnv0_64 ll_tmp ll_tmp | ${EGREP} -v 0x3c8b9c3715fc1920; /bin/true @echo " fnv0_32 ll_tmp ll_tmp2 == 0x6fad81d0" -@./fnv0_32 ll_tmp ll_tmp2 | ${EGREP} -v 0x6fad81d0; /bin/true @echo " fnv0_64 ll_tmp ll_tmp2 == 0x29a78f5dd4759250" -@./fnv0_64 ll_tmp ll_tmp2 | ${EGREP} -v 0x29a78f5dd4759250; /bin/true @echo " fnv0_32 ll_tmp2 ll_tmp == 0x1fad81d0" -@./fnv0_32 ll_tmp2 ll_tmp | ${EGREP} -v 0x1fad81d0; /bin/true @echo " fnv0_64 ll_tmp2 ll_tmp == 0xa8cf5b7784759250" -@./fnv0_64 ll_tmp2 ll_tmp | ${EGREP} -v 0xa8cf5b7784759250; /bin/true @echo " fnv0_32 ll_tmp2 ll_tmp2 == 0x00000000" -@./fnv0_32 ll_tmp2 ll_tmp2 | ${EGREP} -v 0x00000000; /bin/true @echo " fnv0_64 ll_tmp2 ll_tmp2 == 0x0000000000000000" -@./fnv0_64 ll_tmp2 ll_tmp2 | ${EGREP} -v 0x0000000000000000; /bin/true @echo @echo " fnv1_32 -s hi == 0x6977223c" -@./fnv1_32 -s hi | ${EGREP} -v 0x6977223c; /bin/true @echo " fnv1_32 -s hello == 0xb6fa7167" -@./fnv1_32 -s hello | ${EGREP} -v 0xb6fa7167; /bin/true @echo " fnv1_32 -s curds and whey == 0x08ebf912" -@./fnv1_32 -s curds and whey | ${EGREP} -v 0x08ebf912; /bin/true @echo " fnv1_64 -s hi == 0x08326007b4eb2b9c" -@./fnv1_64 -s hi | ${EGREP} -v 0x08326007b4eb2b9c; /bin/true @echo " fnv1_64 -s hello == 0x7b495389bdbdd4c7" -@./fnv1_64 -s hello | ${EGREP} -v 0x7b495389bdbdd4c7; /bin/true @echo " fnv1_64 -s curds and whey == 0x795ad7b2d9a7dc72" -@./fnv1_64 -s curds and whey | ${EGREP} -v 0x795ad7b2d9a7dc72;/bin/true @echo " fnv1_32 < ll_tmp == 0xb8cbeb33" -@./fnv1_32 < ll_tmp | ${EGREP} -v 0xb8cbeb33; /bin/true @echo " fnv1_64 < ll_tmp == 0x79dcad190c3291b3" -@./fnv1_64 < ll_tmp | ${EGREP} -v 0x79dcad190c3291b3; /bin/true @echo " fnv1_32 < ll_tmp2 == 0xce1c9dc5" -@./fnv1_32 < ll_tmp2 | ${EGREP} -v 0xce1c9dc5; /bin/true @echo " fnv1_64 < ll_tmp2 == 0xf8e3e56ce9222325" -@./fnv1_64 < ll_tmp2 | ${EGREP} -v 0xf8e3e56ce9222325; /bin/true @echo " fnv1_32 ll_tmp == 0xb8cbeb33" -@./fnv1_32 ll_tmp | ${EGREP} -v 0xb8cbeb33; /bin/true @echo " fnv1_64 ll_tmp == 0x79dcad190c3291b3" -@./fnv1_64 ll_tmp | ${EGREP} -v 0x79dcad190c3291b3; /bin/true @echo " fnv1_32 ll_tmp2 == 0xce1c9dc5" -@./fnv1_32 ll_tmp2 | ${EGREP} -v 0xce1c9dc5; /bin/true @echo " fnv1_64 ll_tmp2 == 0xf8e3e56ce9222325" -@./fnv1_64 ll_tmp2 | ${EGREP} -v 0xf8e3e56ce9222325; /bin/true @echo " fnv1_32 ll_tmp ll_tmp == 0x08ae22e5" -@./fnv1_32 ll_tmp ll_tmp | ${EGREP} -v 0x08ae22e5; /bin/true @echo " fnv1_64 ll_tmp ll_tmp == 0x10a587a0ff68f305" -@./fnv1_64 ll_tmp ll_tmp | ${EGREP} -v 0x10a587a0ff68f305; /bin/true @echo " fnv1_32 ll_tmp ll_tmp2 == 0x23cbeb33" -@./fnv1_32 ll_tmp ll_tmp2 | ${EGREP} -v 0x23cbeb33; /bin/true @echo " fnv1_64 ll_tmp ll_tmp2 == 0xcafae19b7f3291b3" -@./fnv1_64 ll_tmp ll_tmp2 | ${EGREP} -v 0xcafae19b7f3291b3; /bin/true @echo " fnv1_32 ll_tmp2 ll_tmp == 0x1fcbeb33" -@./fnv1_32 ll_tmp2 ll_tmp | ${EGREP} -v 0x1fcbeb33; /bin/true @echo " fnv1_64 ll_tmp2 ll_tmp == 0x06319755db3291b3" -@./fnv1_64 ll_tmp2 ll_tmp | ${EGREP} -v 0x06319755db3291b3; /bin/true @echo " fnv1_32 ll_tmp2 ll_tmp2 == 0x1b1c9dc5" -@./fnv1_32 ll_tmp2 ll_tmp2 | ${EGREP} -v 0x1b1c9dc5; /bin/true @echo " fnv1_64 ll_tmp2 ll_tmp2 == 0x637a2df54e222325" -@./fnv1_64 ll_tmp2 ll_tmp2 | ${EGREP} -v 0x637a2df54e222325; /bin/true @echo -@rm -f ll_tmp ll_tmp2 @echo " All done!" ================================================ FILE: src/fnv/README ================================================ #=====================# # Fowler/Noll/Vo hash # #=====================# The basis of this hash algorithm was taken from an idea sent as reviewer comments to the IEEE POSIX P1003.2 committee by: Phong Vo (http://www.research.att.com/info/kpv) Glenn Fowler (http://www.research.att.com/~gsf/) In a subsequent ballot round: Landon Curt Noll (http://www.isthe.com/chongo) improved on their algorithm. Some people tried this hash and found that it worked rather well. In an EMail message to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. FNV hashes are designed to be fast while maintaining a low collision rate. The FNV speed allows one to quickly hash lots of data while maintaining a reasonable collision rate. See: http://www.isthe.com/chongo/tech/comp/fnv/index.html for more details as well as other forms of the FNV hash. Comments, questions, bug fixes and suggestions welcome at the address given in the above URL. #==================# # FNV hash utility # #==================# Two hash utilities (32 bit and 64 bit) are provided: fnv0_32 [-b bcnt] [-m [-v]] [-s arg] [arg ...] fnv0_64 [-b bcnt] [-m [-v]] [-s arg] [arg ...] fnv1_32 [-b bcnt] [-m [-v]] [-s arg] [arg ...] fnv1_64 [-b bcnt] [-m [-v]] [-s arg] [arg ...] or: fnv032 [-b bcnt] [-m [-v]] [-s arg] [arg ...] fnv064 [-b bcnt] [-m [-v]] [-s arg] [arg ...] fnv132 [-b bcnt] [-m [-v]] [-s arg] [arg ...] fnv164 [-b bcnt] [-m [-v]] [-s arg] [arg ...] -b bcnt mask off all but the lower bcnt bits (default: 32) -m multiple hashes, one per line for each arg -s hash arg as a string (ignoring terminating NUL bytes) -v verbose mode, print arg after hash (implies -m) arg string (if -s was given) or filename (default stdin) These serve as examples of how to use the FNV hash library. For those who do not like _'s, the same tools exist without the _ are provided. :-) The fnv0_32, fnv0_64 (fnv032, fnv064) implement the historic FNV-0 hash. The fnv1_32, fnv1_64 (fnv132, fnv164) implement the recommended FNV-1 hash. This is the original historic FNV algorithm with a 0 offset basis. It is recommended that FNV-1, with a non-0 offset basis be used instead. #==================# # FNV hash library # #==================# The libfnv.a library implements both a 32 bit and a 64 bit FNV hash on collections of bytes, a NUL terminated strings or on an open file descriptor. Here is the 32 bit FNV hash: Fnv32_t fnv_32_buf(void *buf, int len, Fnv32_t hval); /* byte buf */ Fnv32_t fnv_32_str(char *string, Fnv32_t hval); /* string */ Here is the 64 bit FNV hash: Fnv64_t fnv_64_buf(void *buf, int len, Fnv64_t hval); /* byte buf */ Fnv64_t fnv_64_str(char *string, Fnv64_t hval); /* string */ On the first call to a hash function, one must supply the initial basis that is appropriate for the hash in question: FNV-0: (not recommended) FNV0_32_INIT /* 32 bit FNV-0 initial basis */ FNV0_64_INIT /* 64 bit FNV-0 initial basis */ FNV-1: FNV1_32_INIT /* 32 bit FNV-1 initial basis */ FNV1_64_INIT /* 64 bit FNV-1 initial basis */ For example to perform a 64 bit FNV-1 hash: #include "fnv.h" Fnv64_t hash_val; hash_val = fnv_64_str("a string", FNV1_64_INIT); hash_val = fnv0_64_str("more string", hash_val); produces the same final hash value as: hash_val = fnv_64_str("a stringmore string", FNV1_64_INIT); NOTE: If one used 'FNV0_64_INIT' instead of 'FNV1_64_INIT' one would get the historic FNV-0 hash instead recommended FNV-1 hash. To perform a 32 bit FNV-1 hash: #include "fnv.h" Fnv32_t hash_val; hash_val = fnv_32_buf(buf, length_of_buf, FNV1_32_INIT); hash_val = fnv324_str("more data", hash_val); =-= chongo /\oo/\ http://www.isthe.com/chongo Share and Enjoy! ================================================ FILE: src/fnv/aclocal.m4 ================================================ # libtool.m4 - Configure libtool for the host system. -*-Shell-script-*- ## Copyright 1996, 1997, 1998, 1999, 2000, 2001 ## Free Software Foundation, Inc. ## Originally by Gordon Matzigkeit , 1996 ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ## ## As a special exception to the GNU General Public License, if you ## distribute this file as part of a program that contains a ## configuration script generated by Autoconf, you may include it under ## the same distribution terms that you use for the rest of that program. # serial 46 AC_PROG_LIBTOOL AC_DEFUN([AC_PROG_LIBTOOL], [AC_REQUIRE([AC_LIBTOOL_SETUP])dnl # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl # Prevent multiple expansion define([AC_PROG_LIBTOOL], []) ]) AC_DEFUN([AC_LIBTOOL_SETUP], [AC_PREREQ(2.13)dnl AC_REQUIRE([AC_ENABLE_SHARED])dnl AC_REQUIRE([AC_ENABLE_STATIC])dnl AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_LD])dnl AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl AC_REQUIRE([AC_PROG_NM])dnl AC_REQUIRE([AC_PROG_LN_S])dnl AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl AC_REQUIRE([AC_OBJEXT])dnl AC_REQUIRE([AC_EXEEXT])dnl dnl _LT_AC_PROG_ECHO_BACKSLASH # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then AC_PATH_MAGIC fi ;; esac AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(STRIP, strip, :) ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], enable_win32_dll=yes, enable_win32_dll=no) AC_ARG_ENABLE(libtool-lock, [ --disable-libtool-lock avoid locking (might break parallel builds)]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_SAVE AC_LANG_C AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_RESTORE]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], [*-*-cygwin* | *-*-mingw* | *-*-pw32*) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one AC_CACHE_CHECK([if libtool should supply DllMain function], lt_cv_need_dllmain, [AC_TRY_LINK([], [extern int __attribute__((__stdcall__)) DllMain(void*, int, void*); DllMain (0, 0, 0);], [lt_cv_need_dllmain=no],[lt_cv_need_dllmain=yes])]) case $host/$CC in *-*-cygwin*/gcc*-mno-cygwin*|*-*-mingw*) # old mingw systems require "-dll" to link a DLL, while more recent ones # require "-mdll" SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -mdll" AC_CACHE_CHECK([how to link DLLs], lt_cv_cc_dll_switch, [AC_TRY_LINK([], [], [lt_cv_cc_dll_switch=-mdll],[lt_cv_cc_dll_switch=-dll])]) CFLAGS="$SAVE_CFLAGS" ;; *-*-cygwin* | *-*-pw32*) # cygwin systems need to pass --dll to the linker, and not link # crt.o which will require a WinMain@16 definition. lt_cv_cc_dll_switch="-Wl,--dll -nostartfiles" ;; esac ;; ]) esac _LT_AC_LTCONFIG_HACK ]) # AC_LIBTOOL_HEADER_ASSERT # ------------------------ AC_DEFUN([AC_LIBTOOL_HEADER_ASSERT], [AC_CACHE_CHECK([whether $CC supports assert without backlinking], [lt_cv_func_assert_works], [case $host in *-*-solaris*) if test "$GCC" = yes && test "$with_gnu_ld" != yes; then case `$CC --version 2>/dev/null` in [[12]].*) lt_cv_func_assert_works=no ;; *) lt_cv_func_assert_works=yes ;; esac fi ;; esac]) if test "x$lt_cv_func_assert_works" = xyes; then AC_CHECK_HEADERS(assert.h) fi ])# AC_LIBTOOL_HEADER_ASSERT # _LT_AC_CHECK_DLFCN # -------------------- AC_DEFUN([_LT_AC_CHECK_DLFCN], [AC_CHECK_HEADERS(dlfcn.h) ])# _LT_AC_CHECK_DLFCN # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [dnl # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32*) symcode='[[ABCDGISTW]]' ;; hpux*) # Its linker distinguishes data from code symbols lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; solaris* | sysv5*) symcode='[[BDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $host_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then symcode='[[ABCDGISTW]]' fi # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if egrep ' nm_test_var$' "$nlist" >/dev/null; then if egrep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[[]] = { EOF sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$no_builtin_flag" if AC_TRY_EVAL(ac_link) && test -s conftest; then pipe_works=yes fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AC_FD_CC fi else echo "cannot find nm_test_var in $nlist" >&AC_FD_CC fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC fi else echo "$progname: failed program was:" >&AC_FD_CC cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) global_symbol_pipe="$lt_cv_sys_global_symbol_pipe" if test -z "$lt_cv_sys_global_symbol_pipe"; then global_symbol_to_cdecl= global_symbol_to_c_name_address= else global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl" global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address" fi if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi ]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR # --------------------------------- AC_DEFUN([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR], [# Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) lt_cv_sys_path_separator=';' ;; *) lt_cv_sys_path_separator=':' ;; esac PATH_SEPARATOR=$lt_cv_sys_path_separator fi ])# _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR # _LT_AC_PROG_ECHO_BACKSLASH # -------------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) _LT_AC_LIBTOOL_SYS_PATH_SEPARATOR # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac echo=${ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(ECHO) AC_DIVERT_POP ])# _LT_AC_PROG_ECHO_BACKSLASH # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ------------------------------------------------------------------ AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], [if test "$cross_compiling" = yes; then : [$4] else AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_unknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_AC_TRY_DLOPEN_SELF # AC_LIBTOOL_DLOPEN_SELF # ------------------- AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; cygwin* | mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_AC_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi ])# AC_LIBTOOL_DLOPEN_SELF AC_DEFUN([_LT_AC_LTCONFIG_HACK], [AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])dnl # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([[\\"\\`$\\\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([[\\"\\`\\\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" need_locks="$enable_libtool_lock" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o if test x"$host" != x"$build"; then ac_tool_prefix=${host_alias}- else ac_tool_prefix= fi # Transform linux* to *-*-linux-gnu*, to support old configure scripts. case $host_os in linux-gnu*) ;; linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` esac case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Allow CC to be a program name with arguments. set dummy $CC compiler="[$]2" ## FIXME: this should be a separate macro ## AC_MSG_CHECKING([for objdir]) rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. objdir=_libs fi rmdir .libs 2>/dev/null AC_MSG_RESULT($objdir) ## ## END FIXME ## FIXME: this should be a separate macro ## AC_ARG_WITH(pic, [ --with-pic try to use only PIC/non-PIC objects [default=use both]], pic_mode="$withval", pic_mode=default) test -z "$pic_mode" && pic_mode=default # We assume here that the value for lt_cv_prog_cc_pic will not be cached # in isolation, and that seeing it set (from the cache) indicates that # the associated values are set (in the cache) correctly too. AC_MSG_CHECKING([for $compiler option to produce PIC]) AC_CACHE_VAL(lt_cv_prog_cc_pic, [ lt_cv_prog_cc_pic= lt_cv_prog_cc_shlib= lt_cv_prog_cc_wl= lt_cv_prog_cc_static= lt_cv_prog_cc_no_builtin= lt_cv_prog_cc_can_build_shared=$can_build_shared if test "$GCC" = yes; then lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-static' case $host_os in aix*) # Below there is a dirty hack to force normal static linking with -ldl # The problem is because libdl dynamically linked with both libc and # libC (AIX C++ library), which obviously doesn't included in libraries # list by gcc. This cause undefined symbols with -static flags. # This hack allows C programs to be linked with "-static -ldl", but # not sure about C++ programs. lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC" ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_cv_prog_cc_pic='-fno-common' ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; sysv4*MP*) if test -d /usr/nec; then lt_cv_prog_cc_pic=-Kconform_pic fi ;; *) lt_cv_prog_cc_pic='-fPIC' ;; esac else # PORTME Check for PIC flags for the system compiler. case $host_os in aix3* | aix4* | aix5*) lt_cv_prog_cc_wl='-Wl,' # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_cv_prog_cc_static='-Bstatic' else lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' fi ;; hpux9* | hpux10* | hpux11*) # Is there a better lt_cv_prog_cc_static that works with the bundled CC? lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive" lt_cv_prog_cc_pic='+Z' ;; irix5* | irix6* | nonstopux*) lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' # PIC (with -KPIC) is the default. ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; newsos6) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' ;; osf3* | osf4* | osf5*) # All OSF/1 code is PIC. lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' ;; sco3.2v5*) lt_cv_prog_cc_pic='-Kpic' lt_cv_prog_cc_static='-dn' lt_cv_prog_cc_shlib='-belf' ;; solaris*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Wl,' ;; sunos4*) lt_cv_prog_cc_pic='-PIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' if test "x$host_vendor" = xsni; then lt_cv_prog_cc_wl='-LD' else lt_cv_prog_cc_wl='-Wl,' fi ;; uts4*) lt_cv_prog_cc_pic='-pic' lt_cv_prog_cc_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_cv_prog_cc_pic='-Kconform_pic' lt_cv_prog_cc_static='-Bstatic' fi ;; *) lt_cv_prog_cc_can_build_shared=no ;; esac fi ]) if test -z "$lt_cv_prog_cc_pic"; then AC_MSG_RESULT([none]) else AC_MSG_RESULT([$lt_cv_prog_cc_pic]) # Check to make sure the pic_flag actually works. AC_MSG_CHECKING([if $compiler PIC flag $lt_cv_prog_cc_pic works]) AC_CACHE_VAL(lt_cv_prog_cc_pic_works, [dnl save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" AC_TRY_COMPILE([], [], [dnl case $host_os in hpux9* | hpux10* | hpux11*) # On HP-UX, both CC and GCC only warn that PIC is supported... then # they create non-PIC objects. So, if there were any warnings, we # assume that PIC is not supported. if test -s conftest.err; then lt_cv_prog_cc_pic_works=no else lt_cv_prog_cc_pic_works=yes fi ;; *) lt_cv_prog_cc_pic_works=yes ;; esac ], [dnl lt_cv_prog_cc_pic_works=no ]) CFLAGS="$save_CFLAGS" ]) if test "X$lt_cv_prog_cc_pic_works" = Xno; then lt_cv_prog_cc_pic= lt_cv_prog_cc_can_build_shared=no else lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic" fi AC_MSG_RESULT([$lt_cv_prog_cc_pic_works]) fi ## ## END FIXME # Check for any special shared library compilation flags. if test -n "$lt_cv_prog_cc_shlib"; then AC_MSG_WARN([\`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries]) if echo "$old_CC $old_CFLAGS " | egrep -e "[[ ]]$lt_cv_prog_cc_shlib[[ ]]" >/dev/null; then : else AC_MSG_WARN([add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure]) lt_cv_prog_cc_can_build_shared=no fi fi ## FIXME: this should be a separate macro ## AC_MSG_CHECKING([if $compiler static flag $lt_cv_prog_cc_static works]) AC_CACHE_VAL([lt_cv_prog_cc_static_works], [dnl lt_cv_prog_cc_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" AC_TRY_LINK([], [], [lt_cv_prog_cc_static_works=yes]) LDFLAGS="$save_LDFLAGS" ]) # Belt *and* braces to stop my trousers falling down: test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static= AC_MSG_RESULT([$lt_cv_prog_cc_static_works]) pic_flag="$lt_cv_prog_cc_pic" special_shlib_compile_flags="$lt_cv_prog_cc_shlib" wl="$lt_cv_prog_cc_wl" link_static_flag="$lt_cv_prog_cc_static" no_builtin_flag="$lt_cv_prog_cc_no_builtin" can_build_shared="$lt_cv_prog_cc_can_build_shared" ## ## END FIXME ## FIXME: this should be a separate macro ## # Check to see if options -o and -c are simultaneously supported by compiler AC_MSG_CHECKING([if $compiler supports -c -o file.$ac_objext]) AC_CACHE_VAL([lt_cv_compiler_c_o], [ $rm -r conftest 2>/dev/null mkdir conftest cd conftest echo "int some_variable = 0;" > conftest.$ac_ext mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no if { (eval echo configure:__oline__: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then lt_cv_compiler_c_o=no else lt_cv_compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&AC_FD_CC lt_cv_compiler_c_o=no fi CFLAGS="$save_CFLAGS" chmod u+w . $rm conftest* out/* rmdir out cd .. rmdir conftest $rm -r conftest 2>/dev/null ]) compiler_c_o=$lt_cv_compiler_c_o AC_MSG_RESULT([$compiler_c_o]) if test x"$compiler_c_o" = x"yes"; then # Check to see if we can write to a .lo AC_MSG_CHECKING([if $compiler supports -c -o file.lo]) AC_CACHE_VAL([lt_cv_compiler_o_lo], [ lt_cv_compiler_o_lo=no save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -c -o conftest.lo" save_objext="$ac_objext" ac_objext=lo AC_TRY_COMPILE([], [int some_variable = 0;], [dnl # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then lt_cv_compiler_o_lo=no else lt_cv_compiler_o_lo=yes fi ]) ac_objext="$save_objext" CFLAGS="$save_CFLAGS" ]) compiler_o_lo=$lt_cv_compiler_o_lo AC_MSG_RESULT([$compiler_o_lo]) else compiler_o_lo=no fi ## ## END FIXME ## FIXME: this should be a separate macro ## # Check to see if we can do hard links to lock some files if needed hard_links="nottested" if test "$compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([\`$CC' does not support \`-c -o', so \`make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi ## ## END FIXME ## FIXME: this should be a separate macro ## if test "$GCC" = yes; then # Check to see if options -fno-rtti -fno-exceptions are supported by compiler AC_MSG_CHECKING([if $compiler supports -fno-rtti -fno-exceptions]) echo "int some_variable = 0;" > conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" compiler_rtti_exceptions=no AC_TRY_COMPILE([], [int some_variable = 0;], [dnl # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then compiler_rtti_exceptions=no else compiler_rtti_exceptions=yes fi ]) CFLAGS="$save_CFLAGS" AC_MSG_RESULT([$compiler_rtti_exceptions]) if test "$compiler_rtti_exceptions" = "yes"; then no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' else no_builtin_flag=' -fno-builtin' fi fi ## ## END FIXME ## FIXME: this should be a separate macro ## # See if the linker supports building shared libraries. AC_MSG_CHECKING([whether the linker ($LD) supports shared libraries]) allow_undefined_flag= no_undefined_flag= need_lib_prefix=unknown need_version=unknown # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments archive_cmds= archive_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_into_libs=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported runpath_var= link_all_deplibs=unknown always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an egrep regular expression of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available. ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=yes extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ test -f $output_objdir/impgen.exe || (cd $output_objdir && \ if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ else $CC -o impgen impgen.c ; fi)~ $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' # cygwin and mingw dlls have different entry points and sets of symbols # to exclude. # FIXME: what about values for MSVC? dll_entry=__cygwin_dll_entry@12 dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ case $host_os in mingw*) # mingw values dll_entry=_DllMainCRTStartup@12 dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ ;; esac # mingw and cygwin differ, and it's simplest to just exclude the union # of the two symbol sets. dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one (in ltdll.c) if test "x$lt_cv_need_dllmain" = "xyes"; then ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' else ltdll_obj= ltdll_cmds= fi # Extract the symbol export list from an `--export-all' def file, # then regenerate the def file from the symbol export list, so that # the compiled dll only exports the symbol export list. # Be careful not to strip the DATA tag left be newer dlltools. export_symbols_cmds="$ltdll_cmds"' $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ sed -e "1,/EXPORTS/d" -e "s/ @ [[0-9]]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is. # If DATA tags from a recent dlltool are present, honour them! archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname-def; else echo EXPORTS > $output_objdir/$soname-def; _lt_hint=1; cat $export_symbols | while read symbol; do set dummy \$symbol; case \[$]# in 2) echo " \[$]2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; *) echo " \[$]2 @ \$_lt_hint \[$]3 ; " >> $output_objdir/$soname-def;; esac; _lt_hint=`expr 1 + \$_lt_hint`; done; fi~ '"$ltdll_cmds"' $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' case $host_os in cygwin* | mingw* | pw32*) # dlltool doesn't understand --whole-archive et. al. whole_archive_flag_spec= ;; *) # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi ;; esac fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. hardcode_direct=yes archive_cmds='' hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then shared_flag='${wl}-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall can do strange things, so it is better to # generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. allow_undefined_flag='${wl}-berok' # This is a bit strange, but is similar to how AIX traditionally builds # it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' ;; darwin* | rhapsody*) case "$host_os" in rhapsody* | darwin1.[[012]]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on allow_undefined_flag='-flat_namespace -undefined suppress' ;; esac # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. Also zsh mangles # `"' quotes if we put them in here... so don't! archive_cmds='$nonopt $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring' # We need to add '_' to the symbols in $export_symbols first #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' hardcode_direct=yes hardcode_shlibpath_var=no whole_archive_flag_spec='-all_load $convenience' ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9* | hpux10* | hpux11*) case $host_os in hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. export_dynamic_flag_spec='${wl}-E' ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case "$host_os" in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' #Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes export_dynamic_flag_spec='${wl}-Bexport' ;; solaris*) # gcc --version < 3.0 without binutils cannot create self contained # shared libraries reliably, requiring libgcc.a to resolve some of # the object symbols generated in some cases. Libraries that use # assert need libgcc.a to resolve __eprintf, for example. Linking # a copy of libgcc.a into every shared library to guarantee resolving # such symbols causes other problems: According to Tim Van Holder # , C++ libraries end up with a separate # (to the application) exception stack for one thing. no_undefined_flag=' -z defs' if test "$GCC" = yes; then case `$CC --version 2>/dev/null` in [[12]].*) cat <&2 *** Warning: Releases of GCC earlier than version 3.0 cannot reliably *** create self contained shared libraries on Solaris systems, without *** introducing a dependency on libgcc.a. Therefore, libtool is disabling *** -no-undefined support, which will at least allow you to build shared *** libraries. However, you may find that when you link such libraries *** into an application without using GCC, you have to manually add *** \`gcc --print-libgcc-file-name\` to the link command. We urge you to *** upgrade to a newer version of GCC. Another option is to rebuild your *** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer. EOF no_undefined_flag= ;; esac fi # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) if test "x$host_vendor" = xsno; then archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? else archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5uw7* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi AC_MSG_RESULT([$ld_shlibs]) test "$ld_shlibs" = no && can_build_shared=no ## ## END FIXME ## FIXME: this should be a separate macro ## # Check hardcoding attributes. AC_MSG_CHECKING([how to hardcode library paths into programs]) hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var"; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$hardcode_shlibpath_var" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi AC_MSG_RESULT([$hardcode_action]) ## ## END FIXME ## FIXME: this should be a separate macro ## striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ## ## END FIXME reload_cmds='$LD$reload_flag -o $output$reload_objs' test -z "$deplibs_check_method" && deplibs_check_method=unknown ## FIXME: this should be a separate macro ## # PORTME Fill in your ld.so characteristics AC_MSG_CHECKING([dynamic linker characteristics]) library_names_spec= libname_spec='lib$name' soname_spec= postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}.so$versuffix $libname.a' shlibpath_var=LIBPATH # AIX has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}.so$major' ;; aix4* | aix5*) version_type=linux if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can # not hardcode correct soname into executable. Probably we can # add versioning support to collect2, so additional links can # be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}.so$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' ;; beos*) library_names_spec='${libname}.so' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" export_dynamic_flag_spec=-rdynamic # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin*) library_names_spec='$libname.dll.a' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog .libs/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' ;; yes,mingw*) library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` ;; yes,pw32*) library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' ;; *) library_names_spec='${libname}`echo ${release} | sed -e 's/[[.]]/-/g'`${versuffix}.dll $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; *) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. dynamic_linker="$host_os dld.sl" version_type=sunos need_lib_prefix=no need_version=no shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' soname_spec='${libname}${release}.sl$major' # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) version_type=irix ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; # No shared lib support for Linux oldld, aout, or coff. linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) dynamic_linker=no ;; # This must be Linux ELF. linux-gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' soname_spec='${libname}${release}.so$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case "$host_os" in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH ;; os2*) libname_spec='$name' need_lib_prefix=no library_names_spec='$libname.dll $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_version=no need_lib_prefix=no soname_spec='${libname}${release}.so' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' soname_spec='$libname.so.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no ## ## END FIXME ## FIXME: this should be a separate macro ## # Report the final consequences. AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) ## ## END FIXME ## FIXME: this should be a separate macro ## AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) ## ## END FIXME ## FIXME: this should be a separate macro ## AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) ## ## END FIXME if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi AC_LIBTOOL_DLOPEN_SELF ## FIXME: this should be a separate macro ## if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) AC_CACHE_VAL([lt_cv_archive_cmds_need_lc], [$rm conftest* echo 'static int dummy;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_cv_prog_cc_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if AC_TRY_EVAL(archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$save_allow_undefined_flag else cat conftest.err 1>&5 fi]) AC_MSG_RESULT([$lt_cv_archive_cmds_need_lc]) ;; esac fi need_lc=${lt_cv_archive_cmds_need_lc-yes} ## ## END FIXME ## FIXME: this should be a separate macro ## # The second clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then : else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi if test -f "$ltmain"; then trap "$rm \"${ofile}T\"; exit 1" 1 2 15 $rm -f "${ofile}T" echo creating $ofile # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS \ AR AR_FLAGS CC LD LN_S NM SHELL \ reload_flag reload_cmds wl \ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ thread_safe_flag_spec whole_archive_flag_spec libname_spec \ library_names_spec soname_spec \ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ old_striplib striplib file_magic_cmd export_symbols_cmds \ deplibs_check_method allow_undefined_flag no_undefined_flag \ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ global_symbol_to_c_name_address \ hardcode_libdir_flag_spec hardcode_libdir_separator \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do case $var in reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ postinstall_cmds | postuninstall_cmds | \ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done cat <<__EOF__ > "${ofile}T" #! $SHELL # `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996-2000 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="sed -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$need_lc # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # The default C compiler. CC=$lt_CC # Is the compiler the GNU C compiler? with_gcc=$GCC # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_pic_flag pic_mode=$pic_mode # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_compiler_c_o # Can we write directly to a .lo ? compiler_o_lo=$lt_compiler_o_lo # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_link_static_flag # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "${ofile}T" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac case $host_os in cygwin* | mingw* | pw32* | os2*) cat <<'EOF' >> "${ofile}T" # This is a source program that is used to create dlls on Windows # Don't remove nor modify the starting and closing comments # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ # This is a source program that is used to create import libraries # on Windows for dlls which lack them. Don't remove nor modify the # starting and closing comments # /* impgen.c starts here */ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc. # # This file is part of GNU libtool. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # */ # # #include /* for printf() */ # #include /* for open(), lseek(), read() */ # #include /* for O_RDONLY, O_BINARY */ # #include /* for strdup() */ # # /* O_BINARY isn't required (or even defined sometimes) under Unix */ # #ifndef O_BINARY # #define O_BINARY 0 # #endif # # static unsigned int # pe_get16 (fd, offset) # int fd; # int offset; # { # unsigned char b[2]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 2); # return b[0] + (b[1]<<8); # } # # static unsigned int # pe_get32 (fd, offset) # int fd; # int offset; # { # unsigned char b[4]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 4); # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # static unsigned int # pe_as32 (ptr) # void *ptr; # { # unsigned char *b = ptr; # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # int # main (argc, argv) # int argc; # char *argv[]; # { # int dll; # unsigned long pe_header_offset, opthdr_ofs, num_entries, i; # unsigned long export_rva, export_size, nsections, secptr, expptr; # unsigned long name_rvas, nexp; # unsigned char *expdata, *erva; # char *filename, *dll_name; # # filename = argv[1]; # # dll = open(filename, O_RDONLY|O_BINARY); # if (dll < 1) # return 1; # # dll_name = filename; # # for (i=0; filename[i]; i++) # if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') # dll_name = filename + i +1; # # pe_header_offset = pe_get32 (dll, 0x3c); # opthdr_ofs = pe_header_offset + 4 + 20; # num_entries = pe_get32 (dll, opthdr_ofs + 92); # # if (num_entries < 1) /* no exports */ # return 1; # # export_rva = pe_get32 (dll, opthdr_ofs + 96); # export_size = pe_get32 (dll, opthdr_ofs + 100); # nsections = pe_get16 (dll, pe_header_offset + 4 +2); # secptr = (pe_header_offset + 4 + 20 + # pe_get16 (dll, pe_header_offset + 4 + 16)); # # expptr = 0; # for (i = 0; i < nsections; i++) # { # char sname[8]; # unsigned long secptr1 = secptr + 40 * i; # unsigned long vaddr = pe_get32 (dll, secptr1 + 12); # unsigned long vsize = pe_get32 (dll, secptr1 + 16); # unsigned long fptr = pe_get32 (dll, secptr1 + 20); # lseek(dll, secptr1, SEEK_SET); # read(dll, sname, 8); # if (vaddr <= export_rva && vaddr+vsize > export_rva) # { # expptr = fptr + (export_rva - vaddr); # if (export_rva + export_size > vaddr + vsize) # export_size = vsize - (export_rva - vaddr); # break; # } # } # # expdata = (unsigned char*)malloc(export_size); # lseek (dll, expptr, SEEK_SET); # read (dll, expdata, export_size); # erva = expdata - export_rva; # # nexp = pe_as32 (expdata+24); # name_rvas = pe_as32 (expdata+32); # # printf ("EXPORTS\n"); # for (i = 0; i> "${ofile}T" || (rm -f "${ofile}T"; exit 1) mv -f "${ofile}T" "$ofile" || \ (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T") chmod +x "$ofile" fi ## ## END FIXME ])# _LT_AC_LTCONFIG_HACK # AC_LIBTOOL_DLOPEN - enable checks for dlopen support AC_DEFUN([AC_LIBTOOL_DLOPEN], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) # AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) # AC_ENABLE_SHARED - implement the --enable-shared flag # Usage: AC_ENABLE_SHARED[(DEFAULT)] # Where DEFAULT is either `yes' or `no'. If omitted, it defaults to # `yes'. AC_DEFUN([AC_ENABLE_SHARED], [define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE(shared, changequote(<<, >>)dnl << --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], changequote([, ])dnl [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$ac_save_ifs" ;; esac], enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl ]) # AC_DISABLE_SHARED - set the default shared flag to --disable-shared AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_SHARED(no)]) # AC_ENABLE_STATIC - implement the --enable-static flag # Usage: AC_ENABLE_STATIC[(DEFAULT)] # Where DEFAULT is either `yes' or `no'. If omitted, it defaults to # `yes'. AC_DEFUN([AC_ENABLE_STATIC], [define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE(static, changequote(<<, >>)dnl << --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], changequote([, ])dnl [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$ac_save_ifs" ;; esac], enable_static=AC_ENABLE_STATIC_DEFAULT)dnl ]) # AC_DISABLE_STATIC - set the default static flag to --disable-static AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_STATIC(no)]) # AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag # Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] # Where DEFAULT is either `yes' or `no'. If omitted, it defaults to # `yes'. AC_DEFUN([AC_ENABLE_FAST_INSTALL], [define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl AC_ARG_ENABLE(fast-install, changequote(<<, >>)dnl << --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], changequote([, ])dnl [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$ac_save_ifs" ;; esac], enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl ]) # AC_DISABLE_FAST_INSTALL - set the default to --disable-fast-install AC_DEFUN([AC_DISABLE_FAST_INSTALL], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_FAST_INSTALL(no)]) # AC_LIBTOOL_PICMODE - implement the --with-pic flag # Usage: AC_LIBTOOL_PICMODE[(MODE)] # Where MODE is either `yes' or `no'. If omitted, it defaults to # `both'. AC_DEFUN([AC_LIBTOOL_PICMODE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl pic_mode=ifelse($#,1,$1,default)]) # AC_PATH_TOOL_PREFIX - find a file program which can recognise shared library AC_DEFUN([AC_PATH_TOOL_PREFIX], [AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in /*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; ?:/*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. ;; *) ac_save_MAGIC_CMD="$MAGIC_CMD" IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="ifelse([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$ac_save_ifs" MAGIC_CMD="$ac_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi ]) # AC_PATH_MAGIC - find a file program which can recognise a shared library AC_DEFUN([AC_PATH_MAGIC], [AC_REQUIRE([AC_CHECK_TOOL_PREFIX])dnl AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin:$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then AC_PATH_TOOL_PREFIX(file, /usr/bin:$PATH) else MAGIC_CMD=: fi fi ]) # AC_PROG_LD - find the path to the GNU or non-GNU linker AC_DEFUN([AC_PROG_LD], [AC_ARG_WITH(gnu-ld, [ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | [[A-Za-z]]:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then test "$with_gnu_ld" != no && break else test "$with_gnu_ld" != yes && break fi fi done IFS="$ac_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$lt_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_PROG_LD_GNU ]) # AC_PROG_LD_GNU - AC_DEFUN([AC_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then lt_cv_prog_gnu_ld=yes else lt_cv_prog_gnu_ld=no fi]) with_gnu_ld=$lt_cv_prog_gnu_ld ]) # AC_PROG_LD_RELOAD_FLAG - find reload flag for linker # -- PORTME Some linkers may need a different reload flag. AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], [AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag, [lt_cv_ld_reload_flag='-r']) reload_flag=$lt_cv_ld_reload_flag test -n "$reload_flag" && reload_flag=" $reload_flag" ]) # AC_DEPLIBS_CHECK_METHOD - how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], [AC_CACHE_CHECK([how to recognise dependant libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given egrep regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi4*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | mingw* | pw32*) lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[[012]]) lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1` ;; *) # Darwin 1.3 on lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac ;; freebsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20*|hpux11*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux-gnu*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so\.[[0-9]]+\.[[0-9]]+$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/\.]]+\.so$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv5uw[[78]]* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; esac ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method ]) # AC_PROG_NM - find the path to a BSD-compatible name lister AC_DEFUN([AC_PROG_NM], [AC_REQUIRE([_LT_AC_LIBTOOL_SYS_PATH_SEPARATOR])dnl AC_MSG_CHECKING([for BSD-compatible nm]) AC_CACHE_VAL(lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/${ac_tool_prefix}nm if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then lt_cv_path_NM="$tmp_nm -B" break elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then lt_cv_path_NM="$tmp_nm -p" break else lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags fi fi done IFS="$ac_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" AC_MSG_RESULT([$NM]) ]) # AC_CHECK_LIBM - check for math library AC_DEFUN([AC_CHECK_LIBM], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32*) # These system don't have libm ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, main, LIBM="-lm") ;; esac ]) # AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for # the libltdl convenience library and LTDLINCL to the include flags for # the libltdl header and adds --enable-ltdl-convenience to the # configure arguments. Note that LIBLTDL and LTDLINCL are not # AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not # provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed # with '${top_builddir}/' and LTDLINCL will be prefixed with # '${top_srcdir}/' (note the single quotes!). If your package is not # flat and you're not using automake, define top_builddir and # top_srcdir appropriately in the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ]) # AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for # the libltdl installable library and LTDLINCL to the include flags for # the libltdl header and adds --enable-ltdl-install to the configure # arguments. Note that LIBLTDL and LTDLINCL are not AC_SUBSTed, nor is # AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed # libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will # be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed # with '${top_srcdir}/' (note the single quotes!). If your package is # not flat and you're not using automake, define top_builddir and # top_srcdir appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, main, [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], [if test x"$enable_ltdl_install" = xno; then AC_MSG_WARN([libltdl not installed, but installation disabled]) else enable_ltdl_install=yes fi ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" LTDLINCL= fi # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ]) # old names AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) # This is just to silence aclocal about the macro not being used ifelse([AC_DISABLE_FAST_INSTALL]) ================================================ FILE: src/fnv/config.guess ================================================ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-03-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi dummy=dummy-$$ trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int dummy(){}" > $dummy.c ; for c in cc gcc c89 c99 ; do ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; if test $? = 0 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. cat <$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF eval $set_cc_for_build $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then case `./$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; esac fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy \ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: src/fnv/config.in ================================================ /* config.in. Generated automatically from configure.in by autoheader 2.13. */ /* Define to empty if the keyword does not work. */ #undef const /* Define to `unsigned' if doesn't define. */ #undef size_t /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you have the header file. */ #undef HAVE_DLFCN_H /* Define if you have the header file. */ #undef HAVE_FCNTL_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H ================================================ FILE: src/fnv/config.sub ================================================ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-03-07' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dsp16xx \ | fr30 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el | mips64vr4300 \ | mips64vr4300el | mips64vr5000 | mips64vr5000el \ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ | mipsisa32 | mipsisa64 \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; c4x*) basic_machine=c4x-none os=-coff ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: src/fnv/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --enable-shared[=PKGS] build shared libraries [default=yes]" ac_help="$ac_help --enable-static[=PKGS] build static libraries [default=yes]" ac_help="$ac_help --enable-fast-install[=PKGS] optimize for fast installation [default=yes]" ac_help="$ac_help --with-gnu-ld assume the C compiler uses GNU ld [default=no]" # Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) lt_cv_sys_path_separator=';' ;; *) lt_cv_sys_path_separator=':' ;; esac PATH_SEPARATOR=$lt_cv_sys_path_separator fi # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. IFS="${IFS= }"; save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi ac_help="$ac_help --disable-libtool-lock avoid locking (might break parallel builds)" ac_help="$ac_help --with-pic try to use only PIC/non-PIC objects [default=use both]" ac_help="$ac_help --enable-shared build FNV as a shared library" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file=fnv.h # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi FNV_MAJOR=1 FNV_MINOR=0 FNV_DATE=09-Sep-2002 FNV_VERSION=${FNV_MAJOR}.${FNV_MINOR} FNV_LIB_VERSION=0:1:0 # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:713: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:743: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:794: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:826: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 837 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:842: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:868: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:873: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:901: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break fi done if test -z "$ac_aux_dir"; then { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo "configure:963: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do if test -f $ac_dir/$ac_prog; then if test $ac_prog = install && grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : else ac_cv_path_install="$ac_dir/$ac_prog -c" break 2 fi fi done ;; esac done IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then INSTALL="$ac_cv_path_install" else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL="$ac_install_sh" fi fi echo "$ac_t""$INSTALL" 1>&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 echo "configure:1016: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftestdata if ln -s X conftestdata 2>/dev/null then rm -f conftestdata ac_cv_prog_LN_S="ln -s" else ac_cv_prog_LN_S=ln fi fi LN_S="$ac_cv_prog_LN_S" if test "$ac_cv_prog_LN_S" = "ln -s"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi # Find the correct PATH separator. Usually this is `:', but # DJGPP uses `;' like DOS. if test "X${PATH_SEPARATOR+set}" != Xset; then UNAME=${UNAME-`uname 2>/dev/null`} case X$UNAME in *-DOS) lt_cv_sys_path_separator=';' ;; *) lt_cv_sys_path_separator=':' ;; esac PATH_SEPARATOR=$lt_cv_sys_path_separator fi echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 echo "configure:1048: checking for Cygwin environment" >&5 if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_cygwin=no fi rm -f conftest* rm -f conftest* fi echo "$ac_t""$ac_cv_cygwin" 1>&6 CYGWIN= test "$ac_cv_cygwin" = yes && CYGWIN=yes echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 echo "configure:1081: checking for mingw32 environment" >&5 if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_mingw32=no fi rm -f conftest* rm -f conftest* fi echo "$ac_t""$ac_cv_mingw32" 1>&6 MINGW32= test "$ac_cv_mingw32" = yes && MINGW32=yes echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:1110: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1131: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1148: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1165: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$ac_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static or --disable-static was given. if test "${enable_static+set}" = set; then enableval="$enable_static" p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$ac_save_ifs" ;; esac else enable_static=yes fi # Check whether --enable-fast-install or --disable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval="$enable_fast_install" p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," for pkg in $enableval; do if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$ac_save_ifs" ;; esac else enable_fast_install=yes fi # Make sure we can run config.sub. if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 echo "configure:1265: checking host system type" >&5 host_alias=$host case "$host_alias" in NONE) case $nonopt in NONE) if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } fi ;; *) host_alias=$nonopt ;; esac ;; esac host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 echo "configure:1286: checking build system type" >&5 build_alias=$build case "$build_alias" in NONE) case $nonopt in NONE) build_alias=$host_alias ;; *) build_alias=$nonopt ;; esac ;; esac build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$build" 1>&6 # Check whether --with-gnu-ld or --without-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval="$with_gnu_ld" test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 echo "configure:1315: checking for ld used by GCC" >&5 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 echo "configure:1345: checking for GNU ld" >&5 else echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 echo "configure:1348: checking for non-GNU ld" >&5 fi if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. if "$lt_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then test "$with_gnu_ld" != no && break else test "$with_gnu_ld" != yes && break fi fi done IFS="$ac_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$lt_cv_path_LD" if test -n "$LD"; then echo "$ac_t""$LD" 1>&6 else echo "$ac_t""no" 1>&6 fi test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 echo "configure:1383: checking if the linker ($LD) is GNU ld" >&5 if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then lt_cv_prog_gnu_ld=yes else lt_cv_prog_gnu_ld=no fi fi echo "$ac_t""$lt_cv_prog_gnu_ld" 1>&6 with_gnu_ld=$lt_cv_prog_gnu_ld echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6 echo "configure:1400: checking for $LD option to reload object files" >&5 if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else lt_cv_ld_reload_flag='-r' fi echo "$ac_t""$lt_cv_ld_reload_flag" 1>&6 reload_flag=$lt_cv_ld_reload_flag test -n "$reload_flag" && reload_flag=" $reload_flag" echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 echo "configure:1412: checking for BSD-compatible nm" >&5 if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/${ac_tool_prefix}nm if test -f $tmp_nm || test -f $tmp_nm$ac_exeext ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file if ($tmp_nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep '(/dev/null|Invalid file or object type)' >/dev/null; then lt_cv_path_NM="$tmp_nm -B" break elif ($tmp_nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then lt_cv_path_NM="$tmp_nm -p" break else lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags fi fi done IFS="$ac_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi NM="$lt_cv_path_NM" echo "$ac_t""$NM" 1>&6 echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6 echo "configure:1450: checking how to recognise dependant libraries" >&5 if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given egrep regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi4*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | mingw* | pw32*) lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[012]) lt_cv_file_magic_test_file=`echo /System/Library/Frameworks/System.framework/Versions/*/System | head -1` ;; *) # Darwin 1.3 on lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac ;; freebsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20*|hpux11*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux-gnu*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$' else lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv5uw[78]* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; esac ;; esac fi echo "$ac_t""$lt_cv_deplibs_check_method" 1>&6 file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method echo $ac_n "checking for object suffix""... $ac_c" 1>&6 echo "configure:1627: checking for object suffix" >&5 if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftest* echo 'int i = 1;' > conftest.$ac_ext if { (eval echo configure:1633: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then for ac_file in conftest.*; do case $ac_file in *.c) ;; *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;; esac done else { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; } fi rm -f conftest* fi echo "$ac_t""$ac_cv_objext" 1>&6 OBJEXT=$ac_cv_objext ac_objext=$ac_cv_objext echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 echo "configure:1653: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$CYGWIN" = yes || test "$MINGW32" = yes; then ac_cv_exeext=.exe else rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= if { (eval echo configure:1663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.$ac_ext | *.c | *.o | *.obj) ;; *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; esac done else { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } fi rm -f conftest* test x"${ac_cv_exeext}" = x && ac_cv_exeext=no fi fi EXEEXT="" test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} echo "$ac_t""${ac_cv_exeext}" 1>&6 ac_exeext=$EXEEXT if test $host != $build; then ac_tool_prefix=${host_alias}- else ac_tool_prefix= fi # Check for command to grab the raw symbol name followed by C symbol from nm. echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6 echo "configure:1694: checking command to parse $NM output" >&5 if eval "test \"`echo '$''{'lt_cv_sys_global_symbol_pipe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols lt_cv_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; solaris* | sysv5*) symcode='[BDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $host_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then symcode='[ABCDGISTW]' fi # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo configure:1777: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if egrep ' nm_test_var$' "$nlist" >/dev/null; then if egrep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_global_symbol_to_cdecl"' < "$nlist" >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = { EOF sed "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr) \&\2},/" < "$nlist" >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$no_builtin_flag" if { (eval echo configure:1828: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then pipe_works=yes fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi global_symbol_pipe="$lt_cv_sys_global_symbol_pipe" if test -z "$lt_cv_sys_global_symbol_pipe"; then global_symbol_to_cdecl= global_symbol_to_c_name_address= else global_symbol_to_cdecl="$lt_cv_global_symbol_to_cdecl" global_symbol_to_c_name_address="$lt_cv_global_symbol_to_c_name_address" fi if test -z "$global_symbol_pipe$global_symbol_to_cdec$global_symbol_to_c_name_address"; then echo "$ac_t""failed" 1>&6 else echo "$ac_t""ok" 1>&6 fi for ac_hdr in dlfcn.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:1877: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1887: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6 echo "configure:1922: checking for ${ac_tool_prefix}file" >&5 if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case $MAGIC_CMD in /*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; ?:/*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. ;; *) ac_save_MAGIC_CMD="$MAGIC_CMD" IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="/usr/bin:$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$ac_save_ifs" MAGIC_CMD="$ac_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$ac_t""$MAGIC_CMD" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then echo $ac_n "checking for file""... $ac_c" 1>&6 echo "configure:1984: checking for file" >&5 if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else case $MAGIC_CMD in /*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; ?:/*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a dos path. ;; *) ac_save_MAGIC_CMD="$MAGIC_CMD" IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="/usr/bin:$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$ac_save_ifs" MAGIC_CMD="$ac_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then echo "$ac_t""$MAGIC_CMD" 1>&6 else echo "$ac_t""no" 1>&6 fi else MAGIC_CMD=: fi fi fi ;; esac # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:2055: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" break fi done IFS="$ac_save_ifs" fi fi RANLIB="$ac_cv_prog_RANLIB" if test -n "$RANLIB"; then echo "$ac_t""$RANLIB" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$ac_cv_prog_RANLIB"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:2087: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_RANLIB="ranlib" break fi done IFS="$ac_save_ifs" test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" fi fi RANLIB="$ac_cv_prog_RANLIB" if test -n "$RANLIB"; then echo "$ac_t""$RANLIB" 1>&6 else echo "$ac_t""no" 1>&6 fi else RANLIB=":" fi fi # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:2122: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" break fi done IFS="$ac_save_ifs" fi fi STRIP="$ac_cv_prog_STRIP" if test -n "$STRIP"; then echo "$ac_t""$STRIP" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$ac_cv_prog_STRIP"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:2154: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_STRIP="strip" break fi done IFS="$ac_save_ifs" test -z "$ac_cv_prog_STRIP" && ac_cv_prog_STRIP=":" fi fi STRIP="$ac_cv_prog_STRIP" if test -n "$STRIP"; then echo "$ac_t""$STRIP" 1>&6 else echo "$ac_t""no" 1>&6 fi else STRIP=":" fi fi enable_dlopen=no enable_win32_dll=no # Check whether --enable-libtool-lock or --disable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval="$enable_libtool_lock" : fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in *-*-irix6*) # Find out which ABI we are using. echo '#line 2203 "configure"' > conftest.$ac_ext if { (eval echo configure:2204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 echo "configure:2225: checking whether the C compiler needs -belf" >&5 if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* lt_cv_cc_needs_belf=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* lt_cv_cc_needs_belf=no fi rm -f conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross fi echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" need_locks="$enable_libtool_lock" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o if test x"$host" != x"$build"; then ac_tool_prefix=${host_alias}- else ac_tool_prefix= fi # Transform linux* to *-*-linux-gnu*, to support old configure scripts. case $host_os in linux-gnu*) ;; linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` esac case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Allow CC to be a program name with arguments. set dummy $CC compiler="$2" ## FIXME: this should be a separate macro ## echo $ac_n "checking for objdir""... $ac_c" 1>&6 echo "configure:2367: checking for objdir" >&5 rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. objdir=_libs fi rmdir .libs 2>/dev/null echo "$ac_t""$objdir" 1>&6 ## ## END FIXME ## FIXME: this should be a separate macro ## # Check whether --with-pic or --without-pic was given. if test "${with_pic+set}" = set; then withval="$with_pic" pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # We assume here that the value for lt_cv_prog_cc_pic will not be cached # in isolation, and that seeing it set (from the cache) indicates that # the associated values are set (in the cache) correctly too. echo $ac_n "checking for $compiler option to produce PIC""... $ac_c" 1>&6 echo "configure:2398: checking for $compiler option to produce PIC" >&5 if eval "test \"`echo '$''{'lt_cv_prog_cc_pic'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else lt_cv_prog_cc_pic= lt_cv_prog_cc_shlib= lt_cv_prog_cc_wl= lt_cv_prog_cc_static= lt_cv_prog_cc_no_builtin= lt_cv_prog_cc_can_build_shared=$can_build_shared if test "$GCC" = yes; then lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-static' case $host_os in aix*) # Below there is a dirty hack to force normal static linking with -ldl # The problem is because libdl dynamically linked with both libc and # libC (AIX C++ library), which obviously doesn't included in libraries # list by gcc. This cause undefined symbols with -static flags. # This hack allows C programs to be linked with "-static -ldl", but # not sure about C++ programs. lt_cv_prog_cc_static="$lt_cv_prog_cc_static ${lt_cv_prog_cc_wl}-lC" ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_cv_prog_cc_pic='-fno-common' ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; sysv4*MP*) if test -d /usr/nec; then lt_cv_prog_cc_pic=-Kconform_pic fi ;; *) lt_cv_prog_cc_pic='-fPIC' ;; esac else # PORTME Check for PIC flags for the system compiler. case $host_os in aix3* | aix4* | aix5*) lt_cv_prog_cc_wl='-Wl,' # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_cv_prog_cc_static='-Bstatic' else lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp' fi ;; hpux9* | hpux10* | hpux11*) # Is there a better lt_cv_prog_cc_static that works with the bundled CC? lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static="${lt_cv_prog_cc_wl}-a ${lt_cv_prog_cc_wl}archive" lt_cv_prog_cc_pic='+Z' ;; irix5* | irix6* | nonstopux*) lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' # PIC (with -KPIC) is the default. ;; cygwin* | mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_cv_prog_cc_pic='-DDLL_EXPORT' ;; newsos6) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' ;; osf3* | osf4* | osf5*) # All OSF/1 code is PIC. lt_cv_prog_cc_wl='-Wl,' lt_cv_prog_cc_static='-non_shared' ;; sco3.2v5*) lt_cv_prog_cc_pic='-Kpic' lt_cv_prog_cc_static='-dn' lt_cv_prog_cc_shlib='-belf' ;; solaris*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Wl,' ;; sunos4*) lt_cv_prog_cc_pic='-PIC' lt_cv_prog_cc_static='-Bstatic' lt_cv_prog_cc_wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_cv_prog_cc_pic='-KPIC' lt_cv_prog_cc_static='-Bstatic' if test "x$host_vendor" = xsni; then lt_cv_prog_cc_wl='-LD' else lt_cv_prog_cc_wl='-Wl,' fi ;; uts4*) lt_cv_prog_cc_pic='-pic' lt_cv_prog_cc_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_cv_prog_cc_pic='-Kconform_pic' lt_cv_prog_cc_static='-Bstatic' fi ;; *) lt_cv_prog_cc_can_build_shared=no ;; esac fi fi if test -z "$lt_cv_prog_cc_pic"; then echo "$ac_t""none" 1>&6 else echo "$ac_t""$lt_cv_prog_cc_pic" 1>&6 # Check to make sure the pic_flag actually works. echo $ac_n "checking if $compiler PIC flag $lt_cv_prog_cc_pic works""... $ac_c" 1>&6 echo "configure:2550: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5 if eval "test \"`echo '$''{'lt_cv_prog_cc_pic_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC" cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* case $host_os in hpux9* | hpux10* | hpux11*) # On HP-UX, both CC and GCC only warn that PIC is supported... then # they create non-PIC objects. So, if there were any warnings, we # assume that PIC is not supported. if test -s conftest.err; then lt_cv_prog_cc_pic_works=no else lt_cv_prog_cc_pic_works=yes fi ;; *) lt_cv_prog_cc_pic_works=yes ;; esac else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* lt_cv_prog_cc_pic_works=no fi rm -f conftest* CFLAGS="$save_CFLAGS" fi if test "X$lt_cv_prog_cc_pic_works" = Xno; then lt_cv_prog_cc_pic= lt_cv_prog_cc_can_build_shared=no else lt_cv_prog_cc_pic=" $lt_cv_prog_cc_pic" fi echo "$ac_t""$lt_cv_prog_cc_pic_works" 1>&6 fi ## ## END FIXME # Check for any special shared library compilation flags. if test -n "$lt_cv_prog_cc_shlib"; then echo "configure: warning: \`$CC' requires \`$lt_cv_prog_cc_shlib' to build shared libraries" 1>&2 if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$lt_cv_prog_cc_shlib[ ]" >/dev/null; then : else echo "configure: warning: add \`$lt_cv_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" 1>&2 lt_cv_prog_cc_can_build_shared=no fi fi ## FIXME: this should be a separate macro ## echo $ac_n "checking if $compiler static flag $lt_cv_prog_cc_static works""... $ac_c" 1>&6 echo "configure:2620: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5 if eval "test \"`echo '$''{'lt_cv_prog_cc_static_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else lt_cv_prog_cc_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* lt_cv_prog_cc_static_works=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* LDFLAGS="$save_LDFLAGS" fi # Belt *and* braces to stop my trousers falling down: test "X$lt_cv_prog_cc_static_works" = Xno && lt_cv_prog_cc_static= echo "$ac_t""$lt_cv_prog_cc_static_works" 1>&6 pic_flag="$lt_cv_prog_cc_pic" special_shlib_compile_flags="$lt_cv_prog_cc_shlib" wl="$lt_cv_prog_cc_wl" link_static_flag="$lt_cv_prog_cc_static" no_builtin_flag="$lt_cv_prog_cc_no_builtin" can_build_shared="$lt_cv_prog_cc_can_build_shared" ## ## END FIXME ## FIXME: this should be a separate macro ## # Check to see if options -o and -c are simultaneously supported by compiler echo $ac_n "checking if $compiler supports -c -o file.$ac_objext""... $ac_c" 1>&6 echo "configure:2666: checking if $compiler supports -c -o file.$ac_objext" >&5 if eval "test \"`echo '$''{'lt_cv_compiler_c_o'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else $rm -r conftest 2>/dev/null mkdir conftest cd conftest echo "int some_variable = 0;" > conftest.$ac_ext mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no if { (eval echo configure:2685: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then lt_cv_compiler_c_o=no else lt_cv_compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&5 lt_cv_compiler_c_o=no fi CFLAGS="$save_CFLAGS" chmod u+w . $rm conftest* out/* rmdir out cd .. rmdir conftest $rm -r conftest 2>/dev/null fi compiler_c_o=$lt_cv_compiler_c_o echo "$ac_t""$compiler_c_o" 1>&6 if test x"$compiler_c_o" = x"yes"; then # Check to see if we can write to a .lo echo $ac_n "checking if $compiler supports -c -o file.lo""... $ac_c" 1>&6 echo "configure:2714: checking if $compiler supports -c -o file.lo" >&5 if eval "test \"`echo '$''{'lt_cv_compiler_o_lo'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else lt_cv_compiler_o_lo=no save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -c -o conftest.lo" save_objext="$ac_objext" ac_objext=lo cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then lt_cv_compiler_o_lo=no else lt_cv_compiler_o_lo=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* ac_objext="$save_objext" CFLAGS="$save_CFLAGS" fi compiler_o_lo=$lt_cv_compiler_o_lo echo "$ac_t""$compiler_o_lo" 1>&6 else compiler_o_lo=no fi ## ## END FIXME ## FIXME: this should be a separate macro ## # Check to see if we can do hard links to lock some files if needed hard_links="nottested" if test "$compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo $ac_n "checking if we can lock with hard links""... $ac_c" 1>&6 echo "configure:2767: checking if we can lock with hard links" >&5 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$ac_t""$hard_links" 1>&6 if test "$hard_links" = no; then echo "configure: warning: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" 1>&2 need_locks=warn fi else need_locks=no fi ## ## END FIXME ## FIXME: this should be a separate macro ## if test "$GCC" = yes; then # Check to see if options -fno-rtti -fno-exceptions are supported by compiler echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions""... $ac_c" 1>&6 echo "configure:2790: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 echo "int some_variable = 0;" > conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext" compiler_rtti_exceptions=no cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then compiler_rtti_exceptions=no else compiler_rtti_exceptions=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* CFLAGS="$save_CFLAGS" echo "$ac_t""$compiler_rtti_exceptions" 1>&6 if test "$compiler_rtti_exceptions" = "yes"; then no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' else no_builtin_flag=' -fno-builtin' fi fi ## ## END FIXME ## FIXME: this should be a separate macro ## # See if the linker supports building shared libraries. echo $ac_n "checking whether the linker ($LD) supports shared libraries""... $ac_c" 1>&6 echo "configure:2834: checking whether the linker ($LD) supports shared libraries" >&5 allow_undefined_flag= no_undefined_flag= need_lib_prefix=unknown need_version=unknown # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments archive_cmds= archive_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_into_libs=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported runpath_var= link_all_deplibs=unknown always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an egrep regular expression of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX, the GNU linker is very broken # Note:Check GNU linker on AIX 5-IA64 when/if it becomes available. ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=yes extract_expsyms_cmds='test -f $output_objdir/impgen.c || \ sed -e "/^# \/\* impgen\.c starts here \*\//,/^# \/\* impgen.c ends here \*\// { s/^# //;s/^# *$//; p; }" -e d < $''0 > $output_objdir/impgen.c~ test -f $output_objdir/impgen.exe || (cd $output_objdir && \ if test "x$HOST_CC" != "x" ; then $HOST_CC -o impgen impgen.c ; \ else $CC -o impgen impgen.c ; fi)~ $output_objdir/impgen $dir/$soroot > $output_objdir/$soname-def' old_archive_from_expsyms_cmds='$DLLTOOL --as=$AS --dllname $soname --def $output_objdir/$soname-def --output-lib $output_objdir/$newlib' # cygwin and mingw dlls have different entry points and sets of symbols # to exclude. # FIXME: what about values for MSVC? dll_entry=__cygwin_dll_entry@12 dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12~ case $host_os in mingw*) # mingw values dll_entry=_DllMainCRTStartup@12 dll_exclude_symbols=DllMain@12,DllMainCRTStartup@12,DllEntryPoint@12~ ;; esac # mingw and cygwin differ, and it's simplest to just exclude the union # of the two symbol sets. dll_exclude_symbols=DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12,DllMainCRTStartup@12,DllEntryPoint@12 # recent cygwin and mingw systems supply a stub DllMain which the user # can override, but on older systems we have to supply one (in ltdll.c) if test "x$lt_cv_need_dllmain" = "xyes"; then ltdll_obj='$output_objdir/$soname-ltdll.'"$ac_objext " ltdll_cmds='test -f $output_objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $''0 > $output_objdir/$soname-ltdll.c~ test -f $output_objdir/$soname-ltdll.$ac_objext || (cd $output_objdir && $CC -c $soname-ltdll.c)~' else ltdll_obj= ltdll_cmds= fi # Extract the symbol export list from an `--export-all' def file, # then regenerate the def file from the symbol export list, so that # the compiled dll only exports the symbol export list. # Be careful not to strip the DATA tag left be newer dlltools. export_symbols_cmds="$ltdll_cmds"' $DLLTOOL --export-all --exclude-symbols '$dll_exclude_symbols' --output-def $output_objdir/$soname-def '$ltdll_obj'$libobjs $convenience~ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $output_objdir/$soname-def > $export_symbols' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is. # If DATA tags from a recent dlltool are present, honour them! archive_expsym_cmds='if test "x`head -1 $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname-def; else echo EXPORTS > $output_objdir/$soname-def; _lt_hint=1; cat $export_symbols | while read symbol; do set dummy \$symbol; case \$# in 2) echo " \$2 @ \$_lt_hint ; " >> $output_objdir/$soname-def;; *) echo " \$2 @ \$_lt_hint \$3 ; " >> $output_objdir/$soname-def;; esac; _lt_hint=`expr 1 + \$_lt_hint`; done; fi~ '"$ltdll_cmds"' $CC -Wl,--base-file,$output_objdir/$soname-base '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp~ $CC -Wl,--base-file,$output_objdir/$soname-base $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols '$dll_exclude_symbols' --def $output_objdir/$soname-def --base-file $output_objdir/$soname-base --output-exp $output_objdir/$soname-exp --output-lib $output_objdir/$libname.dll.a~ $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags' ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared -nodefaultlibs $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' case $host_os in cygwin* | mingw* | pw32*) # dlltool doesn't understand --whole-archive et. al. whole_archive_flag_spec= ;; *) # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi ;; esac fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. hardcode_direct=yes archive_cmds='' hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then shared_flag='${wl}-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall can do strange things, so it is better to # generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:/usr/lib:/lib' archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname ${wl}-h$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else hardcode_libdir_flag_spec='${wl}-bnolibpath ${wl}-blibpath:$libdir:/usr/lib:/lib' # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. allow_undefined_flag='${wl}-berok' # This is a bit strange, but is similar to how AIX traditionally builds # it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"' ~$AR -crlo $objdir/$libname$release.a $objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' ;; darwin* | rhapsody*) case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on allow_undefined_flag='-flat_namespace -undefined suppress' ;; esac # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. Also zsh mangles # `"' quotes if we put them in here... so don't! archive_cmds='$nonopt $(test .$module = .yes && echo -bundle || echo -dynamiclib) $allow_undefined_flag -o $lib $libobjs $deplibs$linker_flags -install_name $rpath/$soname $verstring' # We need to add '_' to the symbols in $export_symbols first #archive_expsym_cmds="$archive_cmds"' && strip -s $export_symbols' hardcode_direct=yes hardcode_shlibpath_var=no whole_archive_flag_spec='-all_load $convenience' ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9* | hpux10* | hpux11*) case $host_os in hpux9*) archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. export_dynamic_flag_spec='${wl}-E' ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "-exported_symbol " >> $lib.exp; echo "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' #Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes export_dynamic_flag_spec='${wl}-Bexport' ;; solaris*) # gcc --version < 3.0 without binutils cannot create self contained # shared libraries reliably, requiring libgcc.a to resolve some of # the object symbols generated in some cases. Libraries that use # assert need libgcc.a to resolve __eprintf, for example. Linking # a copy of libgcc.a into every shared library to guarantee resolving # such symbols causes other problems: According to Tim Van Holder # , C++ libraries end up with a separate # (to the application) exception stack for one thing. no_undefined_flag=' -z defs' if test "$GCC" = yes; then case `$CC --version 2>/dev/null` in [12].*) cat <&2 *** Warning: Releases of GCC earlier than version 3.0 cannot reliably *** create self contained shared libraries on Solaris systems, without *** introducing a dependency on libgcc.a. Therefore, libtool is disabling *** -no-undefined support, which will at least allow you to build shared *** libraries. However, you may find that when you link such libraries *** into an application without using GCC, you have to manually add *** \`gcc --print-libgcc-file-name\` to the link command. We urge you to *** upgrade to a newer version of GCC. Another option is to rebuild your *** current GCC to use the GNU linker from GNU binutils 2.9.1 or newer. EOF no_undefined_flag= ;; esac fi # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) if test "x$host_vendor" = xsno; then archive_cmds='$LD -G -Bsymbolic -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? else archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5uw7* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi echo "$ac_t""$ld_shlibs" 1>&6 test "$ld_shlibs" = no && can_build_shared=no ## ## END FIXME ## FIXME: this should be a separate macro ## # Check hardcoding attributes. echo $ac_n "checking how to hardcode library paths into programs""... $ac_c" 1>&6 echo "configure:3523: checking how to hardcode library paths into programs" >&5 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var"; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$hardcode_shlibpath_var" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi echo "$ac_t""$hardcode_action" 1>&6 ## ## END FIXME ## FIXME: this should be a separate macro ## striplib= old_striplib= echo $ac_n "checking whether stripping libraries is possible""... $ac_c" 1>&6 echo "configure:3555: checking whether stripping libraries is possible" >&5 if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi ## ## END FIXME reload_cmds='$LD$reload_flag -o $output$reload_objs' test -z "$deplibs_check_method" && deplibs_check_method=unknown ## FIXME: this should be a separate macro ## # PORTME Fill in your ld.so characteristics echo $ac_n "checking dynamic linker characteristics""... $ac_c" 1>&6 echo "configure:3573: checking dynamic linker characteristics" >&5 library_names_spec= libname_spec='lib$name' soname_spec= postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}.so$versuffix $libname.a' shlibpath_var=LIBPATH # AIX has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}.so$major' ;; aix4* | aix5*) version_type=linux if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}.so$major ${libname}${release}.so$versuffix $libname.so' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can # not hardcode correct soname into executable. Probably we can # add versioning support to collect2, so additional links can # be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}.so$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' ;; beos*) library_names_spec='${libname}.so' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" export_dynamic_flag_spec=-rdynamic # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin*) library_names_spec='$libname.dll.a' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' postinstall_cmds='dlpath=`bash 2>&1 -c '\''. $dir/${file}i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog .libs/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`bash 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' ;; yes,mingw*) library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | sed -e "s/^libraries://" -e "s/;/ /g"` ;; yes,pw32*) library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | sed -e 's/./-/g'`${versuffix}.dll' ;; *) library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no # FIXME: Relying on posixy $() will cause problems for # cross-compilation, but unfortunately the echo tests do not # yet detect zsh echo's removal of \ escapes. library_names_spec='${libname}${release}${versuffix}.$(test .$module = .yes && echo so || echo dylib) ${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib) ${libname}.$(test .$module = .yes && echo so || echo dylib)' soname_spec='${libname}${release}${major}.$(test .$module = .yes && echo so || echo dylib)' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; *) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. dynamic_linker="$host_os dld.sl" version_type=sunos need_lib_prefix=no need_version=no shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' soname_spec='${libname}${release}.sl$major' # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) version_type=irix ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so $libname.so' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" ;; # No shared lib support for Linux oldld, aout, or coff. linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) dynamic_linker=no ;; # This must be Linux ELF. linux-gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' soname_spec='${libname}${release}.so$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case "$host_os" in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH ;; os2*) libname_spec='$name' need_lib_prefix=no library_names_spec='$libname.dll $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_version=no need_lib_prefix=no soname_spec='${libname}${release}.so' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; uts4*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' soname_spec='$libname.so.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; *) dynamic_linker=no ;; esac echo "$ac_t""$dynamic_linker" 1>&6 test "$dynamic_linker" = no && can_build_shared=no ## ## END FIXME ## FIXME: this should be a separate macro ## # Report the final consequences. echo $ac_n "checking if libtool supports shared libraries""... $ac_c" 1>&6 echo "configure:3978: checking if libtool supports shared libraries" >&5 echo "$ac_t""$can_build_shared" 1>&6 ## ## END FIXME ## FIXME: this should be a separate macro ## echo $ac_n "checking whether to build shared libraries""... $ac_c" 1>&6 echo "configure:3986: checking whether to build shared libraries" >&5 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac echo "$ac_t""$enable_shared" 1>&6 ## ## END FIXME ## FIXME: this should be a separate macro ## echo $ac_n "checking whether to build static libraries""... $ac_c" 1>&6 echo "configure:4013: checking whether to build static libraries" >&5 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "$ac_t""$enable_static" 1>&6 ## ## END FIXME if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; cygwin* | mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; *) echo $ac_n "checking for shl_load""... $ac_c" 1>&6 echo "configure:4056: checking for shl_load" >&5 if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char shl_load(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shl_load) || defined (__stub___shl_load) choke me #else shl_load(); #endif ; return 0; } EOF if { (eval echo configure:4084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_shl_load=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_shl_load=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="shl_load" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 echo "configure:4102: checking for shl_load in -ldld" >&5 ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldld $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen""... $ac_c" 1>&6 echo "configure:4140: checking for dlopen" >&5 if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char dlopen(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else dlopen(); #endif ; return 0; } EOF if { (eval echo configure:4168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_dlopen=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_dlopen=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 echo "configure:4186: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6 echo "configure:4224: checking for dlopen in -lsvld" >&5 ac_lib_var=`echo svld'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsvld $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 echo "configure:4262: checking for dld_link in -ldld" >&5 ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldld $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" else echo "$ac_t""no" 1>&6 fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 echo "configure:4337: checking whether a program can dlopen itself" >&5 if eval "test \"`echo '$''{'lt_cv_dlopen_self'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { (eval echo configure:4408: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi echo "$ac_t""$lt_cv_dlopen_self" 1>&6 if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 echo "configure:4431: checking whether a statically linked program can dlopen itself" >&5 if eval "test \"`echo '$''{'lt_cv_dlopen_self_static'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { (eval echo configure:4502: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi ## FIXME: this should be a separate macro ## if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. echo $ac_n "checking whether -lc should be explicitly linked in""... $ac_c" 1>&6 echo "configure:4553: checking whether -lc should be explicitly linked in" >&5 if eval "test \"`echo '$''{'lt_cv_archive_cmds_need_lc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else $rm conftest* echo 'static int dummy;' > conftest.$ac_ext if { (eval echo configure:4560: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_cv_prog_cc_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo configure:4573: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\") 1>&5; (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$save_allow_undefined_flag else cat conftest.err 1>&5 fi fi echo "$ac_t""$lt_cv_archive_cmds_need_lc" 1>&6 ;; esac fi need_lc=${lt_cv_archive_cmds_need_lc-yes} ## ## END FIXME ## FIXME: this should be a separate macro ## # The second clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then : else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi if test -f "$ltmain"; then trap "$rm \"${ofile}T\"; exit 1" 1 2 15 $rm -f "${ofile}T" echo creating $ofile # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS \ AR AR_FLAGS CC LD LN_S NM SHELL \ reload_flag reload_cmds wl \ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ thread_safe_flag_spec whole_archive_flag_spec libname_spec \ library_names_spec soname_spec \ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds \ postuninstall_cmds extract_expsyms_cmds old_archive_from_expsyms_cmds \ old_striplib striplib file_magic_cmd export_symbols_cmds \ deplibs_check_method allow_undefined_flag no_undefined_flag \ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ global_symbol_to_c_name_address \ hardcode_libdir_flag_spec hardcode_libdir_separator \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do case $var in reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ extract_expsyms_cmds | old_archive_from_expsyms_cmds | \ postinstall_cmds | postuninstall_cmds | \ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done cat <<__EOF__ > "${ofile}T" #! $SHELL # `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996-2000 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="sed -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$need_lc # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # The default C compiler. CC=$lt_CC # Is the compiler the GNU C compiler? with_gcc=$GCC # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP=$STRIP # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_pic_flag pic_mode=$pic_mode # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_compiler_c_o # Can we write directly to a .lo ? compiler_o_lo=$lt_compiler_o_lo # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_link_static_flag # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "${ofile}T" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac case $host_os in cygwin* | mingw* | pw32* | os2*) cat <<'EOF' >> "${ofile}T" # This is a source program that is used to create dlls on Windows # Don't remove nor modify the starting and closing comments # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ # This is a source program that is used to create import libraries # on Windows for dlls which lack them. Don't remove nor modify the # starting and closing comments # /* impgen.c starts here */ # /* Copyright (C) 1999-2000 Free Software Foundation, Inc. # # This file is part of GNU libtool. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # */ # # #include /* for printf() */ # #include /* for open(), lseek(), read() */ # #include /* for O_RDONLY, O_BINARY */ # #include /* for strdup() */ # # /* O_BINARY isn't required (or even defined sometimes) under Unix */ # #ifndef O_BINARY # #define O_BINARY 0 # #endif # # static unsigned int # pe_get16 (fd, offset) # int fd; # int offset; # { # unsigned char b[2]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 2); # return b[0] + (b[1]<<8); # } # # static unsigned int # pe_get32 (fd, offset) # int fd; # int offset; # { # unsigned char b[4]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 4); # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # static unsigned int # pe_as32 (ptr) # void *ptr; # { # unsigned char *b = ptr; # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # int # main (argc, argv) # int argc; # char *argv[]; # { # int dll; # unsigned long pe_header_offset, opthdr_ofs, num_entries, i; # unsigned long export_rva, export_size, nsections, secptr, expptr; # unsigned long name_rvas, nexp; # unsigned char *expdata, *erva; # char *filename, *dll_name; # # filename = argv[1]; # # dll = open(filename, O_RDONLY|O_BINARY); # if (dll < 1) # return 1; # # dll_name = filename; # # for (i=0; filename[i]; i++) # if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') # dll_name = filename + i +1; # # pe_header_offset = pe_get32 (dll, 0x3c); # opthdr_ofs = pe_header_offset + 4 + 20; # num_entries = pe_get32 (dll, opthdr_ofs + 92); # # if (num_entries < 1) /* no exports */ # return 1; # # export_rva = pe_get32 (dll, opthdr_ofs + 96); # export_size = pe_get32 (dll, opthdr_ofs + 100); # nsections = pe_get16 (dll, pe_header_offset + 4 +2); # secptr = (pe_header_offset + 4 + 20 + # pe_get16 (dll, pe_header_offset + 4 + 16)); # # expptr = 0; # for (i = 0; i < nsections; i++) # { # char sname[8]; # unsigned long secptr1 = secptr + 40 * i; # unsigned long vaddr = pe_get32 (dll, secptr1 + 12); # unsigned long vsize = pe_get32 (dll, secptr1 + 16); # unsigned long fptr = pe_get32 (dll, secptr1 + 20); # lseek(dll, secptr1, SEEK_SET); # read(dll, sname, 8); # if (vaddr <= export_rva && vaddr+vsize > export_rva) # { # expptr = fptr + (export_rva - vaddr); # if (export_rva + export_size > vaddr + vsize) # export_size = vsize - (export_rva - vaddr); # break; # } # } # # expdata = (unsigned char*)malloc(export_size); # lseek (dll, expptr, SEEK_SET); # read (dll, expdata, export_size); # erva = expdata - export_rva; # # nexp = pe_as32 (expdata+24); # name_rvas = pe_as32 (expdata+32); # # printf ("EXPORTS\n"); # for (i = 0; i> "${ofile}T" || (rm -f "${ofile}T"; exit 1) mv -f "${ofile}T" "$ofile" || \ (rm -f "$ofile" && cp "${ofile}T" "$ofile" && rm -f "${ofile}T") chmod +x "$ofile" fi ## ## END FIXME # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 echo "configure:5163: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:5176: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "memchr" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "free" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF if { (eval echo configure:5243: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_header_stdc=no fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF #define STDC_HEADERS 1 EOF fi for ac_hdr in fcntl.h unistd.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "configure:5270: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:5280: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` cat >> confdefs.h <&6 fi done echo $ac_n "checking for working const""... $ac_c" 1>&6 echo "configure:5308: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } ; return 0; } EOF if { (eval echo configure:5362: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_c_const" 1>&6 if test $ac_cv_c_const = no; then cat >> confdefs.h <<\EOF #define const EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 echo "configure:5383: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else rm -rf conftest* ac_cv_type_size_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_size_t" 1>&6 if test $ac_cv_type_size_t = no; then cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi LIBTOOL=./libtool LIBSUFFIX=la # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" if test "$enableval" = "no"; then LIBTOOL= LIBSUFFIX=a fi fi # JK: as the install/uninstall stuff is not yet ready, I am forcing the # unshared lib by default LIBTOOL= LIBSUFFIX=a trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 DEFS=-DHAVE_CONFIG_H # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo "Makefile config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@CC@%$CC%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@LN_S@%$LN_S%g s%@host@%$host%g s%@host_alias@%$host_alias%g s%@host_cpu@%$host_cpu%g s%@host_vendor@%$host_vendor%g s%@host_os@%$host_os%g s%@build@%$build%g s%@build_alias@%$build_alias%g s%@build_cpu@%$build_cpu%g s%@build_vendor@%$build_vendor%g s%@build_os@%$build_os%g s%@OBJEXT@%$OBJEXT%g s%@EXEEXT@%$EXEEXT%g s%@ECHO@%$ECHO%g s%@RANLIB@%$RANLIB%g s%@STRIP@%$STRIP%g s%@CPP@%$CPP%g s%@LIBTOOL@%$LIBTOOL%g s%@LIBSUFFIX@%$LIBSUFFIX%g s%@FNV_MAJOR@%$FNV_MAJOR%g s%@FNV_MINOR@%$FNV_MINOR%g s%@FNV_DATE@%$FNV_DATE%g s%@FNV_VERSION@%$FNV_VERSION%g s%@FNV_LIB_VERSION@%$FNV_LIB_VERSION%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac case "$ac_given_INSTALL" in [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' ac_dC='\3' ac_dD='%g' # ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='\([ ]\)%\1#\2define\3' ac_uC=' ' ac_uD='\4%g' # ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' if test "${CONFIG_HEADERS+set}" != set; then EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac echo creating $ac_file rm -f conftest.frag conftest.in conftest.out ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` cat $ac_file_inputs > conftest.in EOF # Transform confdefs.h into a sed script conftest.vals that substitutes # the proper values into config.h.in to produce config.h. And first: # Protect against being on the right side of a sed subst in config.status. # Protect against being in an unquoted here document in config.status. rm -f conftest.vals cat > conftest.hdr <<\EOF s/[\\&%]/\\&/g s%[\\$`]%\\&%g s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp s%ac_d%ac_u%gp s%ac_u%ac_e%gp EOF sed -n -f conftest.hdr confdefs.h > conftest.vals rm -f conftest.hdr # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >> conftest.vals <<\EOF s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. rm -f conftest.tail while : do ac_lines=`grep -c . conftest.vals` # grep -c gives empty output for an empty file on some AIX systems. if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi # Write a limited-size here document to conftest.frag. echo ' cat > conftest.frag <> $CONFIG_STATUS sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS echo 'CEOF sed -f conftest.frag conftest.in > conftest.out rm -f conftest.in mv conftest.out conftest.in ' >> $CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail rm -f conftest.vals mv conftest.tail conftest.vals done rm -f conftest.vals cat >> $CONFIG_STATUS <<\EOF rm -f conftest.frag conftest.h echo "/* $ac_file. Generated automatically by configure. */" > conftest.h cat conftest.in >> conftest.h rm -f conftest.in if cmp -s $ac_file conftest.h 2>/dev/null; then echo "$ac_file is unchanged" rm -f conftest.h else # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi rm -f $ac_file mv conftest.h $ac_file fi fi; done EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 ================================================ FILE: src/fnv/configure.in ================================================ dnl Process this file with autoconf to produce a configure script. AC_INIT(fnv.h) dnl Arrange to build config.h from config.in. dnl Manual says this macro should come right after AC_INIT. AC_CONFIG_HEADER(config.h:config.in) dnl Provide the current FNV version information. Do not use numbers dnl with leading zeros for the minor version, as they end up in a C dnl macro, and may be treated as octal constants. Stick to single dnl digits for minor numbers less than 10. There are unlikely to be dnl that many releases anyway. dnl JK: As there was no such release number, I gave it 1.0 and the dnl date of last commit of the Makefile FNV_MAJOR=1 FNV_MINOR=0 FNV_DATE=09-Sep-2002 FNV_VERSION=${FNV_MAJOR}.${FNV_MINOR} dnl Provide versioning information for libtool shared libraries that dnl are built by default on Unix systems. FNV_LIB_VERSION=0:1:0 dnl Checks for programs. AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_LIBTOOL dnl Checks for libraries. dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h unistd.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T dnl Handle --enable-shared-libraries LIBTOOL=./libtool LIBSUFFIX=la AC_ARG_ENABLE(shared, [ --enable-shared build FNV as a shared library], if test "$enableval" = "no"; then LIBTOOL= LIBSUFFIX=a fi ) # JK: as the install/uninstall stuff is not yet ready, I am forcing the # unshared lib by default LIBTOOL= LIBSUFFIX=a dnl Checks for library functions. dnl "Export" these variables AC_SUBST(LIBTOOL) AC_SUBST(LIBSUFFIX) AC_SUBST(FNV_MAJOR) AC_SUBST(FNV_MINOR) AC_SUBST(FNV_DATE) AC_SUBST(FNV_VERSION) AC_SUBST(FNV_LIB_VERSION) AC_OUTPUT(Makefile) ================================================ FILE: src/fnv/configure.scan ================================================ dnl Process this file with autoconf to produce a configure script. AC_INIT(fnv.h) dnl Checks for programs. AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_RANLIB dnl Checks for libraries. dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h unistd.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T dnl Checks for library functions. AC_OUTPUT(Makefile) ================================================ FILE: src/fnv/fnv.h ================================================ /* * fnv - Fowler/Noll/Vo- hash code * * @(#) $Revision$ * @(#) $Id$ * @(#) $Source$ * *** * * Fowler/Noll/Vo- hash * * The basis of this hash algorithm was taken from an idea sent * as reviewer comments to the IEEE POSIX P1003.2 committee by: * * Phong Vo (http://www.research.att.com/info/kpv/) * Glenn Fowler (http://www.research.att.com/~gsf/) * * In a subsequent ballot round: * * Landon Curt Noll (http://www.isthe.com/chongo/) * * improved on their algorithm. Some people tried this hash * and found that it worked rather well. In an EMail message * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. * * FNV hashes are designed to be fast while maintaining a low * collision rate. The FNV speed allows one to quickly hash lots * of data while maintaining a reasonable collision rate. See: * * http://www.isthe.com/chongo/tech/comp/fnv/index.html * * for more details as well as other forms of the FNV hash. * *** * * NOTE: The FNV-0 historic hash is not recommended. One should use * the FNV-1 hash instead. * * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). * * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). * * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). * * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). * *** * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ #if !defined(__FNV_H__) #define __FNV_H__ #include "config.h" /* * 32 bit FNV-0 hash type */ typedef unsigned long Fnv32_t; /* * 32 bit FNV-0 zero initial basis * * This historic hash is not recommended. One should use * the FNV-1 hash and initial basis instead. */ #define FNV0_32_INIT ((Fnv32_t)0) /* * 32 bit FNV-1 non-zero initial basis * * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets: * * chongo /\../\ * * Note that the \'s above are not back-slashing escape characters. * They are literal ASCII backslash 0x5c characters. */ #define FNV1_32_INIT ((Fnv32_t)0x811c9dc5) /* * determine how 64 bit unsigned values are represented */ #include "longlong.h" /* * 64 bit FNV-0 hash */ #if defined(HAVE_64BIT_LONG_LONG) typedef unsigned long long Fnv64_t; #else typedef struct { unsigned long w32[2]; } Fnv64_t; #endif /* * 64 bit FNV-0 zero initial basis * * This historic hash is not recommended. One should use * the FNV-1 hash and initial basis instead. */ #if defined(HAVE_64BIT_LONG_LONG) #define FNV0_64_INIT ((Fnv64_t)0) #else extern const Fnv64_t fnv1_64_init; #define FNV0_64_INIT (fnv1_64_init) #endif /* * 64 bit FNV-1 non-zero initial basis * * The FNV-1 initial basis is the FNV-0 hash of the following 32 octets: * * chongo /\../\ * * Note that the \'s above are not back-slashing escape characters. * They are literal ASCII backslash 0x5c characters. */ #if defined(HAVE_64BIT_LONG_LONG) #define FNV1_64_INIT ((Fnv64_t)0xcbf29ce484222325ULL) #else extern const Fnv64_t fnv1_64_init; #define FNV1_64_INIT (fnv1_64_init) #endif /* * external functions */ extern Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hashval); extern Fnv32_t fnv_32_str(char *buf, Fnv32_t hashval); extern Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hashval); extern Fnv64_t fnv_64_str(char *buf, Fnv64_t hashval); #endif /* __FNV_H__ */ ================================================ FILE: src/fnv/fnv32.c ================================================ /* * fnv32 - 32 bit Fowler/Noll/Vo hash of a buffer or string * * @(#) $Revision$ * @(#) $Id$ * @(#) $Source$ * *** * * usage: * fnv032 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * fnv0_32 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * * fnv132 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * fnv1_32 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * * -b bcnt mask off all but the lower bcnt bits (default 32) * -m multiple hashes, one per line for each arg * -s hash arg as a string (ignoring terminating NUL bytes) * -v verbose mode, print arg after hash (implies -m) * arg string (if -s was given) or filename (default stdin) * * The fnv032 and fnv0_32 basenames perform the 32 bit FNV-0 historic hash. * The fnv132 and fnv1_32 basenames perform the 32 bit recommended FNV-1 hash. * * NOTE: The FNV-0 historic hash is not recommended. * One should use the FNV-1 hash instead. * *** * * Fowler/Noll/Vo hash * * The basis of this hash algorithm was taken from an idea sent * as reviewer comments to the IEEE POSIX P1003.2 committee by: * * Phong Vo (http://www.research.att.com/info/kpv/) * Glenn Fowler (http://www.research.att.com/~gsf/) * * In a subsequent ballot round: * * Landon Curt Noll (http://www.isthe.com/chongo/) * * improved on their algorithm. Some people tried this hash * and found that it worked rather well. In an EMail message * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. * * FNV hashes are designed to be fast while maintaining a low * collision rate. The FNV speed allows one to quickly hash lots * of data while maintaining a reasonable collision rate. See: * * http://www.isthe.com/chongo/tech/comp/fnv/index.html * * for more details as well as other forms of the FNV hash. * *** * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ #include #include #include #include #include #include #include "fnv.h" #ifdef HAVE_FCNTL_H #include #endif #define WIDTH 32 /* bit width of hash */ #define BUF_SIZE (32*1024) /* number of bytes to hash at a time */ static char *usage = "usage: %s [-b bcnt] [-m [-v]] [-s arg] [arg ...]\n"; static char *program; /* our name */ /* * print_fnv - print an FNV hash * * given: * hval the hash value to print * mask lower bit mask * verbose 1 => print arg with hash * arg string or filename arg */ static void print_fnv(Fnv32_t hval, Fnv32_t mask, int verbose, char *arg) { if (verbose) { printf("0x%08lx %s\n", hval & mask, arg); } else { printf("0x%08lx\n", hval & mask); } } /* * main - the main function * * See the above usage for details. */ int main(int argc, char *argv[]) { char buf[BUF_SIZE+1]; /* read buffer */ int readcnt; /* number of characters written */ Fnv32_t hval; /* current hash value */ int s_flag = 0; /* 1 => -s was given, hash args as strings */ int m_flag = 0; /* 1 => print multiple hashes, one per arg */ int v_flag = 0; /* 1 => verbose hash print */ int b_flag = WIDTH; /* -b flag value */ Fnv32_t bmask; /* mask to apply to output */ extern char *optarg; /* option argument */ extern int optind; /* argv index of the next arg */ int fd; /* open file to process */ char *p; int i; /* * parse args */ program = argv[0]; while ((i = getopt(argc, argv, "b:msv")) != -1) { switch (i) { case 'b': /* bcnt bit mask count */ b_flag = atoi(optarg); break; case 'm': /* print multiple hashes, one per arg */ m_flag = 1; break; case 's': /* hash args as strings */ s_flag = 1; break; case 'v': /* verbose hash print */ m_flag = 1; v_flag = 1; break; default: fprintf(stderr, usage, program); exit(1); } } /* -s requires at least 1 arg */ if (s_flag && optind >= argc) { fprintf(stderr, usage, program); exit(2); } /* limit -b values */ if (b_flag < 0 || b_flag > WIDTH) { fprintf(stderr, "%s: -b bcnt: %d must be >= 0 and < %d\n", program, b_flag, WIDTH); exit(3); } if (b_flag == WIDTH) { bmask = (Fnv32_t)0xffffffff; } else { bmask = (Fnv32_t)((1 << b_flag) - 1); } /* * start with the initial basis depending on the hash type */ p = strrchr(program, '/'); if (p == NULL) { p = program; } else { ++p; } if (strcmp(p, "fnv0_32") == 0 || strcmp(p, "fnv032") == 0) { /* using non-recommended FNV-0 and zero initial basis */ hval = FNV0_32_INIT; } else { /* using recommended FNV-1 and non-zero initial basis */ hval = FNV1_32_INIT; } /* * string hashing */ if (s_flag) { /* hash any other strings */ for (i=optind; i < argc; ++i) { hval = fnv_32_str(argv[i], hval); if (m_flag) { print_fnv(hval, bmask, v_flag, argv[i]); } } /* * file hashing */ } else { /* * case: process only stdin */ if (optind >= argc) { /* case: process only stdin */ while ((readcnt = read(0, buf, BUF_SIZE)) > 0) { hval = fnv_32_buf(buf, readcnt, hval); } if (m_flag) { print_fnv(hval, bmask, v_flag, "(stdin)"); } } else { /* * process any other files */ for (i=optind; i < argc; ++i) { /* open the file */ fd = open(argv[i], O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: unable to open file: %s\n", program, argv[i]); exit(4); } /* hash the file */ while ((readcnt = read(fd, buf, BUF_SIZE)) > 0) { hval = fnv_32_buf(buf, readcnt, hval); } /* finish processing the file */ if (m_flag) { print_fnv(hval, bmask, v_flag, argv[i]); } close(fd); } } } /* * report hash and exit */ if (!m_flag) { print_fnv(hval, bmask, v_flag, ""); } return 0; /* exit(0); */ } ================================================ FILE: src/fnv/fnv64.c ================================================ /* * fnv_64 - 64 bit Fowler/Noll/Vo hash of a buffer or string * * @(#) $Revision$ * @(#) $Id$ * @(#) $Source$ * *** * * usage: * fnv064 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * fnv0_64 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * * fnv164 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * fnv1_64 [-b bcnt] [-m [-v]] [-s arg] [arg ...] * * -b bcnt mask off all but the lower bcnt bits (default: 64) * -m multiple hashes, one per line for each arg * -s hash arg as a string (ignoring terminating NUL bytes) * -v verbose mode, print arg after hash (implies -m) * arg string (if -s was given) or filename (default stdin) * * The fnv064 and fnv0_64 basenames perform the 64 bit FNV-0 historic hash. * The fnv164 and fnv1_64 basenames perform the 64 bit recommended FNV-1 hash. * * NOTE: The FNV-0 historic hash is not recommended. * One should use the FNV-1 hash instead. * *** * * Fowler/Noll/Vo hash * * The basis of this hash algorithm was taken from an idea sent * as reviewer comments to the IEEE POSIX P1003.2 committee by: * * Phong Vo (http://www.research.att.com/info/kpv/) * Glenn Fowler (http://www.research.att.com/~gsf/) * * In a subsequent ballot round: * * Landon Curt Noll (http://www.isthe.com/chongo/) * * improved on their algorithm. Some people tried this hash * and found that it worked rather well. In an EMail message * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. * * FNV hashes are designed to be fast while maintaining a low * collision rate. The FNV speed allows one to quickly hash lots * of data while maintaining a reasonable collision rate. See: * * http://www.isthe.com/chongo/tech/comp/fnv/index.html * * for more details as well as other forms of the FNV hash. * *** * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ #include #include #include #include #include #include #include "fnv.h" #include "longlong.h" #ifdef HAVE_FCNTL_H #include #endif #define WIDTH 64 /* bit width of hash */ #define BUF_SIZE (32*1024) /* number of bytes to hash at a time */ static char *usage = "usage: %s [-b bcnt] [-m [-v]] [-s arg] [arg ...]\n"; static char *program; /* our name */ /* * print_fnv - print an FNV hash * * given: * hval the hash value to print * mask lower bit mask * verbose 1 => print arg with hash * arg string or filename arg */ static void print_fnv(Fnv64_t hval, Fnv64_t mask, int verbose, char *arg) { #if defined(HAVE_64BIT_LONG_LONG) if (verbose) { printf("0x%016llx %s\n", hval & mask, arg); } else { printf("0x%016llx\n", hval & mask); } #else if (verbose) { printf("0x%08lx%08lx %s\n", hval.w32[1] & mask.w32[1], hval.w32[0] & mask.w32[0], arg); } else { printf("0x%08lx%08lx\n", hval.w32[1] & mask.w32[1], hval.w32[0] & mask.w32[0]); } #endif } /* * main - the main function * * See the above usage for details. */ int main(int argc, char *argv[]) { char buf[BUF_SIZE+1]; /* read buffer */ int readcnt; /* number of characters written */ Fnv64_t hval; /* current hash value */ int s_flag = 0; /* 1 => -s was given, hash args as strings */ int m_flag = 0; /* 1 => print multiple hashes, one per arg */ int v_flag = 0; /* 1 => verbose hash print */ int b_flag = WIDTH; /* -b flag value */ Fnv64_t bmask; /* mask to apply to output */ extern char *optarg; /* option argument */ extern int optind; /* argv index of the next arg */ int fd; /* open file to process */ char *p; int i; /* * parse args */ program = argv[0]; while ((i = getopt(argc, argv, "b:msv")) != -1) { switch (i) { case 'b': /* bcnt bit mask count */ b_flag = atoi(optarg); break; case 'm': /* print multiple hashes, one per arg */ m_flag = 1; break; case 's': /* hash args as strings */ s_flag = 1; break; case 'v': /* verbose hash print */ m_flag = 1; v_flag = 1; break; default: fprintf(stderr, usage, program); exit(1); } } /* -s requires at least 1 arg */ if (s_flag && optind >= argc) { fprintf(stderr, usage, program); exit(2); } /* limit -b values */ if (b_flag < 0 || b_flag > WIDTH) { fprintf(stderr, "%s: -b bcnt: %d must be >= 0 and < %d\n", program, b_flag, WIDTH); exit(3); } #if defined(HAVE_64BIT_LONG_LONG) if (b_flag == WIDTH) { bmask = (Fnv64_t)0xffffffffffffffffULL; } else { bmask = (Fnv64_t)((1ULL << b_flag) - 1ULL); } #else if (b_flag == WIDTH) { bmask.w32[0] = 0xffffffffUL; bmask.w32[1] = 0xffffffffUL; } else if (b_flag >= WIDTH/2) { bmask.w32[0] = 0xffffffffUL; bmask.w32[1] = ((1UL << (b_flag-(WIDTH/2))) - 1UL); } else { bmask.w32[0] = ((1UL << b_flag) - 1UL); bmask.w32[1] = 0UL; } #endif /* * start with the initial basis depending on the hash type */ p = strrchr(program, '/'); if (p == NULL) { p = program; } else { ++p; } if (strcmp(p, "fnv0_64") == 0 || strcmp(p, "fnv064") == 0) { /* using non-recommended FNV-0 and zero initial basis */ hval = FNV0_64_INIT; } else { /* using recommended FNV-1 and non-zero initial basis */ hval = FNV1_64_INIT; } /* * string hashing */ if (s_flag) { /* hash any other strings */ for (i=optind; i < argc; ++i) { hval = fnv_64_str(argv[i], hval); if (m_flag) { print_fnv(hval, bmask, v_flag, argv[i]); } } /* * file hashing */ } else { /* * case: process only stdin */ if (optind >= argc) { /* case: process only stdin */ while ((readcnt = read(0, buf, BUF_SIZE)) > 0) { hval = fnv_64_buf(buf, readcnt, hval); } if (m_flag) { print_fnv(hval, bmask, v_flag, "(stdin)"); } } else { /* * process any other files */ for (i=optind; i < argc; ++i) { /* open the file */ fd = open(argv[i], O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: unable to open file: %s\n", program, argv[i]); exit(4); } /* hash the file */ while ((readcnt = read(fd, buf, BUF_SIZE)) > 0) { hval = fnv_64_buf(buf, readcnt, hval); } /* finish processing the file */ if (m_flag) { print_fnv(hval, bmask, v_flag, argv[i]); } close(fd); } } } /* * report hash and exit */ if (!m_flag) { print_fnv(hval, bmask, v_flag, ""); } return 0; /* exit(0); */ } ================================================ FILE: src/fnv/hash_32.c ================================================ /* * hash_32 - 32 bit Fowler/Noll/Vo hash code * * @(#) $Revision$ * @(#) $Id$ * @(#) $Source$ * *** * * Fowler/Noll/Vo hash * * The basis of this hash algorithm was taken from an idea sent * as reviewer comments to the IEEE POSIX P1003.2 committee by: * * Phong Vo (http://www.research.att.com/info/kpv/) * Glenn Fowler (http://www.research.att.com/~gsf/) * * In a subsequent ballot round: * * Landon Curt Noll (http://www.isthe.com/chongo/) * * improved on their algorithm. Some people tried this hash * and found that it worked rather well. In an EMail message * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. * * FNV hashes are designed to be fast while maintaining a low * collision rate. The FNV speed allows one to quickly hash lots * of data while maintaining a reasonable collision rate. See: * * http://www.isthe.com/chongo/tech/comp/fnv/index.html * * for more details as well as other forms of the FNV hash. *** * * NOTE: The FNV-0 historic hash is not recommended. One should use * the FNV-1 hash instead. * * To use the 32 bit FNV-0 historic hash, pass FNV0_32_INIT as the * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). * * To use the recommended 32 bit FNV-1 hash, pass FNV1_32_INIT as the * Fnv32_t hashval argument to fnv_32_buf() or fnv_32_str(). * *** * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ #include #include "fnv.h" /* * 32 bit magic FNV-0 and FNV-1 prime */ #define FNV_32_PRIME ((Fnv32_t)0x01000193) /* * fnv_32_buf - perform a 32 bit Fowler/Noll/Vo hash on a buffer * * input: * buf - start of buffer to hash * len - length of buffer in octets * hval - previous hash value or 0 if first call * * returns: * 32 bit hash as a static hash type * * NOTE: To use the 32 bit FNV-0 historic hash, use FNV0_32_INIT as the hval * argument on the first call to either fnv_32_buf() or fnv_32_str(). * * NOTE: To use the recommended 32 bit FNV-1 hash, use FNV1_32_INIT as the hval * argument on the first call to either fnv_32_buf() or fnv_32_str(). */ Fnv32_t fnv_32_buf(void *buf, size_t len, Fnv32_t hval) { unsigned char *bp = (unsigned char *)buf; /* start of buffer */ unsigned char *be = bp + len; /* beyond end of buffer */ /* * FNV-1 hash each octet in the buffer */ while (bp < be) { /* multiply by the 32 bit FNV magic prime mod 2^64 */ hval *= FNV_32_PRIME; /* xor the bottom with the current octet */ hval ^= (Fnv32_t)*bp++; } /* return our new hash value */ return hval; } /* * fnv_32_str - perform a 32 bit Fowler/Noll/Vo hash on a string * * input: * str - string to hash * hval - previous hash value or 0 if first call * * returns: * 32 bit hash as a static hash type * * NOTE: To use the 32 bit FNV-0 historic hash, use FNV0_32_INIT as the hval * argument on the first call to either fnv_32_buf() or fnv_32_str(). * * NOTE: To use the recommended 32 bit FNV-1 hash, use FNV1_32_INIT as the hval * argument on the first call to either fnv_32_buf() or fnv_32_str(). */ Fnv32_t fnv_32_str(char *str, Fnv32_t hval) { unsigned char *s = (unsigned char *)str; /* unsigned string */ /* * FNV-1 hash each octet in the buffer */ while (*s) { /* multiply by the 32 bit FNV magic prime mod 2^64 */ hval *= FNV_32_PRIME; /* xor the bottom with the current octet */ hval ^= (Fnv32_t)*s++; } /* return our new hash value */ return hval; } ================================================ FILE: src/fnv/hash_64.c ================================================ /* * hash_64 - 64 bit Fowler/Noll/Vo-0 hash code * * @(#) $Revision$ * @(#) $Id$ * @(#) $Source$ * *** * * Fowler/Noll/Vo hash * * The basis of this hash algorithm was taken from an idea sent * as reviewer comments to the IEEE POSIX P1003.2 committee by: * * Phong Vo (http://www.research.att.com/info/kpv/) * Glenn Fowler (http://www.research.att.com/~gsf/) * * In a subsequent ballot round: * * Landon Curt Noll (http://www.isthe.com/chongo/) * * improved on their algorithm. Some people tried this hash * and found that it worked rather well. In an EMail message * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash. * * FNV hashes are designed to be fast while maintaining a low * collision rate. The FNV speed allows one to quickly hash lots * of data while maintaining a reasonable collision rate. See: * * http://www.isthe.com/chongo/tech/comp/fnv/index.html * * for more details as well as other forms of the FNV hash. * *** * * NOTE: The FNV-0 historic hash is not recommended. One should use * the FNV-1 hash instead. * * To use the 64 bit FNV-0 historic hash, pass FNV0_64_INIT as the * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). * * To use the recommended 64 bit FNV-1 hash, pass FNV1_64_INIT as the * Fnv64_t hashval argument to fnv_64_buf() or fnv_64_str(). * *** * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ #include #include "fnv.h" /* * FNV-0 defines the initial basis to be zero */ #if !defined(HAVE_64BIT_LONG_LONG) const Fnv64_t fnv0_64_init = { 0, 0 }; #endif /* * FNV-1 defines the initial basis to be non-zero */ #if !defined(HAVE_64BIT_LONG_LONG) const Fnv64_t fnv1_64_init = { 0x84222325, 0xcbf29ce4 }; #endif /* * 64 bit magic FNV-0 and FNV-1 prime */ #if defined(HAVE_64BIT_LONG_LONG) #define FNV_64_PRIME ((Fnv64_t)0x100000001b3ULL) #else #define FNV_64_PRIME_LOW ((unsigned long)0x1b3) /* lower bits of FNV prime */ #define FNV_64_PRIME_SHIFT (8) /* top FNV prime shift above 2^32 */ #endif /* * fnv_64_buf - perform a 64 bit Fowler/Noll/Vo hash on a buffer * * input: * buf - start of buffer to hash * len - length of buffer in octets * hval - previous hash value or 0 if first call * * returns: * 64 bit hash as a static hash type * * NOTE: To use the 64 bit FNV-0 historic hash, use FNV0_64_INIT as the hval * argument on the first call to either fnv_64_buf() or fnv_64_str(). * * NOTE: To use the recommended 64 bit FNV-1 hash, use FNV1_64_INIT as the hval * argument on the first call to either fnv_64_buf() or fnv_64_str(). */ Fnv64_t fnv_64_buf(void *buf, size_t len, Fnv64_t hval) { #if defined(HAVE_64BIT_LONG_LONG) unsigned char *bp = (unsigned char *)buf; /* start of buffer */ unsigned char *be = bp + len; /* beyond end of buffer */ /* * FNV-1 hash each octet of the buffer */ while (bp < be) { /* multiply by the 64 bit FNV magic prime mod 2^64 */ hval *= FNV_64_PRIME; /* xor the bottom with the current octet */ hval ^= (Fnv64_t)*bp++; } #else /* HAVE_64BIT_LONG_LONG */ unsigned long val[4]; /* hash value in base 2^16 */ unsigned long tmp[4]; /* tmp 64 bit value */ /* * Convert Fnv64_t hval into a base 2^16 array */ val[0] = hval->w32[0]; val[1] = (val[0] >> 16); val[0] &= 0xffff; val[2] = hval->w32[1]; val[3] = (val[2] >> 16); val[2] &= 0xffff; /* * FNV-1 hash each octet of the buffer */ while (bp < be) { /* * multiply by the 64 bit FNV magic prime mod 2^64 * * Using 0x100000001b3 we have the following digits base 2^16: * * 0x0 0x100 0x0 0x1b3 * * which is the same as: * * 0x0 1<> 16); val[0] = tmp[0] & 0xffff; tmp[2] += (tmp[1] >> 16); val[1] = tmp[1] & 0xffff; val[3] = tmp[3] + (tmp[2] >> 16); val[2] = tmp[2] & 0xffff; /* * Doing a val[3] &= 0xffff; is not really needed since it simply * removes multiples of 2^64. We can discard these excess bits * outside of the loop when we convert to Fnv64_t. */ /* xor the bottom with the current octet */ val[0] ^= (unsigned long)*bp++; } /* * Convert base 2^16 array back into an Fnv64_t */ hval.w32[1] = ((val[3]<<16) | val[2]); hval.w32[0] = ((val[1]<<16) | val[0]); #endif /* HAVE_64BIT_LONG_LONG */ /* return our new hash value */ return hval; } /* * fnv_64_str - perform a 64 bit Fowler/Noll/Vo hash on a buffer * * input: * buf - start of buffer to hash * hval - previous hash value or 0 if first call * * returns: * 64 bit hash as a static hash type * * NOTE: To use the 64 bit FNV-0 historic hash, use FNV0_64_INIT as the hval * argument on the first call to either fnv_64_buf() or fnv_64_str(). * * NOTE: To use the recommended 64 bit FNV-1 hash, use FNV1_64_INIT as the hval * argument on the first call to either fnv_64_buf() or fnv_64_str(). */ Fnv64_t fnv_64_str(char *str, Fnv64_t hval) { unsigned char *s = (unsigned char *)str; /* unsigned string */ #if defined(HAVE_64BIT_LONG_LONG) /* * FNV-1 hash each octet of the string */ while (*s) { /* multiply by the 64 bit FNV magic prime mod 2^64 */ hval *= FNV_64_PRIME; /* xor the bottom with the current octet */ hval ^= (Fnv64_t)*s++; } #else /* !HAVE_64BIT_LONG_LONG */ unsigned long val[4]; /* hash value in base 2^16 */ unsigned long tmp[4]; /* tmp 64 bit value */ /* * Convert Fnv64_t hval into a base 2^16 array */ val[0] = hval->w32[0]; val[1] = (val[0] >> 16); val[0] &= 0xffff; val[2] = hval->w32[1]; val[3] = (val[2] >> 16); val[2] &= 0xffff; /* * FNV-1 hash each octet of the string */ while (*s) { /* * multiply by the 64 bit FNV magic prime mod 2^64 * * Using 1099511628211, we have the following digits base 2^16: * * 0x0 0x100 0x0 0x1b3 * * which is the same as: * * 0x0 1<> 16); val[0] = tmp[0] & 0xffff; tmp[2] += (tmp[1] >> 16); val[1] = tmp[1] & 0xffff; val[3] = tmp[3] + (tmp[2] >> 16); val[2] = tmp[2] & 0xffff; /* * Doing a val[3] &= 0xffff; is not really needed since it simply * removes multiples of 2^64. We can discard these excess bits * outside of the loop when we convert to Fnv64_t. */ /* xor the bottom with the current octet */ val[0] ^= (unsigned long)(*s++); } /* * Convert base 2^16 array back into an Fnv64_t */ hval.w32[1] = ((val[3]<<16) | val[2]); hval.w32[0] = ((val[1]<<16) | val[0]); #endif /* !HAVE_64BIT_LONG_LONG */ /* return our new hash value */ return hval; } ================================================ FILE: src/fnv/have_ulong64.c ================================================ /* * have_ulong64 - Determine if we have a 64 bit unsigned long long * * usage: * have_ulong64 > longlong.h * * Not all systems have a 'long long type' so this may not compile on * your system. * * This prog outputs the define: * * HAVE_64BIT_LONG_LONG * defined ==> we have a 64 bit unsigned long long * undefined ==> we must simulate a 64 bit unsigned long long */ /* * * Please do not copyright this code. This code is in the public domain. * * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * By: * chongo /\oo/\ * http://www.isthe.com/chongo/ * * Share and Enjoy! :-) */ /* * have the compiler try its hand with unsigned and signed long longs */ unsigned long long val = 1099511628211ULL; int main(void) { int longlong_bits; /* bits in a long long */ /* * ensure that the length of long long val is what we expect */ if (val == 1099511628211ULL && sizeof(val) == 8) { printf("#define HAVE_64BIT_LONG_LONG\t/* yes */\n"); } /* exit(0); */ return 0; } ================================================ FILE: src/fnv/ltconfig ================================================ #! /bin/sh # ltconfig - Create a system-specific libtool. # Copyright (C) 1996-1999 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A lot of this script is taken from autoconf-2.10. # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} echo=echo if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell. exec "$SHELL" "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null`} case X$UNAME in *-DOS) PATH_SEPARATOR=';' ;; *) PATH_SEPARATOR=':' ;; esac fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if (echo_test_string="`eval $cmd`") 2>/dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then break fi done fi if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" for dir in $PATH /usr/ucb; do if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then echo="$dir/echo" break fi done IFS="$save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running ltconfig again with it. ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf "%s\n"' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then # Cool, printf works : elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # The name of this program. progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` # Constants: PROGRAM=ltconfig PACKAGE=libtool VERSION=1.3.4 TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)" ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' rm="rm -f" help="Try \`$progname --help' for more information." # Global variables: default_ofile=libtool can_build_shared=yes enable_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). enable_static=yes enable_fast_install=yes enable_dlopen=unknown enable_win32_dll=no ltmain= silent= srcdir= ac_config_guess= ac_config_sub= host= nonopt= ofile="$default_ofile" verify_host=yes with_gcc=no with_gnu_ld=no need_locks=yes ac_ext=c objext=o libext=a exeext= cache_file= old_AR="$AR" old_CC="$CC" old_CFLAGS="$CFLAGS" old_CPPFLAGS="$CPPFLAGS" old_LDFLAGS="$LDFLAGS" old_LD="$LD" old_LN_S="$LN_S" old_LIBS="$LIBS" old_NM="$NM" old_RANLIB="$RANLIB" old_DLLTOOL="$DLLTOOL" old_OBJDUMP="$OBJDUMP" old_AS="$AS" # Parse the command line options. args= prev= for option do case "$option" in -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then eval "$prev=\$option" prev= continue fi case "$option" in --help) cat <&2 echo "$help" 1>&2 exit 1 ;; *) if test -z "$ltmain"; then ltmain="$option" elif test -z "$host"; then # This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 # if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then # echo "$progname: warning \`$option' is not a valid host type" 1>&2 # fi host="$option" else echo "$progname: too many arguments" 1>&2 echo "$help" 1>&2 exit 1 fi ;; esac done if test -z "$ltmain"; then echo "$progname: you must specify a LTMAIN file" 1>&2 echo "$help" 1>&2 exit 1 fi if test ! -f "$ltmain"; then echo "$progname: \`$ltmain' does not exist" 1>&2 echo "$help" 1>&2 exit 1 fi # Quote any args containing shell metacharacters. ltconfig_args= for arg do case "$arg" in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ltconfig_args="$ltconfig_args '$arg'" ;; *) ltconfig_args="$ltconfig_args $arg" ;; esac done # A relevant subset of AC_INIT. # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 5 compiler messages saved in config.log # 6 checking for... messages and results if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>>./config.log # NLS nuisances. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi if test -n "$cache_file" && test -r "$cache_file"; then echo "loading cache $cache_file within ltconfig" . $cache_file fi if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi if test -z "$srcdir"; then # Assume the source directory is the same one as the path to LTMAIN. srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` test "$srcdir" = "$ltmain" && srcdir=. fi trap "$rm conftest*; exit 1" 1 2 15 if test "$verify_host" = yes; then # Check for config.guess and config.sub. ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/config.guess; then ac_aux_dir=$ac_dir break fi done if test -z "$ac_aux_dir"; then echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 echo "$help" 1>&2 exit 1 fi ac_config_guess=$ac_aux_dir/config.guess ac_config_sub=$ac_aux_dir/config.sub # Make sure we can run config.sub. if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : else echo "$progname: cannot run $ac_config_sub" 1>&2 echo "$help" 1>&2 exit 1 fi echo $ac_n "checking host system type""... $ac_c" 1>&6 host_alias=$host case "$host_alias" in "") if host_alias=`$SHELL $ac_config_guess`; then : else echo "$progname: cannot guess host type; you must specify one" 1>&2 echo "$help" 1>&2 exit 1 fi ;; esac host=`$SHELL $ac_config_sub $host_alias` echo "$ac_t$host" 1>&6 # Make sure the host verified. test -z "$host" && exit 1 elif test -z "$host"; then echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 echo "$help" 1>&2 exit 1 else host_alias=$host fi # Transform linux* to *-*-linux-gnu*, to support old configure scripts. case "$host_os" in linux-gnu*) ;; linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` esac host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` case "$host_os" in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Determine commands to create old-style static archives. old_archive_cmds='$AR cru $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= # Set a sane default for `AR'. test -z "$AR" && AR=ar # Set a sane default for `OBJDUMP'. test -z "$OBJDUMP" && OBJDUMP=objdump # If RANLIB is not set, then run the test. if test "${RANLIB+set}" != "set"; then result=no echo $ac_n "checking for ranlib... $ac_c" 1>&6 IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" for dir in $PATH; do test -z "$dir" && dir=. if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then RANLIB="ranlib" result="ranlib" break fi done IFS="$save_ifs" echo "$ac_t$result" 1>&6 fi if test -n "$RANLIB"; then old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" fi # Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$AS" && AS=as # Check to see if we are using GCC. if test "$with_gcc" != yes || test -z "$CC"; then # If CC is not set, then try to find GCC or a usable CC. if test -z "$CC"; then echo $ac_n "checking for gcc... $ac_c" 1>&6 IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" for dir in $PATH; do test -z "$dir" && dir=. if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then CC="gcc" break fi done IFS="$save_ifs" if test -n "$CC"; then echo "$ac_t$CC" 1>&6 else echo "$ac_t"no 1>&6 fi fi # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". if test -z "$CC"; then echo $ac_n "checking for cc... $ac_c" 1>&6 IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" cc_rejected=no for dir in $PATH; do test -z "$dir" && dir=. if test -f $dir/cc || test -f $dir/cc$ac_exeext; then if test "$dir/cc" = "/usr/ucb/cc"; then cc_rejected=yes continue fi CC="cc" break fi done IFS="$save_ifs" if test $cc_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same name, so the bogon will be chosen # first if we set CC to just the name; use the full file name. shift set dummy "$dir/cc" "$@" shift CC="$@" fi fi if test -n "$CC"; then echo "$ac_t$CC" 1>&6 else echo "$ac_t"no 1>&6 fi if test -z "$CC"; then echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 exit 1 fi fi # Now see if the compiler is really GCC. with_gcc=no echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 echo "$progname:581: checking whether we are using GNU C" >&5 $rm conftest.c cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then with_gcc=yes fi $rm conftest.c echo "$ac_t$with_gcc" 1>&6 fi # Allow CC to be a program name with arguments. set dummy $CC compiler="$2" echo $ac_n "checking for object suffix... $ac_c" 1>&6 $rm conftest* echo 'int i = 1;' > conftest.c echo "$progname:603: checking for object suffix" >& 5 if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then # Append any warnings to the config.log. cat conftest.err 1>&5 for ac_file in conftest.*; do case $ac_file in *.c) ;; *) objext=`echo $ac_file | sed -e s/conftest.//` ;; esac done else cat conftest.err 1>&5 echo "$progname: failed program was:" >&5 cat conftest.c >&5 fi $rm conftest* echo "$ac_t$objext" 1>&6 echo $ac_n "checking for executable suffix... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_exeext="no" $rm conftest* echo 'main () { return 0; }' > conftest.c echo "$progname:629: checking for executable suffix" >& 5 if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then # Append any warnings to the config.log. cat conftest.err 1>&5 for ac_file in conftest.*; do case $ac_file in *.c | *.err | *.$objext ) ;; *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; esac done else cat conftest.err 1>&5 echo "$progname: failed program was:" >&5 cat conftest.c >&5 fi $rm conftest* fi if test "X$ac_cv_exeext" = Xno; then exeext="" else exeext="$ac_cv_exeext" fi echo "$ac_t$ac_cv_exeext" 1>&6 echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 pic_flag= special_shlib_compile_flags= wl= link_static_flag= no_builtin_flag= if test "$with_gcc" = yes; then wl='-Wl,' link_static_flag='-static' case "$host_os" in beos* | irix5* | irix6* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; aix*) # Below there is a dirty hack to force normal static linking with -ldl # The problem is because libdl dynamically linked with both libc and # libC (AIX C++ library), which obviously doesn't included in libraries # list by gcc. This cause undefined symbols with -static flags. # This hack allows C programs to be linked with "-static -ldl", but # we not sure about C++ programs. link_static_flag="$link_static_flag ${wl}-lC" ;; cygwin* | mingw* | os2*) # We can build DLLs from non-PIC. ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. pic_flag='-m68020 -resident32 -malways-restore-a4' ;; sysv4*MP*) if test -d /usr/nec; then pic_flag=-Kconform_pic fi ;; *) pic_flag='-fPIC' ;; esac else # PORTME Check for PIC flags for the system compiler. case "$host_os" in aix3* | aix4*) # All AIX code is PIC. link_static_flag='-bnso -bI:/lib/syscalls.exp' ;; hpux9* | hpux10* | hpux11*) # Is there a better link_static_flag that works with the bundled CC? wl='-Wl,' link_static_flag="${wl}-a ${wl}archive" pic_flag='+Z' ;; irix5* | irix6*) wl='-Wl,' link_static_flag='-non_shared' # PIC (with -KPIC) is the default. ;; cygwin* | mingw* | os2*) # We can build DLLs from non-PIC. ;; osf3* | osf4* | osf5*) # All OSF/1 code is PIC. wl='-Wl,' link_static_flag='-non_shared' ;; sco3.2v5*) pic_flag='-Kpic' link_static_flag='-dn' special_shlib_compile_flags='-belf' ;; solaris*) pic_flag='-KPIC' link_static_flag='-Bstatic' wl='-Wl,' ;; sunos4*) pic_flag='-PIC' link_static_flag='-Bstatic' wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) pic_flag='-KPIC' link_static_flag='-Bstatic' wl='-Wl,' ;; uts4*) pic_flag='-pic' link_static_flag='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then pic_flag='-Kconform_pic' link_static_flag='-Bstatic' fi ;; *) can_build_shared=no ;; esac fi if test -n "$pic_flag"; then echo "$ac_t$pic_flag" 1>&6 # Check to make sure the pic_flag actually works. echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 $rm conftest* echo "int some_variable = 0;" > conftest.c save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $pic_flag -DPIC" echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5 if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then # Append any warnings to the config.log. cat conftest.err 1>&5 case "$host_os" in hpux9* | hpux10* | hpux11*) # On HP-UX, both CC and GCC only warn that PIC is supported... then they # create non-PIC objects. So, if there were any warnings, we assume that # PIC is not supported. if test -s conftest.err; then echo "$ac_t"no 1>&6 can_build_shared=no pic_flag= else echo "$ac_t"yes 1>&6 pic_flag=" $pic_flag" fi ;; *) echo "$ac_t"yes 1>&6 pic_flag=" $pic_flag" ;; esac else # Append any errors to the config.log. cat conftest.err 1>&5 can_build_shared=no pic_flag= echo "$ac_t"no 1>&6 fi CFLAGS="$save_CFLAGS" $rm conftest* else echo "$ac_t"none 1>&6 fi # Check to see if options -o and -c are simultaneously supported by compiler echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 $rm -r conftest 2>/dev/null mkdir conftest cd conftest $rm conftest* echo "int some_variable = 0;" > conftest.c mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.o" echo "$progname:829: checking if $compiler supports -c -o file.o" >&5 if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then echo "$ac_t"no 1>&6 compiler_c_o=no else echo "$ac_t"yes 1>&6 compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&5 compiler_c_o=no echo "$ac_t"no 1>&6 fi CFLAGS="$save_CFLAGS" chmod u+w . $rm conftest* out/* rmdir out cd .. rmdir conftest $rm -r conftest 2>/dev/null if test x"$compiler_c_o" = x"yes"; then # Check to see if we can write to a .lo echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 $rm conftest* echo "int some_variable = 0;" > conftest.c save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -c -o conftest.lo" echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5 if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then echo "$ac_t"no 1>&6 compiler_o_lo=no else echo "$ac_t"yes 1>&6 compiler_o_lo=yes fi else # Append any errors to the config.log. cat conftest.err 1>&5 compiler_o_lo=no echo "$ac_t"no 1>&6 fi CFLAGS="$save_CFLAGS" $rm conftest* else compiler_o_lo=no fi # Check to see if we can do hard links to lock some files if needed hard_links="nottested" if test "$compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no echo "$ac_t$hard_links" 1>&6 $rm conftest* if test "$hard_links" = no; then echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 need_locks=warn fi else need_locks=no fi if test "$with_gcc" = yes; then # Check to see if options -fno-rtti -fno-exceptions are supported by compiler echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 $rm conftest* echo "int some_variable = 0;" > conftest.c save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then echo "$ac_t"no 1>&6 compiler_rtti_exceptions=no else echo "$ac_t"yes 1>&6 compiler_rtti_exceptions=yes fi else # Append any errors to the config.log. cat conftest.err 1>&5 compiler_rtti_exceptions=no echo "$ac_t"no 1>&6 fi CFLAGS="$save_CFLAGS" $rm conftest* if test "$compiler_rtti_exceptions" = "yes"; then no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' else no_builtin_flag=' -fno-builtin' fi fi # Check for any special shared library compilation flags. if test -n "$special_shlib_compile_flags"; then echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : else echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 can_build_shared=no fi fi echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 $rm conftest* echo 'main(){return(0);}' > conftest.c save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $link_static_flag" echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5 if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then echo "$ac_t$link_static_flag" 1>&6 else echo "$ac_t"none 1>&6 link_static_flag= fi LDFLAGS="$save_LDFLAGS" $rm conftest* if test -z "$LN_S"; then # Check to see if we can use ln -s, or we need hard links. echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 $rm conftest.dat if ln -s X conftest.dat 2>/dev/null; then $rm conftest.dat LN_S="ln -s" else LN_S=ln fi if test "$LN_S" = "ln -s"; then echo "$ac_t"yes 1>&6 else echo "$ac_t"no 1>&6 fi fi # Make sure LD is an absolute path. if test -z "$LD"; then ac_prog=ld if test "$with_gcc" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 echo "$progname:991: checking for ld used by GCC" >&5 ac_prog=`($CC -print-prog-name=ld) 2>&5` case "$ac_prog" in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we are not using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then echo $ac_n "checking for GNU ld... $ac_c" 1>&6 echo "$progname:1015: checking for GNU ld" >&5 else echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 echo "$progname:1018: checking for non-GNU ld" >&5 fi if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then test "$with_gnu_ld" != no && break else test "$with_gnu_ld" != yes && break fi fi done IFS="$ac_save_ifs" fi if test -n "$LD"; then echo "$ac_t$LD" 1>&6 else echo "$ac_t"no 1>&6 fi if test -z "$LD"; then echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 exit 1 fi fi # Check to see if it really is or is not GNU ld. echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 # I'd rather use --version here, but apparently some GNU ld's only accept -v. if $LD -v 2>&1 &5; then with_gnu_ld=yes else with_gnu_ld=no fi echo "$ac_t$with_gnu_ld" 1>&6 # See if the linker supports building shared libraries. echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 allow_undefined_flag= no_undefined_flag= need_lib_prefix=unknown need_version=unknown # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments archive_cmds= archive_expsym_cmds= old_archive_from_new_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported runpath_var= always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an egrep regular expression of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. case "$host_os" in cygwin* | mingw*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$with_gcc" != yes; then with_gnu_ld=no fi ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case "$host_os" in aix3* | aix4*) # On AIX, the GNU linker is very broken ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF ;; amigaos*) archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=yes # Extract the symbol export list from an `--export-all' def file, # then regenerate the def file from the symbol export list, so that # the compiled dll only exports the symbol export list. export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols' archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ _lt_hint=1; for symbol in `cat $export_symbols`; do echo " \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def; _lt_hint=`expr 1 + \$_lt_hint`; done~ test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' # can we support soname and/or expsyms with a.out? -oliva fi ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' case $host_os in cygwin* | mingw*) # dlltool doesn't understand --whole-archive et. al. whole_archive_flag_spec= ;; *) # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi ;; esac fi else # PORTME fill in a description of your system's linker (not GNU ld) case "$host_os" in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$with_gcc" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4*) hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' hardcode_libdir_separator=':' if test "$with_gcc" = yes; then collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi shared_flag='-shared' else shared_flag='${wl}-bM:SRE' hardcode_direct=yes fi allow_undefined_flag=' ${wl}-berok' archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' case "$host_os" in aix4.[01]|aix4.[01].*) # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on always_export_symbols=yes ;; esac ;; amigaos*) archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; cygwin* | mingw*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs' fix_srcfile_path='`cygpath -w $srcfile`' ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9* | hpux10* | hpux11*) case "$host_os" in hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; esac hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_minus_L=yes # Not in the search PATH, but as the default # location of the library. export_dynamic_flag_spec='${wl}-E' ;; irix5* | irix6*) if test "$with_gcc" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF fi hardcode_libdir_flag_spec='${wl}-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; openbsd*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' ;; osf3*) if test "$with_gcc" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # As osf3* with the addition of the -msym flag if test "$with_gcc" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case "$host_os" in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; unixware7*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi echo "$ac_t$ld_shlibs" 1>&6 test "$ld_shlibs" = no && can_build_shared=no if test -z "$NM"; then echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 case "$NM" in [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then NM="$ac_dir/nm -B" break elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then NM="$ac_dir/nm -p" break else NM=${NM="$ac_dir/nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags fi fi done IFS="$ac_save_ifs" test -z "$NM" && NM=nm ;; esac echo "$ac_t$NM" 1>&6 fi # Check for command to grab the raw symbol name followed by C symbol from nm. echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" # Define system-specific variables. case "$host_os" in aix*) symcode='[BCDT]' ;; cygwin* | mingw*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" ;; irix*) symcode='[BCDEGRST]' ;; solaris*) symcode='[BDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then symcode='[ABCDGISTW]' fi # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no $rm conftest* cat > conftest.c <&5 if { (eval echo $progname:1636: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then # Now try to grab the symbols. nlist=conftest.nm if { echo "$progname:1639: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if egrep ' nm_test_var$' "$nlist" >/dev/null; then if egrep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.c #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' cat <> conftest.c #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c cat <<\EOF >> conftest.c {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$objext conftstm.$objext save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="conftstm.$objext" CFLAGS="$CFLAGS$no_builtin_flag" if { (eval echo $progname:1691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then pipe_works=yes else echo "$progname: failed program was:" >&5 cat conftest.c >&5 fi LIBS="$save_LIBS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.c >&5 fi $rm conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else global_symbol_pipe= fi done if test "$pipe_works" = yes; then echo "${ac_t}ok" 1>&6 else echo "${ac_t}failed" 1>&6 fi if test -z "$global_symbol_pipe"; then global_symbol_to_cdecl= fi # Check hardcoding attributes. echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var"; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$hardcode_shlibpath_var" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi echo "$ac_t$hardcode_action" 1>&6 reload_flag= reload_cmds='$LD$reload_flag -o $output$reload_objs' echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 # PORTME Some linkers may need a different reload flag. reload_flag='-r' echo "$ac_t$reload_flag" 1>&6 test -n "$reload_flag" && reload_flag=" $reload_flag" # PORTME Fill in your ld.so characteristics library_names_spec= libname_spec='lib$name' soname_spec= postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" file_magic_cmd= file_magic_test_file= deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [regex]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given egrep regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 case "$host_os" in aix3*) version_type=linux library_names_spec='${libname}${release}.so$versuffix $libname.a' shlibpath_var=LIBPATH # AIX has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}.so$major' ;; aix4*) version_type=linux # AIX has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. # We preserve .a as extension for shared libraries though AIX4.2 # and later linker supports .so library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' shlibpath_var=LIBPATH deplibs_check_method=pass_all ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' ;; beos*) library_names_spec='${libname}.so' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH deplibs_check_method=pass_all lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' file_magic_cmd=/usr/bin/file file_magic_test_file=/shlib/libc.so sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" export_dynamic_flag_spec=-rdynamic # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw*) version_type=windows need_version=no need_lib_prefix=no if test "$with_gcc" = yes; then library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' else library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' fi dynamic_linker='Win32 ld.exe' deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' file_magic_cmd='${OBJDUMP} -f' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; freebsd1*) dynamic_linker=no ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case "$version_type" in freebsd-elf*) deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' file_magic_cmd=/usr/bin/file file_magic_test_file=`echo /usr/lib/libc.so*` library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' need_version=no need_lib_prefix=no ;; freebsd-*) deplibs_check_method=unknown library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case "$host_os" in freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. dynamic_linker="$host_os dld.sl" version_type=sunos need_lib_prefix=no need_version=no shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' soname_spec='${libname}${release}.sl$major' # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6*) version_type=irix need_lib_prefix=no need_version=no soname_spec='${libname}${release}.so.$major' library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' case "$host_os" in irix5*) libsuff= shlibsuff= # this will be overridden with pass_all, but let us keep it just in case deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case "$LD" in # libtool.m4 will add one of these switches to LD *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" file_magic_cmd=/usr/bin/file file_magic_test_file=`echo /lib${libsuff}/libc.so*` deplibs_check_method='pass_all' ;; # No shared lib support for Linux oldld, aout, or coff. linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) dynamic_linker=no ;; # This must be Linux ELF. linux-gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' file_magic_cmd=/usr/bin/file file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` if test -f /lib/ld.so.1; then dynamic_linker='GNU ld.so' else # Only the GNU ld.so supports shared libraries on MkLinux. case "$host_cpu" in powerpc*) dynamic_linker=no ;; *) dynamic_linker='Linux ld.so' ;; esac fi ;; netbsd*) version_type=sunos if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' soname_spec='${libname}${release}.so$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH ;; openbsd*) version_type=sunos if test "$with_gnu_ld" = yes; then need_lib_prefix=no need_version=no fi library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH ;; os2*) libname_spec='$name' need_lib_prefix=no library_names_spec='$libname.dll $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_version=no soname_spec='${libname}${release}.so' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' shlibpath_var=LD_LIBRARY_PATH # this will be overridden with pass_all, but let us keep it just in case deplibs_check_method='file_magic COFF format alpha shared library' file_magic_cmd=/usr/bin/file file_magic_test_file=/shlib/libc.so deplibs_check_method='pass_all' sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}.so$major' library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" file_magic_cmd=/usr/bin/file file_magic_test_file=/lib/libc.so ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH case "$host_vendor" in ncr) deplibs_check_method='pass_all' ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' file_magic_cmd=/usr/bin/file file_magic_test_file=`echo /usr/lib/libc.so*` ;; esac ;; uts4*) version_type=linux library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' soname_spec='${libname}${release}.so$major' shlibpath_var=LD_LIBRARY_PATH ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' soname_spec='$libname.so.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; *) dynamic_linker=no ;; esac echo "$ac_t$dynamic_linker" 1>&6 test "$dynamic_linker" = no && can_build_shared=no # Report the final consequences. echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 # Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in # configure.in, otherwise build static only libraries. case "$host_os" in cygwin* | mingw* | os2*) if test x$can_build_shared = xyes; then test x$enable_win32_dll = xno && can_build_shared=no echo "checking if package supports dlls... $can_build_shared" 1>&6 fi ;; esac if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then case "$deplibs_check_method" in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | egrep "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) test "$enable_shared" = yes && enable_static=no ;; esac echo "$ac_t$enable_shared" 1>&6 # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes echo "checking whether to build static libraries... $enable_static" 1>&6 if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi echo $ac_n "checking for objdir... $ac_c" 1>&6 rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. objdir=_libs fi rmdir .libs 2>/dev/null echo "$ac_t$objdir" 1>&6 if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then lt_cv_dlopen=no lt_cv_dlopen_libs= echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 echo "$progname:2212: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen""... $ac_c" 1>&6 echo "$progname:2252: checking for dlopen" >&5 if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_dlopen) || defined (__stub___dlopen) choke me #else dlopen(); #endif ; return 0; } EOF if { (eval echo $progname:2282: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_dlopen=yes" else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_dlopen=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dlopen" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 echo "$progname:2299: checking for dld_link in -ldld" >&5 ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldld $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for shl_load""... $ac_c" 1>&6 echo "$progname:2339: checking for shl_load" >&5 if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_shl_load) || defined (__stub___shl_load) choke me #else shl_load(); #endif ; return 0; } EOF if { (eval echo $progname:2369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_shl_load=yes" else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_shl_load=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="shl_load" else echo "$ac_t""no" 1>&6 echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 echo "$progname:2387: checking for shl_load in -ldld" >&5 ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldld $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else echo "$ac_t""no" 1>&6 fi fi fi fi fi fi if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes fi case "$lt_cv_dlopen" in dlopen) for ac_hdr in dlfcn.h; do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo "$progname:2452: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int fnord = 0; EOF ac_try="$ac_compile >/dev/null 2>conftest.out" { (eval echo $progname:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* eval "ac_cv_header_$ac_safe=yes" else echo "$ac_err" >&5 echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_header_$ac_safe=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 else echo "$ac_t""no" 1>&6 fi done if test "x$ac_cv_header_dlfcn_h" = xyes; then CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" fi eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" LIBS="$lt_cv_dlopen_libs $LIBS" echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 echo "$progname:2490: checking whether a program can dlopen itself" >&5 if test "${lt_cv_dlopen_self+set}" = set; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then lt_cv_dlopen_self=cross else cat > conftest.c < #endif #include #ifdef RTLD_GLOBAL # define LTDL_GLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LTDL_GLOBAL DL_GLOBAL # else # define LTDL_GLOBAL 0 # endif #endif /* We may have to define LTDL_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LTDL_LAZY_OR_NOW # ifdef RTLD_LAZY # define LTDL_LAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LTDL_LAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LTDL_LAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LTDL_LAZY_OR_NOW DL_NOW # else # define LTDL_LAZY_OR_NOW 0 # endif # endif # endif # endif #endif fnord() { int i=42;} main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } EOF if { (eval echo $progname:2544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then lt_cv_dlopen_self=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* lt_cv_dlopen_self=no fi rm -fr conftest* fi fi echo "$ac_t""$lt_cv_dlopen_self" 1>&6 if test "$lt_cv_dlopen_self" = yes; then LDFLAGS="$LDFLAGS $link_static_flag" echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 echo "$progname:2563: checking whether a statically linked program can dlopen itself" >&5 if test "${lt_cv_dlopen_self_static+set}" = set; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then lt_cv_dlopen_self_static=cross else cat > conftest.c < #endif #include #ifdef RTLD_GLOBAL # define LTDL_GLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LTDL_GLOBAL DL_GLOBAL # else # define LTDL_GLOBAL 0 # endif #endif /* We may have to define LTDL_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LTDL_LAZY_OR_NOW # ifdef RTLD_LAZY # define LTDL_LAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LTDL_LAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LTDL_LAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LTDL_LAZY_OR_NOW DL_NOW # else # define LTDL_LAZY_OR_NOW 0 # endif # endif # endif # endif #endif fnord() { int i=42;} main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } EOF if { (eval echo $progname:2617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then lt_cv_dlopen_self_static=yes else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* lt_cv_dlopen_self_static=no fi rm -fr conftest* fi fi echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 fi ;; esac case "$lt_cv_dlopen_self" in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case "$lt_cv_dlopen_self_static" in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Copy echo and quote the copy, instead of the original, because it is # used later. ltecho="$echo" if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then ltecho="$CONFIG_SHELL \$0 --fallback-echo" fi LTSHELL="$SHELL" LTCONFIG_VERSION="$VERSION" # Only quote variables if we're using ltmain.sh. case "$ltmain" in *.sh) # Now quote all the things that may contain metacharacters. for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ old_LD old_LDFLAGS old_LIBS \ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ reload_flag reload_cmds wl \ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ thread_safe_flag_spec whole_archive_flag_spec libname_spec \ library_names_spec soname_spec \ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ hardcode_libdir_flag_spec hardcode_libdir_separator \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do case "$var" in reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ postinstall_cmds | postuninstall_cmds | \ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case "$ltecho" in *'\$0 --fallback-echo"') ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac trap "$rm \"$ofile\"; exit 1" 1 2 15 echo "creating $ofile" $rm "$ofile" cat < "$ofile" #! $SHELL # `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. # # Copyright (C) 1996-1999 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="sed -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi ### BEGIN LIBTOOL CONFIG EOF cfgfile="$ofile" ;; *) # Double-quote the variables that need it (for aesthetics). for var in old_CC old_CFLAGS old_CPPFLAGS \ old_LD old_LDFLAGS old_LIBS \ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do eval "$var=\\\"\$var\\\"" done # Just create a config file. cfgfile="$ofile.cfg" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 echo "creating $cfgfile" $rm "$cfgfile" cat < "$cfgfile" # `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) EOF ;; esac cat <> "$cfgfile" # Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # # CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ # LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ # NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ # DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ # $0$ltconfig_args # # Compiler and other test output produced by $progname, useful for # debugging $progname, is in ./config.log if it exists. # The version of $progname that generated this script. LTCONFIG_VERSION=$LTCONFIG_VERSION # Shell to use when invoking shell scripts. SHELL=$LTSHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$ltecho # The archiver. AR=$AR # The default C compiler. CC=$CC # The linker used to build libraries. LD=$LD # Whether we need hard or soft links. LN_S=$LN_S # A BSD-compatible nm program. NM=$NM # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$reload_flag reload_cmds=$reload_cmds # How to pass a linker flag through the compiler. wl=$wl # Object file suffix (normally "o"). objext="$objext" # Old archive suffix (normally "a"). libext="$libext" # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$pic_flag # Does compiler simultaneously support -c and -o options? compiler_c_o=$compiler_c_o # Can we write directly to a .lo ? compiler_o_lo=$compiler_o_lo # Must we lock files when doing compilation ? need_locks=$need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$link_static_flag # Compiler flag to turn off builtin functions. no_builtin_flag=$no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$library_names_spec # The coded name of the library, if different from the real name. soname_spec=$soname_spec # Commands used to build and install an old-style archive. RANLIB=$RANLIB old_archive_cmds=$old_archive_cmds old_postinstall_cmds=$old_postinstall_cmds old_postuninstall_cmds=$old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$old_archive_from_new_cmds # Commands used to build and install a shared archive. archive_cmds=$archive_cmds archive_expsym_cmds=$archive_expsym_cmds postinstall_cmds=$postinstall_cmds postuninstall_cmds=$postuninstall_cmds # Method to check whether dependent libraries are shared objects. deplibs_check_method=$deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$global_symbol_to_cdecl # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$hardcode_libdir_separator # Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Compile-time system search path for libraries sys_lib_search_path_spec=$sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$exclude_expsyms # Symbols that must always be exported. include_expsyms=$include_expsyms EOF case "$ltmain" in *.sh) echo '### END LIBTOOL CONFIG' >> "$ofile" echo >> "$ofile" case "$host_os" in aix3*) cat <<\EOF >> "$ofile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # Append the ltmain.sh script. sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? chmod +x "$ofile" ;; *) # Compile the libtool program. echo "FIXME: would compile $ltmain" ;; esac test -n "$cache_file" || exit 0 # AC_CACHE_SAVE trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: ================================================ FILE: src/fnv/ltmain.sh ================================================ # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" # Parse our command line options once, thoroughly. while test $# -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" exit 0 ;; --config) sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 exit 0 ;; --debug) echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then case $nonopt in *cc | *++ | gcc* | *-gcc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= prev= lastarg= srcfile="$nonopt" suppress_output= user_target=no for arg do case $prev in "") ;; xcompiler) # Aesthetically quote the previous argument. prev= lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac # Accept any command-line options. case $arg in -o) if test "$user_target" != "no"; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi user_target=next ;; -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; -Xcompiler) prev=xcompiler continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi continue ;; esac case $user_target in next) # The next one is the -o target name user_target=yes continue ;; yes) # We got the output file user_target=set libobj="$arg" continue ;; esac # Accept the current argument as the source file. lastarg="$srcfile" srcfile="$arg" # Aesthetically quote the previous argument. # Backslashify any backslashes, double quotes, and dollar signs. # These are the only characters that are still specially # interpreted inside of double-quoted scrings. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $lastarg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi done case $user_target in set) ;; no) # Get the name of the library object. libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; *) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSfmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $libobj" else removelist="$libobj" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test $pic_mode = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" else # Don't build PIC code command="$base_compile $srcfile" fi if test "$build_old_libs" = yes; then lo_libobj="$libobj" dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$libobj"; then dir="$objdir" else dir="$dir/$objdir" fi libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` if test -d "$dir"; then $show "$rm $libobj" $run $rm $libobj else $show "$mkdir $dir" $run $mkdir $dir status=$? if test $status -ne 0 && test ! -d $dir; then exit $status fi fi fi if test "$compiler_o_lo" = yes; then output_obj="$libobj" command="$command -o $output_obj" elif test "$compiler_c_o" = yes; then output_obj="$obj" command="$command -o $output_obj" fi $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test x"$output_obj" != x"$libobj"; then $show "$mv $output_obj $libobj" if $run $mv $output_obj $libobj; then : else error=$? $run $rm $removelist exit $error fi fi # If we have no pic_flag, then copy the object into place and finish. if (test -z "$pic_flag" || test "$pic_mode" != default) && test "$build_old_libs" = yes; then # Rename the .lo from within objdir to obj if test -f $obj; then $show $rm $obj $run $rm $obj fi $show "$mv $libobj $obj" if $run $mv $libobj $obj; then : else error=$? $run $rm $removelist exit $error fi xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` # Now arrange that obj and lo_libobj become the same file $show "(cd $xdir && $LN_S $baseobj $libobj)" if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 else error=$? $run $rm $removelist exit $error fi fi # Allow error messages only from the first compilation. suppress_output=' >/dev/null 2>&1' fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $srcfile" else # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" output_obj="$obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test x"$output_obj" != x"$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Create an invalid libtool object if no PIC, so that we do not # accidentally link it into a program. if test "$build_libtool_libs" != yes; then $show "echo timestamp > $libobj" $run eval "echo timestamp > \$libobj" || exit $? else # Move the .lo from within objdir $show "$mv $libobj $lo_libobj" if $run $mv $libobj $lo_libobj; then : else error=$? $run $rm $removelist exit $error fi fi fi # Unlock the critical section if it was locked if test "$need_locks" != no; then $run $rm "$lockfile" fi exit 0 ;; # libtool link mode link | relink) modename="$modename: link" case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invokation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args="$nonopt" compile_command="$nonopt" finalize_command="$nonopt" compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= # We need to know -static, to get the right output filenames. for arg do case $arg in -all-static | -static) if test "X$arg" = "X-all-static"; then if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test $# -gt 0; do arg="$1" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n $prev prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | no/*-*-nonstopux*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 exit 1 fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-mingw* | *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.lo | *.$objext) # A library or standard object. if test "$prev" = dlfiles; then # This file was specified with -dlopen. if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $arg" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` prev= else case $arg in *.lo) libobjs="$libobjs $arg" ;; *) objs="$objs $arg" ;; esac fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d $output_objdir; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test $status -ne 0 && test ! -d $output_objdir; then exit $status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit 1 ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test $linkmode = prog; then # Determine which files to process case $pass in dlopen) libs="$dlfiles" save_deplibs="$deplibs" # Collect dlpreopened libraries deplibs= ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi for deplib in $libs; do lib= found=no case $deplib in -l*) if test $linkmode = oldlib && test $linkmode = obj; then $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 continue fi if test $pass = conv; then deplibs="$deplib $deplibs" continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do # Search the libtool library lib="$searchdir/lib${name}.la" if test -f "$lib"; then found=yes break fi done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test $linkmode = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test $pass = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi if test $pass = scan; then deplibs="$deplib $deplibs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test $pass = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test $pass = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) if test "$deplibs_check_method" != pass_all; then echo echo "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not used here." else echo echo "*** Warning: Linking the shared library $output against the" echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test $pass != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test $pass = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test $found = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 exit 1 fi # Check to see that this really is a libtool archive. if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variable installed. installed=yes # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test $linkmode = oldlib && test $linkmode = obj; }; then # Add dl[pre]opened files of deplib test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test $pass = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test $linkmode != prog && test $linkmode != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit 1 fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # This library was specified with -dlopen. if test $pass = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit 1 fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. dlprefiles="$dlprefiles $lib" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test $pass = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit 1 fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test $linkmode = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" fi continue fi if test $linkmode = prog && test $pass != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test $linkalldeplibs = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... link_static=no # Whether the deplib will be linked statically if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # Link against this shared library if test "$linkmode,$pass" = "prog,link" || { test $linkmode = lib && test $hardcode_into_libs = yes; }; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac if test $linkmode = prog; then # We need to hardcode the library path if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi fi fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`echo $soroot | sed -e 's/^.*\///'` newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$extract_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$old_archive_from_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n $old_archive_from_expsyms_cmds if test $linkmode = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test $linkmode = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test $linkmode = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" add="-l$name" fi if test $linkmode = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test $linkmode = prog; then if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi # Try to link the static library # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo echo "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test $linkmode = lib; then if test -n "$dependency_libs" && { test $hardcode_into_libs != yes || test $build_old_libs = yes || test $link_static = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test $link_all_deplibs != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="-L$absdir/$objdir" else eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="-L$absdir" fi ;; *) continue ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$deplibs $path" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test $pass = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test $pass != dlopen; then test $pass != scan && dependency_libs="$newdependency_libs" if test $pass != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do case $deplib in -L*) new_libs="$deplib $new_libs" ;; *) case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi if test "$pass" = "conv" && { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then libs="$deplibs" # reset libs deplibs= fi done # for pass if test $linkmode = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit 1 else echo echo "*** Warning: Linking the shared library $output against the non-libtool" echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test $# -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. libext=al oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi current="$2" revision="$3" age="$4" # Check that each of the things are valid numbers. case $current in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $revision in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $age in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test $age -gt $current; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" major=`expr $current - $age + 1` # Add in all the interfaces that we are compatible with. loop=$revision while test $loop != 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test $loop != 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= verstring="0.0" case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring="" ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs. $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'` deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'` dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test $hardcode_into_libs != yes || test $build_old_libs = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. ;; *) # Add libc to deplibs on all other systems if necessary. if test $build_libtool_need_lc = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behaviour. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | sed 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | sed 10q \ | egrep "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then echo "*** with $libname but no candidates were found. (...for file magic test)" else echo "*** with $libname and none of the candidates passed a file format test" echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check below in file_magic test if eval echo \"$potent_lib\" 2>/dev/null \ | sed 10q \ | egrep "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then echo "*** with $libname but no candidates were found. (...for regex pattern test)" else echo "*** with $libname and none of the candidates passed a file format test" echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | grep . >/dev/null; then echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" echo "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test $allow_undefined = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test $hardcode_into_libs = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi test -z "$dlname" && dlname=$soname lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Ensure that we have .o objects for linkers which dislike .lo # (e.g. aix) in case we are running --disable-static for obj in $libobjs; do xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` if test ! -f $xdir/$oldobj; then $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? fi done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? exit 0 fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. $show "echo timestamp > $libobj" $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" else # Just create a symlink. $show $rm $libobj $run $rm $libobj xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$libobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` $show "(cd $xdir && $LN_S $oldobj $baseobj)" $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; prog) case $host in *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`echo "$arg" | sed -e 's%^.*/%%'` $run eval 'echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test $need_relink = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit 0 fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case $0 in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`echo $output|sed 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe ;; *) exeext= ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # win32 systems need to use the prog path for dll # lookup to work *-*-cygwin* | *-*-pw32*) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ # Export the path to the program. PATH=\"\$progdir:\$PATH\" export PATH exec \$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else # Ensure that we have .o objects in place in case we decided # not to build a shared library, and have fallen back to building # static libs even though --disable-static was passed! for oldobj in $oldobjs; do if test ! -f $oldobj; then xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$oldobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` $show "(cd $xdir && ${LN_S} $obj $baseobj)" $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? fi done eval cmds=\"$old_archive_cmds\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test $need_relink = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case $arg in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test $# -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 continue fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test $# -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`echo $file | sed -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (sed -e '4q' $wrapper | egrep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $wrapper ;; *) . ./$wrapper ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit 1 fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $wrapper ;; *) . ./$wrapper ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir="$tmpdir/libtool-$$" if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyways case $install_prog,$host in /usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`echo $destfile | sed -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $0 --finish$current_libdirs' else exit 0 fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = ":" && exit 0 echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do echo " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" echo "more information, such as the ld(1) and ld.so(8) manual pages." echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved enviroment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi rmdirs= for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$objdir" else objdir="$dir/$objdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test $mode = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test $mode = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" test $mode = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" if test $mode = uninstall; then if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test $? != 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi fi ;; *.lo) if test "$build_old_libs" = yes; then oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` rmfiles="$rmfiles $dir/$oldobj" fi ;; *) # Do a test to see if this is a libtool program. if test $mode = clean && (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$file rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit 1 fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE." exit 0 ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: ================================================ FILE: src/getdate.h ================================================ /* Copyright (C) 1995 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #if defined (vms) # include # include #else # ifdef HAVE_STDLIB_H # include # endif # include # ifdef TIME_WITH_SYS_TIME # include # include # else # ifdef HAVE_SYS_TIME_H # include # else # include # endif # endif #endif /* defined (vms) */ #ifdef NO_MACRO #undef isspace #undef isdigit #undef isalpha #undef isupper #undef islower #undef isxdigit #undef isalnum #undef ispunct #undef isprint #undef isgraph #undef iscntrl #undef isascii #endif time_t get_date (const char *p, const time_t *now); ================================================ FILE: src/getdate.texi ================================================ @node Date input formats @chapter Date input formats @cindex date input formats @findex getdate @quotation Our units of temporal measurement, from seconds on up to months, are so complicated, asymmetrical and disjunctive so as to make coherent mental reckoning in time all but impossible. Indeed, had some tyrannical god contrived to enslave our minds to time, to make it all but impossible for us to escape subjection to sodden routines and unpleasant surprises, he could hardly have done better than handing down our present system. It is like a set of trapezoidal building blocks, with no vertical or horizontal surfaces, like a language in which the simplest thought demands ornate constructions, useless particles and lengthy circumlocutions. Unlike the more successful patterns of language and science, which enable us to face experience boldly or at least level-headedly, our system of temporal calculation silently and persistently encourages our terror of time. @dots{} It is as though architects had to measure length in feet, width in meters and height in ells; as though basic instruction manuals demanded a knowledge of five different languages. It is no wonder then that we often look into our own immediate past or future, last Tuesday or a week from Sunday, with feelings of helpless confusion. @dots{} --- Robert Grudin, @cite{Time and the Art of Living}. @end quotation This section describes the textual date representations that GNU programs accept. These are the strings you, as a user, can supply as arguments to the various programs. The C interface (via the @code{getdate} function) is not described here. @cindex beginning of time, for Unix @cindex epoch, for Unix Although the date syntax here can represent any possible time since zero A.D., computer integers are not big enough for such a (comparatively) long time. The earliest date semantically allowed on Unix systems is midnight, 1 January 1970 UCT. @menu * General date syntax:: Common rules. * Calendar date item:: 19 Dec 1994. * Time of day item:: 9:20pm. * Timezone item:: EST, DST, BST, UCT, AHST, ... * Day of week item:: Monday and others. * Relative item in date strings:: next tuesday, 2 years ago. * Pure numbers in date strings:: 19931219, 1440. * Authors of getdate:: Bellovin, Salz, Berets, et al. @end menu @node General date syntax @section General date syntax @cindex general date syntax @cindex items in date strings A @dfn{date} is a string, possibly empty, containing many items separated by whitespace. The whitespace may be omitted when no ambiguity arises. The empty string means the beginning of today (i.e., midnight). Order of the items is immaterial. A date string may contain many flavors of items: @itemize @bullet @item calendar date items @item time of the day items @item time zone items @item day of the week items @item relative items @item pure numbers. @end itemize @noindent We describe each of these item types in turn, below. @cindex numbers, written-out @cindex ordinal numbers @findex first @r{in date strings} @findex next @r{in date strings} @findex last @r{in date strings} A few numbers may be written out in words in most contexts. This is most useful for specifying day of the week items or relative items (see below). Here is the list: @samp{first} for 1, @samp{next} for 2, @samp{third} for 3, @samp{fourth} for 4, @samp{fifth} for 5, @samp{sixth} for 6, @samp{seventh} for 7, @samp{eighth} for 8, @samp{ninth} for 9, @samp{tenth} for 10, @samp{eleventh} for 11 and @samp{twelfth} for 12. Also, @samp{last} means exactly @math{-1}. @cindex months, written-out When a month is written this way, it is still considered to be written numerically, instead of being ``spelled in full''; this changes the allowed strings. @cindex case, ignored in dates @cindex comments, in dates Alphabetic case is completely ignored in dates. Comments may be introduced between round parentheses, as long as included parentheses are properly nested. Hyphens not followed by a digit are currently ignored. Leading zeros on numbers are ignored. @node Calendar date item @section Calendar date item @cindex calendar date item A @dfn{calendar date item} specifies a day of the year. It is specified differently, depending on whether the month is specified numerically or literally. All these strings specify the same calendar date: @example 1970-09-17 # ISO 8601. 70-9-17 # This century assumed by default. 70-09-17 # Leading zeros are ignored. 9/17/72 # Common U.S. writing. 24 September 1972 24 Sept 72 # September has a special abbreviation. 24 Sep 72 # Three-letter abbreviations always allowed. Sep 24, 1972 24-sep-72 24sep72 @end example The year can also be omitted. In this case, the last specified year is used, or the current year if none. For example: @example 9/17 sep 17 @end example Here are the rules. @cindex ISO 8601 date format @cindex date format, ISO 8601 For numeric months, the ISO 8601 format @samp{@var{year}-@var{month}-@var{day}} is allowed, where @var{year} is any positive number, @var{month} is a number between 01 and 12, and @var{day} is a number between 01 and 31. A leading zero must be present if a number is less than ten. If @var{year} is less than 100, then 1900 is added to it to force a date in this century. The construct @samp{@var{month}/@var{day}/@var{year}}, popular in the United States, is accepted. Also @samp{@var{month}/@var{day}}, omitting the year. @cindex month names in date strings @cindex abbreviations for months Literal months may be spelled out in full: @samp{January}, @samp{February}, @samp{March}, @samp{April}, @samp{May}, @samp{June}, @samp{July}, @samp{August}, @samp{September}, @samp{October}, @samp{November} or @samp{December}. Literal months may be abbreviated to their first three letters, possibly followed by an abbreviating dot. It is also permitted to write @samp{Sept} instead of @samp{September}. When months are written literally, the calendar date may be given as any of the following: @example @var{day} @var{month} @var{year} @var{day} @var{month} @var{month} @var{day} @var{year} @var{day}-@var{month}-@var{year} @end example Or, omitting the year: @example @var{month} @var{day} @end example @node Time of day item @section Time of day item @cindex time of day item A @dfn{time of day item} in date strings specifies the time on a given day. Here are some examples, all of which represent the same time: @example 20:02:0 20:02 8:02pm 20:02-0500 # In EST (Eastern U.S. Standard Time). @end example More generally, the time of the day may be given as @samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is a number between 0 and 23, @var{minute} is a number between 0 and 59, and @var{second} is a number between 0 and 59. Alternatively, @samp{:@var{second}} can be omitted, in which case it is taken to be zero. @findex am @r{in date strings} @findex pm @r{in date strings} @findex midnight @r{in date strings} @findex noon @r{in date strings} If the time is followed by @samp{am} or @samp{pm} (or @samp{a.m.} or @samp{p.m.}), @var{hour} is restricted to run from 1 to 12, and @samp{:@var{minute}} may be omitted (taken to be zero). @samp{am} indicates the first half of the day, @samp{pm} indicates the second half of the day. In this notation, 12 is the predecessor of 1: midnight is @samp{12am} while noon is @samp{12pm}. @cindex timezone correction @cindex minutes, timezone correction by The time may alternatively be followed by a timezone correction, expressed as @samp{@var{s}@var{hh}@var{mm}}, where @var{s} is @samp{+} or @samp{-}, @var{hh} is a number of zone hours and @var{mm} is a number of zone minutes. When a timezone correction is given this way, it forces interpretation of the time in UTC, overriding any previous specification for the timezone or the local timezone. The @var{minute} part of the time of the day may not be elided when a timezone correction is used. This is the only way to specify a timezone correction by fractional parts of an hour. Either @samp{am}/@samp{pm} or a timezone correction may be specified, but not both. @node Timezone item @section Timezone item @cindex timezone item A @dfn{timezone item} specifies an international timezone, indicated by a small set of letters. Any included period is ignored. Military timezone designations use a single letter. Currently, only integral zone hours may be represented in a timezone item. See the previous section for a finer control over the timezone correction. Here are many non-daylight-savings-time timezones, indexed by the zone hour value. @table @asis @item +000 @cindex Greenwich Mean Time @cindex Universal Coordinated Time @cindex Western European Time @samp{GMT} for Greenwich Mean, @samp{UT} or @samp{UTC} for Universal (Coordinated), @samp{WET} for Western European and @samp{Z} for militaries. @item +100 @cindex West African Time @samp{WAT} for West Africa and @samp{A} for militaries. @item +200 @cindex Azores Time @samp{AT} for Azores and @samp{B} for militaries. @item +300 @samp{C} for militaries. @item +400 @cindex Atlantic Standard Time @samp{AST} for Atlantic Standard and @samp{D} for militaries. @item +500 @cindex Eastern Standard Time @samp{E} for militaries and @samp{EST} for Eastern Standard. @item +600 @cindex Central Standard Time @samp{CST} for Central Standard and @samp{F} for militaries. @item +700 @cindex Mountain Standard Time @samp{G} for militaries and @samp{MST} for Mountain Standard. @item +800 @cindex Pacific Standard Time @samp{H} for militaries and @samp{PST} for Pacific Standard. @item +900 @cindex Yukon Standard Time @samp{I} for militaries and @samp{YST} for Yukon Standard. @item +1000 @cindex Alaska-Hawaii Time @cindex Central Alaska Time @cindex Hawaii Standard Time @samp{AHST} for Alaska-Hawaii Standard, @samp{CAT} for Central Alaska, @samp{HST} for Hawaii Standard and @samp{K} for militaries. @item +1100 @cindex Nome Standard Time @samp{L} for militaries and @samp{NT} for Nome. @item +1200 @cindex International Date Line West @samp{IDLW} for International Date Line West and @samp{M} for militaries. @item -100 @cindex Central European Time @cindex Middle European Time @cindex Middle European Winter Time @cindex French Winter Time @cindex Swedish Winter Time @samp{CET} for Central European, @samp{FWT} for French Winter, @samp{MET} for Middle European, @samp{MEWT} for Middle European Winter, @samp{N} for militaries and @samp{SWT} for Swedish Winter. @item -200 @cindex Eastern European Time @cindex USSR Zone @samp{EET} for Eastern European, USSR Zone 1 and @samp{O} for militaries. @item -300 @cindex Baghdad Time @samp{BT} for Baghdad, USSR Zone 2 and @samp{P} for militaries. @item -400 @samp{Q} for militaries and @samp{ZP4} for USSR Zone 3. @item -500 @samp{R} for militaries and @samp{ZP5} for USSR Zone 4. @item -600 @samp{S} for militaries and @samp{ZP6} for USSR Zone 5. @item -700 @cindex West Australian Standard Time @samp{T} for militaries and @samp{WAST} for West Australian Standard. @item -800 @cindex China Coast Time @samp{CCT} for China Coast, USSR Zone 7 and @samp{U} for militaries. @item -900 @cindex Japan Standard Time @samp{JST} for Japan Standard, USSR Zone 8 and @samp{V} for militaries. @item -1000 @cindex East Australian Standard Time @cindex Guam Standard Time @samp{EAST} for East Australian Standard, @samp{GST} for Guam Standard, USSR Zone 9 and @samp{W} for militaries. @item -1100 @samp{X} for militaries. @item -1200 @cindex International Date Line East @cindex New Zealand Standard Time @samp{IDLE} for International Date Line East, @samp{NZST} for New Zealand Standard, @samp{NZT} for New Zealand and @samp{Y} for militaries. @end table @cindex daylight savings time Here are many DST timezones, indexed by the zone hour value. Also, by following a non-DST timezone by the string @samp{DST} in a separate word (that is, separated by some whitespace), the corresponding DST timezone may be specified. @table @asis @item 0 @samp{BST} for British Summer. @item +400 @samp{ADT} for Atlantic Daylight. @item +500 @samp{EDT} for Eastern Daylight. @item +600 @samp{CDT} for Central Daylight. @item +700 @samp{MDT} for Mountain Daylight. @item +800 @samp{PDT} for Pacific Daylight. @item +900 @samp{YDT} for Yukon Daylight. @item +1000 @samp{HDT} for Hawaii Daylight. @item -100 @samp{MEST} for Middle European Summer, @samp{MESZ} for Middle European Summer, @samp{SST} for Swedish Summer and @samp{FST} for French Summer. @item -700 @samp{WADT} for West Australian Daylight. @item -1000 @samp{EADT} for Eastern Australian Daylight. @item -1200 @samp{NZDT} for New Zealand Daylight. @end table @node Day of week item @section Day of week item @cindex day of week item The explicit mention of a day of the week will forward the date (only if necessary) to reach that day of the week in the future. Days of the week may be spelled out in full: @samp{Sunday}, @samp{Monday}, @samp{Tuesday}, @samp{Wednesday}, @samp{Thursday}, @samp{Friday} or @samp{Saturday}. Days may be abbreviated to their first three letters, optionally followed by a period. The special abbreviations @samp{Tues} for @samp{Tuesday}, @samp{Wednes} for @samp{Wednesday} and @samp{Thur} or @samp{Thurs} for @samp{Thursday} are also allowed. @findex next @var{day} @findex last @var{day} A number may precede a day of the week item to move forward supplementary weeks. It is best used in expression like @samp{third monday}. In this context, @samp{last @var{day}} or @samp{next @var{day}} is also acceptable; they move one week before or after the day that @var{day} by itself would represent. A comma following a day of the week item is ignored. @node Relative item in date strings @section Relative item in date strings @cindex relative items in date strings @cindex displacement of dates @dfn{Relative items} adjust a date (or the current date if none) forward or backward. The effects of relative items accumulate. Here are some examples: @example 1 year 1 year ago 3 years 2 days @end example @findex year @r{in date strings} @findex month @r{in date strings} @findex fortnight @r{in date strings} @findex week @r{in date strings} @findex day @r{in date strings} @findex hour @r{in date strings} @findex minute @r{in date strings} The unit of time displacement may be selected by the string @samp{year} or @samp{month} for moving by whole years or months. These are fuzzy units, as years and months are not all of equal duration. More precise units are @samp{fortnight} which is worth 14 days, @samp{week} worth 7 days, @samp{day} worth 24 hours, @samp{hour} worth 60 minutes, @samp{minute} or @samp{min} worth 60 seconds, and @samp{second} or @samp{sec} worth one second. An @samp{s} suffix on these units is accepted and ignored. @findex ago @r{in date strings} The unit of time may be preceded by a multiplier, given as an optionally signed number. Unsigned numbers are taken as positively signed. No number at all implies 1 for a multiplier. Following a relative item by the string @samp{ago} is equivalent to preceding the unit by a multiplicator with value @math{-1}. @findex day @r{in date strings} @findex tomorrow @r{in date strings} @findex yesterday @r{in date strings} The string @samp{tomorrow} is worth one day in the future (equivalent to @samp{day}), the string @samp{yesterday} is worth one day in the past (equivalent to @samp{day ago}). @findex now @r{in date strings} @findex today @r{in date strings} @findex this @r{in date strings} The strings @samp{now} or @samp{today} are relative items corresponding to zero-valued time displacement, these strings come from the fact a zero-valued time displacement represents the current time when not otherwise change by previous items. They may be used to stress other items, like in @samp{12:00 today}. The string @samp{this} also has the meaning of a zero-valued time displacement, but is preferred in date strings like @samp{this thursday}. When a relative item makes the resulting date to cross the boundary between DST and non-DST (or vice-versa), the hour is adjusted according to the local time. @node Pure numbers in date strings @section Pure numbers in date strings @cindex pure numbers in date strings The precise intepretation of a pure decimal number is dependent of the context in the date string. If the decimal number is of the form @var{yyyy}@var{mm}@var{dd} and no other calendar date item (@pxref{Calendar date item}) appears before it in the date string, then @var{yyyy} is read as the year, @var{mm} as the month number and @var{dd} as the day of the month, for the specified calendar date. If the decimal number is of the form @var{hh}@var{mm} and no other time of day item appears before it in the date string, then @var{hh} is read as the hour of the day and @var{mm} as the minute of the hour, for the specified time of the day. @var{mm} can also be omitted. If both a calendar date and a time of day appear to the left of a number in the date string, but no relative item, then the number overrides the year. @node Authors of getdate @section Authors of @code{getdate} @cindex authors of @code{getdate} @cindex Bellovin, Steven M. @cindex Salz, Rich @cindex Berets, Jim @cindex MacKenzie, David @cindex Meyering, Jim @code{getdate} was originally implemented by Steven M. Bellovin (@samp{smb@@research.att.com}) while at the University of North Carolina at Chapel Hill. The code was later tweaked by a couple of people on Usenet, then completely overhauled by Rich $alz (@samp{rsalz@@bbn.com}) and Jim Berets (@samp{jberets@@bbn.com}) in August, 1990. Various revisions for the GNU system were made by David MacKenzie, Jim Meyering, and others. @cindex Pinard, F. @cindex Berry, K. This chapter was originally produced by Fran@,{c}ois Pinard (@samp{pinard@@iro.umontreal.ca}) from the @file{getdate.y} source code, and then edited by K.@: Berry (@samp{kb@@cs.umb.edu}). ================================================ FILE: src/getdate.y ================================================ %{ /* ** Originally written by Steven M. Bellovin while ** at the University of North Carolina at Chapel Hill. Later tweaked by ** a couple of people on Usenet. Completely overhauled by Rich $alz ** and Jim Berets in August, 1990; ** ** This grammar has 13 shift/reduce conflicts. ** ** This code is in the public domain and has no copyright. */ #include "../config.h" #include "setup.h" #ifdef HAVE_CONFIG_H # ifdef FORCE_ALLOCA_H # include # endif #endif /* Since the code of getdate.y is not included in the Emacs executable itself, there is no need to #define static in this file. Even if the code were included in the Emacs executable, it probably wouldn't do any harm to #undef it here; this will only cause problems if we try to write to a static variable, which I don't think this code needs to do. */ #ifdef emacs # undef static #endif #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #ifdef HAVE_STRING_H #include #endif #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) # define IN_CTYPE_DOMAIN(c) 1 #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) #define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) #define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) /* ISDIGIT differs from ISDIGIT_LOCALE, as follows: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. - It's typically faster. Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless it's important to use the locale's definition of `digit' even when the host does not conform to Posix. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #include "getdate.h" #if defined (STDC_HEADERS) || defined (USG) # include #endif /* Some old versions of bison generate parsers that use bcopy. That loses on systems that don't provide the function, so we have to redefine it here. */ #if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy) # define bcopy(from, to, len) memcpy ((to), (from), (len)) #endif /* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), as well as gratuitiously global symbol names, so we can have multiple yacc generated parsers in the same program. Note that these are only the variables produced by yacc. If other parser generators (bison, byacc, etc) produce additional global names that conflict at link time, then those parser generators need to be fixed instead of adding those names to this list. */ #define yymaxdepth gd_maxdepth #define yyparse gd_parse #define yylex gd_lex #define yyerror gd_error #define yylval gd_lval #define yychar gd_char #define yydebug gd_debug #define yypact gd_pact #define yyr1 gd_r1 #define yyr2 gd_r2 #define yydef gd_def #define yychk gd_chk #define yypgo gd_pgo #define yyact gd_act #define yyexca gd_exca #define yyerrflag gd_errflag #define yynerrs gd_nerrs #define yyps gd_ps #define yypv gd_pv #define yys gd_s #define yy_yys gd_yys #define yystate gd_state #define yytmp gd_tmp #define yyv gd_v #define yy_yyv gd_yyv #define yyval gd_val #define yylloc gd_lloc #define yyreds gd_reds /* With YYDEBUG defined */ #define yytoks gd_toks /* With YYDEBUG defined */ #define yylhs gd_yylhs #define yylen gd_yylen #define yydefred gd_yydefred #define yydgoto gd_yydgoto #define yysindex gd_yysindex #define yyrindex gd_yyrindex #define yygindex gd_yygindex #define yytable gd_yytable #define yycheck gd_yycheck static int yylex (void); static int yyerror (char *s); extern int yyparse (void); #define EPOCH 1970 #define HOUR(x) ((x) * 60) #define MAX_BUFF_LEN 128 /* size of buffer to read the date into */ /* ** An entry in the lexical lookup table. */ typedef struct _TABLE { const char *name; int type; int value; } TABLE; /* ** Meridian: am, pm, or 24-hour style. */ typedef enum _MERIDIAN { MERam, MERpm, MER24 } MERIDIAN; /* ** Global variables. We could get rid of most of these by using a good ** union as the yacc stack. (This routine was originally written before ** yacc had the %union construct.) Maybe someday; right now we only use ** the %union very rarely. */ static const char *yyInput; static int yyDayOrdinal; static int yyDayNumber; static int yyHaveDate; static int yyHaveDay; static int yyHaveRel; static int yyHaveTime; static int yyHaveZone; static int yyTimezone; static int yyDay; static int yyHour; static int yyMinutes; static int yyMonth; static int yySeconds; static int yyYear; static MERIDIAN yyMeridian; static int yyRelDay; static int yyRelHour; static int yyRelMinutes; static int yyRelMonth; static int yyRelSeconds; static int yyRelYear; %} %union { int Number; enum _MERIDIAN Meridian; } %token tAGO tDAY tDAY_UNIT tDAYZONE tDST tHOUR_UNIT tID %token tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT %token tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE %type tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT %type tMONTH tMONTH_UNIT %type tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE %type tMERIDIAN o_merid %% spec : /* NULL */ | spec item ; item : time { yyHaveTime++; } | zone { yyHaveZone++; } | date { yyHaveDate++; } | day { yyHaveDay++; } | rel { yyHaveRel++; } | number ; time : tUNUMBER tMERIDIAN { yyHour = $1; yyMinutes = 0; yySeconds = 0; yyMeridian = $2; } | tUNUMBER ':' tUNUMBER o_merid { yyHour = $1; yyMinutes = $3; yySeconds = 0; yyMeridian = $4; } | tUNUMBER ':' tUNUMBER tSNUMBER { yyHour = $1; yyMinutes = $3; yySeconds = 0; yyMeridian = MER24; yyHaveZone++; yyTimezone = ($4 < 0 ? -$4 % 100 + (-$4 / 100) * 60 : - ($4 % 100 + ($4 / 100) * 60)); } | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { yyHour = $1; yyMinutes = $3; yySeconds = $5; yyMeridian = $6; } | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER { yyHour = $1; yyMinutes = $3; yySeconds = $5; yyMeridian = MER24; yyHaveZone++; yyTimezone = ($6 < 0 ? -$6 % 100 + (-$6 / 100) * 60 : - ($6 % 100 + ($6 / 100) * 60)); } ; zone : tZONE { yyTimezone = $1; } | tDAYZONE { yyTimezone = $1 - 60; } | tZONE tDST { yyTimezone = $1 - 60; } ; day : tDAY { yyDayOrdinal = 1; yyDayNumber = $1; } | tDAY ',' { yyDayOrdinal = 1; yyDayNumber = $1; } | tUNUMBER tDAY { yyDayOrdinal = $1; yyDayNumber = $2; } ; date : tUNUMBER '/' tUNUMBER { yyMonth = $1; yyDay = $3; } | tUNUMBER '/' tUNUMBER '/' tUNUMBER { /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. The goal in recognizing YYYY/MM/DD is solely to support legacy machine-generated dates like those in an RCS log listing. If you want portability, use the ISO 8601 format. */ if ($1 >= 1000) { yyYear = $1; yyMonth = $3; yyDay = $5; } else { yyMonth = $1; yyDay = $3; yyYear = $5; } } | tUNUMBER tSNUMBER tSNUMBER { /* ISO 8601 format. yyyy-mm-dd. */ yyYear = $1; yyMonth = -$2; yyDay = -$3; } | tUNUMBER tMONTH tSNUMBER { /* e.g. 17-JUN-1992. */ yyDay = $1; yyMonth = $2; yyYear = -$3; } | tMONTH tUNUMBER { yyMonth = $1; yyDay = $2; } | tMONTH tUNUMBER ',' tUNUMBER { yyMonth = $1; yyDay = $2; yyYear = $4; } | tUNUMBER tMONTH { yyMonth = $2; yyDay = $1; } | tUNUMBER tMONTH tUNUMBER { yyMonth = $2; yyDay = $1; yyYear = $3; } ; rel : relunit tAGO { yyRelSeconds = -yyRelSeconds; yyRelMinutes = -yyRelMinutes; yyRelHour = -yyRelHour; yyRelDay = -yyRelDay; yyRelMonth = -yyRelMonth; yyRelYear = -yyRelYear; } | relunit ; relunit : tUNUMBER tYEAR_UNIT { yyRelYear += $1 * $2; } | tSNUMBER tYEAR_UNIT { yyRelYear += $1 * $2; } | tYEAR_UNIT { yyRelYear++; } | tUNUMBER tMONTH_UNIT { yyRelMonth += $1 * $2; } | tSNUMBER tMONTH_UNIT { yyRelMonth += $1 * $2; } | tMONTH_UNIT { yyRelMonth++; } | tUNUMBER tDAY_UNIT { yyRelDay += $1 * $2; } | tSNUMBER tDAY_UNIT { yyRelDay += $1 * $2; } | tDAY_UNIT { yyRelDay++; } | tUNUMBER tHOUR_UNIT { yyRelHour += $1 * $2; } | tSNUMBER tHOUR_UNIT { yyRelHour += $1 * $2; } | tHOUR_UNIT { yyRelHour++; } | tUNUMBER tMINUTE_UNIT { yyRelMinutes += $1 * $2; } | tSNUMBER tMINUTE_UNIT { yyRelMinutes += $1 * $2; } | tMINUTE_UNIT { yyRelMinutes++; } | tUNUMBER tSEC_UNIT { yyRelSeconds += $1 * $2; } | tSNUMBER tSEC_UNIT { yyRelSeconds += $1 * $2; } | tSEC_UNIT { yyRelSeconds++; } ; number : tUNUMBER { if (yyHaveTime && yyHaveDate && !yyHaveRel) yyYear = $1; else { if ($1>10000) { yyHaveDate++; yyDay= ($1)%100; yyMonth= ($1/100)%100; yyYear = $1/10000; } else { yyHaveTime++; if ($1 < 100) { yyHour = $1; yyMinutes = 0; } else { yyHour = $1 / 100; yyMinutes = $1 % 100; } yySeconds = 0; yyMeridian = MER24; } } } ; o_merid : /* NULL */ { $$ = MER24; } | tMERIDIAN { $$ = $1; } ; %% /* Month and day table. */ static TABLE const MonthDayTable[] = { { "january", tMONTH, 1 }, { "february", tMONTH, 2 }, { "march", tMONTH, 3 }, { "april", tMONTH, 4 }, { "may", tMONTH, 5 }, { "june", tMONTH, 6 }, { "july", tMONTH, 7 }, { "august", tMONTH, 8 }, { "september", tMONTH, 9 }, { "sept", tMONTH, 9 }, { "october", tMONTH, 10 }, { "november", tMONTH, 11 }, { "december", tMONTH, 12 }, { "sunday", tDAY, 0 }, { "monday", tDAY, 1 }, { "tuesday", tDAY, 2 }, { "tues", tDAY, 2 }, { "wednesday", tDAY, 3 }, { "wednes", tDAY, 3 }, { "thursday", tDAY, 4 }, { "thur", tDAY, 4 }, { "thurs", tDAY, 4 }, { "friday", tDAY, 5 }, { "saturday", tDAY, 6 }, { NULL } }; /* Time units table. */ static TABLE const UnitsTable[] = { { "year", tYEAR_UNIT, 1 }, { "month", tMONTH_UNIT, 1 }, { "fortnight", tDAY_UNIT, 14 }, { "week", tDAY_UNIT, 7 }, { "day", tDAY_UNIT, 1 }, { "hour", tHOUR_UNIT, 1 }, { "minute", tMINUTE_UNIT, 1 }, { "min", tMINUTE_UNIT, 1 }, { "second", tSEC_UNIT, 1 }, { "sec", tSEC_UNIT, 1 }, { NULL } }; /* Assorted relative-time words. */ static TABLE const OtherTable[] = { { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, { "today", tMINUTE_UNIT, 0 }, { "now", tMINUTE_UNIT, 0 }, { "last", tUNUMBER, -1 }, { "this", tMINUTE_UNIT, 0 }, { "next", tUNUMBER, 2 }, { "first", tUNUMBER, 1 }, /* { "second", tUNUMBER, 2 }, */ { "third", tUNUMBER, 3 }, { "fourth", tUNUMBER, 4 }, { "fifth", tUNUMBER, 5 }, { "sixth", tUNUMBER, 6 }, { "seventh", tUNUMBER, 7 }, { "eighth", tUNUMBER, 8 }, { "ninth", tUNUMBER, 9 }, { "tenth", tUNUMBER, 10 }, { "eleventh", tUNUMBER, 11 }, { "twelfth", tUNUMBER, 12 }, { "ago", tAGO, 1 }, { NULL } }; /* The timezone table. */ static TABLE const TimezoneTable[] = { { "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */ { "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ { "utc", tZONE, HOUR ( 0) }, { "wet", tZONE, HOUR ( 0) }, /* Western European */ { "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */ { "wat", tZONE, HOUR ( 1) }, /* West Africa */ { "at", tZONE, HOUR ( 2) }, /* Azores */ #if 0 /* For completeness. BST is also British Summer, and GST is * also Guam Standard. */ { "bst", tZONE, HOUR ( 3) }, /* Brazil Standard */ { "gst", tZONE, HOUR ( 3) }, /* Greenland Standard */ #endif #if 0 { "nft", tZONE, HOUR (3.5) }, /* Newfoundland */ { "nst", tZONE, HOUR (3.5) }, /* Newfoundland Standard */ { "ndt", tDAYZONE, HOUR (3.5) }, /* Newfoundland Daylight */ #endif { "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */ { "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */ { "est", tZONE, HOUR ( 5) }, /* Eastern Standard */ { "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */ { "cst", tZONE, HOUR ( 6) }, /* Central Standard */ { "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */ { "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */ { "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */ { "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */ { "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */ { "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */ { "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */ { "hst", tZONE, HOUR (10) }, /* Hawaii Standard */ { "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */ { "cat", tZONE, HOUR (10) }, /* Central Alaska */ { "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */ { "nt", tZONE, HOUR (11) }, /* Nome */ { "idlw", tZONE, HOUR (12) }, /* International Date Line West */ { "cet", tZONE, -HOUR (1) }, /* Central European */ { "met", tZONE, -HOUR (1) }, /* Middle European */ { "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */ { "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ { "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ { "swt", tZONE, -HOUR (1) }, /* Swedish Winter */ { "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */ { "fwt", tZONE, -HOUR (1) }, /* French Winter */ { "fst", tDAYZONE, -HOUR (1) }, /* French Summer */ { "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */ { "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */ #if 0 { "it", tZONE, -HOUR (3.5) },/* Iran */ #endif { "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */ { "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */ #if 0 { "ist", tZONE, -HOUR (5.5) },/* Indian Standard */ #endif { "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */ #if 0 /* For completeness. NST is also Newfoundland Standard, and SST is * also Swedish Summer. */ { "nst", tZONE, -HOUR (6.5) },/* North Sumatra */ { "sst", tZONE, -HOUR (7) }, /* South Sumatra, USSR Zone 6 */ #endif /* 0 */ { "wast", tZONE, -HOUR (7) }, /* West Australian Standard */ { "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */ #if 0 { "jt", tZONE, -HOUR (7.5) },/* Java (3pm in Cronusland!) */ #endif { "javt", tZONE, -HOUR (7) },/* Java */ { "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */ { "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */ #if 0 { "cast", tZONE, -HOUR (9.5) },/* Central Australian Standard */ { "cadt", tDAYZONE, -HOUR (9.5) },/* Central Australian Daylight */ #endif { "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */ { "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */ { "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */ { "nzt", tZONE, -HOUR (12) }, /* New Zealand */ { "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */ { "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */ { "idle", tZONE, -HOUR (12) }, /* International Date Line East */ { NULL } }; /* Military timezone table. */ static TABLE const MilitaryTable[] = { { "a", tZONE, HOUR ( 1) }, { "b", tZONE, HOUR ( 2) }, { "c", tZONE, HOUR ( 3) }, { "d", tZONE, HOUR ( 4) }, { "e", tZONE, HOUR ( 5) }, { "f", tZONE, HOUR ( 6) }, { "g", tZONE, HOUR ( 7) }, { "h", tZONE, HOUR ( 8) }, { "i", tZONE, HOUR ( 9) }, { "k", tZONE, HOUR ( 10) }, { "l", tZONE, HOUR ( 11) }, { "m", tZONE, HOUR ( 12) }, { "n", tZONE, HOUR (- 1) }, { "o", tZONE, HOUR (- 2) }, { "p", tZONE, HOUR (- 3) }, { "q", tZONE, HOUR (- 4) }, { "r", tZONE, HOUR (- 5) }, { "s", tZONE, HOUR (- 6) }, { "t", tZONE, HOUR (- 7) }, { "u", tZONE, HOUR (- 8) }, { "v", tZONE, HOUR (- 9) }, { "w", tZONE, HOUR (-10) }, { "x", tZONE, HOUR (-11) }, { "y", tZONE, HOUR (-12) }, { "z", tZONE, HOUR ( 0) }, { NULL } }; /* ARGSUSED */ static int yyerror (char *s) { return 0; } static int ToHour (int Hours, MERIDIAN Meridian) { switch (Meridian) { case MER24: if (Hours < 0 || Hours > 23) return -1; return Hours; case MERam: if (Hours < 1 || Hours > 12) return -1; if (Hours == 12) Hours = 0; return Hours; case MERpm: if (Hours < 1 || Hours > 12) return -1; if (Hours == 12) Hours = 0; return Hours + 12; default: abort (); } /* NOTREACHED */ } static int ToYear (int Year) { if (Year < 0) Year = -Year; /* XPG4 suggests that years 00-68 map to 2000-2068, and years 69-99 map to 1969-1999. */ if (Year < 69) Year += 2000; else if (Year < 100) Year += 1900; return Year; } static int LookupWord (char *buff) { register char *p; register char *q; register const TABLE *tp; int i; int abbrev; /* Make it lowercase. */ for (p = buff; *p; p++) if (ISUPPER (*p)) *p = tolower (*p); if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) { yylval.Meridian = MERam; return tMERIDIAN; } if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) { yylval.Meridian = MERpm; return tMERIDIAN; } /* See if we have an abbreviation for a month. */ if (strlen (buff) == 3) abbrev = 1; else if (strlen (buff) == 4 && buff[3] == '.') { abbrev = 1; buff[3] = '\0'; } else abbrev = 0; for (tp = MonthDayTable; tp->name; tp++) { if (abbrev) { if (strncmp (buff, tp->name, 3) == 0) { yylval.Number = tp->value; return tp->type; } } else if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } } for (tp = TimezoneTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } if (strcmp (buff, "dst") == 0) return tDST; for (tp = UnitsTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } /* Strip off any plural and try the units table again. */ i = strlen (buff) - 1; if (buff[i] == 's') { buff[i] = '\0'; for (tp = UnitsTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } buff[i] = 's'; /* Put back for "this" in OtherTable. */ } for (tp = OtherTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } /* Military timezones. */ if (buff[1] == '\0' && ISALPHA (*buff)) { for (tp = MilitaryTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } } /* Drop out any periods and try the timezone table again. */ for (i = 0, p = q = buff; *q; q++) if (*q != '.') *p++ = *q; else i++; *p = '\0'; if (i) for (tp = TimezoneTable; tp->name; tp++) if (strcmp (buff, tp->name) == 0) { yylval.Number = tp->value; return tp->type; } return tID; } static int yylex (void) { register char c; register char *p; char buff[20]; int Count; int sign; for (;;) { while (ISSPACE (*yyInput)) yyInput++; if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') { if (c == '-' || c == '+') { sign = c == '-' ? -1 : 1; if (!ISDIGIT (*++yyInput)) /* skip the '-' sign */ continue; } else sign = 0; for (yylval.Number = 0; ISDIGIT (c = *yyInput++);) yylval.Number = 10 * yylval.Number + c - '0'; yyInput--; if (sign < 0) yylval.Number = -yylval.Number; return sign ? tSNUMBER : tUNUMBER; } if (ISALPHA (c)) { for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';) if (p < &buff[sizeof buff - 1]) *p++ = c; *p = '\0'; yyInput--; return LookupWord (buff); } if (c != '(') return *yyInput++; Count = 0; do { c = *yyInput++; if (c == '\0') return c; if (c == '(') Count++; else if (c == ')') Count--; } while (Count > 0); } } #define TM_YEAR_ORIGIN 1900 /* Yield A - B, measured in seconds. */ static long difftm (struct tm *a, struct tm *b) { int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); int by = b->tm_year + (TM_YEAR_ORIGIN - 1); long days = ( /* difference in day of year */ a->tm_yday - b->tm_yday /* + intervening leap days */ + ((ay >> 2) - (by >> 2)) - (ay / 100 - by / 100) + ((ay / 100 >> 2) - (by / 100 >> 2)) /* + difference in years * 365 */ + (long) (ay - by) * 365 ); return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + (a->tm_min - b->tm_min)) + (a->tm_sec - b->tm_sec)); } time_t get_date (const char *p, const time_t *now) { struct tm tm, tm0, *tmp; time_t Start; yyInput = p; Start = now ? *now : time ((time_t *) NULL); tmp = (set_gmtime ? gmtime(&Start) : localtime (&Start)); yyYear = tmp->tm_year + TM_YEAR_ORIGIN; yyMonth = tmp->tm_mon + 1; yyDay = tmp->tm_mday; yyHour = tmp->tm_hour; yyMinutes = tmp->tm_min; yySeconds = tmp->tm_sec; yyMeridian = MER24; yyRelSeconds = 0; yyRelMinutes = 0; yyRelHour = 0; yyRelDay = 0; yyRelMonth = 0; yyRelYear = 0; yyHaveDate = 0; yyHaveDay = 0; yyHaveRel = 0; yyHaveTime = 0; yyHaveZone = 0; if (yyparse () || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) return -1; tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear; tm.tm_mon = yyMonth - 1 + yyRelMonth; tm.tm_mday = yyDay + yyRelDay; if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) { tm.tm_hour = ToHour (yyHour, yyMeridian); if (tm.tm_hour < 0) return -1; tm.tm_min = yyMinutes; tm.tm_sec = yySeconds; } else { tm.tm_hour = tm.tm_min = tm.tm_sec = 0; } tm.tm_hour += yyRelHour; tm.tm_min += yyRelMinutes; tm.tm_sec += yyRelSeconds; tm.tm_isdst = -1; tm0 = tm; Start = mktime (&tm); if (Start == (time_t) -1) { /* Guard against falsely reporting errors near the time_t boundaries when parsing times in other time zones. For example, if the min time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead of UTC, then the min localtime value is 1970-01-01 08:00:00; if we apply mktime to 1970-01-01 00:00:00 we will get an error, so we apply mktime to 1970-01-02 08:00:00 instead and adjust the time zone by 24 hours to compensate. This algorithm assumes that there is no DST transition within a day of the time_t boundaries. */ if (yyHaveZone) { tm = tm0; if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) { tm.tm_mday++; yyTimezone -= 24 * 60; } else { tm.tm_mday--; yyTimezone += 24 * 60; } Start = mktime (&tm); } if (Start == (time_t) -1) return Start; } if (yyHaveDay && !yyHaveDate) { tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7 + 7 * (yyDayOrdinal - (0 < yyDayOrdinal))); Start = mktime (&tm); if (Start == (time_t) -1) return Start; } if (yyHaveZone) { long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start)); if ((Start + delta < Start) != (delta < 0)) return -1; /* time_t overflow */ Start += delta; } return Start; } #if defined (TEST) /* ARGSUSED */ int main (int ac, char *av[]) { char buff[MAX_BUFF_LEN + 1]; time_t d; (void) printf ("Enter date, or blank line to exit.\n\t> "); (void) fflush (stdout); buff[MAX_BUFF_LEN] = 0; while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) { d = get_date (buff, (time_t *) NULL); if (d == -1) (void) printf ("Bad format - couldn't convert.\n"); else (void) printf ("%s", ctime (&d)); (void) printf ("\t> "); (void) fflush (stdout); } exit (0); /* NOTREACHED */ } #endif /* defined (TEST) */ ================================================ FILE: src/getname.c ================================================ #include "hypermail.h" #include "getname.h" #include "setup.h" extern char *set_domainaddr; static int blankstring(char *str) { register char *cp; for (cp = str; *cp; cp++) { if (*cp != ' ' && *cp != '\t' && *cp != '\r' && *cp != '\n') return (0); } return (1); } /* ** Grabs the name and email address from a From: header. ** This could get tricky; I've tried to keep it simple. ** Should be able to handle all the addresses below: ** ** From: user [no @] ** From: kent (Kent Landfield) [no @ - with comment] ** From: [no text name, use email as text name] ** From: Kent Landfield [text name but no @] ** From: (kent) [comment - no email address] ** From: "" [email address but null comment] ** From: [blank From: line] ** From: uu.net!kent [uucp addresses - no comment] ** From: uu.net!kent (kent) [uucp addresses - with comment] ** From: "(Joe Bloggs)" ** From: "Roy T. Fielding" ** From: kent@localhost ** From: kent@uu.net (Kent Landfield) ** From: (George Burgyan) ** From: (George Burgyan) ** From: Kent B. Landfield ** From: IN%"fekete+reply@c2.net" 26-JAN-1997 13:28:55.36 ** From: IN%"vicric@panix.com" "Vicki Richman" 13-AUG-1996 10:54:33.38 ** From: US2RMC::"lwv26@cas.org" "Larry W. Virden, x2487" 22-OCT-1994 09:44:21.44 ** From: Mail Delivery Subsystem ** From: Self ** From: adam@eden.apana.org.au (Adam Frey) ** From: faqserv@penguin-lust.mit.edu ** From: nc0548@freebsd.netcom.com (Mark Hittinger) ** From: "- Pam Greene, one of the *.answers moderators" ** From: "Felan shena Thoron'edras" ** From: David Muir Sharnoff ** From: A.J.Doherty@reading.ac.uk (Andy Doherty) ** From: Jordan Hubbard ** From: ZXPAN%SLACVM.BITNET@MITVMA.MIT.EDU ** From: afs!piz!alf@uu5.psi.com (Alf the Poet) ** From: answers@cp.tn.tudelft.nl ("Moderator *.answers") ** From: mdw%merengue@merengue.oit.unc.edu (Matt Welsh) ** From: bgoffe@whale.st.usm.edu (William L. Goffe) ** ** This is an interesting new one (1998-11-26): ** From: Name.Hidden@era.ericsson.se */ /* AUDIT biege: this code is really tricky and may lead to BOFs in email[] and/or name[] */ void getname(char *line, char **namep, char **emailp) { int i; int len; char *c; int comment_fnd; char email[MAILSTRLEN]; char name[NAMESTRLEN]; len = MAILSTRLEN - 1; comment_fnd = 0; /* ** Zero out data storage. */ memset(email, 0, MAILSTRLEN); memset(name, 0, NAMESTRLEN); *namep = NULL; *emailp = NULL; /* EMail Processing First: ** First, is there an '@' sign we can use as an anchor ? */ if ((c = hm_strchr(line, '@')) == NULL) { /* ** No '@' sign here so ... */ if (strchr(line, '(')) { /* From: bob (The Big Guy) */ c = strchr(line, ':') + 1; while (*c == ' ' || *c == '\t') c++; for (i = 0; *c && *c != '(' && *c != ' ' && *c != '\t' && *c != '\n' && i < len; c++) email[i++] = *c; email[i] = '\0'; } else if ((c = strchr(line, '<'))) { /* From: */ c++; for (i = 0; *c && *c != '>' && *c != ' ' && *c != '\t' && *c != '\n' && i < len; c++) email[i++] = *c; email[i] = '\0'; } else { /* ** - check to see if the From: line is blank, (taken care of) ** - check if From: uu.net!kent formatted line ** - check if "From: kent" formatted line */ c = strchr(line, ':') + 1; while (*c == ' ' || *c == '\t') c++; for (i = 0; *c && *c != ' ' && *c != '\t' && *c != '\n' && *c != ',' && i < len; c++) email[i++] = *c; email[i] = '\0'; } if (email[0] == '\0') /* Was it a junk From line ? */ strcpymax(email, NOEMAIL, MAILSTRLEN); else if (use_domainaddr) { /* * check if site domainizes addresses * but don't modify uucp addresses */ if ((c = strchr(email, '!')) == NULL) { if (strlen(email) < len) { strcat(email, "@"); strncat(email, set_domainaddr, len-strlen(email)); } } } } else { while (*c != ' ' && *c != '\t' && *c != '<' && *c != '"' && *c != ':') c--; c++; for (i = 0; *c && *c != '>' && *c != ' ' && *c != '\t' && *c != '"' && *c != '\n' && *c != ']' && *c != ',' && i < len; c++) email[i++] = *c; email[i] = '\0'; } /* * NAME Processing - Boy are there a bunch of funky formats here. * No promises... I'll do my best. Let me know * what I missed... */ if (strchr(line, '<')) { c = strchr(line, ':') + 1; while (*c == ' ' || *c == '\t') c++; /* if a comment then just look for the end point */ if (*c == '\"') { int rmparen = 0; ++c; if (*c == '(') { ++c; rmparen = 1; } for (i = 0, len = NAMESTRLEN - 1; *c && *c != '\"' && *c != '\n' && i < len; c++) name[i++] = *c; if (rmparen && name[(i - 1)] == ')') --i; /* get rid of "(name-comment)" parens */ comment_fnd = 1; } else if (hm_strchr(line, '(')) { c = hm_strchr(line, '(') + 1; if (*c == '"') /* is there a comment in the comment ? */ c++; } else if (*c == '<') { /* Comment may be on the end */ /* From: Bill Campbell */ char *c2 = strchr(line, '>'); if (c2 != NULL) { c = c2 + 1; for (i = 0, len = NAMESTRLEN - 1; *c && *c != '\n' && i < len; c++) { name[i++] = *c; } comment_fnd = 1; } } } else if (strchr(line, '(')) { c = strchr(line, '('); c++; if (*c == '"') /* is there a comment in the comment ? */ c++; while (*c == ' ' || *c == '\t') c++; } else if (strchr(line, '[')) { c = strchr(line, ':') + 1; while (*c == ' ' || *c == '\t') c++; for (i = 0, len = NAMESTRLEN - 1; *c && *c != '\"' && *c != '[' && *c != '\n' && i < len; c++) name[i++] = *c; name[--i] = '\0'; comment_fnd = 1; } else { /* * Is there an email address available * that we can use for the name ? */ if (!strcmp(email, NOEMAIL)) /* No */ strcpymax(name, NONAME, NAMESTRLEN); else { c = email + strlen(email) - 1; while (isspace(*c)) *c-- = '\0'; strcpymax(name, email, NAMESTRLEN); /* Yes */ } *namep = strsav(name); *emailp = strsav(email); return; } if (!comment_fnd) { int in_ascii = TRUE, esclen = 0; for (i = 0, len = NAMESTRLEN - 1; *c && *c != '<' && *c != '\"' && *c != ')' && *c != '(' && *c != '\n' && i < len; c++) { if (set_iso2022jp) { iso2022_state(c, &in_ascii, &esclen); if (esclen) { for (; esclen; esclen--, c++) name[i++] = *c; for (; in_ascii == FALSE && i < len; c++, iso2022_state(c, &in_ascii, &esclen)) { name[i++] = *c; } c--; } else { name[i++] = *c; } } else { name[i++] = *c; } } } if (i > 0 && name[i - 1] == ' ' && (*c == '<' || *c == '(')) name[--i] = '\0'; else name[i] = '\0'; /* * Is the name string blank ? If so then * force it to get filled with something. */ if (blankstring(name)) name[0] = '\0'; /* Bailing and taking the easy way out... */ if (name[0] == '\0') { if (email[0] == '\0') strcpymax(name, NONAME, NAMESTRLEN); else strcpymax(name, email, NAMESTRLEN); } /* * need to strip spaces off the end of * the email and name strings */ c = email + (strlen(email) - 1); while (c > email && isspace(*c)) *c-- = '\0'; *namep = strsav(name); *emailp = strsav(email); } ================================================ FILE: src/getname.h ================================================ void getname(char *, char **, char **); ================================================ FILE: src/hypermail.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #define MAIN_FILE 1 #include "hypermail.h" #ifdef __LCC__ #include "../lcc/defaults.h" #else #include "defaults.h" #endif #include "setup.h" #include "parse.h" #include "print.h" #include "finelink.h" #include "search.h" #include "struct.h" #ifdef HAVE_LOCALE_H #include #endif /* #include */ extern int getopt(int, char *const *, const char *); extern char *optarg; extern int optind; extern int opterr; /* ** Prints user startup errors stops. */ void cmderr(char *errorstr) { fprintf(stderr, "\n%s: %s: %s\n", lang[MSG_ERROR], PROGNAME, errorstr); usage(); unlock_archive(); exit(-1); } /* ** Prints a program error string and stops. */ void progerr(char *errorstr) { fprintf(stderr, "%s: %s\n", PROGNAME, errorstr); unlock_archive(); exit(-1); } static char *expand_contents(char *variable) { char *return_value = NULL; /* * Potentially read the header and footer files. Check to make * sure the value is a valid file or else assure the original * value is there. */ if (variable) { /* * Check if valid filename. If not then just return the * variable listed. * NOTE !! This really should be an error message! */ if (isfile(variable)) { /* * Now try to assign the contents of the file to * the return value. If it is able to read the file * then free the existing storage and return. * If not then just return the existing value. * NOTE !! This really should be an error message! */ return_value = getfilecontents(variable); } } return return_value; } char *setindex(char *dfltindex, char *indextype, char *suffix) { char *p, *rp; p = (!strcmp(dfltindex, indextype)) ? INDEXNAME : indextype; rp = (char *)emalloc(strlen(p) + strlen(suffix) + 2); sprintf(rp, "%s.%s", p, suffix); return (rp); } /* Print out the version number and die. */ void version(void) { printf("%s: %s: %s %s: %s\n", PROGNAME, lang[MSG_VERSION], VERSION, lang[MSG_PATCHLEVEL], PATCHLEVEL); exit(0); } /* ** Prints the usage. */ void usage(void) { struct language_entry *lte; printf("%s: %s [options]\n", lang[MSG_USAGE], PROGNAME); printf("%s:\n", lang[MSG_OPTIONS]); printf(" -a URL : %s\n", lang[MSG_OPTION_A]); printf(" -A : %s\n", lang[MSG_OPTION_ARCHIVE]); printf(" -b URL : %s\n", lang[MSG_OPTION_B]); printf(" -c file : %s\n", lang[MSG_OPTION_C]); printf(" -d dir : %s\n", lang[MSG_OPTION_D]); #ifdef GDBM printf(" -g : %s\n", lang[MSG_OPTION_G]); #else printf(" [ -g : %s ]\n", lang[MSG_OPTION_G_NOT_BUILD_IN]); #endif printf(" -i : %s\n", lang[MSG_OPTION_I]); printf(" -l label : %s\n", lang[MSG_OPTION_L]); printf(" -m mbox : %s\n", lang[MSG_OPTION_M]); printf(" -M : %s\n", "Use metadata"); printf(" -n listaddr : %s\n", lang[MSG_OPTION_N]); printf(" -o keyword=val: Set config item\n"); printf(" -p : %s\n", lang[MSG_OPTION_P]); printf(" -s htmlsuffix : %s\n", "HTML file suffix (.html, .htm, ..)"); printf(" -t : %s\n", "Use Tables"); printf(" -T : %s\n", "Use index tables"); printf(" -u : %s\n", lang[MSG_OPTION_U]); printf(" -v : %s\n", lang[MSG_OPTION_VERBOSE]); printf(" -V : %s\n", lang[MSG_OPTION_VERSION]); printf(" -x : %s\n", lang[MSG_OPTION_X]); printf(" -X : %s\n", lang[MSG_OPTION_XML]); printf(" -1 : %s\n", lang[MSG_OPTION_1]); printf(" -L lang : %s (", lang[MSG_OPTION_LANG]); /* Print out languages supported */ lte = <able[0]; while (lte->langcode != NULL) { printf("%s ", lte->langcode); lte++; } printf(")\n"); printf("%s : %s\n", lang[MSG_VERSION], VERSION); printf("%s : %s\n", lang[MSG_PATCHLEVEL], PATCHLEVEL); printf("%s : %s\n\n", lang[MSG_DOCS], HMURL); exit(1); } int main(int argc, char **argv) { int i, use_stdin, use_mbox; char *configfile = NULL; char **tlang, *locale_code; int cmd_show_variables; int print_usage; int amount_old = 0; /* number of old mails */ int amount_new = 0; /* number of new mails */ #ifdef HAVE_LOCALE_H setlocale(LC_ALL, ""); #endif lockfile[0] = '\0'; use_stdin = 0; print_usage = 0; use_mbox = 0; firstdatenum = lastdatenum = 0; configfile = strsav(CONFIGFILE); cmd_show_variables = 0; opterr = 0; #define GETOPT_OPTSTRING ("a:Ab:c:d:gil:L:m:n:o:ps:tTuvVxX0:1M?") /* get pre config options here */ while ((i = getopt(argc, argv, GETOPT_OPTSTRING)) != -1) { switch ((char)i) { case 'c': configfile = strreplace(configfile, optarg); break; case 'v': cmd_show_variables = TRUE; break; case 'V': version(); /*NOTREACHED*/ case 'a': case 'A': case 'b': case 'd': case 'g': case 'i': case 'l': case 'L': case 'm': case 'n': case 'o': case 'p': case 's': case 't': case 'T': case 'u': case 'x': case 'X': case '0': case '1': case 'M': break; case '?': default: /* * Because we need to setup the language support, * printing of the usage message must be deferred * until the proper language is determined. */ print_usage = 1; break; } } /* * ...then read the configuration file. */ readconfigs(configfile, cmd_show_variables); /* reset the getopt() index variable */ optind = 1; /* now get the post-config options! */ while ((i = getopt(argc, argv, GETOPT_OPTSTRING)) != -1) { switch ((char)i) { case 'A': set_append = 1; break; case 'a': set_archives = strreplace(set_archives, optarg); break; case 'b': set_about = strreplace(set_about, optarg); break; case 'c': /* config file from pre-config options */ break; case 'd': set_dir = strreplace(set_dir, optarg); break; case 'g': set_usegdbm = 1; break; case 'i': use_stdin = TRUE; break; case 'l': set_label = strreplace(set_label, optarg); break; case 'L': set_language = strreplace(set_language, optarg); break; case 'm': set_mbox = strreplace(set_mbox, optarg); break; case 'n': set_hmail = strreplace(set_hmail, optarg); break; case 'o': ConfigAddItem(optarg); break; case 'p': set_showprogress = TRUE; break; case 's': set_htmlsuffix = strreplace(set_htmlsuffix, optarg); break; case 't': set_usetable = TRUE; break; case 'T': set_indextable = TRUE; break; case 'u': set_increment = TRUE; break; case 'v': cmd_show_variables = TRUE; break; case 'x': set_overwrite = TRUE; break; case 'X': set_writehaof = TRUE; break; case '0': set_delete_msgnum = add_list(set_delete_msgnum, optarg); break; case '1': set_readone = TRUE; break; case 'M': set_usemeta = TRUE; break; case 'N': set_nonsequential = TRUE; break; case '?': default: break; } } #ifdef DEBUG dump_config(); exit(0); #endif /* * Now override the configuration file variables with any explicitly * passed on the command line. This way you need not change the * configuration file settings for a minor change in a single run. */ /* * Check and make sure that the supplied language is a * valid language. Otherwise strange things happen quickly. */ if (strlen(set_language) > 2) { locale_code = strsav(set_language); set_language[2] = 0; /* shorten to 2-letter code */ } else locale_code = NULL; if ((tlang = valid_language(set_language, &locale_code)) == NULL) { snprintf(errmsg, sizeof(errmsg), "\"%s\" %s.", set_language, lang[MSG_LANGUAGE_NOT_SUPPORTED]); cmderr(errmsg); } #ifdef HAVE_LOCALE_H if (!setlocale(LC_ALL, locale_code)) { char *rv; if (!strcmp(locale_code, "en_US")) { /* many systems now install by defualt en_US.UTF-8. Here we assume that the mapping between en_US and en_US.UTF-8 in system messages is identical. We cannot do the same for other languages, though */ rv = setlocale(LC_ALL, "en_US.UTF-8"); } if (!rv) { snprintf(errmsg, sizeof(errmsg), "WARNING: locale \"%s\", not supported.\n", locale_code); fprintf(stderr, "%s", errmsg);/* AUDIT biege: avoid format-bug warning */ } } #endif lang = tlang; /* A good language, make it so. */ if (print_usage) /* Print the usage message and terminate */ usage(); #ifndef GDBM if (set_usegdbm) { fprintf(stderr, "%s: %s\n", PROGNAME, lang[MSG_OPTION_G_NOT_BUILD_IN]); usage(); } #endif #ifndef HAVE_LIBFNV if (set_nonsequential) progerr("Hypermail isn't built with the libfnv hash library.\n" "You cannot use the nonsequential option.\n"); #endif /* HAVE_LIBFNV */ if (set_mbox && !strcasecmp(set_mbox, "NONE")) { use_stdin = TRUE; } /* the list of headers that we always show and that we want to avoid showing twice when printing the body */ set_skip_headers = add_list(set_skip_headers, "from"); set_skip_headers = add_list(set_skip_headers, "date"); set_skip_headers = add_list(set_skip_headers, "subject"); /* * Did they decide to use stdin by specifying it on the command line ? * If not then check and see if that is the default they wanted from * the options.h or environment values. */ if (!use_stdin) { if (optind < argc && set_increment == -1 && !set_mbox) { set_mbox = strsav(argv[optind]); } else if (!set_mbox || !strcasecmp(set_mbox, "NONE")) use_stdin = TRUE; else use_stdin = FALSE; } else { if (set_mbox) free(set_mbox); set_mbox = NULL; } /* ** Deprecated options */ if (set_showhr) { fprintf (stderr, "The \"showhr\" option has been deprecated. Ignoring it.\n"); set_showhr = FALSE; } if (set_usetable) { fprintf (stderr, "The \"usetable\" option has been deprecated. Ignoring it.\n"); set_usetable = FALSE; } /* * Read the contents of the file into the variables to be used * in printing out the pages. */ ihtmlheaderfile = expand_contents(set_ihtmlheader); ihtmlfooterfile = expand_contents(set_ihtmlfooter); ihtmlheadfile = expand_contents(set_ihtmlhead); ihtmlhelpupfile = expand_contents(set_ihtmlhelpup); ihtmlhelplowfile = expand_contents(set_ihtmlhelplow); ihtmlnavbar2upfile = expand_contents(set_ihtmlnavbar2up); mhtmlheaderfile = expand_contents(set_mhtmlheader); mhtmlfooterfile = expand_contents(set_mhtmlfooter); if (set_dir) set_dir = strreplace(set_dir, dirpath(set_dir)); /* * Default names for directories and labels need to be figured out. */ if (use_stdin && (!set_dir || !strcasecmp(set_dir, "NONE"))) set_dir = strreplace(set_dir, DIRNAME); if (!set_dir || !strcasecmp(set_dir, "NONE")) set_dir = strreplace(set_dir, (strrchr(set_mbox, '/')) ? strrchr(set_mbox, '/') + 1 : set_mbox); if (set_dir[strlen(set_dir) - 1] != PATH_SEPARATOR) trio_asprintf(&set_dir, "%s%c", set_dir, PATH_SEPARATOR); if (!set_label || !strcasecmp(set_label, "NONE")) set_label = set_mbox ? (strreplace(set_label, (strrchr(set_mbox, '/')) ? strrchr(set_mbox, '/') + 1 : set_mbox)) : "stdin"; /* * Which index file will be called "index.html"? */ index_name[1][DATE_INDEX] = setindex(set_defaultindex, "date", set_htmlsuffix); index_name[1][THREAD_INDEX] = setindex(set_defaultindex, "thread", set_htmlsuffix); index_name[1][SUBJECT_INDEX] = setindex(set_defaultindex, "subject", set_htmlsuffix); index_name[1][AUTHOR_INDEX] = setindex(set_defaultindex, "author", set_htmlsuffix); if (set_attachmentsindex) { index_name[1][ATTACHMENT_INDEX] = setindex(set_defaultindex, "attachment", set_htmlsuffix); } if (set_folder_by_date || set_msgsperfolder) { index_name[0][DATE_INDEX] = setindex(set_default_top_index, "date", set_htmlsuffix); index_name[0][THREAD_INDEX] = setindex(set_default_top_index, "thread", set_htmlsuffix); index_name[0][SUBJECT_INDEX] = setindex(set_default_top_index, "subject", set_htmlsuffix); index_name[0][AUTHOR_INDEX] = setindex(set_default_top_index, "author", set_htmlsuffix); if (set_attachmentsindex) { index_name[0][ATTACHMENT_INDEX] = setindex(set_default_top_index, "attachment", set_htmlsuffix); } index_name[0][FOLDERS_INDEX] = setindex(set_default_top_index, "folders", set_htmlsuffix); } else { index_name[0][DATE_INDEX] = index_name[1][DATE_INDEX]; index_name[0][THREAD_INDEX] = index_name[1][THREAD_INDEX]; index_name[0][AUTHOR_INDEX] = index_name[1][AUTHOR_INDEX]; index_name[0][SUBJECT_INDEX] = index_name[1][SUBJECT_INDEX]; index_name[0][ATTACHMENT_INDEX] = index_name[1][ATTACHMENT_INDEX]; } init_index_names(); if (set_msgsperfolder && set_folder_by_date) { progerr("msgsperfolder and folder_by_date may not be used at the same time!"); } /* * General settings for mail command and rewriting. */ if (!set_domainaddr || !strcasecmp(set_domainaddr, "NONE")) use_domainaddr = 0; else use_domainaddr = 1; if (!set_mailto || !strcasecmp(set_mailto, "NONE")) use_mailto = 0; else use_mailto = 1; if (!set_mailcommand || !strcasecmp(set_mailcommand, "NONE")) use_mailcommand = 0; else use_mailcommand = 1; #ifndef HAVE_LIBFNV /* the nonsequential mode won't work unless we compiled the FNV hash library (./configure --enable-libfnv) */ if (set_nonsequential) progerr("the nonsequential mode is only available if you enabled the\n compilation" "of the fnv hash library. Try doing a\n\t./configure --enable-libfnv\n" "and recompile if you want to use this option."); #endif /* HAVE_LIBFNV */ /* * A little performance speed up. The following was being done * over and over in the write functions. This way it is done once. * A bigger win on larger archives. */ if (set_hmail && !strcasecmp(set_hmail, "NONE")) { free(set_hmail); set_hmail = NULL; } if (set_archives && !strcasecmp(set_archives, "NONE")) { free(set_archives); set_archives = NULL; } if (set_custom_archives && !strcasecmp(set_custom_archives, "NONE")) { free(set_custom_archives); set_custom_archives = NULL; } if (set_about && !strcasecmp(set_about, "NONE")) { free(set_about); set_about = NULL; } /* Simply show what the values of the variables are and exit */ if (cmd_show_variables) { if (!set_mbox) set_mbox = "NONE"; MakeConfig(TRUE); free(configfile); return (0); } /* Injecting a little sanity... */ if (use_mbox && use_stdin) { cmderr(lang[MSG_CANNOT_READ_FROM_BOTH_FILE_AND_STDIN]); } if (set_append && use_mbox) { cmderr(lang[MSG_CANNOT_BOTH_READ_AND_WRITE_TO_MBOX]); } gettimezone(); getthisyear(); /* * MIME processing requires the files be created as they * are read in loadheaders() so assure the directories are * there first... */ checkdir(set_dir); /* * Let's do it. */ if (set_uselock) lock_archive(set_dir); if (set_increment == -1) { int save_append = set_append; set_append = 0; if (set_mbox_shortened) progerr("can not use increment = -1 option with mbox_shortened option\n"); amount_new = parsemail(set_mbox, use_stdin, 1, -1, set_dir, set_inlinehtml, 0); set_increment = !matches_existing(set_startmsgnum); if (set_increment && set_folder_by_date && !set_usegdbm) progerr("folder_by_date with incremental update requires usegdbm option"); reinit_structs(); set_append = save_append; } if (set_increment) { int num_displayable; int num_added; if (set_linkquotes) replylist = NULL; /* we have to start with the msgnum - 1 so that the rest of the code works ok when there are no old headers. */ max_msgnum = set_startmsgnum - 1; num_displayable = loadoldheaders(set_dir); amount_old = max_msgnum + 1; /* counts gaps as messages */ /* start numbering at this number */ num_added = parsemail(set_mbox, use_stdin, set_readone, set_increment, set_dir, set_inlinehtml, amount_old); if (num_added > 0) { amount_new = num_displayable + num_added; if (set_linkquotes) analyze_headers(max_msgnum + 1); /* write the index of msgno/msgid_hash filenames */ if (set_nonsequential) write_messageindex(0, max_msgnum + 1); writearticles(amount_old, max_msgnum + 1); /* JK: in function of other hypermail configuration options, delete_incremental will continuous escape and add more markup to non-deleted messages that are replies to deleted messages. Thus, a setup option to disable it */ if (set_delete_incremental && deletedlist) update_deletions(amount_old); if (set_show_msg_links) { fixnextheader(set_dir, amount_old, -1); for (i = amount_old; i <= max_msgnum; ++i) { if (set_showreplies) fixreplyheader(set_dir, i, 0, amount_old); fixthreadheader(set_dir, i, amount_old); } } } } else { if (set_mbox_shortened) { if (!set_usegdbm) progerr("mbox_shortened option requires that the usegdbm option be on"); max_msgnum = set_startmsgnum - 1; loadoldheaders(set_dir); } amount_new = parsemail(set_mbox, use_stdin, set_readone, set_increment, set_dir, set_inlinehtml, set_startmsgnum); /* number from 0 */ if (!set_mbox_shortened && !matches_existing(0)) { progerr("First message in mailbox does not " "match first message in archive\n" "or obsolete gdbm file present.\n" "Maybe you want to enable the mbox_shortened option?\n"); } if (set_linkquotes) analyze_headers(max_msgnum + 1); /* write the index of msgno/msgid_hash filenames */ if (set_nonsequential) write_messageindex(0, max_msgnum + 1); writearticles(0, max_msgnum + 1); } if (amount_new) { /* Always write the index files */ if (set_linkquotes) { threadlist = NULL; threadlist_end = NULL; printedthreadlist = NULL; for (i = 0; i <= max_msgnum; ++i) { struct emailinfo *ep; if (hashnumlookup(i, &ep)) { ep->flags &= ~USED_THREAD; #ifdef FASTREPLYCODE ep->isreply = 0; #endif } threadlist_by_msgnum[i] = NULL; } /* redo threading with more complete info than in 1st pass */ crossindexthread1(datelist); for (i = 0; i <= max_msgnum; ++i) { struct emailinfo *ep, *etmp; hashnumlookup(i, &ep); etmp = nextinthread(i); if (etmp && ep->initial_next_in_thread != etmp->msgnum) fixthreadheader(set_dir, etmp->msgnum, amount_new); /* if (ep->flags & THREADING_ALTERED) */ } } count_deleted(max_msgnum + 1); if (show_index[0][DATE_INDEX]) writedates(amount_new, NULL); if (show_index[0][THREAD_INDEX]) writethreads(amount_new, NULL); if (show_index[0][SUBJECT_INDEX]) writesubjects(amount_new, NULL); if (show_index[0][AUTHOR_INDEX]) writeauthors(amount_new, NULL); if (set_attachmentsindex) { writeattachments(amount_new, NULL); } if (set_writehaof) writehaof(amount_new, NULL); if (set_folder_by_date || set_msgsperfolder) write_toplevel_indices(amount_new); if (set_monthly_index || set_yearly_index) write_summary_indices(amount_new); if (set_latest_folder) symlink_latest(); } else { printf("No mails to output!\n"); } if (set_uselock) unlock_archive(); if (configfile) free(configfile); if (ihtmlheaderfile) free(ihtmlheaderfile); if (ihtmlfooterfile) free(ihtmlfooterfile); if (ihtmlheadfile) free(ihtmlheadfile); if (ihtmlhelpupfile) free(ihtmlhelpupfile); if (ihtmlhelplowfile) free(ihtmlhelplowfile); if (ihtmlnavbar2upfile) free(ihtmlnavbar2upfile); if (mhtmlheaderfile) free(mhtmlheaderfile); if (mhtmlfooterfile) free(mhtmlfooterfile); return (0); } ================================================ FILE: src/hypermail.h ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef _HYPERMAIL_HYPERMAIL_H #define _HYPERMAIL_HYPERMAIL_H #ifndef MAIN_FILE #define VAR extern #else #define VAR #endif #ifdef __LCC__ #include "../lcc/config.h" #else #include "../config.h" #endif #include "../patchlevel.h" #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef TM_IN_SYS_TIME #include #else #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_PWD_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_GDBM_H #define GDBM 1 #endif #ifdef NO_MACRO #undef isspace #undef isdigit #undef isalpha #undef isupper #undef islower #undef isxdigit #undef isalnum #undef ispunct #undef isprint #undef isgraph #undef iscntrl #undef isascii #endif /* * this redefines the standard *printf() to use ours */ #define TRIO_REPLACE_STDIO #define HAVE_SSCANF /* avoid problems in setup.c with trio_sscanf */ #include #ifndef NO_FASTREPLYCODE #define FASTREPLYCODE #endif #undef FALSE #define FALSE 0 #undef TRUE #define TRUE 1 #define PROGNAME "hypermail" #define HMURL "http://www.hypermail-project.org/" #define INDEXNAME "index" #define DIRNAME "archive" #define NONAME "(no name)" #define NODATE "(no date)" #define NOEMAIL "(no email)" #define NOSUBJECT "(no subject)" #define GDBM_INDEX_NAME ".hm2index" /* Name of the Hypertext Archive Overview File an XML file * which contains pointers to the various index files * and some header information about each mail * to allow further processing */ #define HAOF_NAME "archive_overview.haof" #define NUMSTRLEN 10 #define MAXLINE 1024 #define MAXFILELEN 256 #define NAMESTRLEN 320 #define MAILSTRLEN 80 #define DATESTRLEN 80 #define MSGDSTRLEN 256 #define REPYSTRLEN 256 #define SUBJSTRLEN 256 #define URLSTRLEN 256 #define HOSTSTRLEN 256 #define TITLESTRLEN 64 #define HASHSIZE 673 #define SHORTDATELEN 12 #define TIMEZONELEN 10 #define YEARLEN 5 #define BASEYEAR 1970 #define DAYSPERYEAR 365 #define SECSPERMIN 60 #define SECSPERHOUR 3600 #define SECSPERDAY 86400 #define IS_LEAP(y) (y > 1752 && (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))) #define PAGE_TOP 1 #define PAGE_BOTTOM 2 typedef enum { DATE_INDEX, THREAD_INDEX, SUBJECT_INDEX, AUTHOR_INDEX, ATTACHMENT_INDEX, FOLDERS_INDEX, NO_INDEX } mindex_t; typedef enum { FILTERED_DELETE = 1, /*spam */ FILTERED_EXPIRE = 2, FILTERED_OUT = 4, FILTERED_REQUIRED = 8, FILTERED_OLD = 16, FILTERED_NEW = 32, FILTERED_DELETE_OTHER = 64 } filtered_reason_t; typedef enum { ANNOTATION_ROBOT_NONE = 0, ANNOTATION_ROBOT_NO_FOLLOW = 1, ANNOTATION_ROBOT_NO_INDEX = 2 } annotation_robot_t; typedef enum { ANNOTATION_CONTENT_NONE = 0, ANNOTATION_CONTENT_EDITED = 1, ANNOTATION_CONTENT_DELETED_OTHER = 2, ANNOTATION_CONTENT_DELETED_SPAM = 4 } annotation_content_t; typedef enum { FORMAT_FIXED = 0, FORMAT_FLOWED = 1 } textplain_format_t; /* conversions supported by string.c:parseemail() */ typedef enum { MAKEMAILCOMMAND = 1, /* makes links clickable */ REPLACE_DOMAIN = 2, /* replaces domain by antispamdomain */ } parseemail_conversion_t; /* * Path separator for attachment file path generation */ #define PATH_SEPARATOR '/' /* ** Use this struct to build expandable buffers. Quick and easy. ** Daniel 1998-11-17. */ struct Push { char *string; size_t len; size_t alloc; }; #define INIT_PUSH(x) memset(&(x), 0, sizeof(struct Push)) #define RETURN_PUSH(x) return (x).string #define PUSH_STRING(x) (x).string #define PUSH_STRLEN(x) (x).len struct reply { int frommsgnum; int msgnum; struct emailinfo *data; int maybereply; /* 0 means pretty sure msgnum is reply to frommsgnum; */ /* 1 means there is doubt. */ struct reply *next; }; struct body { char *line; char html; /* set to TRUE if already converted to HTML */ char header; /* part of header */ char parsedheader; /* this header line has been parsed once */ char attached; /* part of attachment */ char demimed; /* if this is a header, this is set to TRUE if it has passed the decoderfc2047() function */ int format_flowed; /* TRUE if this a text/plain f=f line */ int msgnum; struct body *next; }; struct printed { int msgnum; struct printed *next; }; struct hmlist { char *val; struct hmlist *next; }; struct hashemail { struct emailinfo *data; struct hashemail *next; }; struct emailsubdir { /* used by set_folder_by_date, set_msgsperfolder */ struct emailinfo *first_email; struct emailinfo *last_email; struct emailsubdir *prior_subdir; struct emailsubdir *next_subdir; char *subdir; char *full_path; char *rel_path_to_top; /* usually "../", sometimes "../../" */ /* will be absolute url if set_base_url != 0 */ int count; char *description; /* label to go in folders.html */ time_t a_date; /* date of msg which first generated this subdir. not guaranteed to be earliest date in subdir */ }; struct emailinfo { int msgnum; char *name; char *emailaddr; char *fromdatestr; time_t fromdate; char *datestr; time_t date; char *msgid; char *subject; char *unre_subject; char *inreplyto; char *charset; /* added in 2b10 */ long datenum; /* moved here from 'struct header' */ long flags; /* added 1999-03-19 for the new thread output functions */ #define PRINT_THREAD 1 /* set if already used in the thread output */ #define USED_THREAD 2 /* set if already stored in threadlist */ int initial_next_in_thread; /* msgnum written as next during normal print*/ struct body *bodylist; #ifdef FASTREPLYCODE struct reply *replylist; /* list all possible direct replies to this */ int isreply; #endif struct emailsubdir *subdir; /* NULL unless set_msgsperfolder or set_folder_by_date */ annotation_robot_t annotation_robot; /* special metada for controlling how robots index a message */ long exp_time; annotation_content_t annotation_content; /* annotations concerning the content of the message (edited, spam, deleted) */ int is_deleted; /* 1=deleted (spam), 2=expired, 4=filtered out, */ /* 8=filtered (required line missing), 16=deleted (other) */ int deletion_completed; /* -1 or delete_level that reflects last time */ /* that file was rewritten to reflect is_deleted */ }; struct header { struct emailinfo *data; struct header *left; struct header *right; }; struct attach { char *contenttype; char *name; char *id; char *storedas; /* filename used for storage */ char *descr; /* "Content-Description" */ struct attach *next; }; /* MIME Support */ #define BODY_NONE 0 #define BODY_CONTINUE (1<<0) /* this is a continued line */ #define BODY_HTMLIZED (1<<1) /* this is already htmlified */ #define BODY_HEADER (1<<2) /* this is a header line */ #define BODY_ATTACHED (1<<3) /* this line was attached */ #define BODY_FORMAT_FLOWED (1<<4) /* this line is format-flowed */ #define BODY_DEL_SSQ (1<<5) /* remove both space stuffing and * quotes where applicable for f=f */ struct boundary { struct boundary *next; struct boundary *prev; char *line; }; struct charset_stack { struct charset_stack *next; struct charset_stack *prev; char *charset; char *charsetsave; }; VAR struct header *subjectlist; VAR struct header *authorlist; VAR struct header *datelist; VAR struct hashemail *deletedlist; VAR struct reply *replylist; VAR struct reply *replylist_end; /* last node in replylist */ VAR struct reply *threadlist; VAR struct reply *threadlist_end; /* last node in threadlist */ VAR struct reply **threadlist_by_msgnum; /* array of ptrs into threadlist */ VAR struct printed *printedlist; VAR struct printed *printedthreadlist; VAR struct hashemail *etable[HASHSIZE]; VAR struct emailsubdir *folders; VAR struct hmlist *show_headers; VAR char timezonestr[TIMEZONELEN]; VAR char thisyear[YEARLEN]; VAR char errmsg[MAXLINE]; VAR char lockfile[MAXFILELEN]; #if 0 /* replaced by index_name */ VAR char *authname; /* By author index file */ VAR char *datename; /* By date index file */ VAR char *subjname; /* By subject index file */ VAR char *thrdname; /* By thread index file */ VAR char *attname; /* By attachment index file */ VAR char *top_index[NO_INDEX]; #endif #define MAX_DIRECTORY_LEVELS 2 VAR char *index_name[MAX_DIRECTORY_LEVELS][NO_INDEX]; VAR int show_index[MAX_DIRECTORY_LEVELS][NO_INDEX]; VAR char *antispamdomain; VAR int use_mailcommand; VAR int use_mailto; VAR int use_domainaddr; VAR char *ihtmlheaderfile; VAR char *ihtmlfooterfile; VAR char *ihtmlheadfile; VAR char *ihtmlhelpupfile; VAR char *ihtmlhelplowfile; VAR char *ihtmlnavbar2upfile; VAR char *mhtmlheaderfile; VAR char *mhtmlfooterfile; VAR long firstdatenum; VAR long lastdatenum; VAR int max_msgnum; VAR char **msgnum_id_table; VAR const char *latest_folder_path; #ifdef MAIN_FILE /* ** months[] and days[] should not be converted to native ** language since these are used in protocol and SMTP date parsing. */ char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; char *days[] = { "Sun ", "Mon ", "Tue ", "Wed ", "Thu ", "Fri ", "Sat ", NULL }; #else extern char *months[], *days[]; #endif #include "proto.h" #include "lang.h" #ifdef lint extern int strcasecmp(const char *, const char *); extern int strncasecmp(const char *, const char *, size_t); #endif #endif /* ! _HYPERMAIL_HYPERMAIL_H */ ================================================ FILE: src/lang.c ================================================ #ifdef LANG_PROG #define MAIN_FILE #endif #include #include "hypermail.h" char **valid_language(char *lg, char **locale_code) { struct language_entry *lte; if (!strcmp(lg, "se")) { printf("Warning: language code 'se' not supported. Using 'sv' (Swedish) instead.\n"); lg = "sv"; } lte = <able[0]; while (lte->langcode != NULL) { if (strcmp(lg, lte->langcode) == 0) { if (locale_code != NULL && *locale_code == NULL) *locale_code = lte->locale_code; return (lte->mtable); } lte++; } return (NULL); } #ifdef LANG_PROG extern char *optarg; extern int opterr; int main(int argc, char **argv) { char *progname; char *language = "en"; int c; int verbose = 0; int print_table = 0; opterr = 0; progname = argv[0]; if (argc > 1) { while ((c = getopt(argc, argv, "L:tv")) != EOF) { switch (c) { case 'v': verbose++; break; case 'L': language = optarg; break; case 't': print_table++; break; default: fprintf(stderr, "usage: %s [-tv] [-L lang] [msg-num [..]]\n", progname); return (1); } } } if ((lang = valid_language(language, NULL)) == NULL) { (void)fprintf(stderr, "%s: %s: invalid language specified\n", progname, language); return (1); } if (print_table || (argc <= optind)) { int cnt; for (cnt = 0; lang[cnt] != NULL; cnt++) { printf("%02d: %s\n", cnt, lang[cnt]); } } else { for (; optind < argc; optind++) /* process files to print */ printf("%s: \n", lang[atoi(argv[optind])]); } return (0); /* terminate this process */ } #endif ================================================ FILE: src/lang.h ================================================ /* ** WARNING!!! Don't muck with this file unless you know what you are ** getting yourself into!!!!!! */ /* ** Below are the messages used within hypermail that ** are for user consumption. There are differences ** between user message strings and strings used in ** the HTML and SMTP protocols. Beware not to get ** confused with which is which. ** ** What follows are a set of defines that act as indices ** into the specific language array that is setup for ** this list archive. They need to point to the right ** messages in the language arrays or things get interesting. ** ** To add a new language, simply copy an existing language ** array and make the appropriate translations. For example, ** the Spanish language message array has the English message ** as the comment on the side of the message. (It is hoped ** this makes for easier translations... Also make sure and ** add the language to the supported_languages array. ** ** Currently this does not support wide-characters but it is ** a start in the right direction. */ struct language_entry { char *langcode; char **mtable; char *locale_code; }; /* print.c */ #define MSG_NEW_MESSAGE 0 #define MSG_REPLY 1 #define MSG_ABOUT_THIS_LIST 2 #define MSG_END_OF_MESSAGES 3 #define MSG_START_OF_MESSAGES 4 #define MSG_DATE_VIEW 5 #define MSG_THREAD_VIEW 6 #define MSG_SUBJECT_VIEW 7 #define MSG_AUTHOR_VIEW 8 #define MSG_ATTACHMENT_VIEW 9 #define MSG_MESSAGES 10 #define MSG_STARTING 11 #define MSG_ENDING 12 #define MSG_ABOUT_THIS_ARCHIVE 13 #define MSG_SORTED_BY 14 #define MSG_OTHER_MAIL_ARCHIVES 15 #define MSG_BY_DATE 16 #define MSG_MOST_RECENT_MESSAGES 17 #define MSG_AUTHOR 18 #define MSG_DATE 19 #define MSG_THREAD 20 #define MSG_SUBJECT 21 #define MSG_FOR_OPTIONS 22 #define MSG_WRITING_ARTICLES 23 #define MSG_WRITING_DATE_INDEX 24 #define MSG_WRITING_THREAD_INDEX 25 #define MSG_WRITING_SUBJECT_INDEX 26 #define MSG_WRITING_AUTHOR_INDEX 27 #define MSG_LAST_MESSAGE_DATE 28 #define MSG_ARCHIVED_ON 29 #define MSG_CANNOT_CHMOD 30 #define MSG_COULD_NOT_WRITE 31 #define MSG_NEXT_MESSAGE 32 #define MSG_PREVIOUS_MESSAGE 33 #define MSG_MAYBE_IN_REPLY_TO 34 #define MSG_IN_REPLY_TO 35 #define MSG_NEXT_IN_THREAD 36 #define MSG_MAYBE_REPLY 37 #define MSG_BY_THREAD 38 #define MSG_BY_SUBJECT 39 #define MSG_BY_AUTHOR 40 /* file.c */ #define MSG_CANNOT_CREATE_DIRECTORY 41 #define MSG_CREATING_DIRECTORY 42 #define MSG_CONFIGURATION_VALUES 43 #define MSG_PATH 44 /* mem.c */ #define MSG_RAN_OUT_OF_MEMORY 45 /* printfile.c */ #define MSG_ARCHIVE_GENERATED_BY 46 /* struct.c */ #define MSG_ELEMENTS 47 #define MSG_NO_ELEMENTS 48 /* parse.c */ #define MSG_CANNOT_OPEN_MAIL_ARCHIVE 49 #define MSG_READING_NEW_HEADER 50 #define MSG_LOADING_MAILBOX 51 #define MSG_ENCODING_IS_NOT_SUPPORTED 52 #define MSG_ARTICLES 53 /* hypermail.c */ #define MSG_VERSION 54 #define MSG_PATCHLEVEL 55 #define MSG_DOCS 56 #define MSG_COMMAND_AND_CONTROL_VARIABLES 57 #define MSG_YES 58 #define MSG_NO 59 #define MSG_ABOUT_THE_ARCHIVE_NOT_USED 60 #define MSG_OTHER_ARCHIVES_NOT_USED 61 #define MSG_ADDRESS_NOT_USED 62 #define MSG_BUILTIN_BODY_STATEMENT_USED 63 #define MSG_CANNOT_READ_FROM_BOTH_FILE_AND_STDIN 64 #define MSG_OPTIONS 65 #define MSG_OPTION_A 66 #define MSG_OPTION_B 67 #define MSG_OPTION_C 68 #define MSG_OPTION_D 69 #define MSG_OPTION_I 70 #define MSG_OPTION_L 71 #define MSG_OPTION_M 72 #define MSG_OPTION_P 73 #define MSG_OPTION_VERBOSE 74 #define MSG_OPTION_VERSION 75 #define MSG_OPTION_U 76 #define MSG_OPTION_X 77 #define MSG_OPTION_LANG 78 #define MSG_USAGE 79 #define MSG_LANGUAGE_NOT_SUPPORTED 80 #define MSG_NOT_SET 81 #define MSG_NOT_USED 82 #define MSG_CREATED_ATTACHMENT_FILE 83 #define MSG_ATTACHMENT 84 #define MSG_MODE 85 #define MSG_READING_OLD_HEADERS 86 #define MSG_OPTIONS_STRING2 87 #define MSG_ERROR 88 #define MSG_OPTION_N 89 #define MSG_OPTION_1 90 #define MSG_CAUTHOR 91 #define MSG_CDATE 92 #define MSG_CSUBJECT 93 /* print.c This belong in the first list, but it's quite a lot of work to move all the numbers to add them there :-/ How can we simplify this work? Jose */ #define MSG_MAIL_ACTIONS 94 #define MSG_MA_NEW_MESSAGE 95 #define MSG_MA_REPLY 96 #define MSG_MONTHLY_INDEX 97 #define MSG_YEARLY_INDEX 98 #define MSG_OPTION_G 99 #define MSG_OPTION_G_NOT_BUILD_IN 100 #define MSG_CREATING_GDBM_INDEX 101 #define MSG_CANT_CREATE_GDBM_INDEX 102 #define MSG_OPTION_ARCHIVE 103 #define MSG_CANNOT_BOTH_READ_AND_WRITE_TO_MBOX 104 /* XXX Move these up with the others */ #define MSG_ATTACHMENT_VIEW_OBSOLETED 105 #define MSG_BY_ATTACHMENT 106 #define MSG_WRITING_ATTACHMENT_INDEX 107 #define MSG_BYTES 108 #define MSG_CANNOT_CREATE_SYMLINK 109 #define MSG_CANNOT_UNLINK 110 #define MSG_PREV_DIRECTORY 111 #define MSG_NEXT_DIRECTORY 112 #define MSG_FOLDERS_INDEX 113 #define MSG_DELETED 114 #define MSG_EXPIRED 115 #define MSG_DEL_SHORT 116 #define MSG_TXT_VERSION 117 #define MSG_FILTERED_OUT 118 #define MSG_FROM 119 #define MSG_OPTION_XML 120 #define MSG_WRITING_HAOF 121 /* JK: new messages added by WAI. When this is ready, it would be good to merge them into the above sections. The current use of localization in hypermail makes this quite complex to do. */ /* print.c */ #define MSG_THIS_MESSAGE 122 #define MSG_MSG_BODY 123 #define MSG_RESPOND 124 #define MSG_MORE_OPTIONS 125 #define MSG_RELATED_MESSAGES 126 #define MSG_NEXT 127 #define MSG_PREVIOUS 128 #define MSG_REPLIES 129 #define MSG_CONTEMPORARY_MSGS_SORTED 130 #define MSG_HELP 131 #define MSG_LTITLE_IN_REPLY_TO 132 #define MSG_LTITLE_NEXT_IN_THREAD 133 #define MSG_LTITLE_REPLIES 134 #define MSG_LTITLE_BY_DATE 135 #define MSG_LTITLE_BY_THREAD 136 #define MSG_LTITLE_BY_SUBJECT 137 #define MSG_LTITLE_BY_AUTHOR 138 #define MSG_LTITLE_NEXT 139 #define MSG_LTITLE_PREVIOUS 140 #define MSG_LTITLE_BY_ATTACHMENT 141 #define MSG_NAVBAR2UPPERLEVELS 142 #define MSG_NAVBAR 143 #define MSG_SORT_BY 144 #define MSG_OTHER_PERIODS 145 #define MSG_NEXTPERIOD 146 #define MSG_LTITLE_NEXTPERIOD 147 #define MSG_PREVPERIOD 148 #define MSG_LTITLE_PREVPERIOD 149 #define MSG_LTITLE_FOLDERS_INDEX 150 #define MSG_THIS_PERIOD 151 #define MSG_RECEIVED_ON 152 #define MSG_NEARBY 153 #define MSG_RESORTED 154 #define MSG_LTITLE_LISTED_BY_DATE 155 #define MSG_LTITLE_DISCUSSION_THREADS 156 #define MSG_LTITLE_LISTED_BY_AUTHOR 157 #define MSG_LTITLE_LISTED_BY_SUBJECT 158 #define MSG_LTITLE_LISTED_BY_ATTACHMENT 159 #define MSG_PERIOD 160 #define MSG_TO 161 #define MSG_FROM_TITLE 162 #define MSG_ON_TITLE 163 #define MSG_UNKNOWN_IN_REPLY_TO 164 #define MSG_DELETED_OTHER 165 #define MSG_EDITED 166 #define MSG_SENDER_DELETED 167 #define MSG_SUBJECT_DELETED 168 #ifdef MAIN_FILE /* ** German version of the language table ** Translation by Martin Schulze */ char *de[] = { /* German */ "Neue Nachricht", /* New Message -HTML*/ "Antwort", /* Reply -HTML*/ "ber diese Liste", /* About this list -HTML*/ "Ende der Nachricht", /* End of Messages -HTML*/ "Anfang der Nachricht", /* Start of Messages -HTML*/ "Datumsansicht", /* Date view -HTML*/ "Themenansicht", /* Thread view -HTML*/ "Titelansicht", /* Subject view -HTML*/ "Autorenansicht", /* Author view -HTML*/ "Anhnge-bersicht", /* Attachment view -HTML*/ "Nachrichten", /* Messages -HTML*/ "Anfang", /* Starting -HTML*/ "Ende", /* Ending -HTML*/ "ber dieses Archiv", /* About this archive -HTML*/ "sortiert nach", /* sorted by -HTML*/ "Weitere Mail-Archive", /* Other mail archives -HTML*/ "Nach Datum", /* By Date -HTML*/ "Neueste Nachrichten", /* Most recent messages-HTML*/ "Autor", /* author -HTML*/ "Datum", /* date -HTML*/ "Themenstrang", /* thread -HTML*/ "Titel", /* subject -HTML*/ "fr Optionen", /* for options -STDOUT*/ "Schreibe Nachrichten in", /* Writing messages to-STDOUT*/ "Schreibe Datums-Index in", /* Writing date index to-STDOUT*/ "Schreibe Themenstrang-Index in", /* Writing thread index to -STDOUT*/ "Schreibe Titel-Index in", /* Writing subject index to-STDOUT*/ "Schreibe Autoren-Index in", /* Writing author index to-STDOUT*/ "Letztes Datum", /* Last message date -HTML*/ "Archiviert am", /* Archived on -HTML*/ "Kann Dateimodus nicht ndern", /* Can not chmod -STDERR*/ "Kann nicht schreiben", /* Could not write -STDERR*/ "Nchste Nachricht", /* Next message -HTML*/ "Vorherige Nachricht", /* Previous message -HTML*/ "Vielleicht als Antwort auf", /* Maybe in reply to -HTML*/ "Als Antwort auf", /* In reply to -HTML*/ "Nchste zum Thema", /* Next in thread -HTML*/ "Eventuelle Antwort", /* Maybe reply -HTML*/ "Nach Strang", /* By Thread -HTML*/ "Nach Titel", /* By Subject -HTML*/ "Nach Autor", /* By Author -HTML*/ "Kann das Verzeichnis nicht erstellen", /* Can not create directory -STDERR*/ "Erstelle Verzeichnis", /* Creating directory -STDOUT*/ "Konfiguration", /* Configuration Values -STDOUT*/ "Pfad", /* path -STDOUT*/ "Kein Speicher mehr!", /* Ran out of memory!-STDERR*/ "Dieses Archiv wurde generiert von", /* This archive was generated by-HTML*/ "Elemente", /* Elements -STDOUT*/ "Keine Elemente", /* No Elements -STDOUT*/ "Kann E-Mail-Archiv nicht ffnen", /* Cannot open mail archive */ "Lese neue Kopfzeilen...", /* Reading new header...-STDOUT*/ "Lade Mailbox", /* Loading mailbox -STDOUT*/ "Kodierung wird nicht untersttzt, speichere so", /* encoding is not supported, stored as-is -HTML*/ "Nachrichten", /* messages -HTML*/ "Version", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "Dokus", /* Docs -STDOUT*/ "Befehls- und Kontrollvariablen", /* Command and Control Variables-STDOUT*/ "Ja", /* Yes -STDOUT*/ "Nein", /* No -STDOUT*/ "ber das Archiv: nicht benutzt", /* About the archive: not used-STDOUT */ "Andere Archive: nicht benutzt", /* Other archives: not used-STDOUT*/ "Adresse nicht benutzt", /* address not used -STDOUT*/ "Eingebautes benutzt", /* Builtin statement used-STDOUT*/ "Kann nicht gleichzeitig von Datei und Standardeingabe lesen.", /* Cannot read from both file and stdin. -STDERR*/ "Optionen", /* Options -STDOUT*/ "URL fr weitere Archive", /* URL to other archives -STDOUT*/ "URL fr Informationen ber Archiv", /* URL to archive information -STDOUT*/ "Konfigurationsdatei zum Einlesen", /* Configuration file to read in -STDOUT*/ "Das Verzeichnis, um die HTML-Dateien zu speichern", /* The directory to save HTML files in -STDOUT*/ "Lese Nachrichten von der Standardeingabe", /* Read messages from standard input -STDOUT*/ "Wie soll das Archiv genannt werden", /* What to name the output archive -STDOUT*/ "Mail-Archive zum Einlesen", /* Mail archive to read in -STDOUT*/ "Zeige Zwischenbericht", /* Show progress -STDOUT*/ "Zeigt nur die Konfigurationsvariablen", /* Show configuration variables only -STDOUT*/ "Zeigt Version und beende", /* Show version information and exit -STDOUT*/ "Jeweils einen Artikel hinzufgen", /* Update archive by one article -STDOUT*/ "Vorherige Nachrichten berschreiben", /* Overwrite previous messages -STDOUT*/ "Sprache angeben", /* Specify language to use -STDOUT*/ "Anleitung", /* Usage -STDOUT*/ "Die Sprache wird nicht untersttzt",/* Language not supported -STDERR*/ "Nicht gesetzt", /* Not set -STDOUT*/ "Nicht benutzt", /* Not used -STDOUT*/ "Anhang in Datei gespeichert", /* Created attachment file -STDOUT*/ "Anhang", /* attachment -HTML*/ "Modus", /* mode -STDOUT*/ "Lese alte Kopfzeilen", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "FEHLER", /* ERROR -STDERR*/ "Einsendeadresse fr die Liste", /* The submission address of the list-STDERR*/ "Lese nur eine E-Mail aus der Eingabe", "Autor", /* author -HTML*/ "Datum", /* date -HTML*/ "Titel", /* subject -HTML*/ "Aktionsmglichkeiten", /* Mail actions (MA) header -HTML*/ "Sende E-Mail mit neuen Titel", /* MA New Message -HTML*/ "Antworte auf die E-Mail", /* MA Reply -HTML*/ "Zusammenfassung der monatlichen Index-Dateien", /* monthly -HTML*/ "Zusammenfassung der jhrlichen Index-Dateien", /* yearly -HTML*/ "Lege GDBM-Zwischenspeicher fr Kopfzeilen an", /* Build a GDBM header cache -STDOUT*/ "GDBM-Zwischenspeicher-Option nicht eingebaut", /* GDBM header cache option not build in -STDERR*/ "Erstelle Gdbm Index... ", /* Creating gdbm index -STDOUT*/ "Kann Gdbm Datei nicht erstellen... ", /* Can't create gdbm index -STDOUT*/ "Pflege ein zustzliches mbox-Archiv", /* Maintain an mbox archive -STDOUT*/ "Kann nicht gleichzeitig von mbox lesen und schreiben.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Anhnge-bersicht", /* Attachment view -HTML*/ "Nach Nachrichten mit Anhang",/* By messages with attachments -HTML*/ "Schreibe Anhang-Index in", /* Writing attachment index to -STDOUT*/ "Bytes", /* file size, so far only for attachments -HTML */ "Kann symbolischen Verweis nicht erstellen.", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Kann Datei nicht entfernen", /* MSG_CANNOT_UNLINK -STDOUT */ "Vorheriges Verzeichnis", /* MSG_PREV_DIRECTORY -HTML */ "Nchstes Verzeichnis", /* MSG_NEXT_DIRECTORY -HTML */ "Verzeichnisliste", /* MSG_FOLDERS_INDEX -HTML */ "Diese Nachricht wurde aus dem Archiv entfernt",/* MSG_DELETED -HTML */ "Diese Nachricht ist abgelaufen", /* MSG_EXPIRED -HTML */ "(gelschte Nachricht)", /* MSG_DEL_SHORT -HTML */ "Ursprnglicher Text dieser Nachricht", /* MSG_TXT_VERSION -HTML */ "Diese Nachricht wurde herausgefiltert", /* MSG_FILTERED_OUT -HTML */ "Autor", /* MSG_FROM -HTML*/ "Erstelle haof XML Dateien", /* Write hoaf XML files -STDOUT */ "Schreibe Hoaf in", /* Writing haof to -HTML*/ "Diese Nachricht", /* This message -HTML */ "Inhalt", /* Message body -HTML */ "Antworten", /* Respond -HTML */ "Weitere Mglichkeiten", /* More options -HTML */ "Zugehrige Nachrichten", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Antworten", /* Replies -HTML */ "Nachrichten aus dem gleichen Zeitraum, sortiert", /* Contemporary messages sorted -HTML */ "Hilfe", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Nachrichten im gleichen Zeitraum, nach Datum", /* Contemporary messages by date */ "Themenstrnge im gleichen Zeitraum", /* Contemporary messages by threads - HTML */ "Nachrichten im gleichen Zeitraum, nach Betreff", /* Contemporary messages by subject - HTML */ "Nachrichten im gleichen Zeitraum, nach Autor", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sortieren nach", /* Sort by - HTML*/ "Weitere Zeitrume", /* Other periods - HTML */ "Spter", /* Next folder - HTML */ "Im nchsten Zeitraum gespeicherte Nachrichten, sortiert nach Datum", /* Next folder, by date - HTML link */ "Frher", /* Previous folder - HTML */ "Im vorigen Zeitraum gespeicherte Nachrichten, sortiert nach Datum", /* Previous folder, by date - HTML Link */ "Liste aller Zeitrume", /* List of all periods - HTML*/ "Dieser Zeitraum", /* This period - HTML*/ "Empfangen am", /* Received on - HTML */ "Dazu", /* Nearby - HTML */ "sortiert", /* Resorted - HTML */ "in zeitlicher Reihenfolge", /* listed by date - HTML */ "nach Themenstrang" , /* discussion threads - HTML */ "nach Autor geordnet", /* listed by author - HTML */ "nach Titel", /* listed by subject - HTML */ "nach Anhngen", /* by attachment - HTML */ "Zeitraum", /* period - HTML */ " bis ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Diese Nachricht wurde aus dem Archiv entfernt", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Polish version of the language table (Polska wersja tabeli jzykowej) ** Translation by Adam T. Tkocz */ char *pl[] = { /* English */ "Nowa wiadomo", /* New Message -HTML*/ "Odpowiedz", /* Reply -HTML*/ "O tej licie", /* About this list -HTML*/ "D strony", /* End of Messages -HTML*/ "Gra strony", /* Start of Messages -HTML*/ "Wg daty", /* Date view -HTML*/ "Wg wtkw", /* Thread view -HTML*/ "Wg tematw", /* Subject view -HTML*/ "Wg autorw", /* Author view -HTML*/ "Wg zacznikw", /* Attachment view -HTML*/ "Wiadomoci", /* Messages -HTML*/ "Pocztek", /* Starting -HTML*/ "Koniec", /* Ending -HTML*/ "O tym archiwum", /* About this archive -HTML*/ "sortowane wg", /* Messages sorted by -HTML*/ "Inne archiwa maili", /* Other mail archives -HTML*/ "Wg daty", /* By Date -HTML*/ "Najwiesze wiadomoci", /* Most recent messages-HTML*/ "autora", /* author -HTML*/ "datay", /* date -HTML*/ "wtku", /* thread -HTML*/ "tematu", /* subject -HTML*/ "Dla opcji", /* for options -STDOUT*/ "Zapisywanie wiadomoci do", /* Writing messages to-STDOUT*/ "Zapisywanie indeksu dat do", /* Writing date index to-STDOUT*/ "Zapisywanie indeksu wtkw do", /* Writing thread index to -STDOUT*/ "Zapisywanie indeksu tematw do", /* Writing subject index to-STDOUT*/ "Zapisywanie indeksu autorw do", /* Writing author index to-STDOUT*/ "Data ostatniej wiadomoci", /* Last message date -HTML*/ "Zarchiwizowane w", /* Archived on -HTML*/ "Niedozwolone chmod", /* Can not chmod -STDERR*/ "Nie mona zapisa", /* Could not write -STDERR*/ "Nastpna wiadomo", /* Next message -HTML*/ "Poprzednia wiadomo", /* Previous message -HTML*/ "Przypuszczalnie w odpowiedzi na",/* Maybe in reply to -HTML*/ "W odpowiedzi na", /* In reply to -HTML*/ "Nastpna w wtku", /* Next in thread -HTML*/ "Prawdopodobna odpowied", /* Maybe reply -HTML*/ "Wg wtku", /* By Thread -HTML*/ "Wg tematu", /* By Subject -HTML*/ "Wg autora", /* By Author -HTML*/ "Nie mona stworzy katalogu", /* Can not create directory -STDERR*/ "Tworzenie katalogu", /* Creating directory -STDOUT*/ "Parametry konfiguracji", /* Configuration Values -STDOUT*/ "cieka", /* path -STDOUT*/ "Przekroczona pami!", /* Ran out of memory!-STDERR*/ "To archiwum zostao wygenerowane przez", /* This archive was generated by -HTML*/ "Elementy", /* Elements -STDOUT*/ "adnych elementw", /* No Elements -STDOUT*/ "Nie mona otworzy archiwum", /* Cannot open mail archive */ "Czytanie nowego nagwka", /* Reading new header... -STDOUT */ "adowanie mailboxa", /* Loading mailbox -STDOUT */ "kodowanie nie jest obsugiwane", /* encoding is not supported, stored as-is -HTML*/ "wiadomoci", /* messages -HTML*/ "Wersja", /* Version -STDOUT*/ "Wersja aty", /* Patchlevel -STDOUT*/ "Dokumentacja", /* Docs -STDOUT*/ "Polecenia i zmienne", /* Command and Control Variables-STDOUT*/ "Tak", /* Yes -STDOUT*/ "Nie", /* No -STDOUT*/ "O tym archiwum: nie uywane", /* About the archive: not used-STDOUT */ "Inne archiwa: nie uywane", /* Other archives: not used-STDOUT*/ "adres nie zosta uyty", /* address not used -STDOUT*/ "Wbudowane zostao uyte", /* Builtin statement used-STDOUT*/ "Nie mona odczyta pliku ani stdin.", /* Cannot read from both file and stdin. -STDERR*/ "Opcje", /* Options -STDOUT*/ "URL do innych arciww", /* URL to other archives -STDOUT*/ "URL do informacji o archiwum", /* URL to archive information -STDOUT*/ "Plik konfiguracyjny do wczytania", /* Configuration file to read in -STDOUT*/ "Katalog do zapisu plikw HTML", /* The directory to save HTML files in -STDOUT*/ "Czytaj wiadomoci z stdin", /* Read messages from standard input -STDOUT*/ "Podaj nazw archiwum", /* What to name the output archive -STDOUT*/ "Archiwum do wczytania", /* Mail archive to read in -STDOUT*/ "Poka postpy", /* Show progress -STDOUT*/ "Poka tylko zmienne konfiguracyjne", /* Show configuration variables only -STDOUT*/ "Poka wersj i wyjd", /* Show version information and exit -STDOUT*/ "Uzupelnij archiwum o jedn wiadomo", /* Update archive by one article -STDOUT*/ "Zastp poprzednia wiadomo", /* Overwrite previous messages -STDOUT*/ "Wybierz uywany jzyk", /* Specify language to use -STDOUT*/ "Uycie", /* Usage -STDOUT*/ "Jzyk nie jest wspierany", /* Language not supported -STDERR*/ "Nie ustawione", /* Not set -STDOUT*/ "Nie uywane", /* Not used -STDOUT*/ "Stworzono zacznik", /* Created attachment file -STDOUT*/ "zacznik", /* attachment -HTML*/ "tryb", /* mode -STDOUT*/ "Czytanie starych nagwkw", /* Reading old headers -STDOUT*/ "", /* tylko do wyrwnania -STDOUT*/ "BD", /* ERROR -STDERR*/ "Adres wypisujcy z listy", /* The submission address of the list-STDERR*/ "Czytaj tylko jedn wiadomo", "Autor", /* author -HTML*/ "Data", /* date -HTML*/ "Temat", /* subject -HTML*/ "Wybierz", /* Mail actions (MA) header -HTML*/ "wylij nowy temat", /* MA New Message -HTML*/ "odpowiedz na t wiadomo", /* MA Reply -HTML*/ "Zestawienie miesicy", /* monthly -HTML*/ "Zestawienie lat", /* yearly -HTML*/ "Utwrz cache nagowkw GDBM", /* Build a GDBM header cache -STDOUT*/ "GDBM header cache option not build in", /* GDBM header cache option not build in -STDERR*/ "Tworzenie indeksu GDBM... ", /* Creating gdbm index -STDOUT*/ "Nie mona utworzy pliku GDBM... ", /* Can't create gdbm index -STDOUT*/ "Zachowaj archiwum mbox", /* Maintain an mbox archive -STDOUT*/ "Nie mona odczyta ani zapisa mailboxa.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Wg zacznikw", /* Attachment view -HTML*/ "Wg wiadomoci z zacznikami", /* By messages with attachments -HTML*/ "Zapisywanie indeksu zacznikw", /* Writing attachment index to -STDOUT*/ "bajtw", /* file size, so far only for attachments -HTML */ "Nie mona stworzy aliasa", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Nie mona usun pliku", /* MSG_CANNOT_UNLINK -STDOUT */ "Poprzedni katalog", /* MSG_PREV_DIRECTORY -HTML */ "Nastpny katalog", /* MSG_NEXT_DIRECTORY -HTML */ "Lista Katalogw", /* MSG_FOLDERS_INDEX -HTML */ "Ta wiadomo zostaa usunita z archiwum", /* MSG_DELETED -HTML */ "Ta wiadomo jest przedawniona", /*MSG_EXPIRED -HTML */ "(usunita wiadomo)", /* MSG_DEL_SHORT -HTML */ "Tekst tej zawartoci", /* MSG_TXT_VERSION -HTML */ "Ta wiadomo zostaa odfiltrowana", /* MSG_FILTERED_OUT -HTML */ "Autor", /* MSG_FROM -HTML*/ "Write haof XML files", /* Write hoaf XML files -STDOUT */ "Writing haof to", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Ta wiadomo zostaa usunita z archiwum", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** English version of the language table */ char *en[] = { /* English */ "New Message", /* New Message -HTML*/ "Reply", /* Reply -HTML*/ "About this list", /* About this list -HTML*/ "End of Messages", /* End of Messages -HTML*/ "Start of Messages", /* Start of Messages -HTML*/ "Date view", /* Date view -HTML*/ "Thread view", /* Thread view -HTML*/ "Subject view", /* Subject view -HTML*/ "Author view", /* Author view -HTML*/ "Attachment view", /* Attachment view -HTML*/ "Messages", /* Messages -HTML*/ "Starting", /* Starting -HTML*/ "Ending", /* Ending -HTML*/ "About this archive", /* About this archive -HTML*/ "sorted by", /* Messages sorted by -HTML*/ "Other mail archives", /* Other mail archives -HTML*/ "by date", /* By Date -HTML*/ "Most recent messages", /* Most recent messages-HTML*/ "author", /* author -HTML*/ "date", /* date -HTML*/ "thread", /* thread -HTML*/ "subject", /* subject -HTML*/ "for options", /* for options -STDOUT*/ "Writing messages to", /* Writing messages to-STDOUT*/ "Writing date index to", /* Writing date index to-STDOUT*/ "Writing thread index to", /* Writing thread index to -STDOUT*/ "Writing subject index to", /* Writing subject index to-STDOUT*/ "Writing author index to", /* Writing author index to-STDOUT*/ "Last message date", /* Last message date -HTML*/ "Archived on", /* Archived on -HTML*/ "Can not chmod", /* Can not chmod -STDERR*/ "Could not write", /* Could not write -STDERR*/ "Next message", /* Next message -HTML*/ "Previous message", /* Previous message -HTML*/ "Maybe in reply to", /* Maybe in reply to -HTML*/ "In reply to", /* In reply to -HTML*/ "Next in thread", /* Next in thread -HTML*/ "Maybe reply", /* Maybe reply -HTML*/ "by thread", /* By Thread -HTML*/ "by subject", /* By Subject -HTML*/ "by author", /* By Author -HTML*/ "Can not create directory", /* Can not create directory -STDERR*/ "Creating directory", /* Creating directory -STDOUT*/ "Configuration Values", /* Configuration Values -STDOUT*/ "path", /* path -STDOUT*/ "Ran out of memory!", /* Ran out of memory!-STDERR*/ "This archive was generated by", /* This archive was generated by-HTML*/ "Elements", /* Elements -STDOUT*/ "No Elements", /* No Elements -STDOUT*/ "Cannot open mail archive", /* Cannot open mail archive */ "Reading new header...", /* Reading new header...-STDOUT */ "Loading mailbox", /* Loading mailbox -STDOUT */ "encoding is not supported, stored as-is", /* encoding is not supported, stored as-is -HTML*/ "messages", /* messages -HTML*/ "Version", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "Docs", /* Docs -STDOUT*/ "Command and Control Variables", /* Command and Control Variables-STDOUT*/ "Yes", /* Yes -STDOUT*/ "No", /* No -STDOUT*/ "About the archive: not used", /* About the archive: not used-STDOUT */ "Other archives: not used", /* Other archives: not used-STDOUT*/ "address not used", /* address not used -STDOUT*/ "Builtin statement used", /* Builtin statement used-STDOUT*/ "Cannot read from both file and stdin.", /* Cannot read from both file and stdin. -STDERR*/ "Options", /* Options -STDOUT*/ "URL to other archives", /* URL to other archives -STDOUT*/ "URL to archive information", /* URL to archive information -STDOUT*/ "Configuration file to read in", /* Configuration file to read in -STDOUT*/ "The directory to save HTML files in", /* The directory to save HTML files in -STDOUT*/ "Read messages from standard input",/* Read messages from standard input -STDOUT*/ "What to name the output archive", /* What to name the output archive -STDOUT*/ "Mail archive to read in", /* Mail archive to read in -STDOUT*/ "Show progress", /* Show progress -STDOUT*/ "Show configuration variables only", /* Show configuration variables only -STDOUT*/ "Show version information and exit", /* Show version information and exit -STDOUT*/ "Update archive by one article", /* Update archive by one article -STDOUT*/ "Overwrite previous messages", /* Overwrite previous messages -STDOUT*/ "Specify language to use", /* Specify language to use -STDOUT*/ "Usage", /* Usage -STDOUT*/ "Language not supported", /* Language not supported -STDERR*/ "Not set", /* Not set -STDOUT*/ "Not used", /* Not used -STDOUT*/ "Created attachment file", /* Created attachment file -STDOUT*/ "attachment", /* attachment -HTML*/ "mode", /* mode -STDOUT*/ "Reading old headers", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "ERROR", /* ERROR -STDERR*/ "The submission address of the list", /* The submission address of the list-STDERR*/ "Read only one mail from input", "Author", /* author -HTML*/ "Date", /* date -HTML*/ "Subject", /* subject -HTML*/ "Mail actions", /* Mail actions (MA) header -HTML*/ "mail a new topic", /* MA New Message -HTML*/ "respond to this message", /* MA Reply -HTML*/ "Summary of Monthly Index Files", /* monthly -HTML*/ "Summary of Yearly Index Files", /* yearly -HTML*/ "Build a GDBM header cache", /* Build a GDBM header cache -STDOUT*/ "GDBM header cache option not build in", /* GDBM header cache option not build in -STDERR*/ "Creating gdbm index... ", /* Creating gdbm index -STDOUT*/ "Can't create gdbm file... ", /* Can't create gdbm index -STDOUT*/ "Maintain an mbox archive", /* Maintain an mbox archive -STDOUT*/ "Can't both read from and write to an mbox.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Attachment view", /* Attachment view -HTML*/ "by messages with attachments", /* By messages with attachments -HTML*/ "Writing attachment index to", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ "Cannot create symbolic link", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Cannot remove file", /* MSG_CANNOT_UNLINK -STDOUT */ "Previous Folder", /* MSG_PREV_DIRECTORY -HTML */ "Next Folder", /* MSG_NEXT_DIRECTORY -HTML */ "List of Folders", /* MSG_FOLDERS_INDEX -HTML */ "This message has been deleted from the archive", /* MSG_DELETED -HTML */ "This message has expired", /* MSG_EXPIRED -HTML */ "(deleted message)", /* MSG_DEL_SHORT -HTML */ "Original text of this message", /* MSG_TXT_VERSION -HTML */ "This message has been filtered out", /* MSG_FILTERED_OUT -HTML */ "From", /* MSG_FROM -HTML*/ "Write haof XML files", /* Write hoaf XML files -STDOUT */ "Writing haof to", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "This message has been deleted from the archive", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Spanish version of the language table ** Translation by Francisco Iacobelli . */ char *es[] = { /* Espanol/Spanish */ "Nuevo mensaje", /* New Message - HTML */ "Responder", /* Reply - HTML */ "Acerca de la lista", /* About this list - HTML */ "Fin de los Mensajes", /* End of Messages - HTML */ "Inicio de mensajes", /* Start of Messages - HTML */ "Por fecha", /* Date view - HTML */ "Por conversacin", /* Thread view - HTML */ "Por tema", /* Subject view - HTML */ "Por autor", /* Author view - HTML */ "Por adjuntos", /* Attachment view - HTML */ "Mensajes", /* Messages - HTML */ "Inicio", /* Starting - HTML */ "Fin", /* Ending - HTML */ "Acerca de este archivo", /* About this archive - HTML */ "Ordenados por", /* Messages sorted by - HTML */ "Otros archivos de correo", /* Other mail archives - HTML */ "Por fecha", /* By Date - HTML */ "ltimos mensajes", /* Most recent messages - HTML */ "autor", /* author - HTML */ "fecha", /* date - HTML */ "Hilo de conversacin", /* thread - HTML */ "tema", /* subject - HTML */ "para las opciones", /* for options - STDOUT*/ "Escribiendo mensajes en", /* Writing articles to - STDOUT*/ "Escribiendo ndice de fechas en", /* Writing date index to - STDOUT*/ "Escribiendo ndice de conversaciones en", /* Writing thread index to - STDOUT*/ "Escribiendo ndice de temas en", /* Writing subject index to - STDOUT*/ "Escribiendo ndice de autores en", /* Writing author index to - STDOUT*/ "Fecha del ltimo mensaje", /* Last message date - HTML */ "Archivado el ", /* Archived on - HTML */ "No se puede ejecutar chmod", /* Can not chmod - STDERR*/ "No se pudo escribir", /* Could not write - STDERR*/ "Siguiente mensaje", /* Next message - HTML */ "Mensaje anterior", /* Previous message - HTML */ "Posiblemente en respuesta a ", /* Maybe in reply to - HTML */ "En Respuesta a", /* In reply to - HTML */ "Siguiente en conversacin", /* Next in thread - HTML */ "Posible respuesta", /* Maybe reply - HTML */ "Por conversacin", /* By Thread - HTML */ "Por tema", /* By Subject - HTML */ "Por autor", /* By Author - HTML */ "No se puede crear el directorio", /* Can not create directory - STDERR*/ "Creando el directorio", /* Creating directory - STDOUT*/ "Parmetros de configuracn", /* Configuration Values - STDOUT*/ "ruta", /* path - STDOUT*/ "No hay suficiente memoria!", /* Ran out of memory! - STDERR*/ "Este archivo fue generado por", /* This archive was generated by- HTML */ "Elementos", /* Elements - STDOUT*/ "No existen elementos", /* No Elements - STDOUT*/ "No se puede abrir el archivo de correo", /* Cannot open mail archive - STDERR*/ "Leyendo el encabezado nuevo...", /* Reading new header... - STDOUT*/ "Cargando la casilla", /* Loading mailbox - STDOUT*/ "codificacin no soportada, grabado -tal cual-", /* encoding is not supported, stored as-is - HTML*/ "mensajes", /* articles */ "Versin", /* Version - STDOUT*/ "Parche No.", /* Patchlevel - STDOUT*/ "Docs", /* Docs - STDOUT*/ "Variables de comandos y control", /* Command and Control Variables- STDOUT*/ "Si", /* Yes - STDOUT*/ "No", /* No - STDOUT*/ "Acerca del archivo: no utilizado", /* About the archive: not used - STDOUT*/ "Otros archivos: no utilizado", /* Other archives: not used - STDOUT*/ "direccin no utilizada", /* address not used - STDOUT*/ "Utilizado predefinido", /* Builtin statement used - STDOUT*/ "No se puede leer de archivo y de stdin a la vez.", /* Cannot read from both file and stdin. - STDERR*/ "Opciones", /* Options - STDOUT*/ "URL de otros archivos", /* URL to other archives - STDOUT*/ "URL de informacin de archivos", /* URL to archive information - STDOUT*/ "Archivo de conf. para leer", /* Configuration file to read in - STDOUT*/ "Directorio donde grabar archivos HTML", /* The directory to save HTML files in - STDOUT*/ "Leer mensajes de la entrada por defecto", /* Read messages from standard input - STDOUT*/ "Nombre del archivo de salida", /* What to name the output archive - STDOUT*/ "Archivo de correo para leer", /* Mail archive to read in - STDOUT*/ "Mostrar progreso", /* Show progress - STDOUT*/ "Mostrar solamente variables de conf.", /* Show configuration variables only - STDOUT*/ "Mostrar informacin de versin y salir", /* Show version information and exit - STDOUT*/ "Actualizar archivo con un mensaje",/*Update archive by one article - STDOUT*/ "Sobreescribir mensajes anteriores",/* Overwrite previous messages - STDOUT*/ "Especifique idioma utilizar", /* Specify language to use - STDOUT*/ "Modo de uso", /* Usage - STDOUT*/ "Idioma no soportado", /* Language not supported - STDERR*/ "No establecido", /* Not set - STDOUT*/ "No utilizado", /* Not used - STDOUT*/ "Archivo adjunto creado", /* Created attachment file - STDOUT*/ "adjunto", /* attachment - HTML */ "modo", /* mode - STDOUT*/ "Leyendo encabezados antiguos", /* Reading old headers - STDOUT*/ "", /* (for alignment only) - STDOUT*/ "ERROR", /* ERROR - STDERR*/ "Direccin de correo de la lista", /* The submission address of the list - STDERR*/ "Leer slo un mensaje de la entrada", /* Read only one mail from input */ "Autor", /* author - HTML */ "Fecha", /* date - HTML */ "Tema", /* subject - HTML */ "Cabecera MA (Mail actions)", /* Mail actions (MA) header - HTML */ "Enviar un nuevo tema", /* MA New Message - HTML */ "responder a este mensaje", /* MA Reply - HTML */ "Resumen de ndices mensuales", /* monthly - HTML */ "Resumen de ndices anuales", /* yearly - HTML */ "Costruir cabecera para cach GDBM",/* Build a GDBM header cache - STDOUT*/ "Creando ndice gdbm... ", /* Creating gdbm index - STDOUT*/ "No pudo crearse fichero gdbm... ", /* Can't create gdbm index - STDOUT*/ "Mantener un archivo mbox", /* Maintain an mbox archive - STDOUT*/ "No se puede leer y escribir al tiempo de un fichero mbox.", /* "Can't both read from and write to an mbox." - STDOUT*/ "Por adjuntos", /* Attachment view - HTML */ "Por mensajes con adjuntos", /* By messages with attachments - HTML */ "Escribiendo ndice de adjuntos en",/* Writing attachment index to - STDOUT*/ "bytes", /* file size, so far only for attachments - HTML */ "No pudo crearse enlace simblico", /* MSG_CANNOT_CREATE_SYMLINK - STDOUT*/ "No puede borrarse fichero", /* MSG_CANNOT_UNLINK - STDOUT*/ "Carpeta anterior", /* MSG_PREV_DIRECTORY - HTML */ "Siguiente carpeta", /* MSG_NEXT_DIRECTORY - HTML */ "Lista de carpetas", /* MSG_FOLDERS_INDEX - HTML */ "El mensaje ha sido borrado del archivo", /* MSG_DELETED - HTML */ "El mensaje ha caducado", /* MSG_EXPIRED - HTML */ "(mensaje borrado)", /* MSG_DEL_SHORT - HTML */ "Texto original del mensaje", /* MSG_TXT_VERSION - HTML */ "El mensaje ha sido filtrado", /* MSG_FILTERED_OUT - HTML */ "Autor", /* MSG_FROM - HTML */ "Write haof XML files", /* Write hoaf XML files -STDOUT */ "Writing haof to", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "El mensaje ha sido borrado del archivo", /* MSG_DELETED_OTHER - HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table */ }; /* ** Brazilian Portuguese Version of the language table ** Translation by Hugo Cisneiros . */ char *pt[] = { /* Brazilian Portuguese */ "Nova Mensagem", /* New Message -HTML*/ "Responder", /* Reply -HTML*/ "Sobre esta lista", /* About this list -HTML*/ "Fim das Mensagens", /* End of Messages -HTML*/ "Incio das Mensagens", /* Start of Messages -HTML*/ "Por Data", /* Date view -HTML*/ "Por Tpico", /* Thread view -HTML*/ "Por Assunto", /* Subject view -HTML*/ "Por Autor", /* Author view -HTML*/ "Por Anexo", /* Attachment view -HTML*/ "Mensagens", /* Messages -HTML*/ "Iniciando", /* Starting -HTML*/ "Finalizando", /* Ending -HTML*/ "Sobre este arquivo", /* About this archive -HTML*/ "ordenado por", /* Messages sorted by -HTML*/ "Outros arquivos de lista", /* Other mail archives -HTML*/ "Por Data", /* By Date -HTML*/ "Mensagens mais recentes", /* Most recent messages-HTML*/ "autor", /* author -HTML*/ "data", /* date -HTML*/ "tpico", /* thread -HTML*/ "assunto", /* subject -HTML*/ "para opes", /* for options -STDOUT*/ "Escrevendo mensagens para", /* Writing messages to-STDOUT*/ "Escrevendo ndice por data para", /* Writing date index to-STDOUT*/ "Escrevendo ndice por tpico para", /* Writing thread index to -STDOUT*/ "Escrevendo ndice por assunto para", /* Writing subject index to-STDOUT*/ "Escrevendo ndice por autor para", /* Writing author index to-STDOUT*/ "Data da ltima mensagem", /* Last message date -HTML*/ "Arquivado em", /* Archived on -HTML*/ "No foi possvel utilizar o chmod", /* Can not chmod -STDERR*/ "No foi possivel escrever", /* Could not write -STDERR*/ "Prxima mensagem", /* Next message -HTML*/ "Mensagem anterior", /* Previous message -HTML*/ "Talvez em resposta ", /* Maybe in reply to -HTML*/ "Em resposta ", /* In reply to -HTML*/ "Poxima no tpico", /* Next in thread -HTML*/ "Talvez resposta", /* Maybe reply -HTML*/ "Por Tpico", /* By Thread -HTML*/ "Por Assunto", /* By Subject -HTML*/ "Por Autor", /* By Author -HTML*/ "No foi possvel criar diretrio", /* Can not create directory -STDERR*/ "Criando diretrio", /* Creating directory -STDOUT*/ "Configurando valores", /* Configuration Values -STDOUT*/ "caminho", /* path -STDOUT*/ "Faltou memria!", /* Ran out of memory!-STDERR*/ "Este arquivo foi gerado por", /* This archive was generated by-HTML*/ "Elementos", /* Elements -STDOUT*/ "Sem Elementos", /* No Elements -STDOUT*/ "No foi possvel abrir arquivo de lista", /* Cannot open mail archive */ "Lendo novo cabealho...", /* Reading new header...-STDOUT */ "Carregando caixa de e-mail", /* Loading mailbox -STDOUT */ "Codificao no suportada, armazenando como est", /* encoding is not supported, stored as-is -HTML*/ "mensagens", /* messages -HTML*/ "Verso", /* Version -STDOUT*/ "Nvel de Patch", /* Patchlevel -STDOUT*/ "Documentao", /* Docs -STDOUT*/ "Variveis de Comando e Controle", /* Command and Control Variables-STDOUT*/ "Sim", /* Yes -STDOUT*/ "No", /* No -STDOUT*/ "Sobre este arquivo: no usado", /* About the archive: not used-STDOUT */ "Outros arquivos: no usado", /* Other archives: not used-STDOUT*/ "endereo no usado", /* address not used -STDOUT*/ "Tag integrada usada", /* Builtin statement used-STDOUT*/ "No foi possvel ler de ambos arquivos e entrada padro.", /* Cannot read from both file and stdin. -STDERR*/ "Opes", /* Options -STDOUT*/ "URL para outros arquivos", /* URL to other archives -STDOUT*/ "URL para informao do arquivo", /* URL to archive information -STDOUT*/ "Arquivo de configurao para ler", /* Configuration file to read in -STDOUT*/ "O diretrio onde sero salvos os arquivos HTML", /* The directory to save HTML files in -STDOUT*/ "Ler mensagens da entrada padro", /* Read messages from standard input -STDOUT*/ "Qual o nome do arquivo de lista de sada", /* What to name the output archive -STDOUT*/ "Arquivo de Lista ser lido", /* Mail archive to read in -STDOUT*/ "Mostrar progresso", /* Show progress -STDOUT*/ "Mostrar apenas variveis de configurao", /* Show configuration variables only -STDOUT*/ "Mostrar informao de verso e sair", /* Show version information and exit -STDOUT*/ "Atualizar arquivo por um artigo", /* Update archive by one article -STDOUT*/ "Sobrescrever mensagens anteriores", /* Overwrite previous messages -STDOUT*/ "Especifique a lngua se usar", /* Specify language to use -STDOUT*/ "Uso", /* Usage -STDOUT*/ "Lngua no suportada", /* Language not supported -STDERR*/ "No configurado", /* Not set -STDOUT*/ "No usado", /* Not used -STDOUT*/ "Criado arquivo anexo", /* Created attachment file -STDOUT*/ "anexo", /* attachment -HTML*/ "modo", /* mode -STDOUT*/ "Lendo cabealhos antigos", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "ERRO", /* ERROR -STDERR*/ "O endereo de submisso da lista", /* The submission address of the list-STDERR*/ "Ler apenas um e-mail da entrada", /* Read only one e-mail from mbox */ "Autor", /* author -HTML*/ "Data", /* date -HTML*/ "Assunto", /* subject -HTML*/ "Aes de E-Mail", /* Mail actions (MA) header -HTML*/ "Novo tpico de E-Mail", /* MA New Message -HTML*/ "Responder esta mensagem", /* MA Reply -HTML*/ "Sumrio dos Arquivos Mensais de ndice", /* monthly -HTML*/ "Sumrio dos Arquivos Anuais de ndice", /* yearly -HTML*/ "Compilar cache de cabealho GDBM", /* Build a GDBM header cache -STDOUT*/ "Opo de cabealho GDBM no compilada", /* GDBM header cache option not build in -STDERR*/ "Criando ndice gdbm... ", /* Creating gdbm index -STDOUT*/ "No foi possvel criar o arquivo gdbm... ", /* Can't create gdbm index -STDOUT*/ "Manter um arquivo do tipo mbox", /* Maintain an mbox archive -STDOUT*/ "No foi possvel ler e escrever para uma mbox.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Por Anexo", /* Attachment view -HTML*/ "Por mensagens com anexo", /* By messages with attachments -HTML*/ "Escrevendo ndice de anexos para ", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ "No foi possvel criar link simblico", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "No foi possvel remover o arquivo", /* MSG_CANNOT_UNLINK -STDOUT */ "Diretrio Anterior", /* MSG_PREV_DIRECTORY -HTML */ "Prximo Diretrio", /* MSG_NEXT_DIRECTORY -HTML */ "Lista de Diretrios", /* MSG_FOLDERS_INDEX -HTML */ "Esta mensagem foi removida do arquivo", /* MSG_DELETED -HTML */ "Esta mensagem expirou", /* MSG_EXPIRED -HTML */ "(mensagem removida)", /* MSG_DEL_SHORT -HTML */ "Texto original desta mensagem", /* MSG_TXT_VERSION -HTML */ "Esta mensagem foi filtrada", /* MSG_FILTERED_OUT -HTML */ "De", /* MSG_FROM -HTML*/ "Escrever arquivos XML haof", /* Write hoaf XML files -STDOUT */ "Escrevendo haof em", /* Writing haof to -HTML*/ "Esta mensagem", /* This message -HTML */ "Corpo da mensagem", /* Message body -HTML */ "Responder", /* Respond -HTML */ "Mais opes", /* More options -HTML */ "Mensagens relacionadas", /* Related messages -HTML */ "Prximo", /* Next -HTML */ "Anterior", /* Previous -HTML */ "Respostas", /* Replies -HTML */ "Mensagens contemporneas ordenadas", /* Contemporary messages sorted -HTML */ "Ajuda", /* Help -HTML */ "Mensagens que esta mensagem responde", /* In Reply To - HTML link*/ "Prxima mensagem neste tpico de discusso", /* Next message in thread - HTML link*/ "Mensagem mandada em resposta esta mensagem", /* Replies to this message - HTML link*/ "Mensagens contemporneas por data", /* Contemporary messages by date */ "Mensagens contemporneas por tpico", /* Contemporary messages by threads - HTML */ "Mensagens contemporneas por assunto", /* Contemporary messages by subject - HTML */ "Mensagens contemporneas por autor", /* Contemporary messages by author - HTML*/ "Prxima mensagem na lista", /* Next message - HTML */ "Mensagem anterior na lista", /* Previous message - HTML */ "Mensagens contemporneas por anexo", /* Contemporary messages by attachments - HTML*/ "Barra de navegao para nveis superiores", /* Navigation bar, upper levels - HTML*/ "Barra de navegao", /* Navigation bar - HTML*/ "ordenar por", /* Sort by - HTML*/ "Outros perodos", /* Other periods - HTML */ "Prximo", /* Next folder - HTML */ "Mensagens arquivadas no prximo perodo, ordenadas por data", /* Next folder, by date - HTML link */ "Anterior", /* Previous folder - HTML */ "Mensagens arquivadas no perodo anterior, ordenadas por data", /* Previous folder, by date - HTML Link */ "Lista de todos os perodos", /* List of all periods - HTML*/ "Este perodo", /* This period - HTML*/ "Recebida em", /* Received on - HTML */ "Perto", /* Nearby - HTML */ "re-organizado", /* Resorted - HTML */ "listado por data", /* listed by date - HTML */ "por tpicos de discusso" , /* discussion threads - HTML */ "listado por autor", /* listed by author - HTML */ "por assunto", /* listed by subject - HTML */ "por anexo", /* by attachment - HTML */ "perodo", /* period - HTML */ " para ", /* to - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Esta mensagem foi removida do arquivo", /* MSG_DELETE_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Finnish version of the language table */ char *fi[] = { /* Finnish */ "Lhet uusi viesti", /* New Message -HTML*/ "Kommentoi", /* Reply -HTML*/ "Tietoa listasta", /* About this list -HTML*/ "Viestien loppuun", /* End of Messages -HTML*/ "Viestien alkuun", /* Start of Messages -HTML*/ "Pivysnkym", /* Date view -HTML*/ "Ketjunkym", /* Thread view -HTML*/ "Aihenkym", /* Subject view -HTML*/ "Kirjoittajankym", /* Author view -HTML*/ "Attachment view", /* Attachment view -HTML*/ "Viestit", /* Messages -HTML*/ "alkaa", /* Starting -HTML*/ "loppuu", /* Ending -HTML*/ "Tietoa arkistosta", /* About this archive -HTML*/ "lajiteltuna", /* Messages sorted by -HTML*/ "Muita arkistoja", /* Other mail archives -HTML*/ "Pivyksittin", /* By Date -HTML*/ "Tuoreimmat viestit", /* Most recent messages-HTML*/ "kirjoittajittain", /* author -HTML*/ "pivyksittin", /* date -HTML*/ "ketjuittain", /* thread -HTML*/ "aiheittain", /* subject -HTML*/ "asetuksiin", /* for options -STDOUT*/ "Kirjoitan viestej", /* Writing messages to-STDOUT*/ "Kirjoitan hakemistoa pivyksittin", /* Writing date index to-STDOUT*/ "Kirjoitan hakemistoa ketjuittain", /* Writing thread index to -STDOUT*/ "Kirjoitan hakemistoa aiheittain", /* Writing subject index to-STDOUT*/ "Kirjoitan hakemistoa kirjoittajittain", /* Writing author index to-STDOUT*/ "Viimeinen viesti pivtty", /* Last message date -HTML*/ "Arkistoitu", /* Archived on -HTML*/ "Ei voi muuttaa oikeuksia ", /* Can not chmod -STDERR*/ "Kirjoitus eponnistui", /* Could not write -STDERR*/ "Seuraava viesti", /* Next message -HTML*/ "Edellinen viesti", /* Previous message -HTML*/ "Ehk kommentti viestiin", /* Maybe in reply to -HTML*/ "Kommentti viestiin", /* In reply to -HTML*/ "Seuraava ketjussa", /* Next in thread -HTML*/ "Ehk kommentti", /* Maybe reply -HTML*/ "Ketjuittain", /* By Thread -HTML*/ "Aiheittain", /* By Subject -HTML*/ "Kirjoittajittain", /* By Author -HTML*/ "Ei voi luoda hakemistoa", /* Can not create directory -STDERR*/ "Luon hakemistoa", /* Creating directory -STDOUT*/ "Asetukset", /* Configuration Values -STDOUT*/ "polku", /* path -STDOUT*/ "Muisti loppui!", /* Ran out of memory!-STDERR*/ "Tmn arkiston loi", /* This archive was generated by-HTML*/ "Osaset", /* Elements -STDOUT*/ "Ei osasia", /* No Elements -STDOUT*/ "Ei voi avata postiarkistoa", /* Cannot open mail archive */ "Luen uusia otsikkorivej...", /* Reading new header...-STDOUT */ "Lataan postilaatikkoa", /* Loading mailbox -STDOUT */ "koodaus ei tuettu, talletettu sellaisenaan", /* encoding is not supported, stored as-is -HTML*/ "viesti", /* messages -HTML*/ "Versio", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "Ohjeet", /* Docs -STDOUT*/ "Komento- ja ohjausmuuttujat", /* Command and Control Variables-STDOUT*/ "Kyll", /* Yes -STDOUT*/ "Ei", /* No -STDOUT*/ "Tietoa arkistosta: ei kytss", /* About the archive: not used-STDOUT */ "Muut arkistot: ei kytss", /* Other archives: not used-STDOUT*/ "osoite ei kytss", /* address not used -STDOUT*/ "Kytetn oletus--rakennetta", /* Builtin statement used-STDOUT*/ "Ei voi lukea sek tiedostosta ett syttvirrasta (stdin).", /* Cannot read from both file and stdin. -STDERR*/ "Asetukset", /* Options -STDOUT*/ "URL muihin arkistoihin", /* URL to other archives -STDOUT*/ "URL arkiston tietoihin", /* URL to archive information -STDOUT*/ "Asetustiedosto", /* Configuration file to read in -STDOUT*/ "HTML-tiedostojen talletushakemisto", /* The directory to save HTML files in -STDOUT*/ "Lue viestit syttvirrasta (stdin)",/* Read messages from standard input -STDOUT*/ "Talletettavan arkiston nimi", /* What to name the output archive -STDOUT*/ "Luettava postiarkisto", /* Mail archive to read in -STDOUT*/ "Nyt eteneminen", /* Show progress -STDOUT*/ "Nyt vain asetusmuuttujat", /* Show configuration variables only -STDOUT*/ "Nyt versiotieto ja lopeta ohjelma", /* Show version information and exit -STDOUT*/ "Pivit arkistoa yhdell viestill", /* Update archive by one article -STDOUT*/ "Korvaa aiemmat viestit", /* Overwrite previous messages -STDOUT*/ "Mrit kytettv kieli", /* Specify language to use -STDOUT*/ "Kyttohje", /* Usage -STDOUT*/ "Kieli ei tuettu", /* Language not supported -STDERR*/ "Ei asetettu", /* Not set -STDOUT*/ "Ei kytss", /* Not used -STDOUT*/ "Luotu liitetiedosto", /* Created attachment file -STDOUT*/ "liite", /* attachment -HTML*/ "suojaus", /* mode -STDOUT*/ "Luen vanhoja otsikkorivej", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "VIRHE", /* ERROR -STDERR*/ "Listan lhetysosoite", /* The submission address of the list-STDERR*/ "Lue vain yksi viesti", "Kirjoittajan mukaan", /* author -HTML*/ "Pivyksen mukaan", /* date -HTML*/ "Aiheen mukaan", /* subject -HTML*/ "Mail actions", /* Mail actions (MA) header -HTML*/ "mail a new topic", /* MA New Message -HTML*/ "respond to this message", /* MA Reply -HTML*/ "Summary of Monthly Index Files", /* monthly -HTML*/ "Summary of Yearly Index Files", /* yearly -HTML*/ "Build a GDBM header cache", /* Build a GDBM header cache -STDOUT*/ "GDBM header cache option not build in", /* GDBM header cache option not build in -STDERR*/ "Creating gdbm index... ", /* Creating gdbm index -STDOUT*/ "Can't create gdbm file... ", /* Can't create gdbm index -STDOUT*/ "Maintain an mbox archive", /* Maintain an mbox archive -STDOUT*/ "Can't both read from and write to an mbox.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Attachment view", /* Attachment view -HTML*/ "By messages with attachments", /* By messages with attachments -HTML*/ "Writing attachment index to", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ "Cannot create symbolic link", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Cannot remove file", /* MSG_CANNOT_UNLINK -STDOUT */ "Previous Folder", /* MSG_PREV_DIRECTORY -HTML */ "Next Folder", /* MSG_NEXT_DIRECTORY -HTML */ "List of Folders", /* MSG_FOLDERS_INDEX -HTML */ "This message has been deleted from the archive", /* MSG_DELETED -HTML */ "This message has expired", /* MSG_EXPIRED -HTML */ "(deleted message)", /* MSG_DEL_SHORT -HTML */ "Original text of this message", /* MSG_TXT_VERSION -HTML */ "This message has been filtered out", /* MSG_FILTERED_OUT -HTML */ "Kirjoittajan mukaan", /* MSG_FROM -HTML*/ "Write haof XML files", /* Write hoaf XML files -STDOUT */ "Writing haof to", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "This message has been deleted from the archive", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Italian version of the language table ** Gabriele Bartolini , Prato Linux User Group, Italia ** Marco Nenciarini , Prato Linux User Group, Italia ** */ char *it[] = { /* Italian */ "Nuovo Messaggio", /* New Message -HTML*/ "Rispondi", /* Reply -HTML*/ "Riguardo questa lista", /* About this list -HTML*/ "Fine dei messaggi", /* End of Messages -HTML*/ "Inizio dei messaggi", /* Start of Messages -HTML*/ "Visualizza per data", /* Date view -HTML*/ "Visualizza per discussione", /* Thread view -HTML*/ "Visualizza per oggetto", /* Subject view -HTML*/ "Visualizza per autore", /* Author view -HTML*/ "Altri gruppi", /* Other groups -HTML*/ "Messaggi", /* Messages -HTML*/ "Inizio", /* Starting -HTML*/ "Fine", /* Ending -HTML*/ "Riguardo questo archivio", /* About this archive -HTML*/ "ordinato per", /* Messages sorted by -HTML*/ "Altri archivi di posta", /* Other mail archives -HTML*/ "Per data", /* By Date -HTML*/ "Messaggi pi recenti", /* Most recent messages-HTML*/ "autore", /* author -HTML*/ "data", /* date -HTML*/ "discussione", /* thread -HTML*/ "oggetto", /* subject -HTML*/ "per opzioni", /* for options -STDOUT*/ "Scrittura messaggi su", /* Writing messages to-STDOUT*/ "Scrittura indice delle date su", /* Writing date index to-STDOUT*/ "Scrittura indice delle discussioni su", /* Writing thread index to -STDOUT*/ "Scrittura indice degli oggetti su", /* Writing subject index to-STDOUT*/ "Scrittura indice degli autori su", /* Writing author index to-STDOUT*/ "Data dell'ultimo messaggio", /* Last message date -HTML*/ "Archiviato il", /* Archived on -HTML*/ "Impossibile eseguire 'chmod'", /* Can not chmod -STDERR*/ "Impossibile scrivere", /* Could not write -STDERR*/ "Prossimo messaggio", /* Next message -HTML*/ "Messaggio precedente", /* Previous message -HTML*/ "Forse in risposta a", /* Maybe in reply to -HTML*/ "In risposta a", /* In reply to -HTML*/ "Prossimo nella discussione", /* Next in thread -HTML*/ "Forse risposta", /* Maybe reply -HTML*/ "Per discussione", /* By Thread -HTML*/ "Per oggetto", /* By Subject -HTML*/ "Per autore", /* By Author -HTML*/ "Impossibile creare la directory", /* Can not create directory -STDERR*/ "Creazione directory", /* Creating directory -STDOUT*/ "Valori di configurazione", /* Configuration Values -STDOUT*/ "percorso", /* path -STDOUT*/ "Memoria insufficiente!", /* Ran out of memory!-STDERR*/ "Questo archivio stato generato da", /* This archive was generated by-HTML*/ "Elementi", /* Elements -STDOUT*/ "Nessun elemento", /* No Elements -STDOUT*/ "Impossibile aprire archivio di posta", /* Cannot open mail archive */ "Lettura nuove intestazioni", /* Reading new header...-STDOUT */ "Caricamento casella di posta", /* Loading mailbox -STDOUT */ "Codifica non supportata, memorizzato 'cos come '", /* encoding is not supported, stored as-is -HTML*/ "messaggi", /* messages -HTML*/ "Versione", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "Documenti", /* Docs -STDOUT*/ "Variabili di comando e controllo", /* Command and Control Variables-STDOUT*/ "S", /* Yes -STDOUT*/ "No", /* No -STDOUT*/ "Riguardo l'archivio: non usato", /* About the archive: not used-STDOUT */ "Altri archivi: non usati", /* Other archives: not used-STDOUT*/ "indirizzo inutilizzato", /* address not used -STDOUT*/ "Istruzione di default utilizzata", /* Builtin statement used-STDOUT*/ "Impossibile leggere sia dal file che dal canale stdin", /* Cannot read from both file and stdin. -STDERR*/ "Opzioni", /* Options -STDOUT*/ "URL per gli altri archivi", /* URL to other archives -STDOUT*/ "URL per le informazioni sull'archivio", /* URL to archive information -STDOUT*/ "File di configurazione", /* Configuration file to read in -STDOUT*/ "Directory in cui salvare i file HTML", /* The directory to save HTML files in -STDOUT*/ "Lettura messaggi dal canale stdin",/* Read messages from standard input -STDOUT*/ "Come nominare l'archivio in output", /* What to name the output archive -STDOUT*/ "Archivio di posta in lettura", /* Mail archive to read in -STDOUT*/ "Mostra progresso", /* Show progress -STDOUT*/ "Mostra solo le variabili di configurazione", /* Show configuration variables only -STDOUT*/ "Mostra le informazioni sulla versione ed esci", /* Show version information and exit -STDOUT*/ "Aggiorna l'archivio per un articolo", /* Update archive by one article -STDOUT*/ "Sovrascrivi messaggi precedenti", /* Overwrite previous messages -STDOUT*/ "Specifica il linguaggio da usare", /* Specify language to use -STDOUT*/ "Utilizzo", /* Usage -STDOUT*/ "Linguaggio non supportato", /* Language not supported -STDERR*/ "Non impostato", /* Not set -STDOUT*/ "Non utilizzato", /* Not used -STDOUT*/ "Creato il file per l'allegato", /* Created attachment file -STDOUT*/ "allegato", /* attachment -HTML*/ "modalit", /* mode -STDOUT*/ "Lettura intestazioni vecchie", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "ERRORE", /* ERROR -STDERR*/ "Indirizzo per l'iscrizione alla lista", /* The submission address of the list-STDERR*/ "Legge una mail soltanto dall'input", "Autore", /* author -HTML*/ "Data", /* date -HTML*/ "Oggetto", /* subject -HTML*/ "Azioni di posta", /* Mail actions (MA) header -HTML*/ "spedisci un nuovo argomento", /* MA New Message -HTML*/ "rispondi a questo messaggio", /* MA Reply -HTML*/ "Riepilogo dei file di indice mensili", /* monthly -HTML*/ "Riepilogo dei file di indice annuali", /* yearly -HTML*/ "Costruisci una cache degli header in GDBM", /* Build a GDBM header cache -STDOUT*/ "Creazione dell'indice gdbm ... ", /* Creating gdbm index -STDOUT*/ "Impossibile creare l'indice gdbm ... ", /* Can't create gdbm index -STDOUT*/ "Mantieni un archivio di tipo mbox", /* Maintain an mbox archive -STDOUT*/ "Impossibile leggere da/scrivere su mbox.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Visualizza allegato", /* Attachment view -HTML*/ "Per messaggi con allegato", /* By messages with attachments -HTML*/ "Scrittura indice allegato su", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ "Impossibile creare link simbolico", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Impossibile eliminare file", /* MSG_CANNOT_UNLINK -STDOUT */ "Cartella precedente", /* MSG_PREV_DIRECTORY -HTML */ "Prossima cartella", /* MSG_NEXT_DIRECTORY -HTML */ "Lista delle cartelle", /* MSG_FOLDERS_INDEX -HTML */ "Questo messaggio stato cancellato dall'archivio", /* MSG_DELETED -HTML */ "Il messaggio scaduto", /* MSG_EXPIRED -HTML */ "(messaggio cancellato)", /* MSG_DEL_SHORT -HTML */ "Testo originale di questo messaggio", /* MSG_TXT_VERSION -HTML */ "Questo messaggio stato filtrato", /* MSG_FILTERED_OUT -HTML */ "From", /* MSG_FROM -HTML*/ "Write haof XML files", /* Write hoaf XML files -STDOUT */ "Writing haof to", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Questo messaggio stato cancellato dall'archivio", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** French version of the language table ** Translation by Nicolas Noble */ char *fr[] = { /* French */ "Nouveau Message", /* New Message -HTML*/ "Réponse", /* Reply -HTML*/ "A propos de cette liste", /* About this list -HTML*/ "Fin des Messages", /* End of Messages -HTML*/ "Début des Messages", /* Start of Messages -HTML*/ "Liste par Date", /* Date view -HTML*/ "Liste par Thème", /* Thread view -HTML*/ "Liste par Sujet", /* Subject view -HTML*/ "Liste par Auteur", /* Author view -HTML*/ "Liste par fichier attachs", /* Attachment view -HTML*/ "Messages", /* Messages -HTML*/ "Début", /* Starting -HTML*/ "Fin", /* Ending -HTML*/ "A propos de cette archive", /* About this archive -HTML*/ ", classés par", /* Messages sorted by -HTML*/ "Autres archives", /* Other mail archives -HTML*/ "par Date", /* By Date -HTML*/ "Messages les plus récents", /* Most recent messages-HTML*/ "auteur", /* author -HTML*/ "date", /* date -HTML*/ "thème", /* thread -HTML*/ "sujet", /* subject -HTML*/ "pour les options", /* for options -STDOUT*/ "Ecriture des messages vers", /* Writing messages to-STDOUT*/ "Ecriture de l'index 'date' dans", /* Writing date index to-STDOUT*/ "Ecriture de l'index 'thme' dans", /* Writing thread index to -STDOUT*/ "Ecriture de l'index 'sujet' dans", /* Writing subject index to-STDOUT*/ "Ecriture de l'index 'auteur' dans", /* Writing author index to-STDOUT*/ "Date du dernier message", /* Last message date -HTML*/ "Archivé le", /* Archived on -HTML*/ "Ne peut effectuer de chmod", /* Can not chmod -STDERR*/ "Ne peut crire", /* Could not write -STDERR*/ "Message suivant", /* Next message -HTML*/ "Message précédent", /* Previous message -HTML*/ "Sans doute en réponse à", /* Maybe in reply to -HTML*/ "En réponse à", /* In reply to -HTML*/ "Suivant dans le thème", /* Next in thread -HTML*/ "Sans doute en réponse", /* Maybe reply -HTML*/ "par Th&eagrave;me", /* By Thread -HTML*/ "par Sujet", /* By Subject -HTML*/ "par Auteur", /* By Author -HTML*/ "Ne peut crer le rpertoire", /* Can not create directory -STDERR*/ "Cration du rpertoire", /* Creating directory -STDOUT*/ "Valeurs configures", /* Configuration Values -STDOUT*/ "chemin", /* path -STDOUT*/ "Plus assez de mmoire!", /* Ran out of memory!-STDERR*/ "Cette archive a été créée par", /* This archive was generated by-HTML*/ "Elments", /* Elements -STDOUT*/ "Aucun Elment", /* No Elements -STDOUT*/ "Ne peut ouvrir l'archive de mail", /* Cannot open mail archive */ "Lecture du nouvel en-tte...", /* Reading new header...-STDOUT */ "Chargement de la boite aux lettres", /* Loading mailbox -STDOUT */ "encodage non supporté, stocké tel quel",/* encoding is not supported, stored as-is -HTML*/ "messages", /* messages -HTML*/ "Version", /* Version -STDOUT*/ "Revision", /* Patchlevel -STDOUT*/ "Documents", /* Docs -STDOUT*/ "Variables de Commande et de Contrle", /* Command and Control Variables-STDOUT*/ "Oui", /* Yes -STDOUT*/ "Non", /* No -STDOUT*/ "A propos de l'archive: non utilis", /* About the archive: not used-STDOUT */ "Autres archives: non utilis", /* Other archives: not used-STDOUT*/ "adresse non utilise", /* address not used -STDOUT*/ "Utilisation de la dclaration ", /* Builtin statement used-STDOUT*/ "Impossible de lire simulatanment un fichier et le flot d'entre standard (stdin)", /* Cannot read from both file and stdin. -STDERR*/ "Options", /* Options -STDOUT*/ "URL vers les autres archives", /* URL to other archives -STDOUT*/ "URL vers les informations sur l'archive", /* URL to archive information -STDOUT*/ "Fichier de configuration lire", /* Configuration file to read in -STDOUT*/ "Rpertoire o sauver les fichiers HTML",/* The directory to save HTML files in -STDOUT*/ "Lecture des messages depuis le flot d'entre standard (stdin)", /* Read messages from standard input -STDOUT*/ "Nom de l'archive de sortie", /* What to name the output archive -STDOUT*/ "Archive d'email lire", /* Mail archive to read in -STDOUT*/ "Voir la progression", /* Show progress -STDOUT*/ "Voir les variables de configuration seulement", /* Show configuration variables only -STDOUT*/ "Afficher la version et quitter", /* Show version information and exit -STDOUT*/ "Mettre jour l'archive d'un article", /* Update archive by one article -STDOUT*/ "Ecraser les messages prcdents", /* Overwrite previous messages -STDOUT*/ "Spcifier la langue utiliser", /* Specify language to use -STDOUT*/ "Utilisation", /* Usage -STDOUT*/ "Langue non supporte", /* Language not supported -STDERR*/ "Non dfini", /* Not set -STDOUT*/ "Non utilis", /* Not used -STDOUT*/ "Fichier attach cr", /* Created attachment file -STDOUT*/ "fichier attaché", /* attachment -HTML*/ "mode", /* mode -STDOUT*/ "Lecture des anciens en-ttes", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "ERREUR", /* ERROR -STDERR*/ "Adresse d'envoi la liste", /* The submission address of the list-STDERR*/ "Lire seulement un mail depuis l'entre", "Auteur", /* author -HTML*/ "Date", /* date -HTML*/ "Sujet", /* subject -HTML*/ "Actions sur les mails", /* Mail actions (MA) header -HTML*/ "créer un nouveau thème", /* MA New Message -HTML*/ "répondre à ce message", /* MA Reply -HTML*/ "Récapitulatif des fichiers Index mensuels", /* monthly -HTML*/ "Récapitulatif des fichiers Index annuels", /* yearly -HTML*/ "Creation d'un cache GDBM pour les en-ttes", /* Build a GDBM header cache -STDOUT*/ "GDBM header cache option not build in", /* GDBM header cache option not build in -STDERR*/ "Generation de l'index GDBM... ", /* Creating gdbm index -STDOUT*/ "Impossible de crer un fichier GDBM... ", /* Can't create gdbm index -STDOUT*/ "Maintenance d'une archive email (mbox)", /* Maintain an mbox archive -STDOUT*/ "Impossible de lire et d'crire simultanment dans une archive email (mbox)", /* "Can't both read from and write to an mbox." -STDOUT*/ "Liste par fichier attachés", /* Attachment view -HTML*/ "par messages avec fichiers attachés", /* By messages with attachments -HTML*/ "Ecriture de l'index 'fichiers attachs' dans",/* Writing attachment index to -STDOUT*/ "octets", /* file size, so far only for attachments -HTML */ "Impossible de crer un lien symbolique",/* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Impossible de supprimer le fichier", /* MSG_CANNOT_UNLINK -STDOUT */ "Dossier précédent", /* MSG_PREV_DIRECTORY -HTML */ "Dossier suivant", /* MSG_NEXT_DIRECTORY -HTML */ "Liste des dossiers", /* MSG_FOLDERS_INDEX -HTML */ "Ce message a été supprimé de l'archive", /* MSG_DELETED -HTML */ "Ce message est trop vieux", /* MSG_EXPIRED -HTML */ "(message supprimé)", /* MSG_DEL_SHORT -HTML */ "Texte original de ce message", /* MSG_TXT_VERSION -HTML */ "Ce message a été supprim par filtrage", /* MSG_FILTERED_OUT -HTML */ "Auteur", /* MSG_FROM -HTML*/ "Ecrire fichiers XML haof (archive overview files)", /* Write hoaf XML files -STDOUT */ "Ecriture des fichiers haof (archive overview files) dans", /* Writing haof to -HTML*/ "Ce message", /* This message -HTML */ "Corps du message", /* Message body -HTML */ "Répondre", /* Respond -HTML */ "Autres options", /* More options -HTML */ "Messages en rapport", /* Related messages -HTML */ "Suivant", /* Next -HTML */ "Précedent", /* Previous -HTML */ "Réponses", /* Replies -HTML */ "Messages récents triés", /* Contemporary messages sorted -HTML */ "Aide", /* Help -HTML */ "Message auquels ce message répond", /* In Reply To - HTML link*/ "Message suivant dans la discussion", /* Next message in thread - HTML link*/ "Message envoyé en réponse au message courant", /* Replies to this message - HTML link*/ "Messages récents par date", /* Contemporary messages by date */ "Discussions récentes", /* Contemporary messages by threads - HTML */ "Messages récents par sujet", /* Contemporary messages by subject - HTML */ "Messages récents par auteur", /* Contemporary messages by author - HTML*/ "Message suivant dans la liste", /* Next message - HTML */ "Message précedent dans la liste", /* Previous message - HTML */ "Messages récents par fichier attaché", /* Contemporary messages by attachments - HTML*/ "Barre de navigation vers le niveau supérieur", /* Navigation bar, upper levels - HTML*/ "Barre de navigation", /* Navigation bar - HTML*/ "Trier par", /* Sort by - HTML*/ "Autres périodes", /* Other periods - HTML */ "Suivant", /* Next folder - HTML */ "Messages archives dans la période suivante, triés par date", /* Next folder, by date - HTML link */ "Précedent", /* Previous folder - HTML */ "Messages archives dans la période précedente, triés par date", /* Previous folder, by date - HTML Link */ "Liste de toutes les périodes", /* List of all periods - HTML*/ "Cette période", /* This period - HTML*/ "ReÇu le", /* Received on - HTML */ "A coté de", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listé par date", /* listed by date - HTML */ "par fil de discussion" , /* discussion threads - HTML */ "listé par auteur", /* listed by author - HTML */ "par sujet", /* listed by subject - HTML */ "par fichier attaché", /* by attachment - HTML */ "période", /* period - HTML */ " &eagrave; ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Ce message a été supprimé de l'archive", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Icelandic version of the language table ** Translation by Bjarni R. Einarsson */ char *is[] = { /* Icelandic */ "Ntt brf", /* New Message -HTML*/ "Svar", /* Reply -HTML*/ "Um ennan lista", /* About this list -HTML*/ "Endir safns", /* End of Messages -HTML*/ "Upphaf safns", /* Start of Messages -HTML*/ "Raa e. dagssetningum", /* Date view -HTML*/ "Raa e. umrum", /* Thread view -HTML*/ "Raa e. vifangsefnum", /* Subject view -HTML*/ "Raa e. hfundum", /* Author view -HTML*/ "Attachment view", /* Attachment view -HTML*/ "Brfum", /* Messages -HTML*/ "Fr", /* Starting -HTML*/ "Til", /* Ending -HTML*/ "Um etta safn", /* About this archive -HTML*/ "Raa eftir", /* Messages sorted by -HTML*/ "nnur sfn", /* Other mail archives -HTML*/ "eftir dagssetningum", /* By Date -HTML*/ "Njustu brfin", /* Most recent messages-HTML*/ "hfundum", /* author -HTML*/ "dags.", /* date -HTML*/ "umrum", /* thread -HTML*/ "vifangsefnum", /* subject -HTML*/ "for options", /* for options -STDOUT*/ "Writing messages to", /* Writing messages to-STDOUT*/ "Writing date index to", /* Writing date index to-STDOUT*/ "Writing thread index to", /* Writing thread index to -STDOUT*/ "Writing subject index to", /* Writing subject index to-STDOUT*/ "Writing author index to", /* Writing author index to-STDOUT*/ "Dags. sasta brfs", /* Last message date -HTML*/ "Sasta brf mtteki", /* Archived on -HTML*/ "Can not chmod", /* Can not chmod -STDERR*/ "Could not write", /* Could not write -STDERR*/ "Nsta brf", /* Next message -HTML*/ "Fyrra brf", /* Previous message -HTML*/ "Mgulega frh. af", /* Maybe in reply to -HTML*/ " framhaldi af", /* In reply to -HTML*/ "Nst umru", /* Next in thread -HTML*/ "Mgulegt svar", /* Maybe reply -HTML*/ "eftir umrum", /* By Thread -HTML*/ "eftir vifangsefnum", /* By Subject -HTML*/ "eftir hfundum", /* By Author -HTML*/ "Can not create directory", /* Can not create directory -STDERR*/ "Creating directory", /* Creating directory -STDOUT*/ "Configuration Values", /* Configuration Values -STDOUT*/ "path", /* path -STDOUT*/ "Ran out of memory!", /* Ran out of memory!-STDERR*/ "Framreitt af", /* This archive was generated by-HTML*/ "Elements", /* Elements -STDOUT*/ "No Elements", /* No Elements -STDOUT*/ "Cannot open mail archive", /* Cannot open mail archive */ "Reading new header...", /* Reading new header...-STDOUT */ "Loading mailbox", /* Loading mailbox -STDOUT */ "framandi kun, geymt breytt", /* encoding is not supported, stored as-is -HTML*/ "brf.", /* messages -HTML*/ "Version", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "Docs", /* Docs -STDOUT*/ "Command and Control Variables", /* Command and Control Variables-STDOUT*/ "Yes", /* Yes -STDOUT*/ "No", /* No -STDOUT*/ "About the archive: not used", /* About the archive: not used-STDOUT */ "Other archives: not used", /* Other archives: not used-STDOUT*/ "address not used", /* address not used -STDOUT*/ "Builtin statement used", /* Builtin statement used-STDOUT*/ "Cannot read from both file and stdin.", /* Cannot read from both file and stdin. -STDERR*/ "Options", /* Options -STDOUT*/ "URL to other archives", /* URL to other archives -STDOUT*/ "URL to archive information", /* URL to archive information -STDOUT*/ "Configuration file to read in", /* Configuration file to read in -STDOUT*/ "The directory to save HTML files in", /* The directory to save HTML files in -STDOUT*/ "Read messages from standard input", /* Read messages from standard input -STDOUT*/ "What to name the output archive", /* What to name the output archive -STDOUT*/ "Mail archive to read in", /* Mail archive to read in -STDOUT*/ "Show progress", /* Show progress -STDOUT*/ "Show configuration variables only", /* Show configuration variables only -STDOUT*/ "Show version information and exit", /* Show version information and exit -STDOUT*/ "Update archive by one article", /* Update archive by one article -STDOUT*/ "Overwrite previous messages", /* Overwrite previous messages -STDOUT*/ "Specify language to use", /* Specify language to use -STDOUT*/ "Usage", /* Usage -STDOUT*/ "Language not supported", /* Language not supported -STDERR*/ "Not set", /* Not set -STDOUT*/ "Not used", /* Not used -STDOUT*/ "Created attachment file", /* Created attachment file -STDOUT*/ "vihengi", /* attachment -HTML*/ "mode", /* mode -STDOUT*/ "Reading old headers", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "ERROR", /* ERROR -STDERR*/ "The submission address of the list", /* The submission address of the list-STDERR*/ "Read only one mail from input", "Hfundur", /* author -HTML*/ "Dagssetning", /* date -HTML*/ "Vifangsefni", /* subject -HTML*/ "Mail actions", /* Mail actions (MA) header -HTML*/ "mail a new topic", /* MA New Message -HTML*/ "respond to this message", /* MA Reply -HTML*/ "Summary of Monthly Index Files", /* monthly -HTML*/ "Summary of Yearly Index Files", /* yearly -HTML*/ "Build a GDBM header cache", /* Build a GDBM header cache -STDOUT*/ "GDBM header cache option not build in", /* GDBM header cache option not build in -STDERR*/ "GDBM header cache option not build in", /* GDBM header cache option not build in -STDERR*/ "Creating gdbm index... ", /* Creating gdbm index -STDOUT*/ "Can't create gdbm file... ", /* Can't create gdbm index -STDOUT*/ "Maintain an mbox archive", /* Maintain an mbox archive -STDOUT*/ "Can't both read from and write to an mbox.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Attachment view", /* Attachment view -HTML*/ "By messages with attachments", /* By messages with attachments -HTML*/ "Writing attachment index to", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ "Cannot create symbolic link", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Cannot remove file", /* MSG_CANNOT_UNLINK -STDOUT */ "Previous Folder", /* MSG_PREV_DIRECTORY -HTML */ "Next Folder", /* MSG_NEXT_DIRECTORY -HTML */ "List of Folders", /* MSG_FOLDERS_INDEX -HTML */ "This message has been deleted from the archive", /* MSG_DELETED -HTML */ "This message has expired", /* MSG_EXPIRED -HTML */ "(deleted message)", /* MSG_DEL_SHORT -HTML */ "Original text of this message", /* MSG_TXT_VERSION -HTML */ "This message has been filtered out", /* MSG_FILTERED_OUT -HTML */ "Hfundur", /* MSG_FROM -HTML*/ "Write haof XML files", /* Write hoaf XML files -STDOUT */ "Writing haof to", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "This message has been deleted from the archive", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Swedish version of the language table. Daniel Stenberg translation. ** (a little secret for free: we don't say bork ;-) */ char *sv[] = { "Nytt brev", /* New Message -HTML*/ "Svar" , /* Reply -HTML*/ "Om den här listan", /* About this list -HTML*/ "Slut på brevlistan", /* End of Messages -HTML*/ "Start på brevlistan", /* Start of Messages -HTML*/ "Datumvy", /* Date view -HTML*/ "Trådvy", /* Thread view -HTML*/ "Ämnesvy", /* Subject view -HTML*/ "Författarvy", /* Author view -HTML*/ "Bilagevy", /* Attachment view -HTML*/ "Brev", /* Messages -HTML*/ "Startar", /* Starting -HTML*/ "Slutar", /* Ending -HTML*/ "Om det här arkivet", /* About this archive -HTML*/ "sorterade efter", /* Messages sorted by -HTML*/ "Andra brevarkiv", /* Other mail archives-HTML*/ "Datumsorterat", /* By Date -HTML*/ "Nyast brev", /* Most recent messages-HTML*/ "författare", /* author -HTML*/ "datum", /* date -HTML*/ "tråd", /* thread -HTML*/ "ämne", /* subject -HTML*/ "fr instllningar", /* for options -STDOUT*/ "Skriver brev till", /* Writing messages to-STDOUT*/ "Skriver datumindex till", /* Writing date index to-STDOUT*/ "Skriver trdindex till", /* Writing thread index to -STDOUT*/ "Skriver mnesindex till", /* Writing subject index to-STDOUT*/ "Skriver frfattarindex till", /* Writing author index to-STDOUT*/ "Senaste brevdatum", /* Last message date -HTML*/ "Arkiverat", /* Archived on -HTML*/ "Kan inte chmod", /* Can not chmod -STDERR*/ "Kunde inte skriva", /* Could not write -STDERR*/ "Nästa brev", /* Next message -HTML*/ "Tidigare brev", /* Previous message -HTML*/ "Kanske ett svar till", /* Maybe in reply to -HTML*/ "Svar till", /* In reply to -HTML*/ "Nästa i tråden", /* Next in thread -HTML*/ "Kanske svar", /* Maybe reply -HTML*/ "Trdsorterat", /* By Thread -HTML*/ "mnessorterat", /* By Subject -HTML*/ "Frfattarsorterat", /* By Author -HTML*/ "Kan inte skapa katalog", /* Can not create directory -STDERR*/ "Skapar katalog", /* Creating directory -STDOUT*/ "Konfigureringsvrden", /* Configuration Values -STDOUT*/ "path", /* path -STDOUT*/ "Fick slut p minne!", /* Ran out of memory!-STDERR*/ "Det här arkivet skapades av", /* This archive was generated by-HTML*/ "Delar", /* Elements -STDOUT*/ "Inga delar", /* No Elements -STDOUT*/ "Kan inte ppna brevarkivet", /* Cannot open mail archive */ "Lser nytt huvud...", /* Reading new header...-STDOUT*/ "Laddar mailbox", /* Loading mailbox -STDOUT */ "kodformatet stöds inte, sparat som det är", /* encoding is not supported, stored as-is -HTML*/ "brev", /* messages -HTML*/ "Version", /* Version -STDOUT*/ "Patchniv", /* Patchlevel -STDOUT*/ "Dokumentation", /* Docs -STDOUT*/ "Kommando- och styrvariabler", /* Command and Control Variables-STDOUT*/ "Ja", /* Yes -STDOUT*/ "Nej", /* No -STDOUT*/ "Om arkivet: ej anvnd", /* About the archive: not used-STDOUT */ "Andra arkiv: ej anvnd", /* Other archives: not used-STDOUT*/ "adress ej anvnd", /* address not used -STDOUT*/ "Inbyggd anvnd", /* Builtin statement used-STDOUT*/ "Kan inte lsa bde frn fil och stdin.", /* Cannot read from both file and stdin. -STDERR*/ "Alternativ", /* Options -STDOUT*/ "URL till andra arkiv", /* URL to other archives -STDOUT*/ "URL till arkivinformation", /* URL to archive information -STDOUT*/ "Konfigurationsfil att lsa in", /* Configuration file to read in -STDOUT*/ "Katalog att spara HTML-filerna i", /* The directory to save HTML files in -STDOUT*/ "Ls breven från standard in", /* Read messages from standard input-STDOUT*/ "Namnet p utarkivet", /* What to name the output archive-STDOUT*/ "Brevarkiv att lsa in", /* Mail archive to read in -STDOUT*/ "Visa frlopp", /* Show progress -STDOUT*/ "Visa konfigurationsvariabler enbart", /* Show configuration variables only-STDOUT*/ "Visa versionsinformation och sluta", /* Show version information and exit -STDOUT*/ "Updatera arkivet med ett brev", /*Update archive by one article -STDOUT*/ "Skriv ver tidigare brev", /* Overwrite previous messages -STDOUT*/ "Ange sprk att anvnda", /* Specify language to use -STDOUT*/ "Anvndning", /* Usage -STDOUT*/ "Sprket stds ej", /* Language not supported -STDERR*/ "Ej angivet", /* Not set -STDOUT*/ "Ej anvnt", /* Not used -STDOUT*/ "Skapade bilagefil", /* Created attachment file -STDOUT*/ "bilaga", /* attachment -HTML*/ "lge", /* mode -STDOUT*/ "Lser gamla huvuden", /* Reading old headers -STDOUT*/ "endast fr justering", /* for alignment only -STDOUT*/ "FEL", /* ERROR -STDERR*/ "Adressen fr att posta till listan", /* The submission address of the list-STDERR*/ "Ls bara ett brev frn indata", "Författare", /* author -HTML*/ "Datum", /* date -HTML*/ "Ämne", /* subject -HTML*/ "E-postfunktioner", /* Mail actions (MA) header -HTML*/ "sänd ett nytt ämne", /* MA New Message -HTML*/ "svara på brevet", /* MA Reply -HTML*/ "Sammanfattning över månatliga indexfiler", /* monthly -HTML*/ "Sammanfattning över årliga indexfiler", /* yearly -HTML*/ "Bygger en GDBM-huvudcache", /* Build a GDBM header cache -STDOUT*/ "Tillval fr GDBM-huvudcache inte inkompilerat", /* GDBM header cache option not build in -STDERR*/ "Skapar gdbm-index... ", /* Creating gdbm index -STDOUT*/ "Kan inte skapa gdbm-fil... ", /* Can't create gdbm index -STDOUT*/ "Underhll ett mbox-arkiv", /* Maintain an mbox archive -STDOUT*/ "Kan inte bde lsa frn och skriva till en mbox.", /* "Can't both read from and write to an mbox." -STDOUT*/ "Bilagevy", /* Attachment view -HTML*/ "Efter brev med bilaga", /* By messages with attachments -HTML*/ "Skriver bilageindex till", /* Writing attachment index to -STDOUT*/ "byte", /* file size, so far only for attachments -HTML */ "Kan inte skapa symbolisk lnk", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Kan inte ta bort fil", /* MSG_CANNOT_UNLINK -STDOUT */ "Föregående mapp", /* MSG_PREV_DIRECTORY -HTML */ "Nästa mapp", /* MSG_NEXT_DIRECTORY -HTML */ "Mapplista", /* MSG_FOLDERS_INDEX -HTML */ "Detta brev har tagits bort från arkivet", /* MSG_DELETED -HTML */ "Detta brev har utgått", /* MSG_EXPIRED -HTML */ "(borttaget brev)", /* MSG_DEL_SHORT -HTML */ "Ursprunglig brevtext", /* MSG_TXT_VERSION -HTML */ "Detta brev har filtrerats", /* MSG_FILTERED_OUT -HTML */ "Författare", /* MSG_FROM -HTML*/ "Skriv haof-XML-filer", /* Write hoaf XML files -STDOUT */ "Skriver haof till", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Detta brev har tagits bort från arkivet", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Norwegian version of the language table. ** Translation by Bosse Klykken */ char *no[] = { "Ny melding", /* New Message -HTML*/ "Svar" , /* Reply -HTML*/ "Om denne listen", /* About this list -HTML*/ "Slutt p brevlisten", /* End of Messages -HTML*/ "Start p brevlisten", /* Start of Messages -HTML*/ "Oversikt dato", /* Date view -HTML*/ "Oversikt trd", /* Thread view -HTML*/ "Oversikt emne", /* Subject view -HTML*/ "Oversikt forfatter", /* Author view -HTML*/ "Andre grupper", /* Other groups -HTML*/ "Meldinger", /* Messages -HTML*/ "Starter", /* Starting -HTML*/ "Slutter", /* Ending -HTML*/ "Om dette arkivet", /* About this archive -HTML*/ "sortert etter", /* Messages sorted by -HTML*/ "Andre meldingsarkiv", /* Other mail archives-HTML*/ "Sortert etter dato", /* By Date -HTML*/ "Nyeste melding", /* Most recent messages-HTML*/ "forfatter", /* author -HTML*/ "dato", /* date -HTML*/ "trd", /* thread -HTML*/ "emne", /* subject -HTML*/ "for innstillinger", /* for options -STDOUT*/ "Skriver meldinger til", /* Writing messages to-STDOUT*/ "Skriver datoindeks til", /* Writing date index to-STDOUT*/ "Skriver trdindeks til", /* Writing thread index to -STDOUT*/ "Skriver emneindeks til", /* Writing subject index to-STDOUT*/ "Skriver forfatterindeks til", /* Writing author index to-STDOUT*/ "Siste meldingsdato", /* Last message date -HTML*/ "Arkivert", /* Archived on -HTML*/ "Kan ikke chmod", /* Can not chmod -STDERR*/ "Kunne ikke skrive", /* Could not write -STDERR*/ "Neste melding", /* Next message -HTML*/ "Forrige melding", /* Previous message -HTML*/ "Muligens et svar til", /* Maybe in reply to -HTML*/ "Som svar til", /* In reply to -HTML*/ "Neste i trden", /* Next in thread -HTML*/ "Kanskje svar", /* Maybe reply -HTML*/ "Sortert etter trd", /* By Thread -HTML*/ "Sortert etter emne", /* By Subject -HTML*/ "Sortert etter forfatter", /* By Author -HTML*/ "Kan ikke opprette katalog", /* Can not create directory -STDERR*/ "Oppretter katalog", /* Creating directory -STDOUT*/ "Konfigureringsverdier", /* Configuration Values -STDOUT*/ "bane", /* path -STDOUT*/ "Gikk tom for minne!", /* Ran out of memory!-STDERR*/ "Dette arkivet er generert av", /* This archive was generated by-HTML*/ "Elementer", /* Elements -STDOUT*/ "Ingen elementer", /* No Elements -STDOUT*/ "Kan ikke pne meldingsarkivet", /* Cannot open mail archive */ "Leser nytt meldingshode...", /* Reading new header...-STDOUT*/ "Leser mailboks", /* Loading mailbox -STDOUT */ "kodeformatet er usupportet, lagret som den er", /* encoding is not supported, stored as-is -HTML*/ "meldinger", /* messages -HTML*/ "Versjon", /* Version -STDOUT*/ "Patchniv", /* Patchlevel -STDOUT*/ "Dokumentasjon", /* Docs -STDOUT*/ "Kommando- og kontrollvariabler", /* Command and Control Variables-STDOUT*/ "Ja", /* Yes -STDOUT*/ "Nei", /* No -STDOUT*/ "Om arkivet: ikke i bruk", /* About the archive: not used-STDOUT */ "Andre arkiv: ikke i bruk", /* Other archives: not used-STDOUT*/ "adresse ikke benyttet", /* address not used -STDOUT*/ "Innebygget benyttet", /* Builtin statement used-STDOUT*/ "Kan ikke lese bde fra fil og stdin.", /* Cannot read from both file and stdin. -STDERR*/ "Alternativer", /* Options -STDOUT*/ "URL til andre arkiv", /* URL to other archives -STDOUT*/ "URL til arkivinformasjon", /* URL to archive information -STDOUT*/ "Konfigurasjonsfil til lese inn", /* Configuration file to read in -STDOUT*/ "Katalog til spare HTML-filene i", /* The directory to save HTML files in -STDOUT*/ "Les brevene fra stdin", /* Read messages from standard input-STDOUT*/ "Navn p utarkivet", /* What to name the output archive-STDOUT*/ "Meldingsarkiv som skal leses inn", /* Mail archive to read in -STDOUT*/ "Vise fremdrift", /* Show progress -STDOUT*/ "Vise kun konfigurasjonsvariablene", /* Show configuration variables only-STDOUT*/ "Vise versjonsinformasjon og avslutte", /* Show version information and exit -STDOUT*/ "Oppdatere arkivet med n melding", /*Update archive by one article -STDOUT*/ "Skriv over andre meldinger", /* Overwrite previous messages -STDOUT*/ "Angi sprk som skal benyttes", /* Specify language to use -STDOUT*/ "Bruk", /* Usage -STDOUT*/ "Sprket er ikke stttet", /* Language not supported -STDERR*/ "Ikke angitt", /* Not set -STDOUT*/ "Ikke benyttet", /* Not used -STDOUT*/ "Lagde vedleggfil", /* Created attachment file -STDOUT*/ "vedlegg", /* attachment -HTML*/ "modus", /* mode -STDOUT*/ "Leser gamle meldingshoder", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "FEIL", /* ERROR -STDERR*/ "Adressen som brukes for innlegg til listen", /* The submission address of the list-STDERR*/ "Les bare en melding fra inn", "Forfatter", /* author -HTML*/ "Dato", /* date -HTML*/ "Emne", /* subject -HTML*/ "E-postfunksjoner", /* Mail actions (MA) header -HTML*/ "Lag ny trd", /* MA New Message -HTML*/ "besvare meldingen", /* MA Reply -HTML*/ "Sammenfatning over mnedlige indeksfiler", /* monthly -HTML*/ "Sammenfatning over rlige indeksfiler", /* yearly -HTML*/ "Bygger en GDBM-headercache", /* Build a GDBM header cache -STDOUT*/ "GDBM header cache opsjon ikke innebygget", /* GDBM header cache option not build in -STDERR*/ "Lager gdbm-index... ", /* Creating gdbm index -STDOUT*/ "Kan ikke lage gdbm-fil... ", /* Can't create gdbm index -STDOUT*/ "Opprettholde et mbox-arkiv", /* Maintain an mbox archive -STDOUT*/ "Kan ikke bde lese fra og skrive til en mbox.", /* "Can't both read from and write to an mbox."-STDOUT*/ "Oversikt vedlegg", /* Attachment view -HTML*/ "Etter meldinger med vedlegg", /* By messages with attachments -HTML*/ "Skriver vedleggsindeks til", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ "Kan ikke lage symbolisk link", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ "Kan ikke fjerne link til fil", /* MSG_CANNOT_UNLINK -STDOUT */ "Forrige mappe", /* MSG_PREV_DIRECTORY -HTML */ "Neste mappe", /* MSG_NEXT_DIRECTORY -HTML */ "Mappeliste", /* MSG_FOLDERS_INDEX -HTML */ "Denne meldingen er fjernet fra arkivet", /* MSG_DELETED -HTML */ "Dette meldingen har utgtt", /* MSG_EXPIRED -HTML */ "(slettet melding)", /* MSG_DEL_SHORT -HTML */ "Opprinnelig brevtekst", /* MSG_TXT_VERSION -HTML */ "Denne meldingen har blitt filtrert bort", /* MSG_FILTERED_OUT -HTML */ "Forfatter", /* MSG_FROM -HTML*/ "Skrive haof XML filer", /* Write hoaf XML files -STDOUT */ "Skriver haof til", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ "Denne meldingen er fjernet fra arkivet", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Greek version of the language table ** Translation by Akis Karnouskos ** STDOUT/STDERROR ** ... ** ** update ! */ char *gr[] = { /* Greek */ " ", /* New Message -HTML*/ "", /* Reply -HTML*/ " ", /* About this list -HTML*/ " ", /* End of Messages -HTML*/ " ", /* Start of Messages -HTML*/ " ", /* Date view -HTML*/ " thread", /* Thread view -HTML*/ " ", /* Subject view -HTML*/ " ", /* Author view -HTML*/ " ", /* Attachment view -HTML*/ "", /* Messages -HTML*/ "", /* Starting -HTML*/ "", /* Ending -HTML*/ " ", /* About this archive -HTML*/ " ", /* sorted by -HTML*/ "A Mail ", /* Other mail archives -HTML*/ " ", /* By Date -HTML*/ " ", /* Most recent messages-HTML*/ "", /* author -HTML*/ "", /* date -HTML*/ "thread", /* thread -HTML*/ "", /* subject -HTML*/ " ", /* for options -STDOUT*/ " ", /* Writing messages to-STDOUT*/ " ", /* Writing date index to-STDOUT*/ " thread", /* Writing thread index to -STDOUT*/ " ", /* Writing subject index to-STDOUT*/ " ", /* Writing author index to-STDOUT*/ " ", /* Last message date -HTML*/ "", /* Archived on -HTML*/ " chmod", /* Can not chmod -STDERR*/ " ", /* Could not write -STDERR*/ " ", /* Next message -HTML*/ " ", /* Previous message -HTML*/ " ", /* Maybe in reply to -HTML*/ " ", /* In reply to -HTML*/ " thread", /* Next in thread -HTML*/ " ", /* Maybe reply -HTML*/ " Thread", /* By Thread -HTML*/ " ", /* By Subject -HTML*/ " ", /* By Author -HTML*/ " directory", /* Can not create directory -STDERR*/ " directory", /* Creating directory -STDOUT*/ "configuration", /* Configuration Values -STDOUT*/ "path", /* path -STDOUT*/ " ", /* Ran out of memory!-STDERR*/ " ", /* This archive was generated by-HTML*/ "", /* Elements -STDOUT*/ " ", /* No Elements -STDOUT*/ " ", /* Cannot open mail archive */ " headers", /* Reading new header...-STDOUT*/ " mailbox", /* Loading mailbox -STDOUT*/ " , ", /* encoding is not supported, stored as-is -HTML*/ "", /* messages -HTML*/ "", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "", /* Docs -STDOUT*/ " ", /* Command and Control Variables-STDOUT*/ "", /* Yes -STDOUT*/ "", /* No -STDOUT*/ " : ", /* About the archive: not used-STDOUT */ "A : ", /* Other archives: not used-STDOUT*/ ": ", /* address not used -STDOUT*/ " ", /* Builtin statement used-STDOUT*/ " stdin.", /* Cannot read from both file and stdin. -STDERR*/ "", /* Options -STDOUT*/ "URL ", /* URL to other archives -STDOUT*/ "URL ", /* URL to archive information -STDOUT*/ " ", /* Configuration file to read in -STDOUT*/ " directory HTML ", /* The directory to save HTML files in -STDOUT*/ " ", /* Read messages from standard input -STDOUT*/ " ", /* What to name the output archive -STDOUT*/ " Mail- ", /* Mail archive to read in -STDOUT*/ " ", /* Show progress -STDOUT*/ " ", /* Show configuration variables only -STDOUT*/ " ", /* Show version information and exit -STDOUT*/ " ", /* Update archive by one article -STDOUT*/ " ", /* Overwrite previous messages -STDOUT*/ " ", /* Specify language to use -STDOUT*/ "", /* Usage -STDOUT*/ " ", /* Language not supported -STDERR*/ " ", /* Not set -STDOUT*/ " ", /* Not used -STDOUT*/ " ", /* Created attachment file -STDOUT*/ "", /* attachment -HTML*/ "", /* mode -STDOUT*/ " headers", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "", /* ERROR -STDERR*/ " emails", /* The submission address of the list-STDERR*/ " email ", /* Read only one mail from input */ "", /* author -HTML*/ "", /* date -HTML*/ "", /* subject -HTML*/ "Mail ", /* Mail actions (MA) header -HTML*/ " ", /* MA New Message -HTML*/ " ", /* MA Reply -HTML*/ " ", /* monthly -HTML*/ " ", /* yearly -HTML*/ "Build a GDBM header cache", /* Build a GDBM header cache -STDOUT*/ " gdbm ... ", /* Creating gdbm index -STDOUT*/ " gdbm ... ", /* Can't create gdbm index -STDOUT*/ " mbox ", /* Maintain an mbox archive -STDOUT*/ " mbox ", /* "Can't both read from and write to an mbox." -STDOUT*/ " ", /* Attachment view -HTML*/ " ", /* By messages with attachments -HTML*/ " ", /* Writing attachment index to -STDOUT*/ "bytes", /* file size, so far only for attachments -HTML */ " ", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ " ", /* MSG_CANNOT_UNLINK -STDOUT */ " ", /* MSG_PREV_DIRECTORY -HTML */ " ", /* MSG_NEXT_DIRECTORY -HTML */ " ", /* MSG_FOLDERS_INDEX -HTML */ " ", /* MSG_DELETED -HTML */ " ", /* MSG_EXPIRED -HTML */ "( )", /* MSG_DEL_SHORT -HTML */ " ", /* MSG_TXT_VERSION -HTML */ " ", /* MSG_FILTERED_OUT -HTML */ "", /* MSG_FROM -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ " ", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** Russian version of the language table. ** Translated by Igor Solovyoff (siv@intear.com.ua). */ char *ru[] = { /* Russian */ " ", /* New Message -HTML*/ "", /* Reply -HTML*/ " ", /* About this list -HTML*/ " ", /* End of Messages -HTML*/ " ", /* Start of Messages -HTML*/ " ", /* Date view -HTML*/ " ", /* Thread view -HTML*/ " ", /* Subject view -HTML*/ " ", /* Author view -HTML*/ " ", /* Other groups -HTML*/ "", /* Messages -HTML*/ "", /* Starting -HTML*/ "", /* Ending -HTML*/ " ", /* About this archive -HTML*/ " ", /* Messages sorted by -HTML*/ " ", /* Other mail archives -HTML*/ " ", /* By Date -HTML*/ " ", /* Most recent messages-HTML*/ "", /* author -HTML*/ "", /* date -HTML*/ "", /* thread -HTML*/ "", /* subject -HTML*/ " ", /* for options -STDOUT*/ " ", /* Writing messages to-STDOUT*/ " date index ", /* Writing date index to-STDOUT*/ " thread index ", /* Writing thread index to -STDOUT*/ " subject index ", /* Writing subject index to-STDOUT*/ " author index ", /* Writing author index to-STDOUT*/ " ", /* Last message date -HTML*/ " ", /* Archived on -HTML*/ " chmod", /* Can not chmod -STDERR*/ " ", /* Could not write -STDERR*/ " ", /* Next message -HTML*/ " ", /* Previous message -HTML*/ " ", /* Maybe in reply to -HTML*/ " ", /* In reply to -HTML*/ " ", /* Next in thread -HTML*/ " ", /* Maybe reply -HTML*/ " ", /* By Thread -HTML*/ " ", /* By Subject -HTML*/ " ", /* By Author -HTML*/ " ", /* Can not create directory -STDERR*/ " ", /* Creating directory -STDOUT*/ " ", /* Configuration Values -STDOUT*/ "", /* path -STDOUT*/ " !", /* Ran out of memory!-STDERR*/ " ", /* This archive was generated by-HTML*/ "", /* Elements -STDOUT*/ " ", /* No Elements -STDOUT*/ " ", /* Cannot open mail archive */ " ...", /* Reading new header...-STDOUT */ " mailbox", /* Loading mailbox -STDOUT */ " , ", /* encoding is not supported, stored as-is -HTML*/ ".", /* messages -HTML*/ "", /* Version -STDOUT*/ "Patchlevel", /* Patchlevel -STDOUT*/ "", /* Docs -STDOUT*/ " ", /* Command and Control Variables-STDOUT*/ "", /* Yes -STDOUT*/ "", /* No -STDOUT*/ " : ", /* About the archive: not used-STDOUT */ " : ", /* Other archives: not used-STDOUT*/ " ", /* address not used -STDOUT*/ " ", /* Builtin statement used-STDOUT*/ " and stdin.", /* Cannot read from both file and stdin. -STDERR*/ "", /* Options -STDOUT*/ "URL ", /* URL to other archives -STDOUT*/ "URL ", /* URL to archive information -STDOUT*/ " ", /* Configuration file to read in -STDOUT*/ " HTML ", /* The directory to save HTML files in -STDOUT*/ " ",/* Read messages from standard input -STDOUT*/ " ", /* What to name the output archive -STDOUT*/ " ", /* Mail archive to read in -STDOUT*/ " ", /* Show progress -STDOUT*/ " ", /* Show configuration variables only -STDOUT*/ " ", /* Show version information and exit -STDOUT*/ " ", /* Update archive by one article -STDOUT*/ " ", /* Overwrite previous messages -STDOUT*/ " ", /* Specify language to use -STDOUT*/ "", /* Usage -STDOUT*/ " ", /* Language not supported -STDERR*/ " ", /* Not set -STDOUT*/ " ", /* Not used -STDOUT*/ " -", /* Created attachment file -STDOUT*/ "", /* attachment -HTML*/ "", /* mode -STDOUT*/ " ", /* Reading old headers -STDOUT*/ "", /* for alignment only -STDOUT*/ "", /* ERROR -STDERR*/ " ", /* The submission address of the list-STDERR*/ " ", "", /* author -HTML*/ "", /* date -HTML*/ "", /* subject -HTML*/ " ", /* Mail actions (MA) header -HTML*/ " ", /* MA New Message -HTML*/ " ", /* MA Reply -HTML*/ " ", /* monthly -HTML*/ " ", /* yearly -HTML*/ " GDBM ", /* Build a GDBM header cache -STDOUT*/ " GDBM header cache ",/* GDBM header cache option not build in -STDERR*/ " gdbm ... ", /* Creating gdbm index -STDOUT*/ " gdbm ... ", /* Can't create gdbm index -STDOUT*/ " mbox ", /* Maintain an mbox archive -STDOUT*/ " mbox-.", /* "Can't both read from and write to an mbox." -STDOUT*/ " ", /* Attachment view -HTML*/ " ", /* By messages with attachments -HTML*/ " ", /* Writing attachment index to -STDOUT*/ "", /* file size, so far only for attachments -HTML */ " ", /* MSG_CANNOT_CREATE_SYMLINK -STDOUT */ " ", /* MSG_CANNOT_UNLINK -STDOUT */ " ", /* MSG_PREV_DIRECTORY -HTML */ " ", /* MSG_NEXT_DIRECTORY -HTML */ " ", /* MSG_FOLDERS_INDEX -HTML */ " ", /* MSG_DELETED -HTML */ " ", /* MSG_EXPIRED -HTML */ "( )", /* MSG_DEL_SHORT -HTML */ " ", /* MSG_TXT_VERSION -HTML */ " ", /* MSG_FILTERED_OUT -HTML */ "", /* MSG_FROM -HTML*/ " haof XML ", /* Write hoaf XML files -STDOUT */ " haof ", /* Writing haof to -HTML*/ "This message", /* This message -HTML */ "Message body", /* Message body -HTML */ "Respond", /* Respond -HTML */ "More options", /* More options -HTML */ "Related messages", /* Related messages -HTML */ "Next", /* Next -HTML */ "Previous", /* Previous -HTML */ "Replies", /* Replies -HTML */ "Contemporary messages sorted", /* Contemporary messages sorted -HTML */ "Help", /* Help -HTML */ "Message to which this message replies", /* In Reply To - HTML link*/ "Next message in this discussion thread", /* Next message in thread - HTML link*/ "Message sent in reply to this message", /* Replies to this message - HTML link*/ "Contemporary messages by date", /* Contemporary messages by date */ "Contemporary discussion threads", /* Contemporary messages by threads - HTML */ "Contemporary messages by subject", /* Contemporary messages by subject - HTML */ "Contemporary messages by author", /* Contemporary messages by author - HTML*/ "Next message in the list", /* Next message - HTML */ "Previous message in the list", /* Previous message - HTML */ "Contemporary messages by attachment", /* Contemporary messages by attachments - HTML*/ "Navigation bar to upper levels", /* Navigation bar, upper levels - HTML*/ "Navigation bar", /* Navigation bar - HTML*/ "sort by", /* Sort by - HTML*/ "Other periods", /* Other periods - HTML */ "Next", /* Next folder - HTML */ "Messages archived in the next period, sorted by date", /* Next folder, by date - HTML link */ "Previous", /* Previous folder - HTML */ "Messages archived in the previous period, sorted by date", /* Previous folder, by date - HTML Link */ "List of all periods", /* List of all periods - HTML*/ "This period", /* This period - HTML*/ "Received on", /* Received on - HTML */ "Nearby", /* Nearby - HTML */ "re-sorted", /* Resorted - HTML */ "listed by date", /* listed by date - HTML */ "by discussion threads" , /* discussion threads - HTML */ "listed by author", /* listed by author - HTML */ "by subject", /* listed by subject - HTML */ "by attachment", /* by attachment - HTML */ "period", /* period - HTML */ " to ", /* to - HTML */ "from", /* from - HTML */ "on", /* on - HTML */ "message archived in another list or period", /* unknown in reply to - HTML */ " ", /* MSG_DELETED_OTHER -HTML */ "Note: this message has been edited and differs from the originally archived copy.", /* MSG_EDITED -HTML */ "deleted", /* MSG_SENDER_DELETED -HTML */ "deleted", /* MSG_SUBJECT_DELETED -HTML */ NULL, /* End Of Message Table - NOWHERE*/ }; /* ** list of supported languages */ struct language_entry ltable[] = { { "de", de, "de_DE" }, /* German */ { "en", en, "en_US" }, /* English */ { "es", es, "es_ES" }, /* Spanish */ { "fi", fi, "fi_FI" }, /* Finnish */ { "fr", fr, "fr_FR" }, /* French */ { "is", is, "is_IS" }, /* Icelandic */ { "pl", pl, "pl_PL" }, /* Polish */ { "pt", pt, "pt_BR" }, /* Brazilian Portuguese */ { "sv", sv, "sv_SE" }, /* Swedish */ { "no", no, "no_NO" }, /* Norwegian */ { "el", gr, "el" }, /* Greek */ { "gr", gr, "el_GR" }, /* Greek */ { "ru", ru, "ru_RU" }, /* Russian */ { "it", it, "it_IT" }, /* Italian */ { NULL, NULL, NULL }, /* EOL */ }; /* ** Default language table */ char **lang = en; #else extern char **lang; extern struct language_entry ltable[]; #endif ================================================ FILE: src/lock.c ================================================ #include "hypermail.h" #include "setup.h" #define LOCKBASE ".hypermail.lock" int i_locked_it = 0; void lock_archive(char *dir) { FILE *fp; char buffer[MAXLINE]; int count = 0; /* # minutes waited */ i_locked_it = 0; /* guilty until proven innocent */ snprintf(lockfile, sizeof(lockfile), "%s/%s", dir, LOCKBASE); while ((fp = fopen(lockfile, "r")) != NULL) { fgets(buffer, MAXLINE-1, fp); fclose(fp); /* * "set_locktime" is the config file item named 'locktime', * default is 3600 seconds */ if (time(NULL) > (time_t)(atol(buffer) + set_locktime)) break; /* lock over hour old - break it */ ++count; if (set_showprogress) fprintf(stderr, "Waiting for lock (file '%s')\n", lockfile); sleep(30); } if ((fp = fopen(lockfile, "w")) != NULL) { i_locked_it = 1; fprintf(fp, "%ld\n", (long)time(NULL)); fclose(fp); } else if (dir[0]) { snprintf(errmsg, sizeof(errmsg), "Couldn't create lock file \"%s\".", lockfile); progerr(errmsg); } } void unlock_archive(void) { if (lockfile && i_locked_it) remove(lockfile); lockfile[0] = '\0'; } ================================================ FILE: src/mail.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Jay Weber, weber@eit.com ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "../libcgi/cgi.h" #include "../config.h" void cgi_main(cgi_info *ci) { /* This program has been disabled because it * was probably easy for spammers to use as an open relay. It also * had problems with enabling malicious use of JavaScript and * CRLF Injection. */ printf("\n"); printf("\n"); printf("This page has been disabled due to potential abuse by spammers.\n"); printf("\n\n"); } ================================================ FILE: src/mem.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "hypermail.h" /* Just a tiny malloc() error checker! */ void *emalloc(int i) { void *p; if ((p = (void *)malloc(i)) == NULL) progerr(lang[MSG_RAN_OUT_OF_MEMORY]); return p; } #ifndef HAVE_MEMSET void *memset(void *s, int c, size_t n) { if (n != 0) { register char *d = s; do *d++ = c; while (--n != 0); } return (s); } #endif ================================================ FILE: src/parse.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include "hypermail.h" #include "setup.h" #include "struct.h" #include "uudecode.h" #include "base64.h" #include "search.h" #include "getname.h" #include "parse.h" #include "print.h" #ifdef GDBM #include "gdbm.h" #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_DIRENT_H #ifdef __LCC__ #include "../lcc/dirent.h" #include #else #include #endif #else #include #endif #ifdef HAVE_STRING_H #include #endif /* ** LCC doesn't have lstat() defined in sys/stat.h. We'll define it ** in lcc_extras.h, but really it just calls stat(). */ #ifdef __LCC__ #include #include "../lcc/lcc_extras.h" #endif extern char *mktemp(char *); typedef enum { ENCODE_NORMAL, ENCODE_QP, /* quoted printable */ ENCODE_MULTILINED, /* this is not a real type, but just a separator showing that the types below are encoded in a way that makes one line in the indata may become one or more lines in the outdata */ ENCODE_BASE64, /* base64 */ ENCODE_UUENCODE, /* well, it seems there exist some kind of semi-standard for uu-encoded attachments. */ ENCODE_UNKNOWN /* must be the last one */ } EncodeType; typedef enum { CONTENT_TEXT, /* normal mails are text based default */ CONTENT_BINARY, /* this kind we store separately and href to */ CONTENT_HTML, /* this is html formated text */ CONTENT_IGNORE, /* don't care about this content */ CONTENT_UNKNOWN /* must be the last one */ } ContentType; static int hasblack(char *p) { while(p && *p && isspace(*p++)); return (*p ? TRUE : FALSE); } int ignorecontent(char *type) { if (inlist(set_ignore_types, "$NONPLAIN") && !textcontent(type) && strncasecmp(type, "multipart/", 10)) return 1; if (inlist(set_ignore_types, "$BINARY") && !textcontent(type) && strcasecmp(type, "text/html") && strncasecmp(type, "multipart/", 10)) return 1; return (inlist(set_ignore_types, type)); } int inlinecontent(char *type) { return (inlist(set_inline_types, type)); } int preferedcontent(int *current_weight, char *type, int decode) { int weight = -1; int status; status = 0; if (set_save_alts == 1) return 1; /* We let plain text remain PREFERED at all times */ if (!strcasecmp("text/plain", type)) { if (*current_weight != 0) { /* to avoid having two text/plain alternatives */ *current_weight = 0; status = 1; } } /* find the weight of the type arg. If the weight is inferior to the current_weight, we make it the prefered content */ else { if (set_prefered_types) weight = inlist_pos(set_prefered_types, type); if (weight == -1) { /* not known to be good, use weaker evidence */ if (!strncasecmp("text/", type, 5)) weight = 1000; else weight = 2000 + decode; } if (weight != -1) { /* +1 so that weight 0 is reserved for text/plain */ weight++; if (*current_weight == -1) { *current_weight = weight; status = 1; } else if (*current_weight > weight) { *current_weight = weight; status = 1; } } } return status; } int textcontent(char *type) { /* We let text/plain remain text at all times. Appearantly, older mailers * can still use just "text" as content-type, and we better treat that as * text/plain to make all those users happy. */ if (!strcasecmp("text/plain", type) || !strcasecmp("text", type)) return 1; if (set_text_types) { return (inlist(set_text_types, type)); } return 0; } static int is_applemail_ua(char *ua_string) { /* returns TRUE if the ua_string is one of the declared applemail * clients */ int res = FALSE; if (ua_string && *ua_string != '\0') { char *buff; char *ptr; buff = strsav(ua_string); ptr = strcasestr(buff, " Mail ("); if (ptr) { *ptr = '\0'; res = inlist(set_applemail_ua_value, buff); } free(buff); } return res; } /* * Should return TRUE if the input is a Re: start. The end pointer should * then point on the first character after the Re: * * Identifies "Re:", "Fw:" as well as "Re[]:" strings. */ int isre(char *re, char **end) { char *endp = NULL; if (!strncasecmp("Re:", re, 3)) { endp = re + 3; } else if (!strncasecmp("Fw:", re, 3)) { endp = re + 3; } else if (!strncasecmp("Re[", re, 3)) { long level; re += 3; level = strtol(re, &re, 10); /* eat the number */ if (!strncmp("]:", re, 2)) { /* we have an end "]:" and therefore it qualifies as a Re */ endp = re + 2; } } if (endp) { if (end) *end = endp; return TRUE; } return FALSE; } /* * Find the first re-substring in the input and return the position * where it is. The 'end' parameter will be filled in the first position * *after* the re. */ char *findre(char *in, char **end) { while (*in) { if (isre(in, end)) return in; in++; } return NULL; } void print_progress(int num, char *msg, char *filename) { char bufstr[256]; register int i; static int lastlen = 0; static int longest = 0; int len = 0; int newline = 0; newline = 0; if (msg != NULL) { if (filename != NULL) { trio_snprintf(bufstr, sizeof(bufstr), "%4d %-s %-s", num, msg, filename); if (set_showprogress > 1) newline = 1; } else { trio_snprintf(bufstr, sizeof(bufstr), "%4d %-s.", num, msg); newline = 1; } } else sprintf(bufstr, "%4d", num); for (i = 0; i < lastlen; i++) /* Back up to the beginning of line */ fputc('\b', stdout); fputs(bufstr, stdout); /* put out the string */ len = strlen(bufstr); /* get length of new string */ /* * If there is a new message then erase * the trailing info from the enw string */ if (msg != NULL) { for (i = len; i <= longest; i++) fputc(' ', stdout); for (i = len; i <= longest; i++) fputc('\b', stdout); } lastlen = len; if (lastlen > longest) longest = lastlen; if (newline) fputc('\n', stdout); fflush(stdout); } char *safe_filename(char *name) { register char *sp; register char *np; np = name; while (*np && (*np == ' ' || *np == '\t')) np++; if (!*np) return (NULL); for (sp = name, np = name; *np && *np != '\n';) { /* if valid character then store it */ if (((*np >= 'a' && *np <= 'z') || (*np >= '0' && *np <= '9') || (*np >= 'A' && *np <= 'Z') || (*np == '-') || (*np == '.') || (*np == ':') || (*np == '_')) && !(set_unsafe_chars && strchr(set_unsafe_chars, *np))) { *sp = *np; } else /* Need to replace the character with a safe one */ *sp = REPLACEMENT_CHAR; sp++; np++; } *sp = '\0'; if (sp >= name + 6 && !strcmp(sp - 6, ".shtml")) strcpy(sp - 6, ".html"); return name; } static void create_attachname(char *attachname, int max_len) { int i, max_i; char suffix[8]; max_i = strlen(attachname); if(max_i >= max_len) max_i = max_len - 1; i = max_i; while(i >= 0 && i > max_i - sizeof(suffix) && attachname[i] != '.') --i; if(i >= 0 && attachname[i] == '.') strncpy(suffix, attachname + i, sizeof(suffix) - 1); else suffix[0] = 0; strncpy(attachname, set_filename_base, max_len); strncat(attachname, suffix, max_len - strlen(attachname) - 1); safe_filename(attachname); } /* ** Cross-indexes - adds to a list of replies. If a message is a reply to ** another, the number of the message it's replying to is added to the list. ** This list is searched upon printing. */ void crossindex(void) { int num, status, maybereply; struct emailinfo *email; num = 0; if(!set_linkquotes) replylist = NULL; while (num <= max_msgnum) { if (!hashnumlookup(num, &email)) { ++num; continue; } status = hashreplynumlookup(email->msgnum, email->inreplyto, email->subject, &maybereply); if (status != -1) { struct emailinfo *email2; if (!hashnumlookup(status, &email2)) { ++num; continue; } /* make sure there is no recursion between the message and reply lookup if a message and its reply-to were archived in reverse, both messages share the same subject (regardless of Re), and the message itself was a reply to a non-archived message. */ if (maybereply && !strcmp (email2->inreplyto, email->msgid)) { ++num; continue; } if (set_linkquotes) { struct reply *rp; int found_num = 0; for (rp = replylist; rp != NULL; rp = rp->next) if(rp->msgnum == status && rp->frommsgnum == num) { found_num = 1; break; } if (!found_num && !(maybereply || num <= status)) #ifdef FASTREPLYCODE replylist = addreply2(replylist, email2, email, maybereply, &replylist_end); #else replylist = addreply(replylist, status, email, maybereply, &replylist_end); #endif } else { #ifdef FASTREPLYCODE replylist = addreply2(replylist, email2, email, maybereply, &replylist_end); #else replylist = addreply(replylist, status, email, maybereply, &replylist_end); #endif } } num++; } #if DEBUG_THREAD { struct reply *r; r = replylist; fprintf(stderr, "START of replylist after crossindex\n"); fprintf(stderr, "- msgnum frommsgnum maybereply msgid\n"); while (r != NULL) { fprintf(stderr, "- %d %d %d '%s'\n", r->data->msgnum, r->frommsgnum, r->maybereply, r->data->msgid); r = r->next; } fprintf(stderr, "END of replylist after crossindex\n"); } #endif } /* ** Recursively checks for replies to replies to a message, etc. ** Replies are added to the thread list. */ #ifdef FASTREPLYCODE void crossindexthread2(int num) { struct reply *rp; struct emailinfo *ep; if(!hashnumlookup(num, &ep)) { char errmsg[512]; snprintf(errmsg, sizeof(errmsg), "internal error crossindexthread2 %d", num); progerr(errmsg); } for (rp = ep->replylist; rp != NULL; rp = rp->next) { if (!(rp->data->flags & USED_THREAD)) { rp->data->flags |= USED_THREAD; if (0) fprintf(stderr, "add thread.b %d %d %d\n", num, rp->data->msgnum, rp->msgnum); threadlist = addreply(threadlist, num, rp->data, 0, &threadlist_end); printedlist = markasprinted(printedthreadlist, rp->msgnum); crossindexthread2(rp->msgnum); } } } #else void crossindexthread2(int num) { struct reply *rp; for (rp = replylist; rp != NULL; rp = rp->next) { if (!(rp->data->flags & USED_THREAD) && (rp->frommsgnum == num)) { rp->data->flags |= USED_THREAD; threadlist = addreply(threadlist, num, rp->data, 0, &threadlist_end); printedlist = markasprinted(printedthreadlist, rp->msgnum); crossindexthread2(rp->msgnum); } } } #endif /* ** First, print out the threads in order by date... ** Each message number is appended to a thread list. Threads and individual ** messages are separated by a -1. */ void crossindexthread1(struct header *hp) { int isreply; #ifndef FASTREPLYCODE struct reply *rp; #endif if (hp) { crossindexthread1(hp->left); #ifdef FASTREPLYCODE isreply = hp->data->isreply; #else for (isreply = 0, rp = replylist; rp != NULL; rp = rp->next) { if (rp->msgnum == hp->data->msgnum) { isreply = 1; break; } } #endif /* If this message is not a reply to any other messages then it * is the first message in a thread. If it hasn't already * been dealt with, then add it to the thread list, followed by * any descendants and then the end of thread marker. */ if (!isreply && !wasprinted(printedthreadlist, hp->data->msgnum) && !(hp->data->flags & USED_THREAD)) { hp->data->flags |= USED_THREAD; threadlist = addreply(threadlist, hp->data->msgnum, hp->data, 0, &threadlist_end); crossindexthread2(hp->data->msgnum); threadlist = addreply(threadlist, -1, NULL, 0, &threadlist_end); } crossindexthread1(hp->right); } } /* ** Grabs the date string from a Date: header. (Y2K OK) */ char *getmaildate(char *line) { int i; int len; char *c; struct Push buff; INIT_PUSH(buff); c = strchr(line, ':'); if ((*(c + 1) && *(c + 1) == '\n') || (*(c + 2) && *(c + 2) == '\n')) { PushString(&buff, NODATE); RETURN_PUSH(buff); } c += 2; while (*c == ' ' || *c == '\t') c++; for (i = 0, len = DATESTRLEN - 1; *c && *c != '\n' && i < len; c++) PushByte(&buff, *c); RETURN_PUSH(buff); } /* ** Grabs the date string from a From article separator. (Y2K OK) */ char *getfromdate(char *line) { static char tmpdate[DATESTRLEN]; int i; int len; char *c = NULL; for (i = 0; days[i] != NULL && ((c = strstr(line, days[i])) == NULL); i++); if (days[i] == NULL) tmpdate[0] = '\0'; else { for (i = 0, len = DATESTRLEN - 1; *c && *c != '\n' && i < len; c++) tmpdate[i++] = *c; tmpdate[i] = '\0'; } return tmpdate; } /* ** Grabs the message ID, like <...> from the Message-ID: header. */ char *getid(char *line) { int i; char *c; struct Push buff; INIT_PUSH(buff); if (strrchr(line, '<') == NULL) { /* * bozo alert! * msg-id = "<" addr-spec ">" * try to recover as best we can */ c = strchr(line, ':') + 1; /* we know this exists! */ /* skip spaces before message ID */ while (*c && (*c == ' ' || *c == '\t')) c++; } else c = strrchr(line, '<') + 1; for (i = 0; *c && *c != '>' && *c != '\n'; c++) { if (*c == '\\') continue; PushByte(&buff, *c); i++; } if (i == 0) PushString(&buff, "BOZO"); RETURN_PUSH(buff); } /* ** Grabs the subject from the Subject: header. ** ** Need to add a table of Re: equivalents (different languages, MUA, etc...) ** ** Returns ALLOCATED string. */ char *getsubject(char *line) { int i; int len; char *c; char *startp; char *strip_subject = NULL; char *postre = NULL; struct Push buff; INIT_PUSH(buff); c = strchr(line, ':'); if (!c) return NULL; c += 2; if (set_stripsubject) { /* compute a new subject */ strip_subject = replace(c, set_stripsubject, ""); /* point to it */ c = strip_subject; } while (isspace(*c)) c++; startp = c; for (i = len = 0; c && *c && (*c != '\n'); c++) { i++; /* keep track of the max length without trailing white spaces: */ if (!isspace(*c)) len = i; } if (isre(startp, &postre)) { if (!*postre || (*postre == '\n')) len = 0; } if (!len) PushString(&buff, NOSUBJECT); else PushNString(&buff, startp, len); if (set_stripsubject && (strip_subject != NULL)) free(strip_subject); RETURN_PUSH(buff); } /* ** Grabs the annotation values given in the annotation user-defined header ** ** annotation_content is set to the value of the content annotation ** annotation_robot is set to the values of the robot annotations ** Returns TRUE if an annotation was found, FALSE otherwise. */ static bool getannotation(char *line, annotation_content_t *annotation_content, annotation_robot_t *annotation_robot) { char *c; *annotation_content = ANNOTATION_CONTENT_NONE;; *annotation_robot = ANNOTATION_ROBOT_NONE; c = strchr(line, ':'); if (!c) return FALSE; c++; while (*c != '\n') { int len; char *startp; while (isspace(*c)) c++; startp = c; while (!isspace (*c) && *c != '\n' && *c != ',') { c++; } len = (int) (c-startp); if (len > 0) { if (!strncasecmp (startp, "deleted", len)) { *annotation_content = ANNOTATION_CONTENT_DELETED_OTHER; break; } else if (!strncasecmp (startp, "spam", len)) { *annotation_content = ANNOTATION_CONTENT_DELETED_SPAM; break; } else if (!strncasecmp (startp, "edited", len)) *annotation_content = ANNOTATION_CONTENT_EDITED; else if (!strncasecmp (startp, "noindex", len)) *annotation_robot |= ANNOTATION_ROBOT_NO_INDEX; else if (!strncasecmp (startp, "nofollow", len)) *annotation_robot |= ANNOTATION_ROBOT_NO_FOLLOW; } if (*c == ',') c++; } /* only return true if at least a valid annotation was found */ return (*annotation_content != ANNOTATION_CONTENT_NONE || *annotation_robot != ANNOTATION_ROBOT_NONE); } /* ** Grabs the message ID, or date, from the In-reply-to: header. ** ** Maybe I'm confused but.... ** What either ? Should it not be consistent and choose to return ** one (the msgid) as the default and fall back to date when a ** msgid cannot be found ? ** ** Who knows what other formats are out there... ** ** In-Reply-To: <1DD9B854E27@everett.pitt.cc.nc.us> ** In-Reply-To: <199709181645.MAA02097@mail.clark.net> from "Marcus J. Ranum" at Sep 18, 97 12:41:40 pm ** In-Reply-To: <199709181645.MAA02097@mail.clark.net> from ** In-Reply-To: "L. Detweiler"'s message of Fri, 04 Feb 94 22:51:22 -0700 <199402050551.WAA16189@longs.lance.colostate.edu> ** ** The message id should always be returned for threading purposes. Mixing ** message-ids and dates just does not allow for proper threading lookups. ** ** Returns ALLOCATED string. */ char *getreply(char *line) { char *c; char *m; struct Push buff; INIT_PUSH(buff); /* Check for blank line */ /* * Check for line with " from " and " at ". Format of the line is * from "quoted user name" at date-string */ if (strstr(line, " from ") != NULL) { if ((strstr(line, " at ")) != NULL) { if ((m = strchr(line, '<')) != NULL) { for (m++; *m && *m != '>' && *m != '\n'; m++) { PushByte(&buff, *m); } RETURN_PUSH(buff); } } /* * If no 'at' the line may be a continued line or a truncated line. * Both will be picked up later. */ } /* * Check for line with " message of ". Format of the line is * "quoted user name"'s message of date-string */ if ((c = strstr(line, "message of ")) != NULL) { /* * Check to see if there is a message ID on the line. * If not this is a continued line and when you add a readline() * function that concatenates continuation lines collapsing * white space, you might want to revisit this... */ if ((m = strchr(line, '<')) != NULL) { for (m++; *m && *m != '>' && *m != '\n'; m++) { PushByte(&buff, *m); } RETURN_PUSH(buff); } /* Nope... Go for the Date info... Bug... */ c += 11; while (isspace(*c)) c++; if (*c == '"') c++; for (; *c && *c != '.' && *c != '\n'; c++) { PushByte(&buff, *c); } RETURN_PUSH(buff); } if ((c = strstr(line, "dated: ")) != NULL) { c += 7; for (; *c && *c != '.' && *c != '\n'; c++) { PushByte(&buff, *c); } RETURN_PUSH(buff); } if ((c = strstr(line, "dated ")) != NULL) { c += 6; for (; *c && *c != '.' && *c != '\n'; c++) { PushByte(&buff, *c); } RETURN_PUSH(buff); } if ((c = strchr(line, '<')) != NULL) { c++; for (; *c && *c != '>' && *c != '\n'; c++) { if (*c == '\\') continue; PushByte(&buff, *c); } RETURN_PUSH(buff); } if ((c = strstr(line, "sage of ")) != NULL) { c += 8; if (*c == '\"') c++; for (; *c && *c != '.' && *c != '\n' && *c != 'f'; c++) { PushByte(&buff, *c); } RETURN_PUSH(buff); } PushByte(&buff, '\0'); RETURN_PUSH(buff); } static char * extract_rfc2047_content(char *iptr) { char *end_ptr, *ptr; struct Push buff; INIT_PUSH(buff); /* skip the charset, find the encoding */ ptr = strchr (iptr + 2, '?'); ptr++; if ((*ptr == 'Q' || *ptr == 'q' || *ptr == 'B' || *ptr == 'b') && *(ptr + 1) == '?') { /* it's a valid encoding */ ptr = ptr + 2; end_ptr = strstr(ptr, "?="); if (end_ptr && ptr > iptr) { PushNString(&buff, ptr, end_ptr - ptr); RETURN_PUSH(buff); } } return NULL; } /* ** RFC 2047 defines MIME extensions for mail headers. ** ** This function decodes that into binary/8bit data. ** ** Example: ** =?iso-8859-1?q?I'm_called_?= =?iso-8859-1?q?Daniel?= ** ** Should result in "I'm called Daniel", but: ** ** =?iso-8859-1?q?I'm_called?= Daniel ** ** Should result in "I'm called Daniel" too. ** ** Returns the newly allcated string, or the previous if nothing changed */ static char *mdecodeRFC2047(char *string, int length, char *charsetsave) { char *iptr = string; char *oldptr; char *storage = (char *)emalloc(length*4 + 1); char *output = storage; char charset[129]; char encoding[33]; char dummy[129]; char *ptr, *endptr; char *old_output; #ifdef NOTUSED char equal; #endif int value; char didanything = FALSE; while (*iptr) { if (!strncmp(iptr, "=?", 2) && (3 == sscanf(iptr + 2, "%128[^?]?%32[^?]?%128[^ ]", charset, encoding, dummy))) { /* This is a full, valid 'encoded-word'. Decode! */ char *ptr; char *blurb = extract_rfc2047_content(iptr); if (!blurb) { *output++ = *iptr++; /* it wasn't a real encoded-word */ continue; } ptr = blurb; didanything = TRUE; /* yes, we decode something */ /* we could've done this with a %n in the sscanf, but we know all sscanfs don't grok that */ iptr += 2 + strlen(charset) + 1 + strlen(encoding) + 1 + strlen(blurb) + 2; if (!strcasecmp("q", encoding)) { /* quoted printable decoding */ endptr = ptr + strlen(ptr); #ifdef HAVE_ICONV char *orig2,*output2,*output3; size_t len, charsetlen; orig2=output2=malloc(strlen(string)+1); memset(output2,0,strlen(string)+1); old_output=output; for (; ptr < endptr; ptr++) { switch (*ptr) { case '=': sscanf(ptr + 1, "%02X", &value); *output2++ = value; ptr += 2; break; case '_': *output2++ = ' '; break; default: *output2++ = *ptr; break; } } output3=i18n_convstring(orig2,charset,"UTF-8",&len); free(orig2); memcpy(output,output3,len); output += len; free(output3); charsetlen = strlen(charset) < 255 ? strlen(charset) : 255; memcpy(charsetsave,charset,charsetlen); charsetsave[charsetlen] = '\0'; #else for (; ptr < endptr; ptr++) { switch (*ptr) { case '=': sscanf(ptr + 1, "%02X", &value); *output++ = value; ptr += 2; break; case '_': *output++ = ' '; break; default: *output++ = *ptr; break; } } #endif } else if (!strcasecmp("b", encoding)) { /* base64 decoding */ int len; size_t charsetlen; #ifdef HAVE_ICONV size_t tmplen; char *output2; base64Decode(ptr, output, &len); output2=i18n_convstring(output,charset,"UTF-8",&tmplen); memcpy(output,output2,tmplen); output += tmplen; free(output2); charsetlen = strlen(charset) < 255 ? strlen(charset) : 255; memcpy(charsetsave,charset,charsetlen); charsetsave[charsetlen] = '\0'; #else base64Decode(ptr, output, &len); output += len; #endif } else { /* unsupported encoding type */ strcpy(output, ""); output += 9; } free(blurb); blurb = ptr = NULL; oldptr = iptr; /* save start position */ while (*iptr && isspace(*iptr)) iptr++; /* pass all whitespaces */ /* if this is an encoded word here, we should skip the passed whitespaces. If it isn't an encoded-word, we should include the whitespaces in the output. */ if (!strncmp(iptr, "=?", 2) && (3 == sscanf(iptr + 2, "%128[^?]?%32[^?]?%128[^?]?", charset, encoding, dummy)) && (blurb = extract_rfc2047_content(iptr))) { free(blurb); continue; /* this IS an encoded-word, continue from here */ } else /* this IS NOT an encoded-word, move back to the first whitespace */ iptr = oldptr; } else *output++ = *iptr++; } *output = 0; if (didanything) { /* this check prevents unneccessary strsav() calls if not needed */ free(string); /* free old memory */ #if DEBUG_PARSE /* debug display */ printf("NEW: %s\n", storage); { char *f; puts("NEW:"); for (f = storage; f < output; f++) { if (isgraph(*f)) printf("%c", *f); else printf("%02X", (unsigned char)*f); } puts(""); } #endif return storage; /* return new */ } else { free(storage); #ifdef HAVE_ICONV /* make sure there are only ascii chars in the string ** for messages that don't respect rfc2047 */ i18n_replace_non_ascii_chars(string); #endif return string; } } /* ** RFC 3676 format=flowed parsing routines */ /* get_quote_level returns the number of quotes in a line, following the RFC 3676 section 4.5 criteria. */ static int get_quotelevel (const char *line) { int quoted = 0; char *p = (char *) line; while (p && *p == '>') { quoted++; p++; } return quoted; } /* ** rfc3676_handler parses lines according to RFC 3676. Its inputs are ** the current line to parse, the delsp value (from the message ** headers), the previous line quotelevel, and a flag saying if the ** previous line was marked as a continuing one. ** ** The function updates the quotelevel to that of the current parsed ** line. The function will update the continue_prev_flow_flag to say ** if the current line should be joined to the previous one, and, if ** positive, the padding offset that should be applied to the current ** line when merging it (for skipping quotes or space-stuffing). ** ** If delsp is true, the function will remove the space in the soft ** line break if the line is flowed. ** ** The function returns true if the current line is flowed. ** */ static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel, bool *continue_prev_flow_flag) { int new_quotelevel = 0; int tmp_padding = 0; bool sig_sep = FALSE; bool flowed = FALSE; /* rules for evaluation if the flow should stop: 1. new quote level is different from previous one 2. The line is a signature "[(quotes)][(ss)]-- \n" 3. The line is a hard break "\n" 4. The message body has ended rules for removing space-stuffing: 1. if f=f, then remove the first space of any line beginning with a space, before processing for f=f. 2. space char may depend on charset. rules for quotes: 1. quoted lines always begin with a '>' char. This symbol may depend on the msg charset. 2. They are not ss before the quote symbol but may be after it appears. rules for seeing if a line should be flowed with the next one: 1. line ends with a soft line break sp\n 2. remove the sp if delsp=true; keep it otherwise special case, space-stuffed or f=f? A line that has only this content: " \n": this is a space-stuffed newline. @@ test this special case with mutt */ #if DEBUG_PARSE printf("RFC3676: Previous quote level: %d\n", *quotelevel); printf("RFC3676: Previous line flow flag: %d\n", *continue_prev_flow_flag); #endif /* ** hard crlf detection. */ if (rfc3676_ishardlb(line)) { /* Hard crlf, reset flags */ *quotelevel = 0; *continue_prev_flow_flag = FALSE; #if DEBUG_PARSE printf("RFC3676: hard CRLF detected. Stopping ff\n"); #endif return FALSE; } /* ** quote level detection */ new_quotelevel = get_quotelevel (line); #if DEBUG_PARSE printf("RFC3676: New quote level: %d\n", new_quotelevel); #endif /* change of quote level, stop ff */ if (new_quotelevel != *quotelevel || (new_quotelevel > 0 && set_format_flowed_disable_quoted)) { *continue_prev_flow_flag = FALSE; #if DEBUG_PARSE printf("RFC3676: different quote levels detected. Stopping ff\n"); #endif } tmp_padding = new_quotelevel; /* ** skip space stuffing if any */ if (line[tmp_padding] == ' ') { tmp_padding++; #if DEBUG_PARSE printf("RFC3676: space-stuffing detected; skipping space\n"); #endif } /* ** hard crlf detection after quotes */ if (rfc3676_ishardlb(line+tmp_padding)) { /* Hard crlf, reset flags */ /* *continue_prev_flow_flag = FALSE; */ *quotelevel = new_quotelevel; #if DEBUG_PARSE printf("RFC3676: hard CRLF detected after quote. Stopping ff\n"); #endif return FALSE; } /* ** signature detection */ /* Is it a signature separator? */ /* rfc3676 gives "-- \n" and "--\r\n" as signatures. We also add "--\n" to this list, as mutt allows it */ if (!strcmp (line + tmp_padding, "-- \n") || !strcmp (line + tmp_padding, "-- \r\n") || !strcmp (line + tmp_padding, "--\n")) { /* yes, stop f=f */ *continue_prev_flow_flag = FALSE; sig_sep = TRUE; #if DEBUG_PARSE printf ("RFC3676: -- signature detected. Stopping ff\n", sig_sep); #endif if (delsp_flag) { rfc3676_trim_softlb (line); } } /* ** is this line f=f? */ if (!sig_sep) { char *eold; eold = strrchr (line, '\n'); if (line != eold) { if (*(eold - 1) == '\r') eold--; } if (line != eold && (line + tmp_padding) != eold) { if (*(eold - 1) == ' ') { if (!sig_sep) { flowed = TRUE; #if DEBUG_PARSE printf("RFC3676: f=f line detected\n"); #endif } if (delsp_flag) { /* remove the space stuffing and copy the end of line */ rfc3676_trim_softlb(line); } } } } /* ** update flags */ *quotelevel = new_quotelevel; #if DEBUG_PARSE if (*continue_prev_flow_flag) printf("RFC3676: Continuing previous flow\n"); if (flowed) { printf("RFC3676: Current line is flowed\n"); } #endif return flowed; } /* ** Decode this [virtual] Quoted-Printable line as defined by RFC2045. ** Written by Daniel.Stenberg@haxx.nu */ static char * mdecodeQP(FILE *file, char *input, char **result, int *length, FILE *fpo) { int outcount = 0; char i_buffer[MAXLINE]; char *buffer; unsigned char inchar; char *output; struct Push pbuf; int len = strlen(input); output = strsav(input); INIT_PUSH(pbuf); while ((inchar = *input) != '\0') { if (outcount >= len - 1) { /* we need to enlarge the destination area! */ /* double the size each time enlargement is needed */ char *newp = (char *)realloc(output, len * 2); if (newp) { output = newp; len *= 2; } else break; } input++; if ('=' == inchar) { int value; if ('\n' == *input) { if (!fgets(i_buffer, MAXLINE, file)) break; buffer = i_buffer + set_ietf_mbox; if (set_append) { if(fputs(buffer, fpo) < 0) { progerr("Can't write to \"mbox\""); /* revisit me */ } } input = buffer; PushString(&pbuf, buffer); continue; } else if ('=' == *input) { inchar = '='; input++; /* pass this */ } else if (isxdigit(*input)) { sscanf(input, "%02X", &value); inchar = (unsigned char)value; input += 2; /* pass the two letters */ } else inchar = '='; } output[outcount++] = inchar; } output[outcount] = 0; /* zero terminate */ *result = output; *length = outcount; RETURN_PUSH(pbuf); } char *createlink(char *format, char *dir, char *file, int num, char *type) { struct Push buff; char buffer[16]; INIT_PUSH(buff); if (!format || !*format) /* nothing set, use internal default: */ format = "%p"; while (*format) { if ('%' == *format) { format++; switch (*format) { default: PushByte(&buff, '%'); PushByte(&buff, *format); break; case '%': PushByte(&buff, '%'); break; case 'p': /* the full path+file */ PushString(&buff, dir); PushByte(&buff, '/'); /* this is for a HTML link and always uses this path separator */ if (file) PushString(&buff, file); else PushString(&buff, ""); break; case 'f': /* file name */ PushString(&buff, file); break; case 'd': /* dir name */ PushString(&buff, dir); break; case 'n': /* message number */ sprintf(buffer, "%04d", num); PushString(&buff, buffer); break; case 'c': /* content-type (TODO: URL-encode this) */ PushString(&buff, type); break; } } else { PushByte(&buff, *format); } format++; } RETURN_PUSH(buff); } void emptydir(char *directory) { struct stat fileinfo; char *realdir = directory; if (!lstat(realdir, &fileinfo)) { if (S_ISDIR(fileinfo.st_mode)) { /* It exists AND it is a dir */ DIR *dir = opendir(realdir); char *filename; if (dir) { #ifdef HAVE_DIRENT_H struct dirent *entry; #else struct direct *entry; #endif while ((entry = readdir(dir))) { if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) continue; trio_asprintf(&filename, "%s%c%s", realdir, PATH_SEPARATOR, entry->d_name); if (set_showprogress) fprintf(stderr, "\nWe delete %s\n", filename); unlink(filename); free(filename); } closedir(dir); } } } } static int do_uudecode(FILE *fp, char *line, char *line_buf, struct Push *raw_text_buf, FILE *fpo) { struct Push pbuf; char *p2; INIT_PUSH(pbuf); if (uudecode(fp, line, line, NULL, &pbuf)) /* * oh gee, we failed this is chaos */ return 0; p2 = PUSH_STRING(pbuf); if (p2) { if (set_append) { if(fputs(p2, fpo) < 0) { progerr("Can't write to \"mbox\""); } } if (set_txtsuffix) { PushString(raw_text_buf, line_buf); line_buf[0] = 0; /*avoid dup at next for iter*/ PushString(raw_text_buf, p2); } free(p2); } return 1; } static void write_txt_file(struct emailinfo *emp, struct Push *raw_text_buf) { char *txt_filename; char *p = PUSH_STRING(*raw_text_buf); char tmp_buf[32]; sprintf(tmp_buf, "%.4d", emp->msgnum); txt_filename = htmlfilename(tmp_buf, emp, set_txtsuffix); if ((!emp->is_deleted || ((emp->is_deleted & (FILTERED_DELETE | FILTERED_OLD | FILTERED_NEW | FILTERED_DELETE_OTHER)) && set_delete_level > 2) || (emp->is_deleted == FILTERED_EXPIRE && set_delete_level == 2)) && (set_overwrite || !isfile(txt_filename))) { FILE *fp = fopen(txt_filename, "w"); if (fp) { fwrite(p, strlen(p), 1, fp); fclose(fp); } } free(p); INIT_PUSH(*raw_text_buf); } /* ** Parsing...the heart of Hypermail! ** This loads in the articles from stdin or a mailbox, adding the right ** field variables to the right structures. If readone is set, it will ** think anything it reads in is one article only. Increment should be set ** if this updates an archive. */ int parsemail(char *mbox, /* file name */ int use_stdin, /* read from stdin */ int readone, /* only one mail */ int increment, /* update an existing archive */ char *dir, int inlinehtml, /* if HTML should be inlined */ int startnum) { FILE *fp; struct Push raw_text_buf; FILE *fpo = NULL; char *date = NULL; char *subject = NULL; char *msgid = NULL; char *inreply = NULL; char *namep = NULL; char *emailp = NULL; char *line = NULL; char line_buf[MAXLINE], fromdate[DATESTRLEN] = ""; char *cp; char *dp = NULL; int num, isinheader, hassubject, hasdate; int num_added = 0; long exp_time = -1; time_t delete_older_than = (set_delete_older ? convtoyearsecs(set_delete_older) : 0); time_t delete_newer_than = (set_delete_newer ? convtoyearsecs(set_delete_newer) : 0); annotation_robot_t annotation_robot = ANNOTATION_ROBOT_NONE; annotation_content_t annotation_content = ANNOTATION_CONTENT_NONE; int is_deleted = 0; int pos; bool *require_filter, *require_filter_full; int require_filter_len, require_filter_full_len; struct hmlist *tlist; char filename[MAXFILELEN]; char directory[MAXFILELEN]; char pathname[MAXFILELEN]; struct emailinfo *emp; char *att_dir = NULL; /* directory name to store attachments in */ char *meta_dir = NULL; /* directory name where we're storing the meta data that describes the attachments */ typedef enum { NO_FILE, MAKE_FILE, MADE_FILE } FileStatus; /* for attachments */ /* -- variables for the multipart/alternative parser -- */ struct body *origbp = NULL; /* store the original bp */ struct body *origlp = NULL; /* ... and the original lp */ char alternativeparser = FALSE; /* set when inside alternative parser mode */ int alternative_weight = -1; /* the current weight of the prefered alternative content */ char *prefered_content_charset = NULL; /* the current charset of the alternative */ struct body *alternative_lp = NULL; /* the previous alternative lp */ struct body *alternative_bp = NULL; /* the previous alternative bp */ struct body *append_bp = NULL; /* text to append to body after parse done*/ struct body *append_lp = NULL; FileStatus alternative_lastfile_created = NO_FILE; /* previous alternative attachments, for non-inline MIME types */ char alternative_file[129]; /* file name where we store the non-inline alternatives */ char alternative_lastfile[129]; /* last file name where we store the non-inline alternatives */ char last_alternative_type[129]; /* the alternative Content-Type value */ int att_counter = 0; /* used to generate a unique name for attachments */ int parse_multipart_alternative_force_save_alts = 0; /* used to control if we are parsing alternative as multipart */ int old_set_save_alts = -1; /* used to store the set_save_alts when overriding it for apple mail */ int applemail_ua_header_len = (set_applemail_mimehack) ? strlen (set_applemail_ua_header) : 0; /* code optimization to avoid computing it each time */ /* ** keeps track of attachment file name used so far for this message */ struct hmlist *att_name_list = NULL; struct hmlist *att_name_last = NULL; /* -- end of alternative parser variables -- */ struct body *bp; struct body *lp = NULL; /* the last pointer, points to the last node in the body list. Initially set to NULL since we have none at the moment. */ struct body *headp = NULL; /* stored pointer to the point where we last scanned the headers of this mail. */ struct body *content_type_p = NULL; /* pointer to the Content-Type header */ char Mime_B = FALSE; char boundbuffer[256] = ""; struct boundary *boundp = NULL; /* This variable is used to store a stack of boundary separators in cases with mimed mails inside mimed mails */ struct boundary *multipartp = NULL; /* This variable is used to store a stack of mimetypes when dealing with multipart mails */ struct charset_stack *charsetsp = NULL; /* This variable is used to store a stack of charset/charset_save values when dealing with multipart mails */ bool skip_mime_epilogue = FALSE; /* This variable is used to help skip multipart/foo epilogues */ char multilinenoend = FALSE; /* This variable is set TRUE if we have read a partial line off a multiline-encoded line, and the next line we read is supposed to get appended to the previous one */ int bodyflags = 0; /* This variable is set to extra flags that the addbody() calls should OR in the flag parameter */ /* RFC 3676 related variables, set while parsing the headers and body content */ textplain_format_t textplain_format = FORMAT_FIXED; bool flowed_line = FALSE; int quotelevel = 0; bool continue_previous_flow_flag = FALSE; bool delsp_flag = FALSE; int binfile = -1; char *charset = NULL; /* this is the LOCAL charset used in the mail */ char *charsetsave; /* charset in MIME encoded text */ char *boundary_id = NULL; char type[129]; /* for Content-Type type */ char charbuffer[129]; /* for Content-Type charset */ FileStatus file_created = NO_FILE; /* for attachments */ char attachname[129]; /* for attachment file names */ char inline_force = FALSE; /* show a attachment in-line, regardles of the content_disposition */ char *description = NULL; /* user-supplied description for an attachment */ /* @@@ test for attachment */ char attach_force; /* @@@ */ EncodeType decode = ENCODE_NORMAL; ContentType content = CONTENT_TEXT; charsetsave=malloc(256); memset(charsetsave,0,255); if (use_stdin || !mbox || !strcasecmp(mbox, "NONE")) fp = stdin; else if ((fp = fopen(mbox, "rb")) == NULL) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_CANNOT_OPEN_MAIL_ARCHIVE], mbox); progerr(errmsg); } if(set_append) { /* add to an mbox as we read */ *directory = 0; *filename = 0; *pathname = 0; if (set_append_filename) { time_t curtime; const struct tm *local_curtime; time(&curtime); local_curtime = localtime(&curtime); if(strncmp(set_append_filename, "$DIR/", 5) == 0) { strncpy(directory, dir, MAXFILELEN - 1); strftime(filename, MAXFILELEN - 1, set_append_filename+5, local_curtime); } else { strftime(filename, MAXFILELEN - 1, set_append_filename, local_curtime); } } else { strncpy(directory, dir, MAXFILELEN - 1); strncpy(filename, "mbox", MAXFILELEN - 1); } if(trio_snprintf(pathname, sizeof(pathname), "%s%s", directory, filename) == sizeof(pathname)) { progerr("Can't build mbox filename"); } if(!(fpo = fopen(pathname, "a"))) { trio_snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_CANNOT_OPEN_MAIL_ARCHIVE], pathname); progerr(errmsg); } } num = startnum; INIT_PUSH(raw_text_buf); hassubject = 0; hasdate = 0; isinheader = 1; inreply = NULL; msgid = NULL; bp = NULL; subject = NOSUBJECT; parse_multipart_alternative_force_save_alts = 0; old_set_save_alts = -1; require_filter_len = require_filter_full_len = 0; for (tlist = set_filter_require; tlist != NULL; require_filter_len++, tlist = tlist->next) ; for (tlist = set_filter_require_full_body; tlist != NULL; require_filter_full_len++, tlist = tlist->next) ; pos = require_filter_len + require_filter_full_len; require_filter = (pos ? (bool *)emalloc(pos * sizeof(*require_filter)) : NULL); require_filter_full = require_filter + require_filter_len; for (pos = 0; pos < require_filter_len; ++pos) require_filter[pos] = FALSE; for (pos = 0; pos < require_filter_full_len; ++pos) require_filter_full[pos] = FALSE; if (!increment) { replylist = NULL; subjectlist = NULL; authorlist = NULL; datelist = NULL; } /* now what has this to do if readone is set or not? (Daniel) */ if (set_showprogress) { if (readone) printf("%s\n", lang[MSG_READING_NEW_HEADER]); else { if ((mbox && !strcasecmp(mbox, "NONE")) || use_stdin) printf("%s...\n", lang[MSG_LOADING_MAILBOX]); else printf("%s \"%s\"...\n", lang[MSG_LOADING_MAILBOX], mbox); } } for ( ; fgets(line_buf, MAXLINE, fp) != NULL; set_txtsuffix ? PushString(&raw_text_buf, line_buf) : 0) { #if DEBUG_PARSE fprintf(stderr,"\n^IN: %s", line_buf); fprintf(stderr, "^ BP %.0s: %.40s|\n^ LP %.0s: %.40s|\n^ ABP %.0s: %.40s|\n^ ALP %.0s: %.40s|\n^ OBP %.0s: %.40s|\n^ " "OLP %.0s: %.40s|\n^HEAD %.0s: %.40s|\n", "bp", (bp) ? bp->line : "", "lp", (lp) ? lp->line : "", "alternative_bp", (alternative_bp) ? alternative_bp->line : "", "alternative_lp", (alternative_lp) ? alternative_lp->line : "", "origbp", (origbp) ? origbp->line : "", "origlp", (origlp) ? origlp->line : "", "headp", (headp) ? headp->line : ""); #endif if(set_append) { if(fputs(line_buf, fpo) < 0) { progerr("Can't write to \"mbox\""); /* revisit me */ } } line = line_buf + set_ietf_mbox; if (skip_mime_epilogue) { if (line[0] == '\n') { continue; } else { skip_mime_epilogue = FALSE; } } if (!is_deleted && inlist_regex_pos(set_filter_out_full_body, line) != -1) { is_deleted = FILTERED_OUT; } pos = inlist_regex_pos(set_filter_require_full_body, line); if (pos != -1 && pos < require_filter_full_len) { require_filter_full[pos] = TRUE; } if (isinheader) { if (!strncasecmp(line_buf, "From ", 5)) strcpymax(fromdate, dp = getfromdate(line), DATESTRLEN); /* check for MIME */ else if (!strncasecmp(line, "MIME-Version:", 13)) Mime_B = TRUE; else if (isspace(line[0]) && ('\n' != line[0]) \ && !('\r' == line[0] && '\n' == line[1])) { /* * since this begins with a whitespace, it means the * previous line is continued on this line, leave only * one space character and go! */ char *ptr = line; while (isspace(*ptr)) ptr++; ptr--; /* leave one space */ *ptr = ' '; /* make it a true space, no tabs here! */ bp = addbody(bp, &lp, ptr, BODY_CONTINUE | BODY_HEADER | bodyflags); } else if (line[0] == '\n' || (line[0] == '\r' && line[1] == '\n')) { struct body *head; char savealternative; /* * we mark this as a header-line, and we use it to * track end-of-header displays */ /* skip the alternate "\n", otherwise, we'll have an extra "\n" in the HTMLized message */ if (!alternativeparser) bp = addbody(bp, &lp, line, BODY_HEADER | bodyflags); isinheader--; /* * This signals us that we are no longer in the header, * let's fill in all those fields we are interested in. * Parse the headers up to now and copy to the target * variables */ for (head = bp; head; head = head->next) { char head_name[128]; if (head->header && !head->demimed) { head->line = mdecodeRFC2047(head->line, strlen(head->line),charsetsave); head->demimed = TRUE; } if (head->parsedheader || head->attached || !head->header) { continue; } if (!sscanf(head->line, "%127[^:]", head_name)) continue; if (inlist(set_deleted, head_name)) { char *val = getsubject(head->line); /* revisit me */ if (!strcasecmp(val, "yes")) is_deleted = FILTERED_DELETE; free(val); } if (inlist(set_expires, head_name)) { char *val = getmaildate(head->line); exp_time = convtoyearsecs(val); if (exp_time != -1 && exp_time < time(NULL)) is_deleted = FILTERED_EXPIRE; free(val); } if (inlist(set_annotated, head_name)) { getannotation(head->line, &annotation_content, &annotation_robot); if (annotation_content == ANNOTATION_CONTENT_DELETED_OTHER) is_deleted = FILTERED_DELETE_OTHER; else if (annotation_content == ANNOTATION_CONTENT_DELETED_SPAM) is_deleted = FILTERED_DELETE; head->parsedheader = TRUE; } if (!is_deleted && inlist_regex_pos(set_filter_out, head->line) != -1) { is_deleted = FILTERED_OUT; } pos = inlist_regex_pos(set_filter_require, head->line); if (pos != -1 && pos < require_filter_len) { require_filter[pos] = TRUE; } if (!strncasecmp(head->line, "Date:", 5)) { date = getmaildate(head->line); head->parsedheader = TRUE; hasdate = 1; } else if (!strncasecmp(head->line, "From:", 5)) { getname(head->line, &namep, &emailp); head->parsedheader = TRUE; if (set_spamprotect) { emailp = spamify(strsav(emailp)); /* we need to "fix" the name as well, as sometimes the email ends up in the name part */ namep = spamify(strsav(namep)); } } else if (!strncasecmp(head->line, "Message-Id:", 11)) { msgid = getid(head->line); head->parsedheader = TRUE; } else if (!strncasecmp(head->line, "Subject:", 8)) { subject = getsubject(head->line); hassubject = 1; head->parsedheader = TRUE; } else if (!strncasecmp(head->line, "In-Reply-To:", 12)) { inreply = getreply(head->line); head->parsedheader = TRUE; } else if (!strncasecmp(head->line, "References:", 11)) { /* * Adding threading capability for the "References" * header, ala RFC 822, used only for messages that * have "References" but do not have an "In-reply-to" * field. This is partically a concession for Netscape's * email composer, which erroneously uses "References" * when it should use "In-reply-to". */ if (!inreply) inreply = getid(head->line); if (set_linkquotes) { bp = addbody(bp, &lp, line, 0); } head->parsedheader = TRUE; } else if (!strncasecmp(head->line, "Content-Type:", 13)) { content_type_p = head; } else if (applemail_ua_header_len > 0 && !strncasecmp(head_name, set_applemail_ua_header, applemail_ua_header_len)) { /* we only need to set this one up once per message*/ head->parsedheader = TRUE; if (alternativeparser || !Mime_B || set_save_alts || !set_applemail_mimehack) { continue; } /* If the UA is an apple mail client and we're configured to do the * applemail hack and we're not already configured to * save the alternatives, memorize the old setting and force * the alternatives save */ if (!parse_multipart_alternative_force_save_alts && is_applemail_ua(head->line + applemail_ua_header_len + 2)) { parse_multipart_alternative_force_save_alts = 1; /* to avoid confusion and quoting out of ** context, we won't show the alternatives ** in-line. */ old_set_save_alts = set_save_alts; set_save_alts = 2; #if DEBUG_PARSE printf("Applemail_hack force save_alts: yes\n"); printf("Applemail_hack set_save_alts changed from %d to %d\n", old_set_save_alts, set_save_alts); #endif } } } if (!is_deleted && set_delete_older && (date || fromdate)) { time_t email_time = convtoyearsecs(date); if (email_time == -1) email_time = convtoyearsecs(fromdate); if (email_time != -1 && email_time < delete_older_than) is_deleted = FILTERED_OLD; } if (!is_deleted && set_delete_newer && (date || fromdate)) { time_t email_time = convtoyearsecs(date); if (email_time == -1) email_time = convtoyearsecs(fromdate); if (email_time != -1 && email_time > delete_newer_than) is_deleted = FILTERED_NEW; } if (!headp) headp = bp; savealternative = FALSE; attach_force = FALSE; description = NULL; for (head = headp; head; head = head->next) { if (head->parsedheader || !head->header) continue; /* Content-Description is defined ... where?? */ if (!strncasecmp(head->line, "Content-Description:", 20)) { char *ptr = head->line; description = ptr + 21; } /* Content-Disposition is defined in RFC 2183 */ else if (!strncasecmp (head->line, "Content-Disposition:", 20)) { char *ptr = head->line + 20; char *fname; char *jp; char *np; while (*ptr && isspace(*ptr)) ptr++; if (!strncasecmp(ptr, "attachment;", 11) && (content != CONTENT_IGNORE)) { /* signal we want to attach, rather than embeed this MIME attachment */ if (inlist(set_ignore_types, "$NONPLAIN") || inlist(set_ignore_types, "$BINARY")) content = CONTENT_IGNORE; else { attach_force = TRUE; /* make sure it is binary */ content = CONTENT_BINARY; /* see if there's a file name to use: */ fname = strcasestr(ptr, "filename="); if (fname) { np = fname+9; if (*np == '"') np++; for (jp = attachname; np && *np != '\n' && *np != '"' && jp < attachname + sizeof(attachname) - 1;) { *jp++ = *np++; } *jp = '\0'; safe_filename(attachname); } else { attachname[0] = '\0'; /* just clear it */ } file_created = MAKE_FILE; /* please make one */ } } #if 0 /* ** Why was this limited to just type image ? There are more inline types than just image. ** I removed the image restriction and all of a sudden more attachments had the proper name. */ else if (!strncasecmp(ptr, "inline;", 7) && (content != CONTENT_IGNORE) && (!strncasecmp(type, "image/", 5))) { /* @@@ <-- here I should use the inline thingy */ #endif else if (!strncasecmp(ptr, "inline;", 7) && (content != CONTENT_IGNORE) && inlinecontent(type)) { inline_force = TRUE; /* make sure it is binary */ content = CONTENT_BINARY; /* see if there's a file name to use: */ fname = strcasestr(ptr, "filename="); if (fname) { np = fname+9; if (*np == '"') np++; for (jp = attachname; np && *np != '\n' && *np != '"' && jp < attachname + sizeof(attachname) - 1;) { *jp++ = *np++; } *jp = '\0'; safe_filename(attachname); } else { attachname[0] = '\0'; /* just clear it */ } file_created = MAKE_FILE; /* please make one */ } /* inline */ } /* Content-Disposition: */ else if (!strncasecmp(head->line, "Content-Base:", 13)) { #ifdef NOTUSED char *ptr = head->line + 13; #endif content=CONTENT_IGNORE; /* we must make sure this is not parsed more times than this */ head->parsedheader = TRUE; } else if (!strncasecmp(head->line, "Content-Type:", 13)) { char *ptr = head->line + 13; #define DISP_HREF 1 #define DISP_IMG 2 #define DISP_IGNORE 3 /* we must make sure this is not parsed more times than this */ head->parsedheader = TRUE; while (isspace(*ptr)) ptr++; sscanf(ptr, "%128[^;]", type); cp = type + strlen(type) - 1; while (cp > type && isspace(*cp)) { *cp = '\0'; /* rm newlines, etc */ --cp; } /* now, check if there's a charset indicator here too! */ cp = strcasestr(ptr, "charset="); if (cp) { cp += 8; /* pass charset= */ if ('\"' == *cp) cp++; /* pass a quote too if one is there */ sscanf(cp, "%128[^;\"\n]", charbuffer); /* save the charset info */ charset = strsav(charbuffer); } /* now check if there's a format indicator */ if (set_format_flowed) { cp = strcasestr(ptr, "format="); if (cp) { cp += 7; /* pass charset= */ if ('\"' == *cp) cp++; /* pass a quote too if one is there */ sscanf(cp, "%128[^;\"\n]", charbuffer); /* save the format info */ if (!strcasecmp (charbuffer, "flowed")) textplain_format = FORMAT_FLOWED; } /* now check if there's a delsp indicator */ cp = strcasestr(ptr, "delsp="); if (cp) { cp += 6; /* pass charset= */ if ('\"' == *cp) cp++; /* pass a quote too if one is there */ sscanf(cp, "%128[^;\"\n]", charbuffer); /* save the delsp info */ if (!strcasecmp (charbuffer, "yes")) delsp_flag = TRUE; } } if (alternativeparser) { struct body *next; struct body *temp_bp = NULL; /* We are parsing alternatives... */ if (parse_multipart_alternative_force_save_alts && multipartp && !strcasecmp(multipartp->line, "multipart/alternative") && *last_alternative_type && !strcasecmp(last_alternative_type, "text/plain")) { /* if the UA is Apple mail and if the only ** alternatives are text/plain and ** text/html and if the preference is ** text/plain, skip the text/html version ** if the applemail_hack is enabled */ if (!strcasecmp(type, "text/html")) { #if DEBUG_PARSE fprintf(stderr, "Discarding apparently equivalent text//html alternative\n"); #endif content = CONTENT_IGNORE; break; } } if (preferedcontent(&alternative_weight, type, decode)) { /* ... this is a prefered type, we want to store this [instead of the earlier one]. */ /* erase the previous alternative info */ temp_bp = alternative_bp; /* remember the value of bp for GC */ alternative_bp = alternative_lp = NULL; if (prefered_content_charset) { free(prefered_content_charset); } prefered_content_charset = strsav (charset); strncpy(last_alternative_type, type, sizeof(last_alternative_type) - 1); #ifdef DEBUG_PARSE fprintf(stderr, "setting new prefered alternative charset to %s\n", charset); #endif alternative_lastfile_created = NO_FILE; content = CONTENT_UNKNOWN; if (alternative_lastfile[0] != '\0') { /* remove the previous attachment */ unlink(alternative_lastfile); alternative_lastfile[0] = '\0'; } } else if (set_save_alts == 2) { content = CONTENT_BINARY; } else { /* ...and this type is not a prefered one. Thus, we * shall ignore it completely! */ content = CONTENT_IGNORE; /* erase the current alternative info */ temp_bp = bp; /* remember the value of bp for GC */ lp = alternative_lp; bp = alternative_bp; strcpy(alternative_file, alternative_lastfile); file_created = alternative_lastfile_created; alternative_bp = alternative_lp = NULL; alternative_lastfile_created = NO_FILE; alternative_lastfile[0] = '\0'; /* we haven't yet created any attachment file, so there's no need to erase it yet */ } /* free any previous alternative */ while (temp_bp) { next = temp_bp->next; if (temp_bp->line) free(temp_bp->line); free(temp_bp); temp_bp = next; } /* @@ not sure if I should add a diff flag to do this break */ if (content == CONTENT_IGNORE) /* end the header parsing... we already know what we want */ break; } if (content == CONTENT_IGNORE) continue; else if (ignorecontent(type)) /* don't save this */ content = CONTENT_IGNORE; else if (textcontent(type) || (inlinehtml && !strcasecmp(type, "text/html"))) { /* text content or text/html follows. */ if (set_save_alts && alternativeparser && content == CONTENT_BINARY) { file_created = MAKE_FILE; /* please make one */ description = set_alts_text ? set_alts_text : "alternate version of message"; if (strlen(description) >= sizeof(attachname)) progerr("alts_text too long"); strcpy(attachname, description); safe_filename(attachname); } else if (!strcasecmp(type, "text/html")) content = CONTENT_HTML; else content = CONTENT_TEXT; if (!alternativeparser && !prefered_content_charset) { /* there are apparently no alternatives in this message, let's use the first text/* charset we found as the prefered one */ prefered_content_charset = strsav (charset); } continue; } else if (!strncasecmp(type, "message/rfc822", 14)) { /* * Here comes an attached mail! This can be ugly, * since the attached mail may very well itself * contain attached binaries, or why not another * attached mail? :-) * * We need to store the current boundary separator * in order to get it back when we're done parsing * this particular mail, since each attached mail * will have its own boundary separator that *might* * be used. */ bp = addbody(bp, &lp, "

    attached mail follows:


    ", BODY_HTMLIZED | bodyflags); bodyflags |= BODY_ATTACHED; /* @@ should it be 1 or 2 ?? should we use another method? */ #if 0 isinheader = 2; #endif isinheader = 1; continue; } else if (strncasecmp(type, "multipart/", 10)) { /* * This is not a multipart and not text */ char *fname = NULL; /* attachment filename */ /* * only do anything here if we're not * ignoring this content */ if (CONTENT_IGNORE != content) { fname = strcasestr(ptr, "name="); if (fname) { fname += 5; if ('\"' == *fname) fname++; sscanf(fname, "%128[^\"]", attachname); safe_filename(attachname); } else { attachname[0] = '\0'; /* just clear it */ } file_created = MAKE_FILE; /* please make one */ content = CONTENT_BINARY; /* uknown turns into binary */ } continue; } else { /* * Find the first boundary separator */ struct body *tmpbp; struct body *tmplp; boundary_id = strcasestr(ptr, "boundary="); #if DEBUG_PARSE printf("boundary found in %s\n", ptr); #endif if (boundary_id) { boundary_id = strchr(boundary_id, '='); if (boundary_id) { boundary_id++; while (isspace(*boundary_id)) boundary_id++; if ('\"' == *boundary_id) { sscanf(++boundary_id, "%255[^\"]", boundbuffer); } else sscanf(boundary_id, "%255[^;\n]", boundbuffer); boundary_id = boundbuffer; } /* restart on a new list: */ tmpbp = tmplp = NULL; while (fgets(line_buf, MAXLINE, fp)) { if(set_append) { if(fputs(line_buf, fpo) < 0) { progerr("Can't write to \"mbox\""); /* revisit me */ } } if (!strncmp(line_buf + set_ietf_mbox, "--", 2) && !strncmp(line_buf + set_ietf_mbox + 2, boundbuffer, strlen(boundbuffer))) { break; } if (!strncasecmp(line_buf, "From ", 5)) { #if DEBUG_PARSE printf("Error, new message found instead of boundary!\n"); #endif isinheader = 0; if (tmpbp) bp = append_body(bp, &lp, tmpbp); boundary_id = NULL; goto leave_header; } /* save lines in case no boundary found */ tmpbp = addbody(tmpbp, &tmplp, line_buf, bodyflags); } if (!strncmp(line_buf + set_ietf_mbox + 2 + strlen(boundary_id), "--", 2) && tmpbp) { #if DEBUG_PARSE printf("Error, end of mime found before mime start!\n"); #endif /* end of mime found before mime start */ bp = append_body(bp, &lp, tmpbp); boundary_id = NULL; goto leave_header; } free_body(tmpbp); /* * This stores the boundary string in a stack * of strings: */ boundp = bound(boundp, boundbuffer); multipartp = multipart(multipartp, type); skip_mime_epilogue = FALSE; /* printf("set new boundary: %s\n", boundp->line); */ /* @@JK Take into account errors when we abort, malformed mime, etc, probably put this call up, before detecting errors? */ charsetsp = charsets(charsetsp, charset, charsetsave); #ifdef DEBUG_PARSE fprintf(stderr, "pushing charset %s and charsetsave %s\n", charset, charsetsave); #endif if (charset) { free(charset); charset = NULL; } charsetsave[0] = '\0'; #ifdef DEBUG_PARSE fprintf(stderr, "restoring parents charset %s and charsetsave %s\n", charset, charsetsave); #endif /* * We set ourselves, "back in header" since there is * gonna come MIME headers now after the separator */ isinheader = 1; /* Daniel Stenberg started adding the * "multipart/alternative" parser 13th of July * 1998! We check if this is a 'multipart/ * alternative' header, in which case we need to * treat it very special. */ if (!strncasecmp (&ptr[10], "alternative", 11)) { /* It *is* an alternative session! Alternative * means there will be X parts with the same text * using different content-types. We are supposed * to take the most prefered format of the ones * used and only output that one. MIME defines * the order of the texts to start with pure text * and then continue with more and more obscure * formats. (well, it doesn't use those terms but * that's what it means! ;-)) */ /* How "we" are gonna deal with them: * * We create a "spare" linked list body for the * very first part. Since the first part is * defined to be the most readable, we save that * in case no content-type present is prefered! * * We skip all parts that are not prefered. All * prefered parts found will replace the first * one that is saved. When we reach the end of * the alternatives, we will use the last saved * one as prefered. */ savealternative = TRUE; #if DEBUG_PARSE printf("SAVEALTERNATIVE: yes\n"); #endif } } else boundary_id = NULL; } } else if (!strncasecmp (head->line, "Content-Transfer-Encoding:", 26)) { char *ptr = head->line + 26; head->parsedheader = TRUE; while (isspace(*ptr)) ptr++; if (!strncasecmp(ptr, "QUOTED-PRINTABLE", 16)) { decode = ENCODE_QP; } else if (!strncasecmp(ptr, "BASE64", 6)) { decode = ENCODE_BASE64; } else if (!strncasecmp(ptr, "8BIT", 4)) { decode = ENCODE_NORMAL; } else if (!strncasecmp(ptr, "7BIT", 4)) { decode = ENCODE_NORMAL; } else if (!strncasecmp(ptr, "x-uue", 5)) { decode = ENCODE_UUENCODE; if (!do_uudecode(fp, line, line_buf, &raw_text_buf, fpo)) break; } else { /* Unknown format, we use default decoding */ char code[64]; /* is there any value for content-encoding or is it missing? */ if (sscanf(ptr, "%63s", code) != EOF) { snprintf(line, sizeof(line_buf) - set_ietf_mbox, " ('%s' %s)\n", code, lang[MSG_ENCODING_IS_NOT_SUPPORTED]); bp = addbody(bp, &lp, line, BODY_HTMLIZED | bodyflags); #if DEBUG_PARSE printf("Ignoring unknown Content-Transfer-Encoding: %s\n", code); #endif } else { #if DEBUG_PARSE printf("Missing Content-Transfer-Encoding value\n"); #endif } } #if DEBUG_PARSE printf("DECODE set to %d\n", decode); #endif } } /* @@@ here we try to do a post parsing cleanup */ /* have to find out all the conditions to turn it off */ if (attach_force) { savealternative = FALSE; isinheader = 0; } if (savealternative) { /* let's remember 'bp' and 'lp' */ origbp = bp; origlp = lp; alternativeparser = TRUE; /* restart on a new list: */ lp = bp = NULL; /* clean the alternative status variables */ alternative_weight = -1; alternative_lp = alternative_bp = NULL; alternative_lastfile_created = NO_FILE; alternative_file[0] = alternative_lastfile[0] = '\0'; last_alternative_type[0] = '\0'; } headp = lp; /* start at this point next time */ } else { bp = addbody(bp, &lp, line, BODY_HEADER | bodyflags); } } else { /* not in header */ leave_header: /* If this isn't a single mail: see if the line is a message * separator. If there is a "^From " found, check to see if there * is a valid date field in the line. If not then consider it a * part of the body of the message and skip it. * Daniel: I don't like this. I don't think there is something like * "a valid date field" in that line 100%. */ if (!readone && !strncmp(line_buf, "From ", 5) && (*(dp = getfromdate(line)) != '\0')) { if (-1 != binfile) { close(binfile); binfile = -1; } /* as long as we don't handle UTF-8 throughout), use the prefered content charset if we got one */ if (prefered_content_charset) { if (charset) { free(charset); } charset = prefered_content_charset; prefered_content_charset = NULL; } #ifdef HAVE_ICONV if (!charset) { if (*charsetsave!=0){ #ifdef DEBUG_PARSE printf("put charset from subject header..\n"); #endif charset=strsav(charsetsave); } else{ /* default charset for plain/text is US-ASCII */ /* ISO-8859-1 is modern, however (DM) */ charset=strsav("US-ASCII"); #ifdef DEBUG_PARSE fprintf(stderr, "found no charset for body, set ISO-8859-1.\n"); #endif } } else { /* if body is us-ascii but subject is not, try to use subject's charset. */ if (strncasecmp(charset,"us-ascii",8)==0){ if (*charsetsave!=0 && strcasecmp(charsetsave,"us-ascii")!=0){ free(charset); charset=strsav(charsetsave); } } } #endif #ifdef DEBUG_PARSE fprintf(stderr, "Message will be stored using charset %s\n", charset); #endif isinheader = 1; if (!hassubject) subject = NOSUBJECT; else hassubject = 1; if (!hasdate) date = NODATE; else hasdate = 1; if (!inreply) inreply = oneunre(subject); /* control the use of format and delsp according to RFC 3676 */ if (textplain_format == FORMAT_FLOWED && content != CONTENT_TEXT || (content == CONTENT_TEXT && strcasecmp (type, "text/plain"))) { /* format flowed only allowed on text/plain */ textplain_format = FORMAT_FIXED; } if (textplain_format == FORMAT_FIXED && delsp_flag) { /* delsp only accepted for format=flowed */ delsp_flag = FALSE; } if (append_bp && append_bp != bp) { /* if we had attachments, close the structure */ append_bp = addbody(append_bp, &append_lp, "\n", BODY_HTMLIZED | bodyflags); bp = append_body(bp, &lp, append_bp); append_bp = append_lp = NULL; } else if(!bp) /* probably never used */ bp = addbody(bp, &lp, "Hypermail was not able " "to parse this message correctly.\n", bodyflags); while (rmlastlines(bp)); if (set_mbox_shortened && !increment && num == startnum && max_msgnum >= set_startmsgnum) { emp = hashlookupbymsgid(msgid); if (!emp) { snprintf(errmsg, sizeof(errmsg), "Message with msgid '%s' not found in .hm2index", msgid); progerr(errmsg); } num = emp->msgnum; num_added = insert_older_msgs(num); } emp = NULL; if (set_mbox_shortened) { if (hashnumlookup(num, &emp)) { if(strcmp(msgid, emp->msgid) && !strstr(emp->msgid, "hypermail.dummy")) { snprintf(errmsg, sizeof(errmsg), "msgid mismatch %s %s", msgid, emp->msgid); progerr(errmsg); } } } if (!emp) emp = addhash(num, date, namep, emailp, msgid, subject, inreply, fromdate, charset, NULL, NULL, bp); /* * dp, if it has a value, has a date from the "From " line of * the message after the one we are just finishing. * SMR 19 Oct 99: moved this *after* the addhash() call so it * isn't erroneously associate with the previous message */ strcpymax(fromdate, dp ? dp : "", DATESTRLEN); if (emp) { emp->exp_time = exp_time; emp->is_deleted = is_deleted; emp->annotation_robot = annotation_robot; emp->annotation_content = annotation_content; if (insert_in_lists(emp, require_filter, require_filter_len + require_filter_full_len)) ++num_added; num++; } else if (att_dir != NULL) { emptydir(att_dir); rmdir(att_dir); } for (pos = 0; pos < require_filter_len; ++pos) require_filter[pos] = FALSE; for (pos = 0; pos < require_filter_full_len; ++pos) require_filter_full[pos] = FALSE; if (set_txtsuffix && emp && set_increment != -1) write_txt_file(emp, &raw_text_buf); if (hasdate) free(date); if (hassubject) free(subject); if (inreply) { free(inreply); inreply = NULL; } if (charset) { free(charset); charset = NULL; } if (charsetsave){ *charsetsave = 0; } if (prefered_content_charset) { free(prefered_content_charset); prefered_content_charset = NULL; } if (msgid) { free(msgid); msgid = NULL; } if (namep) { free(namep); namep = NULL; } if (emailp) { free(emailp); emailp = NULL; } bp = NULL; bodyflags = 0; /* reset state flags */ /* reset related RFC 3676 state flags */ textplain_format = FORMAT_FIXED; delsp_flag = FALSE; flowed_line = FALSE; quotelevel = 0; continue_previous_flow_flag = FALSE; /* go back to default mode: */ content = CONTENT_TEXT; decode = ENCODE_NORMAL; Mime_B = FALSE; skip_mime_epilogue = FALSE; headp = NULL; content_type_p = NULL; multilinenoend = FALSE; if (att_dir) { free(att_dir); att_dir = NULL; } if (set_usemeta && meta_dir) { free(meta_dir); meta_dir = NULL; } att_counter = 0; att_name_list = NULL; inline_force = FALSE; attachname[0] = '\0'; /* by default we have none! */ hassubject = 0; hasdate = 0; annotation_robot = ANNOTATION_ROBOT_NONE; annotation_content = ANNOTATION_CONTENT_NONE; is_deleted = 0; exp_time = -1; free_bound (boundp); boundp = NULL; free_multipart (multipartp); multipartp = NULL; free_charsets (charsetsp); charsetsp = NULL; alternativeparser = FALSE; /* there is none anymore */ if (parse_multipart_alternative_force_save_alts) { parse_multipart_alternative_force_save_alts = 0; #if DEBUG_PARSE printf("Applemail_hack resetting parse_multipart_alternative_force_save_alts\n"); #endif if (old_set_save_alts != -1) { set_save_alts = old_set_save_alts; old_set_save_alts = -1; #if DEBUG_PARSE printf("Applemail_hack resetting save_alts to %d\n", old_set_save_alts); #endif } } if (!(num % 10) && set_showprogress && !readone) { print_progress(num - startnum, NULL, NULL); } #if DEBUG_PARSE printf("LAST: %s", line); #endif } else { /* decode MIME complient gibberish */ char newbuffer[MAXLINE]; char *data; int datalen = -1; /* -1 means use strlen to get length */ if (set_linkquotes && !inreply) { /* why only if set_linkquotes? pcm */ char *new_inreply = getreply(line); if (new_inreply && !*new_inreply) free(new_inreply); else inreply = new_inreply; } if (Mime_B) { if (boundp && !strncmp(line, "--", 2) && !strncmp(line + 2, boundp->line, strlen(boundp->line))) { /* right at this point, we have another part coming up */ #if DEBUG_PARSE printf("hit %s\n", line); #endif if (!strncmp(line + 2 + strlen(boundp->line), "--", 2)) { /* @@@ don't know why we had this line here. Doesn't hurt to take it out, though */ #if 0 bp = addbody(bp, &lp, "\n", BODY_HTMLIZED | bodyflags); #endif isinheader = 0; /* no header, the ending boundary can't have any describing headers */ #if DEBUG_PARSE printf("End boundary %s\n", line); printf("alternativeparser %d\n", alternativeparser); printf("has_more_alternatives %d\n", has_multipart(multipartp, "multipart/alternative")); #endif boundp = bound(boundp, NULL); if (!boundp) { bodyflags &= ~BODY_ATTACHED; } /* skip the MIME epilogue until the next section (or next message!) */ skip_mime_epilogue = TRUE; multipartp = multipart(multipartp, NULL); /* retrieve the parent's charset and charsetsave */ if (charsetsp->prev != NULL) { charsetsp = charsets(charsetsp, NULL, NULL); } if (charsetsp) { if (charset) { free(charset); if (charsetsp) { charset = (charsetsp->charset) ? strsav (charsetsp->charset) : NULL; } } else { charsetsave[0]='\0'; } strcpy (charsetsave, charsetsp->charsetsave); } #ifdef DEBUG_PARSE fprintf(stderr, "Pulling charset %s and charsetsave %s\n", charset, charsetsave); #endif if (!boundp && charsetsp->prev == NULL) { #ifdef DEBUG_PARSE fprintf(stderr, "No more MIME parts, freeing charsetsp\n"); #endif free_charsets(charsetsp); charsetsp = NULL; } if (alternativeparser && !has_multipart(multipartp, "multipart/alternative")) { #ifdef NOTUSED struct body *next; #endif #if DEBUG_PARSE printf("We no longer have alternatives\n"); #endif /* we no longer have alternatives */ alternativeparser = FALSE; /* reset the alternative variables (I think we can skip this step without problems */ alternative_weight = -1; alternative_bp = NULL; alternative_lastfile_created = NO_FILE; alternative_file[0] = alternative_lastfile[0] = '\0'; last_alternative_type[0] = '\0'; #if DEBUG_PARSE printf("We DUMP the chosen alternative\n"); #endif if (bp != origbp) origbp = append_body(origbp, &origlp, bp); bp = origbp; lp = origlp; origbp = origlp = NULL; headp = NULL; } #if DEBUG_PARSE if (boundp) printf("back %s\n", boundp->line); else printf("back to NONE\n"); if (multipartp) printf("current multipart: %s\n", multipartp->line); else printf("current multipart: NONE\n"); #endif } else { /* we found the beginning of a new section */ skip_mime_epilogue = FALSE; if (alternativeparser && !set_save_alts) { /* * parsing another alternative, so we save the * precedent values */ alternative_bp = bp; alternative_lp = lp; alternative_lastfile_created = file_created; strcpy(alternative_lastfile, alternative_file); strncpy(last_alternative_type, type, sizeof(last_alternative_type) - 1); /* and now reset them */ headp = bp = lp = NULL; alternative_file[0] = '\0'; } else { att_counter++; if (alternativeparser && set_save_alts == 1) { bp = addbody(bp, &lp, set_alts_text ? set_alts_text : "
    ", BODY_HTMLIZED | bodyflags); } } #if DEBUG_PARSE printf("mime parsing isinheader set to 1\n"); #endif isinheader = 1; /* back on a kind-of-header */ /* @@@ why are we changing the status of this variable? */ file_created = NO_FILE; /* not created any file yet */ } /* go back to the MIME attachment default mode */ content = CONTENT_TEXT; decode = ENCODE_NORMAL; multilinenoend = FALSE; /* reset related RFC 3676 state flags */ textplain_format = FORMAT_FIXED; delsp_flag = FALSE; flowed_line = FALSE; quotelevel = 0; continue_previous_flow_flag = FALSE; /* restore the parent's charset/charsetsave values */ if (charsetsp) { if (charset) { free(charset); } if (charsetsp->charset) { charset = strsav(charsetsp->charset); } else { charset = NULL; } strcpy(charsetsave, charsetsp->charsetsave); #ifdef DEBUG_PARSE printf("New section: restoring charset %s and charsetsave %s\n", charset, charsetsave); #endif } if (-1 != binfile) { close(binfile); binfile = -1; } continue; } } switch (decode) { case ENCODE_QP: { char *p2 = mdecodeQP(fp, line, &data, &datalen, fpo); if (p2) { if (set_txtsuffix) { PushString(&raw_text_buf, line); line_buf[0] = 0; PushString(&raw_text_buf, p2); } free(p2); } } break; case ENCODE_BASE64: base64Decode(line, newbuffer, &datalen); data = newbuffer; break; case ENCODE_UUENCODE: uudecode(NULL, line, newbuffer, &datalen, NULL); data = newbuffer; break; case ENCODE_NORMAL: data = line; break; default: /* we have no clue! */ data = NULL; break; } #if DEBUG_PARSE printf("LINE %s\n", (content != CONTENT_BINARY) ? data : ""); #endif if (data) { if ((content == CONTENT_TEXT) || (content == CONTENT_HTML)) { if (decode > ENCODE_MULTILINED) { /* * This can be more than one resulting line, * as the decoded the string may look like: * "#!/bin/sh\r\n\r\nhelp() {\r\n echo 'Usage: difftree" */ char *p = data; char *n; char store; #if DEBUG_PARSE printf("decode type %d\n", decode); #endif while ((n = strchr(p, '\n'))) { store = n[1]; n[1] = 0; #if DEBUG_PARSE printf("UNFOLDED %s", p); #endif bp = addbody(bp, &lp, p, (content == CONTENT_HTML ? BODY_HTMLIZED : 0) | (multilinenoend ? BODY_CONTINUE : 0) | bodyflags); multilinenoend = FALSE; /* full line pushed */ n[1] = store; p = n + 1; } if (strlen(p)) { /* * This line doesn't really end here, * we will get another line soon that * should get appended! */ #if DEBUG_PARSE printf("CONTINUE %s\n", p); #endif bp = addbody(bp, &lp, p, (content == CONTENT_HTML ? BODY_HTMLIZED : 0) | (multilinenoend ? BODY_CONTINUE : 0) | bodyflags); /* * We want the next line to get appended to this! */ multilinenoend = TRUE; } } else { if (!isinheader && (textplain_format == FORMAT_FLOWED)) { /* remove both space stuffing and quotes * where applicable for f=f */ bodyflags |= BODY_DEL_SSQ; flowed_line = rfc3676_handler (data, delsp_flag, "elevel, &continue_previous_flow_flag); if (continue_previous_flow_flag) { bodyflags |= BODY_CONTINUE; } else { bodyflags &= ~BODY_CONTINUE; if (flowed_line) { bodyflags |= BODY_FORMAT_FLOWED; } else { bodyflags &= ~BODY_FORMAT_FLOWED; } } continue_previous_flow_flag = flowed_line; } else { bodyflags &= ~BODY_DEL_SSQ; } bp = addbody(bp, &lp, data, (content == CONTENT_HTML ? BODY_HTMLIZED : 0) | bodyflags); } #if DEBUG_PARSE printf("ALIVE?\n"); #endif } else if (content == CONTENT_BINARY) { /* don't create the attachments of deleted files */ /* (JK: this seems like a good place to call emptydir() to remove existing attachments) from deleted messages */ if (is_deleted && file_created == MAKE_FILE) { file_created = MADE_FILE; } #ifndef REMOVED_990310 /* If there is no file created, we create and init one */ if (file_created == MAKE_FILE) { char *fname; char *binname; char *file = NULL; char buffer[512]; file_created = MADE_FILE; /* we have, or at least we tried */ /* create the attachment directory if it doesn't exist */ if (att_dir == NULL) { /* first check the DIR_PREFIXER */ #ifdef JOSE trio_asprintf(&att_dir,"%s%c" DIR_PREFIXER "%s", dir, PATH_SEPARATOR, message_name (emp)) #else trio_asprintf(&att_dir,"%s%c" DIR_PREFIXER "%04d", dir, PATH_SEPARATOR, num); #endif if (set_increment != -1) check1dir(att_dir); /* If this is a repeated run on the same archive we already * have HTML'ized, we risk extracting the same attachments * several times and therefore we need to remove all the * attachments currently present before we go ahead! *(Daniel -- August 6, 1999) */ /* jk: removed it for a while, as it's not so necessary once we can generate the same file names */ #if DEBUG_PARSE emptydir(att_dir); #endif if (set_usemeta && set_increment != -1) { /* make the meta dir where we'll store the meta info, such as content-type */ trio_asprintf(&meta_dir, "%s%c" META_DIR, att_dir, PATH_SEPARATOR); check1dir(meta_dir); } } /* If the attachment has a name, we keep it and add the current value of the counter, to guarantee that we have a unique name. Otherwise, we use a fixed name + the counter. We go thru all this trouble so that we can easily regenerate the same archive, without breaking any links */ if (att_counter > 99) binname = NULL; else { if (set_filename_base) create_attachname(attachname, sizeof(attachname)); if (attachname[0]) fname = attachname; else fname = FILE_SUFFIXER; if (!attachname[0] || inlist(att_name_list, fname)) trio_asprintf(&binname, "%s%c%02d-%s", att_dir, PATH_SEPARATOR, att_counter, fname); else trio_asprintf(&binname, "%s%c%s", att_dir, PATH_SEPARATOR, fname); if (att_name_list == NULL) att_name_list = att_name_last = (struct hmlist *)malloc(sizeof(struct hmlist)); else { att_name_last->next = (struct hmlist *)malloc(sizeof(struct hmlist)); att_name_last = att_name_last->next; } att_name_last->next = NULL; att_name_last->val = strsav(fname); /* @@ move this one up */ /* att_counter++; */ } /* * Saving of the attachments is being done * inline as they are encountered. The * directories must exist first... */ #ifdef O_BINARY #define OPENBITMASK O_WRONLY | O_CREAT | O_TRUNC | O_BINARY #else #define OPENBITMASK O_WRONLY | O_CREAT | O_TRUNC #endif if (binname) { binfile = open(binname, OPENBITMASK, set_filemode); #if DEBUG_PARSE printf("%4d open attachment %s\n", num, binname); #endif if (-1 != binfile) { chmod(binname, set_filemode); if (set_showprogress) print_progress(num, lang [MSG_CREATED_ATTACHMENT_FILE], binname); if (set_usemeta) { /* write the mime meta info */ FILE *file_ptr; char *meta_file; char *ptr; ptr = strrchr(binname, PATH_SEPARATOR); *ptr = '\0'; trio_asprintf(&meta_file, "%s%c%s" META_EXTENSION, meta_dir, PATH_SEPARATOR, ptr + 1); *ptr = PATH_SEPARATOR; file_ptr = fopen(meta_file, "w"); if (file_ptr) { if (type) { if (charset) fprintf(file_ptr, "Content-Type: %s; charset=\"%s\"\n", type, charset); else fprintf(file_ptr, "Content-Type: %s\n", type); } if (annotation_robot && set_userobotmeta) { /* annotate the attachments using the experimental google X-Robots-Tag HTTP header. See https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag */ char *value; if (annotation_robot == 1) value = "nofollow"; else if (annotation_robot == 2) value = "noindex"; else if (annotation_robot == 3) value = "nofollow, noindex"; fprintf(file_ptr,"X-Robots-Tag: %s\n", value); } fclose(file_ptr); chmod(meta_file, set_filemode); free(meta_file); } } if (alternativeparser) { /* save the last name, in case we need to supress it */ strncpy(alternative_file, binname, sizeof(alternative_file) - 1); /* save the last mime type to help deal with the * apple mail hack */ strncpy(last_alternative_type, type, sizeof(last_alternative_type) - 1); } } else { if (alternativeparser) { /* save the last name, in case we need to supress it */ alternative_file[0] = '\0'; /* save the last mime type to help deal with the apple * hack */ last_alternative_type[0] = '\0'; } } /* point to the filename and skip the separator */ file = &binname[strlen(att_dir) + 1]; /* protection against having a filename bigger than buffer */ if (strlen(file) <= 500) { char *desc; char *sp; struct emailsubdir *subdir; if (description && description[0] != '\0' && hasblack(description)) desc = convchars(description, charset); else if (inline_force || inlinecontent(type)) desc = attachname[0] ? attachname : "picture"; else desc = attachname[0] ? attachname : "stored"; if (description) description = NULL; subdir = NULL; if (set_msgsperfolder || set_folder_by_date) { struct emailinfo e; fill_email_dates(&e, date, fromdate, NULL, NULL); subdir = msg_subdir(num, set_use_sender_date ? e.date : e.fromdate); } if (inline_force || inlinecontent(type)) { /* if we know our browsers can show this type of context as-is, we make a tag instead of
    ! */ if(set_inline_addlink){ char *created_link = createlink(set_attachmentlink, &att_dir[strlen(dir) + 1], file, num, type); trio_snprintf(buffer, sizeof(buffer), "

    \"%s\"\n
    \n(%s %s:
    %s)

    \n", subdir ? subdir->rel_path_to_top : "", &att_dir[strlen(dir) + 1], PATH_SEPARATOR, file, desc, type, lang[MSG_ATTACHMENT], subdir ? subdir->rel_path_to_top : "", created_link, file); free(created_link); }else { trio_snprintf(buffer, sizeof(buffer), "\"%s\"\n", subdir ? subdir->rel_path_to_top : "", &att_dir[strlen(dir) + 1], PATH_SEPARATOR, file, desc); } } else { char *created_link = createlink(set_attachmentlink, &att_dir[strlen(dir) + 1], file, num, type); if ((sp = strchr(desc, '\n')) != NULL) *sp = '\0'; trio_snprintf(buffer, sizeof(buffer), "
      \n
    • %s %s: %s
    • \n
    \n", type, lang[MSG_ATTACHMENT], subdir ? subdir->rel_path_to_top : "", created_link, desc); free(created_link); } /* Print attachment comment before attachment */ /* add a DIV to store all this info first */ if (!append_bp) append_bp = addbody(append_bp, &append_lp, "
    \n", BODY_HTMLIZED | bodyflags); append_bp = addbody(append_bp, &append_lp, buffer, BODY_HTMLIZED | bodyflags); trio_snprintf(buffer, sizeof(buffer), "\n", file); append_bp = addbody(append_bp, &append_lp, buffer, BODY_HTMLIZED | bodyflags); } } inline_force = FALSE; attachname[0] = '\0'; if (binname && (binfile != -1)) content = CONTENT_BINARY; else content = CONTENT_UNKNOWN; if (binname) free(binname); } } #endif if (-1 != binfile) { if (datalen < 0) datalen = strlen(data); write(binfile, data, datalen); } } if (ENCODE_QP == decode) free(data); /* this was allocatd by mdecodeQP() */ } } } if(set_append && fclose(fpo)) { progerr("Can't close \"mbox\""); } if (!isinheader || readone) { #ifdef HAVE_ICONV if (!charset){ if (*charsetsave!=0){ /** if(set_showprogress){ printf("\nput charset from subject header..\n"); } **/ charset=strsav(charsetsave); }else{ /* default charset is US-ASCII */ charset=strsav("US-ASCII"); /** if(set_showprogress){ printf("\nfound no charset for body, set ISO-8859-1.\n"); } **/ } }else{ /* if body is us-ascii but subject is not, try to use subject's charset. */ if (strncasecmp(charset,"us-ascii",8)==0){ if (*charsetsave!=0 && strcasecmp(charsetsave,"us-ascii")!=0){ free(charset); charset=strsav(charsetsave); } } } #endif if (!hassubject) subject = NOSUBJECT; if (!hasdate) date = NODATE; if (!inreply) inreply = oneunre(subject); /* control the use of format and delsp according to RFC2646 */ if (textplain_format == FORMAT_FLOWED && content != CONTENT_TEXT || (content == CONTENT_TEXT && strcasecmp (type, "text/plain"))) { /* format flowed only allowed on text/plain */ textplain_format = FORMAT_FIXED; } if (textplain_format == FORMAT_FIXED && delsp_flag) { /* delsp only accepted for format=flowed */ delsp_flag = FALSE; } if (append_bp && append_bp != bp) { /* close the DIV */ append_bp = addbody(append_bp, &append_lp, "
    \n", BODY_HTMLIZED | bodyflags); bp = append_body(bp, &lp, append_bp); append_bp = append_lp = NULL; } while (rmlastlines(bp)); strcpymax(fromdate, dp ? dp : "", DATESTRLEN); if (prefered_content_charset) { if (prefered_content_charset[0] != '\0') { #ifdef DEBUG_PARSE fprintf(stderr, "Replacing charset %s with prefered_content_charset %s\n", charset, prefered_content_charset); #endif if (charset) { free(charset); } charset = prefered_content_charset; } else { free(prefered_content_charset); } prefered_content_charset = NULL; } emp = addhash(num, date, namep, emailp, msgid, subject, inreply, fromdate, charset, NULL, NULL, bp); if (emp) { emp->exp_time = exp_time; emp->is_deleted = is_deleted; emp->annotation_robot = annotation_robot; emp->annotation_content = annotation_content; if (insert_in_lists(emp, require_filter, require_filter_len + require_filter_full_len)) ++num_added; if (set_txtsuffix && set_increment != -1) write_txt_file(emp, &raw_text_buf); num++; } /* @@@ if we didn't add the message, we should consider erasing the attdir if it's there */ if (hasdate) free(date); if (hassubject) free(subject); if (inreply) { free(inreply); inreply = NULL; } if (charset) { free(charset); charset = NULL; } if (charsetsave){ *charsetsave = 0; } if (prefered_content_charset) { free(prefered_content_charset); prefered_content_charset = NULL; } if (msgid) { free(msgid); msgid = NULL; } if (namep) { free(namep); namep = NULL; } if (emailp) { free(emailp); emailp = NULL; } /* reset the status counters */ /* @@ verify we're doing it everywhere */ bodyflags = 0; /* reset state flags */ /* reset related RFC 3676 state flags */ textplain_format = FORMAT_FIXED; delsp_flag = FALSE; flowed_line = FALSE; quotelevel = 0; continue_previous_flow_flag = FALSE; /* go back to default mode: */ content = CONTENT_TEXT; decode = ENCODE_NORMAL; Mime_B = FALSE; skip_mime_epilogue = FALSE; headp = NULL; multilinenoend = FALSE; if (att_dir) { free(att_dir); att_dir = NULL; } if (set_usemeta && meta_dir) { free(meta_dir); meta_dir = NULL; } att_counter = 0; while (att_name_list != NULL) { struct hmlist *ptr_next_att = att_name_list->next; free(att_name_list->val); free(att_name_list); att_name_list = ptr_next_att; } att_name_list = NULL; description = NULL; if (parse_multipart_alternative_force_save_alts) { parse_multipart_alternative_force_save_alts = 0; #if DEBUG_PARSE printf("Applemail_hack resetting parse_multipart_alternative_force_save_alts\n"); #endif if (old_set_save_alts != -1) { set_save_alts = old_set_save_alts; old_set_save_alts = -1; #if DEBUG_PARSE printf("Applemail_hack resetting save_alts to %d\n", old_set_save_alts); #endif } } /* by default we have none! */ hassubject = 0; hasdate = 0; annotation_robot = ANNOTATION_ROBOT_NONE; annotation_content = ANNOTATION_CONTENT_NONE; } if (require_filter) free(require_filter); if (set_showprogress && !readone) print_progress(num, lang[MSG_ARTICLES], NULL); #if DEBUG_PARSE printf("\b\b\b\b%4d %s.\n", num, lang[MSG_ARTICLES]); #endif /* kpm - this is to prevent the closing of std and hypermail crashing * if the input is from stdin */ if (fp != stdin) fclose(fp); #ifdef FASTREPLYCODE threadlist_by_msgnum = (struct reply **)emalloc((num + 1)*sizeof(struct reply *)); { int i; for (i = 0; i <= num; ++i) threadlist_by_msgnum[i] = NULL; } #endif if (num > max_msgnum) max_msgnum = num - 1; crossindex(); threadlist = NULL; printedthreadlist = NULL; crossindexthread1(datelist); #if DEBUG_THREAD { struct reply *r; r = threadlist; fprintf(stderr, "START of threadlist after crossindexthread1\n"); fprintf(stderr, "- msgnum frommsgnum maybereply msgid\n"); while (r != NULL) { if (r->data == NULL) { fprintf(stderr, "- XX %d %d XX\n", r->frommsgnum, r->maybereply); } else { fprintf(stderr, "- %d %d %d '%s'\n", r->data->msgnum, r->frommsgnum, r->maybereply, r->data->msgid); } r = r->next; } fprintf(stderr, "END of threadlist after crossindexthread1\n"); } #endif /* can we clean up a bit please... */ free_bound (boundp); free_multipart (multipartp); if(charsetsave){ free(charsetsave); } return num_added; /* amount of mails read */ } static void check_expiry(struct emailinfo *emp) { time_t email_time; const char *option = "expires"; if (!emp->is_deleted) { if (emp->exp_time != -1 && emp->exp_time < time(NULL)) emp->is_deleted = FILTERED_EXPIRE; email_time = emp->fromdate; if (email_time == -1) email_time = emp->date; if (email_time != -1 && set_delete_older && email_time < convtoyearsecs(set_delete_older)) { emp->is_deleted = FILTERED_OLD; option = "delete_older"; } if (email_time != -1 && set_delete_newer && email_time < convtoyearsecs(set_delete_newer)) { emp->is_deleted = FILTERED_NEW; option = "delete_newer"; } if (emp->is_deleted) printf("message %d deleted under option %s. msgid: %s\n", emp->msgnum+1, option, emp->msgid); } } int parse_old_html(int num, struct emailinfo *ep, int parse_body, int do_insert, struct reply **replylist_tmp, int cmp_msgid) { char line[MAXLINE]; char *name = NULL; char *email = NULL; char *date = NULL; char *msgid = NULL; char *subject = NULL; char *inreply = NULL; char *fromdate = NULL; char *charset = NULL; char *isodate = NULL; char *isofromdate = NULL; char command[100]; char *valp; char legal = FALSE; int reply_msgnum = -1; long exp_time = -1; int is_deleted = 0; int num_added = 0; struct body *bp = NULL; struct body *lp = NULL; int msgids_are_same = 0; struct emailsubdir *subdir = ep ? ep->subdir : msg_subdir(num, 0); char *filename; FILE *fp; char inreply_start[256]; static char *inreply_start_old = "
  • In reply to: %s: subdir : "", msgnum_id_table[num], set_htmlsuffix); else trio_asprintf(&filename, "%s%s%.4d.%s", set_dir, subdir ? subdir->subdir : "", num, set_htmlsuffix); /* * fromdate == * date == * name == * email == * subject == * msgid == * inreply == * * New for 2b10: * charset == * * New for 2b18: * isofromdate == * isodate == */ if ((fp = fopen(filename, "r")) != NULL) { while (fgets(line, sizeof(line), fp)) { if (1 == sscanf(line, "") && set_linkquotes) msgid = NULL;/* old version of Hypermail wrote junk? */ } else if (!strcasecmp(command, "charset")) charset = getvalue(line); else if (!strcasecmp(command, "isosent")) isodate = getvalue(line); else if (!strcasecmp(command, "isoreceived")) isofromdate = getvalue(line); else if (!strcasecmp(command, "expires")) { valp = getvalue(line); if (valp) { exp_time = strcmp(valp, "-1") ? iso_to_secs(valp) : -1; free(valp); } } else if (!strcasecmp(command, "isdeleted")) { valp = getvalue(line); if (valp) { is_deleted = atoi(valp); free(valp); } } else if (!strcasecmp(command, "inreplyto")) { char *raw_msgid = getvalue(line); valp = unspamify(raw_msgid); if (raw_msgid) free(raw_msgid); if (valp) { inreply = unconvchars(valp); free(valp); } } else if (!strcasecmp(command, "body")) { /* * When we reach the mail body, we know we've got all the * headers there were! */ if (parse_body) { while (fgets(line, MAXLINE, fp)) { char *ptr; char *line2; if (!strcmp(line,"\n")) break; #if 0 if (!strcmp(line,"

    \n")) break; #endif line2 = remove_hypermail_tags(line); if (line2) { if (!bp && *line2 != '\n') { bp = addbody(bp, &lp, "\n", 0); if (ep != NULL) ep->bodylist = bp; } ptr = unconvchars(line2); bp = addbody(bp, &lp, ptr ? ptr : "", 0); if (ep != NULL && !ep->bodylist->line[0]) ep->bodylist = bp; if(0) fprintf(stderr,"addbody %p %d from %s", bp, !ep->bodylist->line[0], ptr); free(ptr); if (set_linkquotes && !inreply) { char *new_inreply = getreply(line2); if (!*new_inreply) free(new_inreply); else inreply = new_inreply; } free(line2); } } } if (!bp) bp = addbody(bp, &lp, "\0", 0); fclose(fp); legal = TRUE; /* with a body tag we consider this a valid syntax */ break; } } else if (set_linkquotes) { char *ptr; if ((ptr = strcasestr(line, inreply_start)) != NULL) reply_msgnum = atoi(ptr + strlen(inreply_start)); else if ((ptr = strstr(line, inreply_start_old)) != NULL) reply_msgnum = atoi(ptr + strlen(inreply_start_old)); } } } else if (cmp_msgid) return -1; if (legal) { /* only do this if the input was reliable */ struct emailinfo *emp; #if HAVE_ICONV if (charset){ char *tmpptr; size_t tmplen=0; tmpptr=subject; subject=i18n_convstring(tmpptr,charset,"UTF-8",&tmplen); if(tmpptr) free(tmpptr); tmpptr=name; name=i18n_convstring(tmpptr,charset,"UTF-8",&tmplen); if(tmpptr) free(tmpptr); } #endif if (replylist_tmp == NULL || !do_insert) emp = ep; else emp = addhash(num, date ? date : NODATE, name, email, msgid, subject, inreply, fromdate, charset, isodate, isofromdate, bp); if (cmp_msgid) msgids_are_same = !strcmp(ep->msgid, msgid); if (emp != NULL && replylist_tmp != NULL) { if (do_insert) { emp->exp_time = exp_time; emp->is_deleted = is_deleted; check_expiry(emp); if (insert_in_lists(emp, NULL, 0)) ++num_added; } if(set_linkquotes && reply_msgnum != -1) { #ifdef FASTREPLYCODE struct emailinfo *email2; if (hashnumlookup(reply_msgnum, &email2)) *replylist_tmp = addreply2(*replylist_tmp, email2, emp, 0, NULL); #else *replylist_tmp = addreply(*replylist_tmp, reply_msgnum, emp, 0, NULL); #endif } } } if (charset) { free(charset); } if (name) { free(name); } if (subject) { free(subject); } if (msgid) { free(msgid); } if (inreply) { free(inreply); } if (fromdate) { free(fromdate); } if (date) { free(date); } if (email) { free(email); } if (isodate) { free(isodate); } if (isofromdate) { free(isofromdate); } free(filename); #if 0 if (bp != NULL) { /* revisit me */ if (bp->line) free(bp->line); free(bp); } #endif return (cmp_msgid ? msgids_are_same : num_added); } /* ** All this does is get all the relevant header information from the ** comment fields in existing archive files. Everything is loaded into ** structures in the exact same way as if articles were being read from ** stdin or a mailbox. ** ** Return the number of mails read. */ static int loadoldheadersfrommessages(char *dir, int num_from_gdbm) { int num = 0; int num_added = 0; int max_num; struct emailinfo *e0 = NULL; struct reply *replylist_tmp = NULL; int first_read_body = set_startmsgnum; if (num_from_gdbm != -1) max_num = num_from_gdbm - 1; else if (set_nonsequential) max_num = find_max_msgnum_id(); else max_num = find_max_msgnum(); if (max_num > max_msgnum) max_msgnum = max_num; if (set_searchbackmsgnum) { first_read_body = max_num - set_searchbackmsgnum; if (first_read_body < set_startmsgnum) first_read_body = set_startmsgnum; if (num_from_gdbm != -1) num = first_read_body; } #if 0 else if (set_searchbackmsgnum && set_increment) { int jump = 1000; /* search for biggest message number */ while (jump && first_read_body >= 0) { subdir = msg_subdir(first_read_body, 0); trio_asprintf(&filename,"%s%s%.4d.%s", set_dir, subdir ? subdir->subdir : "", first_read_body, set_htmlsuffix); if ((fp = fopen(filename, "r")) != NULL) { fclose(fp); if (jump < 0) jump = -jump/2; first_read_body += jump; } else { if (jump > 0) jump = -jump/2; first_read_body += jump; } free(filename); free(subdir); } first_read_body -= set_searchbackmsgnum + 1; } #endif if (set_folder_by_date) { if (!num_from_gdbm) return 0; #ifdef GDBM if (set_usegdbm && !hashnumlookup(first_read_body, &e0) && set_startmsgnum == 0 && first_read_body == 0 && num_from_gdbm != -1 && hashnumlookup(1, &e0)) { /* kludge to handle old archives that mistakenly started with 0001 */ first_read_body = 1; } #endif if (!hashnumlookup(first_read_body, &e0)) { #ifdef GDBM if (set_usegdbm) { if (num_from_gdbm == -1) { if (is_empty_archive()) return 0; snprintf(errmsg, sizeof(errmsg), "Error: This archive does not appear to be empty, " "and it has no gdbm file\n(%s). If you want to " "use incremental updates with the folder_by_date\n" "option, you must start with an empty archive or " "with an archive\nthat was generated using the " "usegdbm option.", GDBM_INDEX_NAME); } else snprintf(errmsg, sizeof(errmsg), "Error set_folder_by_date msg %d num_from_gdbm %d", first_read_body, num_from_gdbm); } else snprintf(errmsg, sizeof(errmsg), "folder_by_date with incremental update requires usegdbm option"); #else snprintf(errmsg, sizeof(errmsg), "folder_by_date requires usegdbm option" ". gdbm support has not been compiled into this" " copy of hypermail. You probably need to install" "gdbm and rerun configure."); #endif progerr(errmsg); } } if (num_from_gdbm == -1) authorlist = subjectlist = datelist = NULL; #ifdef WANTDUPMESSAGES if (set_showprogress) printf("%s...\n", lang[MSG_READING_OLD_HEADERS]); #endif /* Strategy: loop on files, opening each and copying the header comments * into dynamically-allocated memory, then saving if it's not corrupt. */ if (set_nonsequential) /* read the msgid to msgnum table */ msgnum_id_table = read_msgnum_id_table (max_num); while (num <= max_num) { struct emailinfo *ep0 = NULL; int parse_body = (set_linkquotes && num >= first_read_body); if (num_from_gdbm != -1 || set_folder_by_date) { if (!hashnumlookup(num, &ep0)) { if (++num > max_num) break; continue; } } num_added += parse_old_html(num, ep0, parse_body, num_from_gdbm == -1, &replylist_tmp, 0); num++; if (!(num % 10) && set_showprogress) { printf("\r%4d", num); fflush(stdout); } } if (set_nonsequential) { /* free the msgnum_id_table */ free_msgnum_id_table (msgnum_id_table, max_num); msgnum_id_table = NULL; } #ifdef WANTDUPMESSAGES if (set_showprogress) printf("\b\b\b\b%4d %s.\n", num, lang[MSG_ARTICLES]); #endif if (set_linkquotes) set_alt_replylist(replylist_tmp); return num_added; } /* end loadoldheadersfrommessages() */ /* ** Load message summary information from a GDBM index. */ #ifdef GDBM int loadoldheadersfromGDBMindex(char *dir, int get_count_only) { char *indexname; GDBM_FILE gp; int num; int num_added = 0; int old_delete_level = -1; if (!get_count_only) authorlist = subjectlist = datelist = NULL; /* Use gdbm performance hack: instead of opening each and * every .html file to get the comment information, get it * from a gdbm index, where the key is the message number and * the content is a string containing the values separated by * nullchars, in this order: * fromdate * date * name * email * subject * inreply * charset v2.0 * isofromdate v2.0 * isodate v2.0 */ trio_asprintf(&indexname, (dir[strlen(dir)-1] == '/') ? "%s%s" : "%s/%s", dir, GDBM_INDEX_NAME); if ((gp = gdbm_open(indexname, 0, GDBM_READER, 0, 0))) { /* we _can_ read the index */ datum content; datum key; int max_num; key.dptr = "delete_level"; key.dsize = strlen(key.dptr); content = gdbm_fetch(gp, key); if (content.dptr) old_delete_level = atoi(content.dptr); key.dptr = (char *) # key.dsize = sizeof(num); num = -1; content = gdbm_fetch(gp, key); if (!content.dptr) max_num = -1; else max_num = atoi(content.dptr); if (get_count_only) { gdbm_close(gp); return max_num; } for(num = 0; max_num == -1 || num <= max_num; num++) { char *dp, *dp_end; char *name=NULL; char *email=NULL; char *date=NULL; char *msgid=NULL; char *subject=NULL; char *inreply=NULL; char *fromdate=NULL; char *charset=NULL; char *isodate=NULL; char *isofromdate=NULL; long exp_time = -1; int is_deleted = 0; struct emailinfo *emp; struct body *bp = NULL; struct body *lp = NULL; bp = addbody(bp, &lp, "\0", 0); content = gdbm_fetch(gp, key); if(!(dp = content.dptr)) { if (max_num == -1) /* old file where gaps in nums not legal */ break; /* must be at end */ continue; } dp_end = dp + content.dsize; fromdate = dp; dp += strlen(dp) + 1; date = dp; dp += strlen(dp) + 1; name = dp; dp += strlen(dp) + 1; email = dp; dp += strlen(dp) + 1; subject = unconvchars(dp); dp += strlen(dp) + 1; msgid = dp; dp += strlen(dp) + 1; inreply = unconvchars(dp); dp += strlen(dp) + 1; charset = dp; dp += strlen(dp) + 1; isofromdate = dp; dp += strlen(dp) + 1; isodate = dp; dp += strlen(dp) + 1; if (dp < dp_end) { exp_time = iso_to_secs(dp); if (!*dp) exp_time = -1; dp += strlen(dp) + 1; } if (dp < dp_end) { is_deleted = atoi(dp); dp += strlen(dp) + 1; } if ((emp = addhash(num, date, name, email, msgid, subject, inreply, fromdate, charset, isodate, isofromdate, bp))) { emp->exp_time = exp_time; emp->is_deleted = is_deleted; emp->deletion_completed = old_delete_level; check_expiry(emp); if (insert_in_lists(emp, NULL, 0)) ++num_added; if (num == max_num) { char *filename = articlehtmlfilename(emp); if (!isfile(filename) && !is_deleted) { trio_snprintf(errmsg, sizeof(errmsg), "%s \"%s\". If you deleted files," " you need to delete the gdbm file %s as well.", lang[MSG_CANNOT_OPEN_MAIL_ARCHIVE], filename, indexname); progerr(errmsg); } free(filename); } } free(subject); free(inreply); #if 0 if(bp) { if (bp->line) free(bp->line); free(bp); } #endif if (!(num % 10) && set_showprogress) { printf("\r%4d", num); fflush(stdout); } } /* end loop on messages */ gdbm_close(gp); if (set_linkquotes) loadoldheadersfrommessages(dir, num); } /* end case of able to read gdbm index */ else { struct emailinfo *emp; if (get_count_only) return 0; /* can't read? create. */ if (set_showprogress) printf(lang[MSG_CREATING_GDBM_INDEX]); num = loadoldheadersfrommessages(dir, -1); if(!(gp = gdbm_open(indexname, 0, GDBM_NEWDB, 0600, 0))){ /* Serious problem here: can't create! So, just muddle on. */ if (set_showprogress) printf(lang[MSG_CANT_CREATE_GDBM_INDEX]); return num; } /* Can create new; now, populate it */ for (num = 0; hashnumlookup(num, &emp); num++) { togdbm((void *) gp, emp); } gdbm_close(gp); } /* end case of could not read gdbm index */ free(indexname); return num_added; } /* end loadoldheadersfromGDBMindex() */ #endif /* All this does is get all the relevant header information. ** Everything is loaded into structures in the exact same way as if ** articles were being read from stdin or a mailbox. ** ** Return the number of mails read. */ int loadoldheaders(char *dir) { int num; if (set_showprogress) printf("%s...\n", lang[MSG_READING_OLD_HEADERS]); #ifdef GDBM if(set_usegdbm) num = loadoldheadersfromGDBMindex(dir, 0); else #endif num = loadoldheadersfrommessages(dir, -1); if (set_showprogress) printf("\b\b\b\b%4d %s.\n", num, lang[MSG_ARTICLES]); return num; } /* end loadoldheaders() */ /* ** Adds a "Next:" link in the proper article, after the archive has been ** incrementally updated. */ void fixnextheader(char *dir, int num, int direction) { char *filename; char line[MAXLINE]; struct emailinfo *email; struct body *bp, *cp, *dp = NULL, *lp = NULL; int ul; FILE *fp; char *ptr; struct emailinfo *e3 = NULL; dp = NULL; ul = 0; if ((e3 = neighborlookup(num, direction)) != NULL && (email = neighborlookup(num-1, 1)) != NULL) filename = articlehtmlfilename(e3); else return; bp = NULL; fp = fopen(filename, "r"); if (fp) { while ((fgets(line, MAXLINE, fp)) != NULL) bp = addbody(bp, &lp, line, 0); } else return; fclose(fp); cp = bp; /* save start of list to free later */ #ifdef HAVE_ICONV char *numsubject,*numname; numsubject=i18n_utf2numref(email->subject,1); numname=i18n_utf2numref(email->name,1); #endif fp = fopen(filename, "w+"); if (fp) { while (bp) { if (!strncmp(bp->line, " BSD licensed # # GNU Readline library finder if(READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NCURSES_LIBRARY) set(READLINE_FOUND TRUE) else(READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NCURSES_LIBRARY) FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h /usr/include/readline ) # 2008-04-22 The next clause used to read like this: # # FIND_LIBRARY(READLINE_LIBRARY NAMES readline) # FIND_LIBRARY(NCURSES_LIBRARY NAMES ncurses ) # include(FindPackageHandleStandardArgs) # FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG NCURSES_LIBRARY READLINE_INCLUDE_DIR READLINE_LIBRARY ) # # I was advised to modify it such that it will find an ncurses library if # required, but not if one was explicitly given, that is, it allows the # default to be overridden. PH FIND_LIBRARY(READLINE_LIBRARY NAMES readline) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG READLINE_INCLUDE_DIR READLINE_LIBRARY ) MARK_AS_ADVANCED(READLINE_INCLUDE_DIR READLINE_LIBRARY) endif(READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NCURSES_LIBRARY) ================================================ FILE: src/pcre/compile ================================================ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2018 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/pcre/config-cmake.h.in ================================================ /* config.h for CMake builds */ #cmakedefine HAVE_DIRENT_H 1 #cmakedefine HAVE_SYS_STAT_H 1 #cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_WINDOWS_H 1 #cmakedefine HAVE_STDINT_H 1 #cmakedefine HAVE_INTTYPES_H 1 #cmakedefine HAVE_TYPE_TRAITS_H 1 #cmakedefine HAVE_BITS_TYPE_TRAITS_H 1 #cmakedefine HAVE_BCOPY 1 #cmakedefine HAVE_MEMMOVE 1 #cmakedefine HAVE_STRERROR 1 #cmakedefine HAVE_STRTOLL 1 #cmakedefine HAVE_STRTOQ 1 #cmakedefine HAVE__STRTOI64 1 #cmakedefine PCRE_STATIC 1 #cmakedefine SUPPORT_PCRE8 1 #cmakedefine SUPPORT_PCRE16 1 #cmakedefine SUPPORT_PCRE32 1 #cmakedefine SUPPORT_JIT 1 #cmakedefine SUPPORT_PCREGREP_JIT 1 #cmakedefine SUPPORT_UTF 1 #cmakedefine SUPPORT_UCP 1 #cmakedefine EBCDIC 1 #cmakedefine EBCDIC_NL25 1 #cmakedefine BSR_ANYCRLF 1 #cmakedefine NO_RECURSE 1 #cmakedefine HAVE_LONG_LONG 1 #cmakedefine HAVE_UNSIGNED_LONG_LONG 1 #cmakedefine SUPPORT_LIBBZ2 1 #cmakedefine SUPPORT_LIBZ 1 #cmakedefine SUPPORT_LIBEDIT 1 #cmakedefine SUPPORT_LIBREADLINE 1 #cmakedefine SUPPORT_VALGRIND 1 #cmakedefine SUPPORT_GCOV 1 #define NEWLINE @NEWLINE@ #define POSIX_MALLOC_THRESHOLD @PCRE_POSIX_MALLOC_THRESHOLD@ #define LINK_SIZE @PCRE_LINK_SIZE@ #define PARENS_NEST_LIMIT @PCRE_PARENS_NEST_LIMIT@ #define MATCH_LIMIT @PCRE_MATCH_LIMIT@ #define MATCH_LIMIT_RECURSION @PCRE_MATCH_LIMIT_RECURSION@ #define PCREGREP_BUFSIZE @PCREGREP_BUFSIZE@ #define MAX_NAME_SIZE 32 #define MAX_NAME_COUNT 10000 /* end config.h for CMake builds */ ================================================ FILE: src/pcre/config.guess ================================================ #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-03-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval "$set_cc_for_build" cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" # If ldd exists, use it to detect musl libc. if command -v ldd >/dev/null && \ ldd --version 2>&1 | grep -q ^musl then LIBC=musl fi ;; esac # Note: order is significant - the case branches are not exclusive. case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine="${arch}${endian}"-unknown ;; *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval "$set_cc_for_build" SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval "$set_cc_for_build" sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ [ "$TARGET_BINARY_INTERFACE"x = x ] then echo m88k-dg-dgux"$UNAME_RELEASE" else echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval "$set_cc_for_build" sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` case "$UNAME_MACHINE" in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "$HP_ARCH" = "" ]; then eval "$set_cc_for_build" sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ "$HP_ARCH" = hppa2.0w ] then eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) eval "$set_cc_for_build" sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo "$UNAME_MACHINE"-unknown-osf1mk else echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) case "$UNAME_MACHINE" in x86) echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval "$set_cc_for_build" sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv"$UNAME_RELEASE" else echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: src/pcre/config.h.generic ================================================ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* PCRE is written in Standard C, but there are a few non-standard things it can cope with, allowing it to run on SunOS4 and other "close to standard" systems. In environments that support the GNU autotools, config.h.in is converted into config.h by the "configure" script. In environments that use CMake, config-cmake.in is converted into config.h. If you are going to build PCRE "by hand" without using "configure" or CMake, you should copy the distributed config.h.generic to config.h, and edit the macro definitions to be the way you need them. You must then add -DHAVE_CONFIG_H to all of your compile commands, so that config.h is included at the start of every source. Alternatively, you can avoid editing by using -D on the compiler command line to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H, but if you do, default values will be taken from config.h for non-boolean macros that are not defined on the command line. Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE8 should either be defined (conventionally to 1) for TRUE, and not defined at all for FALSE. All such macros are listed as a commented #undef in config.h.generic. Macros such as MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are surrounded by #ifndef/#endif lines so that the value can be overridden by -D. PCRE uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make sure both macros are undefined; an emulation function will then be used. */ /* By default, the \R escape sequence matches any Unicode line ending character or sequence of characters. If BSR_ANYCRLF is defined (to any value), this is changed so that backslash-R matches only CR, LF, or CRLF. The build-time default can be overridden by the user of PCRE at runtime. */ /* #undef BSR_ANYCRLF */ /* If you are compiling for a system that uses EBCDIC instead of ASCII character codes, define this macro to any value. You must also edit the NEWLINE macro below to set a suitable EBCDIC newline, commonly 21 (0x15). On systems that can use "configure" or CMake to set EBCDIC, NEWLINE is automatically adjusted. When EBCDIC is set, PCRE assumes that all input strings are in EBCDIC. If you do not define this macro, PCRE will assume input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build a version of PCRE that supports both EBCDIC and UTF-8/16/32. */ /* #undef EBCDIC */ /* In an EBCDIC environment, define this macro to any value to arrange for the NL character to be 0x25 instead of the default 0x15. NL plays the role that LF does in an ASCII/Unicode environment. The value must also be set in the NEWLINE macro below. On systems that can use "configure" or CMake to set EBCDIC_NL25, the adjustment of NEWLINE is automatic. */ /* #undef EBCDIC_NL25 */ /* Define to 1 if you have the `bcopy' function. */ /* #undef HAVE_BCOPY */ /* Define to 1 if you have the header file. */ /* #undef HAVE_BITS_TYPE_TRAITS_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_BZLIB_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_DIRENT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_DLFCN_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDITLINE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_EDIT_READLINE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_INTTYPES_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LIMITS_H */ /* Define to 1 if the system has the type `long long'. */ /* #undef HAVE_LONG_LONG */ /* Define to 1 if you have the `memmove' function. */ /* #undef HAVE_MEMMOVE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_MEMORY_H */ /* Define if you have POSIX threads libraries and header files. */ /* #undef HAVE_PTHREAD */ /* Have PTHREAD_PRIO_INHERIT. */ /* #undef HAVE_PTHREAD_PRIO_INHERIT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_HISTORY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_READLINE_READLINE_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STDINT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STDLIB_H */ /* Define to 1 if you have the `strerror' function. */ /* #undef HAVE_STRERROR */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STRING */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STRINGS_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_STRING_H */ /* Define to 1 if you have `strtoimax'. */ /* #undef HAVE_STRTOIMAX */ /* Define to 1 if you have `strtoll'. */ /* #undef HAVE_STRTOLL */ /* Define to 1 if you have `strtoq'. */ /* #undef HAVE_STRTOQ */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_STAT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_TYPES_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_TYPE_TRAITS_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_UNISTD_H */ /* Define to 1 if the system has the type `unsigned long long'. */ /* #undef HAVE_UNSIGNED_LONG_LONG */ /* Define to 1 if the compiler supports simple visibility declarations. */ /* #undef HAVE_VISIBILITY */ /* Define to 1 if you have the header file. */ /* #undef HAVE_WINDOWS_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_ZLIB_H */ /* Define to 1 if you have `_strtoi64'. */ /* #undef HAVE__STRTOI64 */ /* The value of LINK_SIZE determines the number of bytes used to store links as offsets within the compiled regex. The default is 2, which allows for compiled patterns up to 64K long. This covers the vast majority of cases. However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows for longer patterns in extreme cases. */ #ifndef LINK_SIZE #define LINK_SIZE 2 #endif /* Define to the sub-directory where libtool stores uninstalled libraries. */ /* This is ignored unless you are using libtool. */ #ifndef LT_OBJDIR #define LT_OBJDIR ".libs/" #endif /* The value of MATCH_LIMIT determines the default number of times the internal match() function can be called during a single execution of pcre_exec(). There is a runtime interface for setting a different limit. The limit exists in order to catch runaway regular expressions that take for ever to determine that they do not match. The default is set very large so that it does not accidentally catch legitimate cases. */ #ifndef MATCH_LIMIT #define MATCH_LIMIT 10000000 #endif /* The above limit applies to all calls of match(), whether or not they increase the recursion depth. In some environments it is desirable to limit the depth of recursive calls of match() more strictly, in order to restrict the maximum amount of stack (or heap, if NO_RECURSE is defined) that is used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of match(). To have any useful effect, it must be less than the value of MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is a runtime method for setting a different limit. */ #ifndef MATCH_LIMIT_RECURSION #define MATCH_LIMIT_RECURSION MATCH_LIMIT #endif /* This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #ifndef MAX_NAME_COUNT #define MAX_NAME_COUNT 10000 #endif /* This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #ifndef MAX_NAME_SIZE #define MAX_NAME_SIZE 32 #endif /* The value of NEWLINE determines the default newline character sequence. PCRE client programs can override this by selecting other values at run time. In ASCII environments, the value can be 10 (LF), 13 (CR), or 3338 (CRLF); in EBCDIC environments the value can be 21 or 37 (LF), 13 (CR), or 3349 or 3365 (CRLF) because there are two alternative codepoints (0x15 and 0x25) that are used as the NL line terminator that is equivalent to ASCII LF. In both ASCII and EBCDIC environments the value can also be -1 (ANY), or -2 (ANYCRLF). */ #ifndef NEWLINE #define NEWLINE 10 #endif /* PCRE uses recursive function calls to handle backtracking while matching. This can sometimes be a problem on systems that have stacks of limited size. Define NO_RECURSE to any value to get a version that doesn't use recursion in the match() function; instead it creates its own stack by steam using pcre_recurse_malloc() to obtain memory from the heap. For more detail, see the comments and other stuff just above the match() function. */ /* #undef NO_RECURSE */ /* Name of package */ #define PACKAGE "pcre" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "PCRE" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "PCRE 8.43" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "8.43" /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system stack that is used while compiling a pattern. */ #ifndef PARENS_NEST_LIMIT #define PARENS_NEST_LIMIT 250 #endif /* The value of PCREGREP_BUFSIZE determines the size of buffer used by pcregrep to hold parts of the file it is searching. This is also the minimum value. The actual amount of memory used by pcregrep is three times this number, because it allows for the buffering of "before" and "after" lines. */ #ifndef PCREGREP_BUFSIZE #define PCREGREP_BUFSIZE 20480 #endif /* If you are compiling for a system other than a Unix-like system or Win32, and it needs some magic to be inserted before the definition of a function that is exported by the library, define this macro to contain the relevant magic. If you do not define this macro, a suitable __declspec value is used for Windows systems; in other environments "extern" is used for a C compiler and "extern C" for a C++ compiler. This macro apears at the start of every exported function that is part of the external API. It does not appear on functions that are "external" in the C sense, but which are internal to the library. */ /* #undef PCRE_EXP_DEFN */ /* Define to any value if linking statically (TODO: make nice with Libtool) */ /* #undef PCRE_STATIC */ /* When calling PCRE via the POSIX interface, additional working storage is required for holding the pointers to capturing substrings because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using malloc() for each call. The threshold above which the stack is no longer used is defined by POSIX_MALLOC_THRESHOLD. */ #ifndef POSIX_MALLOC_THRESHOLD #define POSIX_MALLOC_THRESHOLD 10 #endif /* Define to necessary symbol if this constant uses a non-standard name on your system. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* Define to 1 if you have the ANSI C header files. */ /* #undef STDC_HEADERS */ /* Define to any value to enable support for Just-In-Time compiling. */ /* #undef SUPPORT_JIT */ /* Define to any value to allow pcregrep to be linked with libbz2, so that it is able to handle .bz2 files. */ /* #undef SUPPORT_LIBBZ2 */ /* Define to any value to allow pcretest to be linked with libedit. */ /* #undef SUPPORT_LIBEDIT */ /* Define to any value to allow pcretest to be linked with libreadline. */ /* #undef SUPPORT_LIBREADLINE */ /* Define to any value to allow pcregrep to be linked with libz, so that it is able to handle .gz files. */ /* #undef SUPPORT_LIBZ */ /* Define to any value to enable the 16 bit PCRE library. */ /* #undef SUPPORT_PCRE16 */ /* Define to any value to enable the 32 bit PCRE library. */ /* #undef SUPPORT_PCRE32 */ /* Define to any value to enable the 8 bit PCRE library. */ /* #undef SUPPORT_PCRE8 */ /* Define to any value to enable JIT support in pcregrep. */ /* #undef SUPPORT_PCREGREP_JIT */ /* Define to any value to enable support for Unicode properties. */ /* #undef SUPPORT_UCP */ /* Define to any value to enable support for the UTF-8/16/32 Unicode encoding. This will work even in an EBCDIC environment, but it is incompatible with the EBCDIC macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16/32, but not both at once. */ /* #undef SUPPORT_UTF */ /* Define to any value for valgrind support to find invalid memory reads. */ /* #undef SUPPORT_VALGRIND */ /* Version number of package */ #define VERSION "8.43" /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef int64_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ ================================================ FILE: src/pcre/config.h.in ================================================ /* config.h.in. Generated from configure.ac by autoheader. */ /* PCRE is written in Standard C, but there are a few non-standard things it can cope with, allowing it to run on SunOS4 and other "close to standard" systems. In environments that support the GNU autotools, config.h.in is converted into config.h by the "configure" script. In environments that use CMake, config-cmake.in is converted into config.h. If you are going to build PCRE "by hand" without using "configure" or CMake, you should copy the distributed config.h.generic to config.h, and edit the macro definitions to be the way you need them. You must then add -DHAVE_CONFIG_H to all of your compile commands, so that config.h is included at the start of every source. Alternatively, you can avoid editing by using -D on the compiler command line to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H, but if you do, default values will be taken from config.h for non-boolean macros that are not defined on the command line. Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE8 should either be defined (conventionally to 1) for TRUE, and not defined at all for FALSE. All such macros are listed as a commented #undef in config.h.generic. Macros such as MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are surrounded by #ifndef/#endif lines so that the value can be overridden by -D. PCRE uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make sure both macros are undefined; an emulation function will then be used. */ /* By default, the \R escape sequence matches any Unicode line ending character or sequence of characters. If BSR_ANYCRLF is defined (to any value), this is changed so that backslash-R matches only CR, LF, or CRLF. The build-time default can be overridden by the user of PCRE at runtime. */ #undef BSR_ANYCRLF /* If you are compiling for a system that uses EBCDIC instead of ASCII character codes, define this macro to any value. You must also edit the NEWLINE macro below to set a suitable EBCDIC newline, commonly 21 (0x15). On systems that can use "configure" or CMake to set EBCDIC, NEWLINE is automatically adjusted. When EBCDIC is set, PCRE assumes that all input strings are in EBCDIC. If you do not define this macro, PCRE will assume input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build a version of PCRE that supports both EBCDIC and UTF-8/16/32. */ #undef EBCDIC /* In an EBCDIC environment, define this macro to any value to arrange for the NL character to be 0x25 instead of the default 0x15. NL plays the role that LF does in an ASCII/Unicode environment. The value must also be set in the NEWLINE macro below. On systems that can use "configure" or CMake to set EBCDIC_NL25, the adjustment of NEWLINE is automatic. */ #undef EBCDIC_NL25 /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY /* Define to 1 if you have the header file. */ #undef HAVE_BITS_TYPE_TRAITS_H /* Define to 1 if you have the header file. */ #undef HAVE_BZLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_EDITLINE_READLINE_H /* Define to 1 if you have the header file. */ #undef HAVE_EDIT_READLINE_READLINE_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if the system has the type `long long'. */ #undef HAVE_LONG_LONG /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Have PTHREAD_PRIO_INHERIT. */ #undef HAVE_PTHREAD_PRIO_INHERIT /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_HISTORY_H /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_READLINE_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRING /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have `strtoimax'. */ #undef HAVE_STRTOIMAX /* Define to 1 if you have `strtoll'. */ #undef HAVE_STRTOLL /* Define to 1 if you have `strtoq'. */ #undef HAVE_STRTOQ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TYPE_TRAITS_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the type `unsigned long long'. */ #undef HAVE_UNSIGNED_LONG_LONG /* Define to 1 if the compiler supports simple visibility declarations. */ #undef HAVE_VISIBILITY /* Define to 1 if you have the header file. */ #undef HAVE_WINDOWS_H /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H /* Define to 1 if you have `_strtoi64'. */ #undef HAVE__STRTOI64 /* The value of LINK_SIZE determines the number of bytes used to store links as offsets within the compiled regex. The default is 2, which allows for compiled patterns up to 64K long. This covers the vast majority of cases. However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows for longer patterns in extreme cases. */ #undef LINK_SIZE /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* The value of MATCH_LIMIT determines the default number of times the internal match() function can be called during a single execution of pcre_exec(). There is a runtime interface for setting a different limit. The limit exists in order to catch runaway regular expressions that take for ever to determine that they do not match. The default is set very large so that it does not accidentally catch legitimate cases. */ #undef MATCH_LIMIT /* The above limit applies to all calls of match(), whether or not they increase the recursion depth. In some environments it is desirable to limit the depth of recursive calls of match() more strictly, in order to restrict the maximum amount of stack (or heap, if NO_RECURSE is defined) that is used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of match(). To have any useful effect, it must be less than the value of MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is a runtime method for setting a different limit. */ #undef MATCH_LIMIT_RECURSION /* This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #undef MAX_NAME_COUNT /* This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns. */ #undef MAX_NAME_SIZE /* The value of NEWLINE determines the default newline character sequence. PCRE client programs can override this by selecting other values at run time. In ASCII environments, the value can be 10 (LF), 13 (CR), or 3338 (CRLF); in EBCDIC environments the value can be 21 or 37 (LF), 13 (CR), or 3349 or 3365 (CRLF) because there are two alternative codepoints (0x15 and 0x25) that are used as the NL line terminator that is equivalent to ASCII LF. In both ASCII and EBCDIC environments the value can also be -1 (ANY), or -2 (ANYCRLF). */ #undef NEWLINE /* PCRE uses recursive function calls to handle backtracking while matching. This can sometimes be a problem on systems that have stacks of limited size. Define NO_RECURSE to any value to get a version that doesn't use recursion in the match() function; instead it creates its own stack by steam using pcre_recurse_malloc() to obtain memory from the heap. For more detail, see the comments and other stuff just above the match() function. */ #undef NO_RECURSE /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system stack that is used while compiling a pattern. */ #undef PARENS_NEST_LIMIT /* to make a symbol visible */ #undef PCRECPP_EXP_DECL /* to make a symbol visible */ #undef PCRECPP_EXP_DEFN /* The value of PCREGREP_BUFSIZE determines the size of buffer used by pcregrep to hold parts of the file it is searching. This is also the minimum value. The actual amount of memory used by pcregrep is three times this number, because it allows for the buffering of "before" and "after" lines. */ #undef PCREGREP_BUFSIZE /* to make a symbol visible */ #undef PCREPOSIX_EXP_DECL /* to make a symbol visible */ #undef PCREPOSIX_EXP_DEFN /* to make a symbol visible */ #undef PCRE_EXP_DATA_DEFN /* to make a symbol visible */ #undef PCRE_EXP_DECL /* If you are compiling for a system other than a Unix-like system or Win32, and it needs some magic to be inserted before the definition of a function that is exported by the library, define this macro to contain the relevant magic. If you do not define this macro, a suitable __declspec value is used for Windows systems; in other environments "extern" is used for a C compiler and "extern C" for a C++ compiler. This macro apears at the start of every exported function that is part of the external API. It does not appear on functions that are "external" in the C sense, but which are internal to the library. */ #undef PCRE_EXP_DEFN /* Define to any value if linking statically (TODO: make nice with Libtool) */ #undef PCRE_STATIC /* When calling PCRE via the POSIX interface, additional working storage is required for holding the pointers to capturing substrings because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using malloc() for each call. The threshold above which the stack is no longer used is defined by POSIX_MALLOC_THRESHOLD. */ #undef POSIX_MALLOC_THRESHOLD /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to any value to enable support for Just-In-Time compiling. */ #undef SUPPORT_JIT /* Define to any value to allow pcregrep to be linked with libbz2, so that it is able to handle .bz2 files. */ #undef SUPPORT_LIBBZ2 /* Define to any value to allow pcretest to be linked with libedit. */ #undef SUPPORT_LIBEDIT /* Define to any value to allow pcretest to be linked with libreadline. */ #undef SUPPORT_LIBREADLINE /* Define to any value to allow pcregrep to be linked with libz, so that it is able to handle .gz files. */ #undef SUPPORT_LIBZ /* Define to any value to enable the 16 bit PCRE library. */ #undef SUPPORT_PCRE16 /* Define to any value to enable the 32 bit PCRE library. */ #undef SUPPORT_PCRE32 /* Define to any value to enable the 8 bit PCRE library. */ #undef SUPPORT_PCRE8 /* Define to any value to enable JIT support in pcregrep. */ #undef SUPPORT_PCREGREP_JIT /* Define to any value to enable support for Unicode properties. */ #undef SUPPORT_UCP /* Define to any value to enable support for the UTF-8/16/32 Unicode encoding. This will work even in an EBCDIC environment, but it is incompatible with the EBCDIC macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16/32, but not both at once. */ #undef SUPPORT_UTF /* Define to any value for valgrind support to find invalid memory reads. */ #undef SUPPORT_VALGRIND /* Version number of package */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ #undef int64_t /* Define to `unsigned int' if does not define. */ #undef size_t ================================================ FILE: src/pcre/config.sub ================================================ #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-03-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo "$1" | sed 's/-[^-]*$//'` if [ "$basic_machine" != "$1" ] then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2*) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; nsv-tandem) basic_machine=nsv-tandem ;; nsx-tandem) basic_machine=nsx-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh5el) basic_machine=sh5le-unknown ;; simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; x64) basic_machine=x86_64-pc ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases that might get confused # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # es1800 is here to avoid being matched by es* (a different OS) -es1800*) os=-ose ;; # Now accept the basic system types. # The portable systems comes first. # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -xray | -os68k* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4*) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -pikeos*) # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. case $basic_machine in arm*) os=-eabi ;; *) os=-elf ;; esac ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; pru-*) os=-elf ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac echo "$basic_machine$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: src/pcre/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for PCRE 8.43. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='PCRE' PACKAGE_TARNAME='pcre' PACKAGE_VERSION='8.43' PACKAGE_STRING='PCRE 8.43' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="pcre.h.in" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS WITH_GCOV_FALSE WITH_GCOV_TRUE GCOV_LIBS GCOV_CXXFLAGS GCOV_CFLAGS GENHTML LCOV SHTOOL VALGRIND_LIBS VALGRIND_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG LIBBZ2 LIBZ DISTCHECK_CONFIGURE_FLAGS EXTRA_LIBPCRECPP_LDFLAGS EXTRA_LIBPCREPOSIX_LDFLAGS EXTRA_LIBPCRE32_LDFLAGS EXTRA_LIBPCRE16_LDFLAGS EXTRA_LIBPCRE_LDFLAGS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC ax_pthread_config PCRE_STATIC_CFLAG LIBREADLINE WITH_VALGRIND_FALSE WITH_VALGRIND_TRUE WITH_UTF_FALSE WITH_UTF_TRUE WITH_JIT_FALSE WITH_JIT_TRUE WITH_REBUILD_CHARTABLES_FALSE WITH_REBUILD_CHARTABLES_TRUE WITH_PCRE_CPP_FALSE WITH_PCRE_CPP_TRUE WITH_PCRE32_FALSE WITH_PCRE32_TRUE WITH_PCRE16_FALSE WITH_PCRE16_TRUE WITH_PCRE8_FALSE WITH_PCRE8_TRUE pcre_have_bits_type_traits pcre_have_type_traits pcre_have_ulong_long pcre_have_long_long enable_cpp enable_pcre32 enable_pcre16 enable_pcre8 PCRE_DATE PCRE_PRERELEASE PCRE_MINOR PCRE_MAJOR HAVE_VISIBILITY VISIBILITY_CXXFLAGS VISIBILITY_CFLAGS CXXCPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED LIBTOOL OBJDUMP DLLTOOL AS host_os host_vendor host_cpu host build_os build_vendor build_cpu build EGREP GREP CPP am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC ac_ct_AR AR AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock enable_pcre8 enable_pcre16 enable_pcre32 enable_cpp enable_jit enable_pcregrep_jit enable_rebuild_chartables enable_utf8 enable_utf enable_unicode_properties enable_newline_is_cr enable_newline_is_lf enable_newline_is_crlf enable_newline_is_anycrlf enable_newline_is_any enable_bsr_anycrlf enable_ebcdic enable_ebcdic_nl25 enable_stack_for_recursion enable_pcregrep_libz enable_pcregrep_libbz2 with_pcregrep_bufsize enable_pcretest_libedit enable_pcretest_libreadline with_posix_malloc_threshold with_link_size with_parens_nest_limit with_match_limit with_match_limit_recursion enable_valgrind enable_coverage ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC CPP LT_SYS_LIBRARY_PATH CXXCPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR VALGRIND_CFLAGS VALGRIND_LIBS LCOV GENHTML' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures PCRE 8.43 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/pcre] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of PCRE 8.43:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-pcre8 disable 8 bit character support --enable-pcre16 enable 16 bit character support --enable-pcre32 enable 32 bit character support --disable-cpp disable C++ support --enable-jit enable Just-In-Time compiling support --disable-pcregrep-jit disable JIT support in pcregrep --enable-rebuild-chartables rebuild character tables in current locale --enable-utf8 another name for --enable-utf. Kept only for compatibility reasons --enable-utf enable UTF-8/16/32 support (incompatible with --enable-ebcdic) --enable-unicode-properties enable Unicode properties support (implies --enable-utf) --enable-newline-is-cr use CR as newline character --enable-newline-is-lf use LF as newline character (default) --enable-newline-is-crlf use CRLF as newline sequence --enable-newline-is-anycrlf use CR, LF, or CRLF as newline sequence --enable-newline-is-any use any valid Unicode newline sequence --enable-bsr-anycrlf \R matches only CR, LF, CRLF by default --enable-ebcdic assume EBCDIC coding rather than ASCII; incompatible with --enable-utf; use only in (uncommon) EBCDIC environments; it implies --enable-rebuild-chartables --enable-ebcdic-nl25 set EBCDIC code for NL to 0x25 instead of 0x15; it implies --enable-ebcdic --disable-stack-for-recursion don't use stack recursion when matching --enable-pcregrep-libz link pcregrep with libz to handle .gz files --enable-pcregrep-libbz2 link pcregrep with libbz2 to handle .bz2 files --enable-pcretest-libedit link pcretest with libedit --enable-pcretest-libreadline link pcretest with libreadline --enable-valgrind valgrind support --enable-coverage enable code coverage reports using gcov Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-pcregrep-bufsize=N pcregrep buffer size (default=20480, minimum=8192) --with-posix-malloc-threshold=NBYTES threshold for POSIX malloc usage (default=10) --with-link-size=N internal link size (2, 3, or 4 allowed; default=2) --with-parens-nest-limit=N nested parentheses limit (default=250) --with-match-limit=N default limit on internal looping (default=10000000) --with-match-limit-recursion=N default limit on internal recursion (default=MATCH_LIMIT) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXXCPP C++ preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path VALGRIND_CFLAGS C compiler flags for VALGRIND, overriding pkg-config VALGRIND_LIBS linker flags for VALGRIND, overriding pkg-config LCOV the ltp lcov program GENHTML the ltp genhtml program Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF PCRE configure 8.43 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_find_intX_t LINENO BITS VAR # ----------------------------------- # Finds a signed integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_intX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 $as_echo_n "checking for int$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in int$2_t 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else case $ac_type in #( int$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_intX_t # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES # --------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_cxx_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_mongrel # ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES # --------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_cxx_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_type # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by PCRE $as_me 8.43, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='pcre' VERSION='8.43' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' ac_config_headers="$ac_config_headers config.h" # This is a new thing required to stop a warning from automake 1.12 DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 $as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 $as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} { $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 $as_echo_n "checking the archiver ($AR) interface... " >&6; } if ${am_cv_ar_interface+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 $as_echo "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) as_fn_error $? "could not determine $AR interface" "$LINENO" 5 ;; esac # This was added at the suggestion of libtoolize (03-Jan-10) # The default CFLAGS and CXXFLAGS in Autoconf are "-g -O2" for gcc and just # "-g" for any other compiler. There doesn't seem to be a standard way of # getting rid of the -g (which I don't think is needed for a production # library). This fudge seems to achieve the necessary. First, we remember the # externally set values of CFLAGS and CXXFLAGS. Then call the AC_PROG_CC and # AC_PROG_CXX macros to find the compilers - if CFLAGS and CXXFLAGS are not # set, they will be set to Autoconf's defaults. Afterwards, if the original # values were not set, remove the -g from the Autoconf defaults. # (PH 02-May-07) remember_set_CFLAGS="$CFLAGS" remember_set_CXXFLAGS="$CXXFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi if test "x$remember_set_CFLAGS" = "x" then if test "$CFLAGS" = "-g -O2" then CFLAGS="-O2" elif test "$CFLAGS" = "-g" then CFLAGS="" fi fi if test "x$remember_set_CXXFLAGS" = "x" then if test "$CXXFLAGS" = "-g -O2" then CXXFLAGS="-O2" elif test "$CXXFLAGS" = "-g" then CXXFLAGS="" fi fi # AC_PROG_CXX will return "g++" even if no c++ compiler is installed. # Check for that case, and just disable c++ code if g++ doesn't run. ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else CXX=""; CXXCP=""; CXXFLAGS="" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check for a 64-bit integer type ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" case $ac_cv_c_int64_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int64_t $ac_cv_c_int64_t _ACEOF ;; esac # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="${ac_tool_prefix}as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AS"; then ac_ct_AS=$AS # Extract the first word of "as", so it can be a program name with args. set dummy as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AS"; then ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AS="as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AS=$ac_cv_prog_ac_ct_AS if test -n "$ac_ct_AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 $as_echo "$ac_ct_AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AS" = x; then AS="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AS=$ac_ct_AS fi else AS="$ac_cv_prog_AS" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi ;; esac test -z "$AS" && AS=as test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$OBJDUMP" && OBJDUMP=objdump case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6.42-b88ce' macro_revision='2.4.6.42' ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 $AR $AR_FLAGS libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done func_stripname_cnf () { case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;; esac } # func_stripname_cnf # Set options enable_dlopen=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes file_list_spec='@' ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -z "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC func_cc_basename $compiler cc_basename=$func_cc_basename_result if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec_CXX='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. no_undefined_flag_CXX='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' $wl-bernotok' allow_undefined_flag_CXX=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='$wl--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds_CXX='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else ld_shlibs_CXX=no fi ;; os2*) hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_minus_L_CXX=yes allow_undefined_flag_CXX=unsupported shrext_cmds=.dll archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes file_list_spec_CXX='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='$wl-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' export_dynamic_flag_spec_CXX='$wl--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='$wl-E' whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then no_undefined_flag_CXX=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='$wl-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='$wl-z,text' allow_undefined_flag_CXX='$wl-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='$wl-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no GCC_CXX=$GXX LD_CXX=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX=$prev$p else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX=$prev$p else postdeps_CXX="${postdeps_CXX} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$predep_objects_CXX"; then predep_objects_CXX=$p else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX=$p else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi lt_prog_compiler_pic_CXX='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static_CXX='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test no = "$ld_shlibs_CXX" && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec_CXX='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test yes = "$hardcode_automatic_CXX"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct_CXX" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" && test no != "$hardcode_minus_L_CXX"; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test relink = "$hardcode_action_CXX" || test yes = "$inherit_rpath_CXX"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # Check for GCC visibility feature VISIBILITY_CFLAGS= VISIBILITY_CXXFLAGS= HAVE_VISIBILITY=0 if test -n "$GCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the -Werror option is usable" >&5 $as_echo_n "checking whether the -Werror option is usable... " >&6; } if ${pcre_cv_cc_vis_werror+:} false; then : $as_echo_n "(cached) " >&6 else pcre_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : pcre_cv_cc_vis_werror=yes else pcre_cv_cc_vis_werror=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$pcre_save_CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pcre_cv_cc_vis_werror" >&5 $as_echo "$pcre_cv_cc_vis_werror" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for simple visibility declarations" >&5 $as_echo_n "checking for simple visibility declarations... " >&6; } if ${pcre_cv_cc_visibility+:} false; then : $as_echo_n "(cached) " >&6 else pcre_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fvisibility=hidden" if test $pcre_cv_cc_vis_werror = yes; then CFLAGS="$CFLAGS -Werror" fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern __attribute__((__visibility__("hidden"))) int hiddenvar; extern __attribute__((__visibility__("default"))) int exportedvar; extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); extern __attribute__((__visibility__("default"))) int exportedfunc (void); void dummyfunc (void) {} int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : pcre_cv_cc_visibility=yes else pcre_cv_cc_visibility=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$pcre_save_CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pcre_cv_cc_visibility" >&5 $as_echo "$pcre_cv_cc_visibility" >&6; } if test $pcre_cv_cc_visibility = yes; then VISIBILITY_CFLAGS="-fvisibility=hidden" VISIBILITY_CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" HAVE_VISIBILITY=1 $as_echo "#define PCRE_EXP_DECL extern __attribute__ ((visibility (\"default\")))" >>confdefs.h $as_echo "#define PCRE_EXP_DEFN __attribute__ ((visibility (\"default\")))" >>confdefs.h $as_echo "#define PCRE_EXP_DATA_DEFN __attribute__ ((visibility (\"default\")))" >>confdefs.h $as_echo "#define PCREPOSIX_EXP_DECL extern __attribute__ ((visibility (\"default\")))" >>confdefs.h $as_echo "#define PCREPOSIX_EXP_DEFN extern __attribute__ ((visibility (\"default\")))" >>confdefs.h $as_echo "#define PCRECPP_EXP_DECL extern __attribute__ ((visibility (\"default\")))" >>confdefs.h $as_echo "#define PCRECPP_EXP_DEFN __attribute__ ((visibility (\"default\")))" >>confdefs.h fi fi cat >>confdefs.h <<_ACEOF #define HAVE_VISIBILITY $HAVE_VISIBILITY _ACEOF # Versioning PCRE_MAJOR="8" PCRE_MINOR="43" PCRE_PRERELEASE="" PCRE_DATE="2019-02-23" if test "$PCRE_MINOR" = "08" -o "$PCRE_MINOR" = "09" then echo "***" echo "*** Minor version number $PCRE_MINOR must not be used. ***" echo "*** Use only 01 to 07 or 10 onwards, to avoid octal issues. ***" echo "***" exit 1 fi # Set a more sensible default value for $(htmldir). if test "x$htmldir" = 'x${docdir}' then htmldir='${docdir}/html' fi # Handle --disable-pcre8 (enabled by default) # Check whether --enable-pcre8 was given. if test "${enable_pcre8+set}" = set; then : enableval=$enable_pcre8; else enable_pcre8=unset fi # Handle --enable-pcre16 (disabled by default) # Check whether --enable-pcre16 was given. if test "${enable_pcre16+set}" = set; then : enableval=$enable_pcre16; else enable_pcre16=unset fi # Handle --enable-pcre32 (disabled by default) # Check whether --enable-pcre32 was given. if test "${enable_pcre32+set}" = set; then : enableval=$enable_pcre32; else enable_pcre32=unset fi # Handle --disable-cpp. The substitution of enable_cpp is needed for use in # pcre-config. # Check whether --enable-cpp was given. if test "${enable_cpp+set}" = set; then : enableval=$enable_cpp; else enable_cpp=unset fi # Handle --enable-jit (disabled by default) # Check whether --enable-jit was given. if test "${enable_jit+set}" = set; then : enableval=$enable_jit; else enable_jit=no fi # This code enables JIT if the hardware supports it. if test "$enable_jit" = "auto"; then ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define SLJIT_CONFIG_AUTO 1 #include "sljit/sljitConfigInternal.h" #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #error unsupported #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : enable_jit=yes else enable_jit=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # Handle --disable-pcregrep-jit (enabled by default) # Check whether --enable-pcregrep-jit was given. if test "${enable_pcregrep_jit+set}" = set; then : enableval=$enable_pcregrep_jit; else enable_pcregrep_jit=yes fi # Handle --enable-rebuild-chartables # Check whether --enable-rebuild-chartables was given. if test "${enable_rebuild_chartables+set}" = set; then : enableval=$enable_rebuild_chartables; else enable_rebuild_chartables=no fi # Handle --enable-utf8 (disabled by default) # Check whether --enable-utf8 was given. if test "${enable_utf8+set}" = set; then : enableval=$enable_utf8; else enable_utf8=unset fi # Handle --enable-utf (disabled by default) # Check whether --enable-utf was given. if test "${enable_utf+set}" = set; then : enableval=$enable_utf; else enable_utf=unset fi # Handle --enable-unicode-properties # Check whether --enable-unicode-properties was given. if test "${enable_unicode_properties+set}" = set; then : enableval=$enable_unicode_properties; else enable_unicode_properties=no fi # Handle newline options ac_pcre_newline=lf # Check whether --enable-newline-is-cr was given. if test "${enable_newline_is_cr+set}" = set; then : enableval=$enable_newline_is_cr; ac_pcre_newline=cr fi # Check whether --enable-newline-is-lf was given. if test "${enable_newline_is_lf+set}" = set; then : enableval=$enable_newline_is_lf; ac_pcre_newline=lf fi # Check whether --enable-newline-is-crlf was given. if test "${enable_newline_is_crlf+set}" = set; then : enableval=$enable_newline_is_crlf; ac_pcre_newline=crlf fi # Check whether --enable-newline-is-anycrlf was given. if test "${enable_newline_is_anycrlf+set}" = set; then : enableval=$enable_newline_is_anycrlf; ac_pcre_newline=anycrlf fi # Check whether --enable-newline-is-any was given. if test "${enable_newline_is_any+set}" = set; then : enableval=$enable_newline_is_any; ac_pcre_newline=any fi enable_newline="$ac_pcre_newline" # Handle --enable-bsr-anycrlf # Check whether --enable-bsr-anycrlf was given. if test "${enable_bsr_anycrlf+set}" = set; then : enableval=$enable_bsr_anycrlf; else enable_bsr_anycrlf=no fi # Handle --enable-ebcdic # Check whether --enable-ebcdic was given. if test "${enable_ebcdic+set}" = set; then : enableval=$enable_ebcdic; else enable_ebcdic=no fi # Handle --enable-ebcdic-nl25 # Check whether --enable-ebcdic-nl25 was given. if test "${enable_ebcdic_nl25+set}" = set; then : enableval=$enable_ebcdic_nl25; else enable_ebcdic_nl25=no fi # Handle --disable-stack-for-recursion # Check whether --enable-stack-for-recursion was given. if test "${enable_stack_for_recursion+set}" = set; then : enableval=$enable_stack_for_recursion; else enable_stack_for_recursion=yes fi # Handle --enable-pcregrep-libz # Check whether --enable-pcregrep-libz was given. if test "${enable_pcregrep_libz+set}" = set; then : enableval=$enable_pcregrep_libz; else enable_pcregrep_libz=no fi # Handle --enable-pcregrep-libbz2 # Check whether --enable-pcregrep-libbz2 was given. if test "${enable_pcregrep_libbz2+set}" = set; then : enableval=$enable_pcregrep_libbz2; else enable_pcregrep_libbz2=no fi # Handle --with-pcregrep-bufsize=N # Check whether --with-pcregrep-bufsize was given. if test "${with_pcregrep_bufsize+set}" = set; then : withval=$with_pcregrep_bufsize; else with_pcregrep_bufsize=20480 fi # Handle --enable-pcretest-libedit # Check whether --enable-pcretest-libedit was given. if test "${enable_pcretest_libedit+set}" = set; then : enableval=$enable_pcretest_libedit; else enable_pcretest_libedit=no fi # Handle --enable-pcretest-libreadline # Check whether --enable-pcretest-libreadline was given. if test "${enable_pcretest_libreadline+set}" = set; then : enableval=$enable_pcretest_libreadline; else enable_pcretest_libreadline=no fi # Handle --with-posix-malloc-threshold=NBYTES # Check whether --with-posix-malloc-threshold was given. if test "${with_posix_malloc_threshold+set}" = set; then : withval=$with_posix_malloc_threshold; else with_posix_malloc_threshold=10 fi # Handle --with-link-size=N # Check whether --with-link-size was given. if test "${with_link_size+set}" = set; then : withval=$with_link_size; else with_link_size=2 fi # Handle --with-parens-nest-limit=N # Check whether --with-parens-nest-limit was given. if test "${with_parens_nest_limit+set}" = set; then : withval=$with_parens_nest_limit; else with_parens_nest_limit=250 fi # Handle --with-match-limit=N # Check whether --with-match-limit was given. if test "${with_match_limit+set}" = set; then : withval=$with_match_limit; else with_match_limit=10000000 fi # Handle --with-match-limit_recursion=N # # Note: In config.h, the default is to define MATCH_LIMIT_RECURSION # symbolically as MATCH_LIMIT, which in turn is defined to be some numeric # value (e.g. 10000000). MATCH_LIMIT_RECURSION can otherwise be set to some # different numeric value (or even the same numeric value as MATCH_LIMIT, # though no longer defined in terms of the latter). # # Check whether --with-match-limit-recursion was given. if test "${with_match_limit_recursion+set}" = set; then : withval=$with_match_limit_recursion; else with_match_limit_recursion=MATCH_LIMIT fi # Handle --enable-valgrind # Check whether --enable-valgrind was given. if test "${enable_valgrind+set}" = set; then : enableval=$enable_valgrind; else enable_valgrind=no fi # Enable code coverage reports using gcov # Check whether --enable-coverage was given. if test "${enable_coverage+set}" = set; then : enableval=$enable_coverage; else enable_coverage=no fi # Copy enable_utf8 value to enable_utf for compatibility reasons if test "x$enable_utf8" != "xunset" then if test "x$enable_utf" != "xunset" then as_fn_error $? "--enable/disable-utf8 is kept only for compatibility reasons and its value is copied to --enable/disable-utf. Newer code must use --enable/disable-utf alone." "$LINENO" 5 fi enable_utf=$enable_utf8 fi # Set the default value for pcre8 if test "x$enable_pcre8" = "xunset" then enable_pcre8=yes fi # Set the default value for pcre16 if test "x$enable_pcre16" = "xunset" then enable_pcre16=no fi # Set the default value for pcre32 if test "x$enable_pcre32" = "xunset" then enable_pcre32=no fi # Make sure enable_pcre8 or enable_pcre16 was set if test "x$enable_pcre8$enable_pcre16$enable_pcre32" = "xnonono" then as_fn_error $? "At least one of 8, 16 or 32 bit pcre library must be enabled" "$LINENO" 5 fi # Make sure that if enable_unicode_properties was set, that UTF support is enabled. if test "x$enable_unicode_properties" = "xyes" then if test "x$enable_utf" = "xno" then as_fn_error $? "support for Unicode properties requires UTF-8/16/32 support" "$LINENO" 5 fi enable_utf=yes fi # enable_utf is disabled by default. if test "x$enable_utf" = "xunset" then enable_utf=no fi # enable_cpp copies the value of enable_pcre8 by default if test "x$enable_cpp" = "xunset" then enable_cpp=$enable_pcre8 fi # Make sure that if enable_cpp was set, that enable_pcre8 support is enabled if test "x$enable_cpp" = "xyes" then if test "x$enable_pcre8" = "xno" then as_fn_error $? "C++ library requires pcre library with 8 bit characters" "$LINENO" 5 fi fi # Convert the newline identifier into the appropriate integer value. The first # three are ASCII values 0x0a, 0x0d, and 0x0d0a, but if EBCDIC is enabled, they # are changed below. case "$enable_newline" in lf) ac_pcre_newline_value=10 ;; cr) ac_pcre_newline_value=13 ;; crlf) ac_pcre_newline_value=3338 ;; anycrlf) ac_pcre_newline_value=-2 ;; any) ac_pcre_newline_value=-1 ;; *) as_fn_error $? "invalid argument \"$enable_newline\" to --enable-newline option" "$LINENO" 5 ;; esac # --enable-ebcdic-nl25 implies --enable-ebcdic if test "x$enable_ebcdic_nl25" = "xyes"; then enable_ebcdic=yes fi # Make sure that if enable_ebcdic is set, rebuild_chartables is also enabled, # and the newline value is adjusted appropriately (CR is still 13, but LF is # 21 or 37). Also check that UTF support is not requested, because PCRE cannot # handle EBCDIC and UTF in the same build. To do so it would need to use # different character constants depending on the mode. # if test "x$enable_ebcdic" = "xyes"; then enable_rebuild_chartables=yes if test "x$enable_utf" = "xyes"; then as_fn_error $? "support for EBCDIC and UTF-8/16/32 cannot be enabled at the same time" "$LINENO" 5 fi if test "x$enable_ebcdic_nl25" = "xno"; then case "$ac_pcre_newline_value" in 10) ac_pcre_newline_value=21 ;; 3338) ac_pcre_newline_value=3349 ;; esac else case "$ac_pcre_newline_value" in 10) ac_pcre_newline_value=37 ;; 3338) ac_pcre_newline_value=3365 ;; esac fi fi # Check argument to --with-link-size case "$with_link_size" in 2|3|4) ;; *) as_fn_error $? "invalid argument \"$with_link_size\" to --with-link-size option" "$LINENO" 5 ;; esac # Checks for header files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in limits.h sys/types.h sys/stat.h dirent.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in windows.h do : ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" if test "x$ac_cv_header_windows_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_WINDOWS_H 1 _ACEOF HAVE_WINDOWS_H=1 fi done # The files below are C++ header files. pcre_have_type_traits="0" pcre_have_bits_type_traits="0" if test "x$enable_cpp" = "xyes" -a -z "$CXX"; then as_fn_error $? "Invalid C++ compiler or C++ compiler flags" "$LINENO" 5 fi if test "x$enable_cpp" = "xyes" -a -n "$CXX" then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # Older versions of pcre defined pcrecpp::no_arg, but in new versions # it's called pcrecpp::RE::no_arg. For backwards ABI compatibility, # we want to make one an alias for the other. Different systems do # this in different ways. Some systems, for instance, can do it via # a linker flag: -alias (for os x 10.5) or -i (for os x <=10.4). OLD_LDFLAGS="$LDFLAGS" for flag in "-alias,__ZN7pcrecpp2RE6no_argE,__ZN7pcrecpp6no_argE" \ "-i__ZN7pcrecpp6no_argE:__ZN7pcrecpp2RE6no_argE"; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alias support in the linker" >&5 $as_echo_n "checking for alias support in the linker... " >&6; } LDFLAGS="$OLD_LDFLAGS -Wl,$flag" # We try to run the linker with this new ld flag. If the link fails, # we give up and remove the new flag from LDFLAGS. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ namespace pcrecpp { class RE { static int no_arg; }; int RE::no_arg; } int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; EXTRA_LIBPCRECPP_LDFLAGS="$EXTRA_LIBPCRECPP_LDFLAGS -Wl,$flag"; break; else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done LDFLAGS="$OLD_LDFLAGS" # We could be more clever here, given we're doing AC_SUBST with this # (eg set a var to be the name of the include file we want). But we're not # so it's easy to change back to 'regular' autoconf vars if we needed to. for ac_header in string do : ac_fn_cxx_check_header_mongrel "$LINENO" "string" "ac_cv_header_string" "$ac_includes_default" if test "x$ac_cv_header_string" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRING 1 _ACEOF pcre_have_cpp_headers="1" else pcre_have_cpp_headers="0" fi done for ac_header in bits/type_traits.h do : ac_fn_cxx_check_header_mongrel "$LINENO" "bits/type_traits.h" "ac_cv_header_bits_type_traits_h" "$ac_includes_default" if test "x$ac_cv_header_bits_type_traits_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BITS_TYPE_TRAITS_H 1 _ACEOF pcre_have_bits_type_traits="1" else pcre_have_bits_type_traits="0" fi done for ac_header in type_traits.h do : ac_fn_cxx_check_header_mongrel "$LINENO" "type_traits.h" "ac_cv_header_type_traits_h" "$ac_includes_default" if test "x$ac_cv_header_type_traits_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TYPE_TRAITS_H 1 _ACEOF pcre_have_type_traits="1" else pcre_have_type_traits="0" fi done # (This isn't c++-specific, but is only used in pcrecpp.cc, so try this # in a c++ context. This matters becuase strtoimax is C99 and may not # be supported by the C++ compiler.) # Figure out how to create a longlong from a string: strtoll and # equiv. It's not enough to call AC_CHECK_FUNCS: hpux has a # strtoll, for instance, but it only takes 2 args instead of 3! # We have to call AH_TEMPLATE since AC_DEFINE_UNQUOTED below is complex. have_strto_fn=0 for fn in strtoq strtoll _strtoi64 strtoimax; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $fn" >&5 $as_echo_n "checking for $fn... " >&6; } if test "$fn" = strtoimax; then include=stdint.h else include=stdlib.h fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$include> int main () { char* e; return $fn("100", &e, 10) ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_`echo $fn | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` 1 _ACEOF have_strto_fn=1 break else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done if test "$have_strto_fn" = 1; then ac_fn_cxx_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" if test "x$ac_cv_type_long_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LONG_LONG 1 _ACEOF pcre_have_long_long="1" else pcre_have_long_long="0" fi ac_fn_cxx_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default" if test "x$ac_cv_type_unsigned_long_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UNSIGNED_LONG_LONG 1 _ACEOF pcre_have_ulong_long="1" else pcre_have_ulong_long="0" fi else pcre_have_long_long="0" pcre_have_ulong_long="0" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi # Using AC_SUBST eliminates the need to include config.h in a public .h file # Conditional compilation if test "x$enable_pcre8" = "xyes"; then WITH_PCRE8_TRUE= WITH_PCRE8_FALSE='#' else WITH_PCRE8_TRUE='#' WITH_PCRE8_FALSE= fi if test "x$enable_pcre16" = "xyes"; then WITH_PCRE16_TRUE= WITH_PCRE16_FALSE='#' else WITH_PCRE16_TRUE='#' WITH_PCRE16_FALSE= fi if test "x$enable_pcre32" = "xyes"; then WITH_PCRE32_TRUE= WITH_PCRE32_FALSE='#' else WITH_PCRE32_TRUE='#' WITH_PCRE32_FALSE= fi if test "x$enable_cpp" = "xyes"; then WITH_PCRE_CPP_TRUE= WITH_PCRE_CPP_FALSE='#' else WITH_PCRE_CPP_TRUE='#' WITH_PCRE_CPP_FALSE= fi if test "x$enable_rebuild_chartables" = "xyes"; then WITH_REBUILD_CHARTABLES_TRUE= WITH_REBUILD_CHARTABLES_FALSE='#' else WITH_REBUILD_CHARTABLES_TRUE='#' WITH_REBUILD_CHARTABLES_FALSE= fi if test "x$enable_jit" = "xyes"; then WITH_JIT_TRUE= WITH_JIT_FALSE='#' else WITH_JIT_TRUE='#' WITH_JIT_FALSE= fi if test "x$enable_utf" = "xyes"; then WITH_UTF_TRUE= WITH_UTF_FALSE='#' else WITH_UTF_TRUE='#' WITH_UTF_FALSE= fi if test "x$enable_valgrind" = "xyes"; then WITH_VALGRIND_TRUE= WITH_VALGRIND_FALSE='#' else WITH_VALGRIND_TRUE='#' WITH_VALGRIND_FALSE= fi # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi # Checks for library functions. for ac_func in bcopy memmove strerror do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Check for the availability of libz (aka zlib) for ac_header in zlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ZLIB_H 1 _ACEOF HAVE_ZLIB_H=1 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5 $as_echo_n "checking for gzopen in -lz... " >&6; } if ${ac_cv_lib_z_gzopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gzopen (); int main () { return gzopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_gzopen=yes else ac_cv_lib_z_gzopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzopen" >&5 $as_echo "$ac_cv_lib_z_gzopen" >&6; } if test "x$ac_cv_lib_z_gzopen" = xyes; then : HAVE_LIBZ=1 fi # Check for the availability of libbz2. Originally we just used AC_CHECK_LIB, # as for libz. However, this had the following problem, diagnosed and fixed by # a user: # # - libbz2 uses the Pascal calling convention (WINAPI) for the functions # under Win32. # - The standard autoconf AC_CHECK_LIB fails to include "bzlib.h", # therefore missing the function definition. # - The compiler thus generates a "C" signature for the test function. # - The linker fails to find the "C" function. # - PCRE fails to configure if asked to do so against libbz2. # # Solution: # # - Replace the AC_CHECK_LIB test with a custom test. for ac_header in bzlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default" if test "x$ac_cv_header_bzlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BZLIB_H 1 _ACEOF HAVE_BZLIB_H=1 fi done # Original test # AC_CHECK_LIB([bz2], [BZ2_bzopen], [HAVE_LIBBZ2=1]) # # Custom test follows { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libbz2" >&5 $as_echo_n "checking for libbz2... " >&6; } OLD_LIBS="$LIBS" LIBS="$LIBS -lbz2" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_BZLIB_H #include #endif int main () { return (int)BZ2_bzopen("conftest", "rb"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; };HAVE_LIBBZ2=1; break; else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$OLD_LIBS" # Check for the availabiity of libreadline if test "$enable_pcretest_libreadline" = "yes"; then for ac_header in readline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_readline_readline_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_READLINE_READLINE_H 1 _ACEOF HAVE_READLINE_H=1 fi done for ac_header in readline/history.h do : ac_fn_c_check_header_mongrel "$LINENO" "readline/history.h" "ac_cv_header_readline_history_h" "$ac_includes_default" if test "x$ac_cv_header_readline_history_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_READLINE_HISTORY_H 1 _ACEOF HAVE_HISTORY_H=1 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : LIBREADLINE="-lreadline" else unset ac_cv_lib_readline_readline; { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline -ltinfo $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : LIBREADLINE="-ltinfo" else unset ac_cv_lib_readline_readline; { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline -lcurses $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : LIBREADLINE="-lcurses" else unset ac_cv_lib_readline_readline; { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline -lncurses $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : LIBREADLINE="-lncurses" else unset ac_cv_lib_readline_readline; { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline -lncursesw $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : LIBREADLINE="-lncursesw" else unset ac_cv_lib_readline_readline; { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline -ltermcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : LIBREADLINE="-ltermcap" else LIBREADLINE="" fi fi fi fi fi fi if test -n "$LIBREADLINE"; then if test "$LIBREADLINE" != "-lreadline"; then echo "-lreadline needs $LIBREADLINE" LIBREADLINE="-lreadline $LIBREADLINE" fi fi fi # Check for the availability of libedit. Different distributions put its # headers in different places. Try to cover the most common ones. if test "$enable_pcretest_libedit" = "yes"; then for ac_header in editline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "editline/readline.h" "ac_cv_header_editline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_editline_readline_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EDITLINE_READLINE_H 1 _ACEOF HAVE_EDITLINE_READLINE_H=1 else for ac_header in edit/readline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "edit/readline/readline.h" "ac_cv_header_edit_readline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_edit_readline_readline_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EDIT_READLINE_READLINE_H 1 _ACEOF HAVE_READLINE_READLINE_H=1 else for ac_header in readline/readline.h do : ac_fn_c_check_header_mongrel "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default" if test "x$ac_cv_header_readline_readline_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_READLINE_READLINE_H 1 _ACEOF HAVE_READLINE_READLINE_H=1 fi done fi done fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -ledit" >&5 $as_echo_n "checking for readline in -ledit... " >&6; } if ${ac_cv_lib_edit_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ledit $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_edit_readline=yes else ac_cv_lib_edit_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_readline" >&5 $as_echo "$ac_cv_lib_edit_readline" >&6; } if test "x$ac_cv_lib_edit_readline" = xyes; then : LIBEDIT="-ledit" fi fi # This facilitates -ansi builds under Linux PCRE_STATIC_CFLAG="" if test "x$enable_shared" = "xno" ; then $as_echo "#define PCRE_STATIC 1" >>confdefs.h PCRE_STATIC_CFLAG="-DPCRE_STATIC" fi # Here is where pcre specific defines are handled if test "$enable_pcre8" = "yes"; then $as_echo "#define SUPPORT_PCRE8 /**/" >>confdefs.h fi if test "$enable_pcre16" = "yes"; then $as_echo "#define SUPPORT_PCRE16 /**/" >>confdefs.h fi if test "$enable_pcre32" = "yes"; then $as_echo "#define SUPPORT_PCRE32 /**/" >>confdefs.h fi # Unless running under Windows, JIT support requires pthreads. if test "$enable_jit" = "yes"; then if test "$HAVE_WINDOWS_H" != "1"; then ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 $as_echo "$ax_pthread_ok" >&6; } if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case ${host_os} in solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ax_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ax_pthread_config"; then ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ax_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" fi fi ax_pthread_config=$ac_cv_prog_ax_pthread_config if test -n "$ax_pthread_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 $as_echo "$ax_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; } int main () { pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 $as_echo "$ax_pthread_ok" >&6; } if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr = $attr; return attr /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : attr_name=$attr; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 $as_echo "$attr_name" >&6; } if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then cat >>confdefs.h <<_ACEOF #define PTHREAD_CREATE_JOINABLE $attr_name _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case ${host_os} in aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; osf* | hpux*) flag="-D_REENTRANT";; solaris*) if test "$GCC" = "yes"; then flag="-D_REENTRANT" else flag="-mt -D_REENTRANT" fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 $as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int i = PTHREAD_PRIO_INHERIT; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_PTHREAD_PRIO_INHERIT=yes else ax_cv_PTHREAD_PRIO_INHERIT=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 $as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then : $as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then for ac_prog in xlc_r cc_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h : else ax_pthread_ok=no as_fn_error $? "JIT support requires pthreads" "$LINENO" 5 fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$PTHREAD_CC" CFLAGS="$PTHREAD_CFLAGS $CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" fi $as_echo "#define SUPPORT_JIT /**/" >>confdefs.h else enable_pcregrep_jit="no" fi if test "$enable_pcregrep_jit" = "yes"; then $as_echo "#define SUPPORT_PCREGREP_JIT /**/" >>confdefs.h fi if test "$enable_utf" = "yes"; then $as_echo "#define SUPPORT_UTF /**/" >>confdefs.h fi if test "$enable_unicode_properties" = "yes"; then $as_echo "#define SUPPORT_UCP /**/" >>confdefs.h fi if test "$enable_stack_for_recursion" = "no"; then $as_echo "#define NO_RECURSE /**/" >>confdefs.h fi if test "$enable_pcregrep_libz" = "yes"; then $as_echo "#define SUPPORT_LIBZ /**/" >>confdefs.h fi if test "$enable_pcregrep_libbz2" = "yes"; then $as_echo "#define SUPPORT_LIBBZ2 /**/" >>confdefs.h fi if test $with_pcregrep_bufsize -lt 8192 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $with_pcregrep_bufsize is too small for --with-pcregrep-bufsize; using 8192" >&5 $as_echo "$as_me: WARNING: $with_pcregrep_bufsize is too small for --with-pcregrep-bufsize; using 8192" >&2;} with_pcregrep_bufsize="8192" else if test $? -gt 1 ; then as_fn_error $? "Bad value for --with-pcregrep-bufsize" "$LINENO" 5 fi fi cat >>confdefs.h <<_ACEOF #define PCREGREP_BUFSIZE $with_pcregrep_bufsize _ACEOF if test "$enable_pcretest_libedit" = "yes"; then $as_echo "#define SUPPORT_LIBEDIT /**/" >>confdefs.h LIBREADLINE="$LIBEDIT" elif test "$enable_pcretest_libreadline" = "yes"; then $as_echo "#define SUPPORT_LIBREADLINE /**/" >>confdefs.h fi cat >>confdefs.h <<_ACEOF #define NEWLINE $ac_pcre_newline_value _ACEOF if test "$enable_bsr_anycrlf" = "yes"; then $as_echo "#define BSR_ANYCRLF /**/" >>confdefs.h fi cat >>confdefs.h <<_ACEOF #define LINK_SIZE $with_link_size _ACEOF cat >>confdefs.h <<_ACEOF #define POSIX_MALLOC_THRESHOLD $with_posix_malloc_threshold _ACEOF cat >>confdefs.h <<_ACEOF #define PARENS_NEST_LIMIT $with_parens_nest_limit _ACEOF cat >>confdefs.h <<_ACEOF #define MATCH_LIMIT $with_match_limit _ACEOF cat >>confdefs.h <<_ACEOF #define MATCH_LIMIT_RECURSION $with_match_limit_recursion _ACEOF $as_echo "#define MAX_NAME_SIZE 32" >>confdefs.h $as_echo "#define MAX_NAME_COUNT 10000" >>confdefs.h if test "$enable_ebcdic" = "yes"; then cat >>confdefs.h <<_ACEOF #define EBCDIC /**/ _ACEOF fi if test "$enable_ebcdic_nl25" = "yes"; then cat >>confdefs.h <<_ACEOF #define EBCDIC_NL25 /**/ _ACEOF fi if test "$enable_valgrind" = "yes"; then cat >>confdefs.h <<_ACEOF #define SUPPORT_VALGRIND /**/ _ACEOF fi # Platform specific issues NO_UNDEFINED= EXPORT_ALL_SYMBOLS= case $host_os in cygwin* | mingw* ) if test X"$enable_shared" = Xyes; then NO_UNDEFINED="-no-undefined" EXPORT_ALL_SYMBOLS="-Wl,--export-all-symbols" fi ;; esac # The extra LDFLAGS for each particular library # (Note: The libpcre*_version bits are m4 variables, assigned above) EXTRA_LIBPCRE_LDFLAGS="$EXTRA_LIBPCRE_LDFLAGS \ $NO_UNDEFINED -version-info 3:11:2" EXTRA_LIBPCRE16_LDFLAGS="$EXTRA_LIBPCRE16_LDFLAGS \ $NO_UNDEFINED -version-info 2:11:2" EXTRA_LIBPCRE32_LDFLAGS="$EXTRA_LIBPCRE32_LDFLAGS \ $NO_UNDEFINED -version-info 0:11:0" EXTRA_LIBPCREPOSIX_LDFLAGS="$EXTRA_LIBPCREPOSIX_LDFLAGS \ $NO_UNDEFINED -version-info 0:6:0" EXTRA_LIBPCRECPP_LDFLAGS="$EXTRA_LIBPCRECPP_LDFLAGS \ $NO_UNDEFINED -version-info 0:1:0 \ $EXPORT_ALL_SYMBOLS" # When we run 'make distcheck', use these arguments. Turning off compiler # optimization makes it run faster. DISTCHECK_CONFIGURE_FLAGS="CFLAGS='' CXXFLAGS='' --enable-pcre16 --enable-pcre32 --enable-jit --enable-cpp --enable-unicode-properties" # Check that, if --enable-pcregrep-libz or --enable-pcregrep-libbz2 is # specified, the relevant library is available. if test "$enable_pcregrep_libz" = "yes"; then if test "$HAVE_ZLIB_H" != "1"; then echo "** Cannot --enable-pcregrep-libz because zlib.h was not found" exit 1 fi if test "$HAVE_LIBZ" != "1"; then echo "** Cannot --enable-pcregrep-libz because libz was not found" exit 1 fi LIBZ="-lz" fi if test "$enable_pcregrep_libbz2" = "yes"; then if test "$HAVE_BZLIB_H" != "1"; then echo "** Cannot --enable-pcregrep-libbz2 because bzlib.h was not found" exit 1 fi if test "$HAVE_LIBBZ2" != "1"; then echo "** Cannot --enable-pcregrep-libbz2 because libbz2 was not found" exit 1 fi LIBBZ2="-lbz2" fi # Similarly for --enable-pcretest-readline if test "$enable_pcretest_libedit" = "yes"; then if test "$enable_pcretest_libreadline" = "yes"; then echo "** Cannot use both --enable-pcretest-libedit and --enable-pcretest-readline" exit 1 fi if test "$HAVE_EDITLINE_READLINE_H" != "1" -a \ "$HAVE_READLINE_READLINE_H" != "1"; then echo "** Cannot --enable-pcretest-libedit because neither editline/readline.h" echo "** nor readline/readline.h was found." exit 1 fi if test -z "$LIBEDIT"; then echo "** Cannot --enable-pcretest-libedit because libedit library was not found." exit 1 fi fi if test "$enable_pcretest_libreadline" = "yes"; then if test "$HAVE_READLINE_H" != "1"; then echo "** Cannot --enable-pcretest-readline because readline/readline.h was not found." exit 1 fi if test "$HAVE_HISTORY_H" != "1"; then echo "** Cannot --enable-pcretest-readline because readline/history.h was not found." exit 1 fi if test -z "$LIBREADLINE"; then echo "** Cannot --enable-pcretest-readline because readline library was not found." exit 1 fi fi # Handle valgrind support if test "$enable_valgrind" = "yes"; then if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND" >&5 $as_echo_n "checking for VALGRIND... " >&6; } if test -n "$VALGRIND_CFLAGS"; then pkg_cv_VALGRIND_CFLAGS="$VALGRIND_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind\""; } >&5 ($PKG_CONFIG --exists --print-errors "valgrind") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_VALGRIND_CFLAGS=`$PKG_CONFIG --cflags "valgrind" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$VALGRIND_LIBS"; then pkg_cv_VALGRIND_LIBS="$VALGRIND_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind\""; } >&5 ($PKG_CONFIG --exists --print-errors "valgrind") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_VALGRIND_LIBS=`$PKG_CONFIG --libs "valgrind" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then VALGRIND_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "valgrind" 2>&1` else VALGRIND_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "valgrind" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$VALGRIND_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (valgrind) were not met: $VALGRIND_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables VALGRIND_CFLAGS and VALGRIND_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables VALGRIND_CFLAGS and VALGRIND_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else VALGRIND_CFLAGS=$pkg_cv_VALGRIND_CFLAGS VALGRIND_LIBS=$pkg_cv_VALGRIND_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi # Handle code coverage reporting support if test "$enable_coverage" = "yes"; then if test "x$GCC" != "xyes"; then as_fn_error $? "Code coverage reports can only be generated when using GCC" "$LINENO" 5 fi # ccache is incompatible with gcov # Extract the first word of "shtool", so it can be a program name with args. set dummy shtool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SHTOOL+:} false; then : $as_echo_n "(cached) " >&6 else case $SHTOOL in [\\/]* | ?:[\\/]*) ac_cv_path_SHTOOL="$SHTOOL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SHTOOL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_SHTOOL" && ac_cv_path_SHTOOL="false" ;; esac fi SHTOOL=$ac_cv_path_SHTOOL if test -n "$SHTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHTOOL" >&5 $as_echo "$SHTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi case `$SHTOOL path $CC` in *ccache*) cc_ccache=yes;; *) cc_ccache=no;; esac if test "$cc_ccache" = "yes"; then if test -z "$CCACHE_DISABLE" -o "$CCACHE_DISABLE" != "1"; then as_fn_error $? "must export CCACHE_DISABLE=1 to disable ccache for code coverage" "$LINENO" 5 fi fi # Extract the first word of "lcov", so it can be a program name with args. set dummy lcov; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LCOV+:} false; then : $as_echo_n "(cached) " >&6 else case $LCOV in [\\/]* | ?:[\\/]*) ac_cv_path_LCOV="$LCOV" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LCOV="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_LCOV" && ac_cv_path_LCOV="false" ;; esac fi LCOV=$ac_cv_path_LCOV if test -n "$LCOV"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LCOV" >&5 $as_echo "$LCOV" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$LCOV" = "xfalse"; then as_fn_error $? "lcov not found" "$LINENO" 5 fi # Extract the first word of "genhtml", so it can be a program name with args. set dummy genhtml; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GENHTML+:} false; then : $as_echo_n "(cached) " >&6 else case $GENHTML in [\\/]* | ?:[\\/]*) ac_cv_path_GENHTML="$GENHTML" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GENHTML="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GENHTML" && ac_cv_path_GENHTML="false" ;; esac fi GENHTML=$ac_cv_path_GENHTML if test -n "$GENHTML"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GENHTML" >&5 $as_echo "$GENHTML" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$GENHTML" = "xfalse"; then as_fn_error $? "genhtml not found" "$LINENO" 5 fi # Set flags needed for gcov GCOV_CFLAGS="-O0 -ggdb3 -fprofile-arcs -ftest-coverage" GCOV_CXXFLAGS="-O0 -ggdb3 -fprofile-arcs -ftest-coverage" GCOV_LIBS="-lgcov" fi # enable_coverage if test "x$enable_coverage" = "xyes"; then WITH_GCOV_TRUE= WITH_GCOV_FALSE='#' else WITH_GCOV_TRUE='#' WITH_GCOV_FALSE= fi # Produce these files, in addition to config.h. ac_config_files="$ac_config_files Makefile libpcre.pc libpcre16.pc libpcre32.pc libpcreposix.pc libpcrecpp.pc pcre-config pcre.h pcre_stringpiece.h pcrecpparg.h" # Make the generated script files executable. ac_config_commands="$ac_config_commands script-chmod" # Make sure that pcre_chartables.c is removed in case the method for # creating it was changed by reconfiguration. ac_config_commands="$ac_config_commands delete-old-chartables" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_PCRE8_TRUE}" && test -z "${WITH_PCRE8_FALSE}"; then as_fn_error $? "conditional \"WITH_PCRE8\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_PCRE16_TRUE}" && test -z "${WITH_PCRE16_FALSE}"; then as_fn_error $? "conditional \"WITH_PCRE16\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_PCRE32_TRUE}" && test -z "${WITH_PCRE32_FALSE}"; then as_fn_error $? "conditional \"WITH_PCRE32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_PCRE_CPP_TRUE}" && test -z "${WITH_PCRE_CPP_FALSE}"; then as_fn_error $? "conditional \"WITH_PCRE_CPP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_REBUILD_CHARTABLES_TRUE}" && test -z "${WITH_REBUILD_CHARTABLES_FALSE}"; then as_fn_error $? "conditional \"WITH_REBUILD_CHARTABLES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_JIT_TRUE}" && test -z "${WITH_JIT_FALSE}"; then as_fn_error $? "conditional \"WITH_JIT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_UTF_TRUE}" && test -z "${WITH_UTF_FALSE}"; then as_fn_error $? "conditional \"WITH_UTF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_VALGRIND_TRUE}" && test -z "${WITH_VALGRIND_FALSE}"; then as_fn_error $? "conditional \"WITH_VALGRIND\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_GCOV_TRUE}" && test -z "${WITH_GCOV_FALSE}"; then as_fn_error $? "conditional \"WITH_GCOV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by PCRE $as_me 8.43, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ PCRE config.status 8.43 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in AS \ DLLTOOL \ OBJDUMP \ SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ sharedlib_from_linklib_cmd \ AR \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "libpcre.pc") CONFIG_FILES="$CONFIG_FILES libpcre.pc" ;; "libpcre16.pc") CONFIG_FILES="$CONFIG_FILES libpcre16.pc" ;; "libpcre32.pc") CONFIG_FILES="$CONFIG_FILES libpcre32.pc" ;; "libpcreposix.pc") CONFIG_FILES="$CONFIG_FILES libpcreposix.pc" ;; "libpcrecpp.pc") CONFIG_FILES="$CONFIG_FILES libpcrecpp.pc" ;; "pcre-config") CONFIG_FILES="$CONFIG_FILES pcre-config" ;; "pcre.h") CONFIG_FILES="$CONFIG_FILES pcre.h" ;; "pcre_stringpiece.h") CONFIG_FILES="$CONFIG_FILES pcre_stringpiece.h" ;; "pcrecpparg.h") CONFIG_FILES="$CONFIG_FILES pcrecpparg.h" ;; "script-chmod") CONFIG_COMMANDS="$CONFIG_COMMANDS script-chmod" ;; "delete-old-chartables") CONFIG_COMMANDS="$CONFIG_COMMANDS delete-old-chartables" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. Try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='CXX ' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Assembler program. AS=$lt_AS # DLL creation program. DLLTOOL=$lt_DLLTOOL # Object dumper program. OBJDUMP=$lt_OBJDUMP # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive (by configure). lt_ar_flags=$lt_ar_flags # Flags to create an archive. AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; "script-chmod":C) chmod a+x pcre-config ;; "delete-old-chartables":C) rm -f pcre_chartables.c ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # Print out a nice little message after configure is run displaying the # chosen options. ebcdic_nl_code=n/a if test "$enable_ebcdic_nl25" = "yes"; then ebcdic_nl_code=0x25 elif test "$enable_ebcdic" = "yes"; then ebcdic_nl_code=0x15 fi cat <], [char* e; return $fn("100", &e, 10)])], [AC_MSG_RESULT(yes) AC_DEFINE_UNQUOTED(HAVE_`echo $fn | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`, 1, [Define to 1 if you have `$fn'.]) have_strto_fn=1 break], [AC_MSG_RESULT(no)]) done if test "$have_strto_fn" = 1; then AC_CHECK_TYPES([long long], [pcre_have_long_long="1"], [pcre_have_long_long="0"]) AC_CHECK_TYPES([unsigned long long], [pcre_have_ulong_long="1"], [pcre_have_ulong_long="0"]) else pcre_have_long_long="0" pcre_have_ulong_long="0" fi AC_SUBST(pcre_have_long_long) AC_SUBST(pcre_have_ulong_long) AC_LANG_POP fi # Using AC_SUBST eliminates the need to include config.h in a public .h file AC_SUBST(pcre_have_type_traits) AC_SUBST(pcre_have_bits_type_traits) # Conditional compilation AM_CONDITIONAL(WITH_PCRE8, test "x$enable_pcre8" = "xyes") AM_CONDITIONAL(WITH_PCRE16, test "x$enable_pcre16" = "xyes") AM_CONDITIONAL(WITH_PCRE32, test "x$enable_pcre32" = "xyes") AM_CONDITIONAL(WITH_PCRE_CPP, test "x$enable_cpp" = "xyes") AM_CONDITIONAL(WITH_REBUILD_CHARTABLES, test "x$enable_rebuild_chartables" = "xyes") AM_CONDITIONAL(WITH_JIT, test "x$enable_jit" = "xyes") AM_CONDITIONAL(WITH_UTF, test "x$enable_utf" = "xyes") AM_CONDITIONAL(WITH_VALGRIND, test "x$enable_valgrind" = "xyes") # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T # Checks for library functions. AC_CHECK_FUNCS(bcopy memmove strerror) # Check for the availability of libz (aka zlib) AC_CHECK_HEADERS([zlib.h], [HAVE_ZLIB_H=1]) AC_CHECK_LIB([z], [gzopen], [HAVE_LIBZ=1]) # Check for the availability of libbz2. Originally we just used AC_CHECK_LIB, # as for libz. However, this had the following problem, diagnosed and fixed by # a user: # # - libbz2 uses the Pascal calling convention (WINAPI) for the functions # under Win32. # - The standard autoconf AC_CHECK_LIB fails to include "bzlib.h", # therefore missing the function definition. # - The compiler thus generates a "C" signature for the test function. # - The linker fails to find the "C" function. # - PCRE fails to configure if asked to do so against libbz2. # # Solution: # # - Replace the AC_CHECK_LIB test with a custom test. AC_CHECK_HEADERS([bzlib.h], [HAVE_BZLIB_H=1]) # Original test # AC_CHECK_LIB([bz2], [BZ2_bzopen], [HAVE_LIBBZ2=1]) # # Custom test follows AC_MSG_CHECKING([for libbz2]) OLD_LIBS="$LIBS" LIBS="$LIBS -lbz2" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_BZLIB_H #include #endif]], [[return (int)BZ2_bzopen("conftest", "rb");]])], [AC_MSG_RESULT([yes]);HAVE_LIBBZ2=1; break;], AC_MSG_RESULT([no])) LIBS="$OLD_LIBS" # Check for the availabiity of libreadline if test "$enable_pcretest_libreadline" = "yes"; then AC_CHECK_HEADERS([readline/readline.h], [HAVE_READLINE_H=1]) AC_CHECK_HEADERS([readline/history.h], [HAVE_HISTORY_H=1]) AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lreadline"], [unset ac_cv_lib_readline_readline; AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-ltinfo"], [unset ac_cv_lib_readline_readline; AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lcurses"], [unset ac_cv_lib_readline_readline; AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lncurses"], [unset ac_cv_lib_readline_readline; AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lncursesw"], [unset ac_cv_lib_readline_readline; AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-ltermcap"], [LIBREADLINE=""], [-ltermcap])], [-lncursesw])], [-lncurses])], [-lcurses])], [-ltinfo])]) AC_SUBST(LIBREADLINE) if test -n "$LIBREADLINE"; then if test "$LIBREADLINE" != "-lreadline"; then echo "-lreadline needs $LIBREADLINE" LIBREADLINE="-lreadline $LIBREADLINE" fi fi fi # Check for the availability of libedit. Different distributions put its # headers in different places. Try to cover the most common ones. if test "$enable_pcretest_libedit" = "yes"; then AC_CHECK_HEADERS([editline/readline.h], [HAVE_EDITLINE_READLINE_H=1], [AC_CHECK_HEADERS([edit/readline/readline.h], [HAVE_READLINE_READLINE_H=1], [AC_CHECK_HEADERS([readline/readline.h], [HAVE_READLINE_READLINE_H=1])])]) AC_CHECK_LIB([edit], [readline], [LIBEDIT="-ledit"]) fi # This facilitates -ansi builds under Linux dnl AC_DEFINE([_GNU_SOURCE], [], [Enable GNU extensions in glibc]) PCRE_STATIC_CFLAG="" if test "x$enable_shared" = "xno" ; then AC_DEFINE([PCRE_STATIC], [1], [ Define to any value if linking statically (TODO: make nice with Libtool)]) PCRE_STATIC_CFLAG="-DPCRE_STATIC" fi AC_SUBST(PCRE_STATIC_CFLAG) # Here is where pcre specific defines are handled if test "$enable_pcre8" = "yes"; then AC_DEFINE([SUPPORT_PCRE8], [], [ Define to any value to enable the 8 bit PCRE library.]) fi if test "$enable_pcre16" = "yes"; then AC_DEFINE([SUPPORT_PCRE16], [], [ Define to any value to enable the 16 bit PCRE library.]) fi if test "$enable_pcre32" = "yes"; then AC_DEFINE([SUPPORT_PCRE32], [], [ Define to any value to enable the 32 bit PCRE library.]) fi # Unless running under Windows, JIT support requires pthreads. if test "$enable_jit" = "yes"; then if test "$HAVE_WINDOWS_H" != "1"; then AX_PTHREAD([], [AC_MSG_ERROR([JIT support requires pthreads])]) CC="$PTHREAD_CC" CFLAGS="$PTHREAD_CFLAGS $CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" fi AC_DEFINE([SUPPORT_JIT], [], [ Define to any value to enable support for Just-In-Time compiling.]) else enable_pcregrep_jit="no" fi if test "$enable_pcregrep_jit" = "yes"; then AC_DEFINE([SUPPORT_PCREGREP_JIT], [], [ Define to any value to enable JIT support in pcregrep.]) fi if test "$enable_utf" = "yes"; then AC_DEFINE([SUPPORT_UTF], [], [ Define to any value to enable support for the UTF-8/16/32 Unicode encoding. This will work even in an EBCDIC environment, but it is incompatible with the EBCDIC macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16/32, but not both at once.]) fi if test "$enable_unicode_properties" = "yes"; then AC_DEFINE([SUPPORT_UCP], [], [ Define to any value to enable support for Unicode properties.]) fi if test "$enable_stack_for_recursion" = "no"; then AC_DEFINE([NO_RECURSE], [], [ PCRE uses recursive function calls to handle backtracking while matching. This can sometimes be a problem on systems that have stacks of limited size. Define NO_RECURSE to any value to get a version that doesn't use recursion in the match() function; instead it creates its own stack by steam using pcre_recurse_malloc() to obtain memory from the heap. For more detail, see the comments and other stuff just above the match() function.]) fi if test "$enable_pcregrep_libz" = "yes"; then AC_DEFINE([SUPPORT_LIBZ], [], [ Define to any value to allow pcregrep to be linked with libz, so that it is able to handle .gz files.]) fi if test "$enable_pcregrep_libbz2" = "yes"; then AC_DEFINE([SUPPORT_LIBBZ2], [], [ Define to any value to allow pcregrep to be linked with libbz2, so that it is able to handle .bz2 files.]) fi if test $with_pcregrep_bufsize -lt 8192 ; then AC_MSG_WARN([$with_pcregrep_bufsize is too small for --with-pcregrep-bufsize; using 8192]) with_pcregrep_bufsize="8192" else if test $? -gt 1 ; then AC_MSG_ERROR([Bad value for --with-pcregrep-bufsize]) fi fi AC_DEFINE_UNQUOTED([PCREGREP_BUFSIZE], [$with_pcregrep_bufsize], [ The value of PCREGREP_BUFSIZE determines the size of buffer used by pcregrep to hold parts of the file it is searching. This is also the minimum value. The actual amount of memory used by pcregrep is three times this number, because it allows for the buffering of "before" and "after" lines.]) if test "$enable_pcretest_libedit" = "yes"; then AC_DEFINE([SUPPORT_LIBEDIT], [], [ Define to any value to allow pcretest to be linked with libedit.]) LIBREADLINE="$LIBEDIT" elif test "$enable_pcretest_libreadline" = "yes"; then AC_DEFINE([SUPPORT_LIBREADLINE], [], [ Define to any value to allow pcretest to be linked with libreadline.]) fi AC_DEFINE_UNQUOTED([NEWLINE], [$ac_pcre_newline_value], [ The value of NEWLINE determines the default newline character sequence. PCRE client programs can override this by selecting other values at run time. In ASCII environments, the value can be 10 (LF), 13 (CR), or 3338 (CRLF); in EBCDIC environments the value can be 21 or 37 (LF), 13 (CR), or 3349 or 3365 (CRLF) because there are two alternative codepoints (0x15 and 0x25) that are used as the NL line terminator that is equivalent to ASCII LF. In both ASCII and EBCDIC environments the value can also be -1 (ANY), or -2 (ANYCRLF).]) if test "$enable_bsr_anycrlf" = "yes"; then AC_DEFINE([BSR_ANYCRLF], [], [ By default, the \R escape sequence matches any Unicode line ending character or sequence of characters. If BSR_ANYCRLF is defined (to any value), this is changed so that backslash-R matches only CR, LF, or CRLF. The build-time default can be overridden by the user of PCRE at runtime.]) fi AC_DEFINE_UNQUOTED([LINK_SIZE], [$with_link_size], [ The value of LINK_SIZE determines the number of bytes used to store links as offsets within the compiled regex. The default is 2, which allows for compiled patterns up to 64K long. This covers the vast majority of cases. However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows for longer patterns in extreme cases.]) AC_DEFINE_UNQUOTED([POSIX_MALLOC_THRESHOLD], [$with_posix_malloc_threshold], [ When calling PCRE via the POSIX interface, additional working storage is required for holding the pointers to capturing substrings because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using malloc() for each call. The threshold above which the stack is no longer used is defined by POSIX_MALLOC_THRESHOLD.]) AC_DEFINE_UNQUOTED([PARENS_NEST_LIMIT], [$with_parens_nest_limit], [ The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system stack that is used while compiling a pattern.]) AC_DEFINE_UNQUOTED([MATCH_LIMIT], [$with_match_limit], [ The value of MATCH_LIMIT determines the default number of times the internal match() function can be called during a single execution of pcre_exec(). There is a runtime interface for setting a different limit. The limit exists in order to catch runaway regular expressions that take for ever to determine that they do not match. The default is set very large so that it does not accidentally catch legitimate cases.]) AC_DEFINE_UNQUOTED([MATCH_LIMIT_RECURSION], [$with_match_limit_recursion], [ The above limit applies to all calls of match(), whether or not they increase the recursion depth. In some environments it is desirable to limit the depth of recursive calls of match() more strictly, in order to restrict the maximum amount of stack (or heap, if NO_RECURSE is defined) that is used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of match(). To have any useful effect, it must be less than the value of MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is a runtime method for setting a different limit.]) AC_DEFINE([MAX_NAME_SIZE], [32], [ This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns.]) AC_DEFINE([MAX_NAME_COUNT], [10000], [ This limit is parameterized just in case anybody ever wants to change it. Care must be taken if it is increased, because it guards against integer overflow caused by enormously large patterns.]) AH_VERBATIM([PCRE_EXP_DEFN], [ /* If you are compiling for a system other than a Unix-like system or Win32, and it needs some magic to be inserted before the definition of a function that is exported by the library, define this macro to contain the relevant magic. If you do not define this macro, a suitable __declspec value is used for Windows systems; in other environments "extern" is used for a C compiler and "extern C" for a C++ compiler. This macro apears at the start of every exported function that is part of the external API. It does not appear on functions that are "external" in the C sense, but which are internal to the library. */ #undef PCRE_EXP_DEFN]) if test "$enable_ebcdic" = "yes"; then AC_DEFINE_UNQUOTED([EBCDIC], [], [ If you are compiling for a system that uses EBCDIC instead of ASCII character codes, define this macro to any value. You must also edit the NEWLINE macro below to set a suitable EBCDIC newline, commonly 21 (0x15). On systems that can use "configure" or CMake to set EBCDIC, NEWLINE is automatically adjusted. When EBCDIC is set, PCRE assumes that all input strings are in EBCDIC. If you do not define this macro, PCRE will assume input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build a version of PCRE that supports both EBCDIC and UTF-8/16/32.]) fi if test "$enable_ebcdic_nl25" = "yes"; then AC_DEFINE_UNQUOTED([EBCDIC_NL25], [], [ In an EBCDIC environment, define this macro to any value to arrange for the NL character to be 0x25 instead of the default 0x15. NL plays the role that LF does in an ASCII/Unicode environment. The value must also be set in the NEWLINE macro below. On systems that can use "configure" or CMake to set EBCDIC_NL25, the adjustment of NEWLINE is automatic.]) fi if test "$enable_valgrind" = "yes"; then AC_DEFINE_UNQUOTED([SUPPORT_VALGRIND], [], [ Define to any value for valgrind support to find invalid memory reads.]) fi # Platform specific issues NO_UNDEFINED= EXPORT_ALL_SYMBOLS= case $host_os in cygwin* | mingw* ) if test X"$enable_shared" = Xyes; then NO_UNDEFINED="-no-undefined" EXPORT_ALL_SYMBOLS="-Wl,--export-all-symbols" fi ;; esac # The extra LDFLAGS for each particular library # (Note: The libpcre*_version bits are m4 variables, assigned above) EXTRA_LIBPCRE_LDFLAGS="$EXTRA_LIBPCRE_LDFLAGS \ $NO_UNDEFINED -version-info libpcre_version" EXTRA_LIBPCRE16_LDFLAGS="$EXTRA_LIBPCRE16_LDFLAGS \ $NO_UNDEFINED -version-info libpcre16_version" EXTRA_LIBPCRE32_LDFLAGS="$EXTRA_LIBPCRE32_LDFLAGS \ $NO_UNDEFINED -version-info libpcre32_version" EXTRA_LIBPCREPOSIX_LDFLAGS="$EXTRA_LIBPCREPOSIX_LDFLAGS \ $NO_UNDEFINED -version-info libpcreposix_version" EXTRA_LIBPCRECPP_LDFLAGS="$EXTRA_LIBPCRECPP_LDFLAGS \ $NO_UNDEFINED -version-info libpcrecpp_version \ $EXPORT_ALL_SYMBOLS" AC_SUBST(EXTRA_LIBPCRE_LDFLAGS) AC_SUBST(EXTRA_LIBPCRE16_LDFLAGS) AC_SUBST(EXTRA_LIBPCRE32_LDFLAGS) AC_SUBST(EXTRA_LIBPCREPOSIX_LDFLAGS) AC_SUBST(EXTRA_LIBPCRECPP_LDFLAGS) # When we run 'make distcheck', use these arguments. Turning off compiler # optimization makes it run faster. DISTCHECK_CONFIGURE_FLAGS="CFLAGS='' CXXFLAGS='' --enable-pcre16 --enable-pcre32 --enable-jit --enable-cpp --enable-unicode-properties" AC_SUBST(DISTCHECK_CONFIGURE_FLAGS) # Check that, if --enable-pcregrep-libz or --enable-pcregrep-libbz2 is # specified, the relevant library is available. if test "$enable_pcregrep_libz" = "yes"; then if test "$HAVE_ZLIB_H" != "1"; then echo "** Cannot --enable-pcregrep-libz because zlib.h was not found" exit 1 fi if test "$HAVE_LIBZ" != "1"; then echo "** Cannot --enable-pcregrep-libz because libz was not found" exit 1 fi LIBZ="-lz" fi AC_SUBST(LIBZ) if test "$enable_pcregrep_libbz2" = "yes"; then if test "$HAVE_BZLIB_H" != "1"; then echo "** Cannot --enable-pcregrep-libbz2 because bzlib.h was not found" exit 1 fi if test "$HAVE_LIBBZ2" != "1"; then echo "** Cannot --enable-pcregrep-libbz2 because libbz2 was not found" exit 1 fi LIBBZ2="-lbz2" fi AC_SUBST(LIBBZ2) # Similarly for --enable-pcretest-readline if test "$enable_pcretest_libedit" = "yes"; then if test "$enable_pcretest_libreadline" = "yes"; then echo "** Cannot use both --enable-pcretest-libedit and --enable-pcretest-readline" exit 1 fi if test "$HAVE_EDITLINE_READLINE_H" != "1" -a \ "$HAVE_READLINE_READLINE_H" != "1"; then echo "** Cannot --enable-pcretest-libedit because neither editline/readline.h" echo "** nor readline/readline.h was found." exit 1 fi if test -z "$LIBEDIT"; then echo "** Cannot --enable-pcretest-libedit because libedit library was not found." exit 1 fi fi if test "$enable_pcretest_libreadline" = "yes"; then if test "$HAVE_READLINE_H" != "1"; then echo "** Cannot --enable-pcretest-readline because readline/readline.h was not found." exit 1 fi if test "$HAVE_HISTORY_H" != "1"; then echo "** Cannot --enable-pcretest-readline because readline/history.h was not found." exit 1 fi if test -z "$LIBREADLINE"; then echo "** Cannot --enable-pcretest-readline because readline library was not found." exit 1 fi fi # Handle valgrind support if test "$enable_valgrind" = "yes"; then m4_ifdef([PKG_CHECK_MODULES], [PKG_CHECK_MODULES([VALGRIND],[valgrind])], [AC_MSG_ERROR([pkg-config not supported])]) fi # Handle code coverage reporting support if test "$enable_coverage" = "yes"; then if test "x$GCC" != "xyes"; then AC_MSG_ERROR([Code coverage reports can only be generated when using GCC]) fi # ccache is incompatible with gcov AC_PATH_PROG([SHTOOL],[shtool],[false]) case `$SHTOOL path $CC` in *ccache*) cc_ccache=yes;; *) cc_ccache=no;; esac if test "$cc_ccache" = "yes"; then if test -z "$CCACHE_DISABLE" -o "$CCACHE_DISABLE" != "1"; then AC_MSG_ERROR([must export CCACHE_DISABLE=1 to disable ccache for code coverage]) fi fi AC_ARG_VAR([LCOV],[the ltp lcov program]) AC_PATH_PROG([LCOV],[lcov],[false]) if test "x$LCOV" = "xfalse"; then AC_MSG_ERROR([lcov not found]) fi AC_ARG_VAR([GENHTML],[the ltp genhtml program]) AC_PATH_PROG([GENHTML],[genhtml],[false]) if test "x$GENHTML" = "xfalse"; then AC_MSG_ERROR([genhtml not found]) fi # Set flags needed for gcov GCOV_CFLAGS="-O0 -ggdb3 -fprofile-arcs -ftest-coverage" GCOV_CXXFLAGS="-O0 -ggdb3 -fprofile-arcs -ftest-coverage" GCOV_LIBS="-lgcov" AC_SUBST([GCOV_CFLAGS]) AC_SUBST([GCOV_CXXFLAGS]) AC_SUBST([GCOV_LIBS]) fi # enable_coverage AM_CONDITIONAL([WITH_GCOV],[test "x$enable_coverage" = "xyes"]) # Produce these files, in addition to config.h. AC_CONFIG_FILES( Makefile libpcre.pc libpcre16.pc libpcre32.pc libpcreposix.pc libpcrecpp.pc pcre-config pcre.h pcre_stringpiece.h pcrecpparg.h ) # Make the generated script files executable. AC_CONFIG_COMMANDS([script-chmod], [chmod a+x pcre-config]) # Make sure that pcre_chartables.c is removed in case the method for # creating it was changed by reconfiguration. AC_CONFIG_COMMANDS([delete-old-chartables], [rm -f pcre_chartables.c]) AC_OUTPUT # Print out a nice little message after configure is run displaying the # chosen options. ebcdic_nl_code=n/a if test "$enable_ebcdic_nl25" = "yes"; then ebcdic_nl_code=0x25 elif test "$enable_ebcdic" = "yes"; then ebcdic_nl_code=0x15 fi cat <. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/pcre/dftables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This is a freestanding support program to generate a file containing character tables for PCRE. The tables are built according to the current locale. Now that pcre_maketables is a function visible to the outside world, we make use of its code from here in order to be consistent. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "pcre_internal.h" #define DFTABLES /* pcre_maketables.c notices this */ #include "pcre_maketables.c" int main(int argc, char **argv) { FILE *f; int i = 1; const unsigned char *tables; const unsigned char *base_of_tables; /* By default, the default C locale is used rather than what the building user happens to have set. However, if the -L option is given, set the locale from the LC_xxx environment variables. */ if (argc > 1 && strcmp(argv[1], "-L") == 0) { setlocale(LC_ALL, ""); /* Set from environment variables */ i++; } if (argc < i + 1) { fprintf(stderr, "dftables: one filename argument is required\n"); return 1; } tables = pcre_maketables(); base_of_tables = tables; f = fopen(argv[i], "wb"); if (f == NULL) { fprintf(stderr, "dftables: failed to open %s for writing\n", argv[1]); return 1; } /* There are several fprintf() calls here, because gcc in pedantic mode complains about the very long string otherwise. */ fprintf(f, "/*************************************************\n" "* Perl-Compatible Regular Expressions *\n" "*************************************************/\n\n" "/* This file was automatically written by the dftables auxiliary\n" "program. It contains character tables that are used when no external\n" "tables are passed to PCRE by the application that calls it. The tables\n" "are used only for characters whose code values are less than 256.\n\n"); fprintf(f, "The following #includes are present because without them gcc 4.x may remove\n" "the array definition from the final binary if PCRE is built into a static\n" "library and dead code stripping is activated. This leads to link errors.\n" "Pulling in the header ensures that the array gets flagged as \"someone\n" "outside this compilation unit might reference this\" and so it will always\n" "be supplied to the linker. */\n\n"); /* Force config.h in z/OS */ #if defined NATIVE_ZOS fprintf(f, "/* For z/OS, config.h is forced */\n" "#ifndef HAVE_CONFIG_H\n" "#define HAVE_CONFIG_H 1\n" "#endif\n\n"); #endif fprintf(f, "#ifdef HAVE_CONFIG_H\n" "#include \"config.h\"\n" "#endif\n\n" "#include \"pcre_internal.h\"\n\n"); fprintf(f, "const pcre_uint8 PRIV(default_tables)[] = {\n\n" "/* This table is a lower casing table. */\n\n"); fprintf(f, " "); for (i = 0; i < 256; i++) { if ((i & 7) == 0 && i != 0) fprintf(f, "\n "); fprintf(f, "%3d", *tables++); if (i != 255) fprintf(f, ","); } fprintf(f, ",\n\n"); fprintf(f, "/* This table is a case flipping table. */\n\n"); fprintf(f, " "); for (i = 0; i < 256; i++) { if ((i & 7) == 0 && i != 0) fprintf(f, "\n "); fprintf(f, "%3d", *tables++); if (i != 255) fprintf(f, ","); } fprintf(f, ",\n\n"); fprintf(f, "/* This table contains bit maps for various character classes.\n" "Each map is 32 bytes long and the bits run from the least\n" "significant end of each byte. The classes that have their own\n" "maps are: space, xdigit, digit, upper, lower, word, graph\n" "print, punct, and cntrl. Other classes are built from combinations. */\n\n"); fprintf(f, " "); for (i = 0; i < cbit_length; i++) { if ((i & 7) == 0 && i != 0) { if ((i & 31) == 0) fprintf(f, "\n"); fprintf(f, "\n "); } fprintf(f, "0x%02x", *tables++); if (i != cbit_length - 1) fprintf(f, ","); } fprintf(f, ",\n\n"); fprintf(f, "/* This table identifies various classes of character by individual bits:\n" " 0x%02x white space character\n" " 0x%02x letter\n" " 0x%02x decimal digit\n" " 0x%02x hexadecimal digit\n" " 0x%02x alphanumeric or '_'\n" " 0x%02x regular expression metacharacter or binary zero\n*/\n\n", ctype_space, ctype_letter, ctype_digit, ctype_xdigit, ctype_word, ctype_meta); fprintf(f, " "); for (i = 0; i < 256; i++) { if ((i & 7) == 0 && i != 0) { fprintf(f, " /* "); if (isprint(i-8)) fprintf(f, " %c -", i-8); else fprintf(f, "%3d-", i-8); if (isprint(i-1)) fprintf(f, " %c ", i-1); else fprintf(f, "%3d", i-1); fprintf(f, " */\n "); } fprintf(f, "0x%02x", *tables++); if (i != 255) fprintf(f, ","); } fprintf(f, "};/* "); if (isprint(i-8)) fprintf(f, " %c -", i-8); else fprintf(f, "%3d-", i-8); if (isprint(i-1)) fprintf(f, " %c ", i-1); else fprintf(f, "%3d", i-1); fprintf(f, " */\n\n/* End of pcre_chartables.c */\n"); fclose(f); free((void *)base_of_tables); return 0; } /* End of dftables.c */ ================================================ FILE: src/pcre/doc/html/NON-AUTOTOOLS-BUILD.txt ================================================ Building PCRE without using autotools ------------------------------------- NOTE: This document relates to PCRE releases that use the original API, with library names libpcre, libpcre16, and libpcre32. January 2015 saw the first release of a new API, known as PCRE2, with release numbers starting at 10.00 and library names libpcre2-8, libpcre2-16, and libpcre2-32. The old libraries (now called PCRE1) are still being maintained for bug fixes, but there will be no new development. New projects are advised to use the new PCRE2 libraries. This document contains the following sections: General Generic instructions for the PCRE C library The C++ wrapper functions Building for virtual Pascal Stack size in Windows environments Linking programs in Windows environments Calling conventions in Windows environments Comments about Win32 builds Building PCRE on Windows with CMake Use of relative paths with CMake on Windows Testing with RunTest.bat Building under Windows CE with Visual Studio 200x Building under Windows with BCC5.5 Building using Borland C++ Builder 2007 (CB2007) and higher Building PCRE on OpenVMS Building PCRE on Stratus OpenVOS Building PCRE on native z/OS and z/VM GENERAL I (Philip Hazel) have no experience of Windows or VMS sytems and how their libraries work. The items in the PCRE distribution and Makefile that relate to anything other than Linux systems are untested by me. There are some other comments and files (including some documentation in CHM format) in the Contrib directory on the FTP site: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/Contrib The basic PCRE library consists entirely of code written in Standard C, and so should compile successfully on any system that has a Standard C compiler and library. The C++ wrapper functions are a separate issue (see below). The PCRE distribution includes a "configure" file for use by the configure/make (autotools) build system, as found in many Unix-like environments. The README file contains information about the options for "configure". There is also support for CMake, which some users prefer, especially in Windows environments, though it can also be run in Unix-like environments. See the section entitled "Building PCRE on Windows with CMake" below. Versions of config.h and pcre.h are distributed in the PCRE tarballs under the names config.h.generic and pcre.h.generic. These are provided for those who build PCRE without using "configure" or CMake. If you use "configure" or CMake, the .generic versions are not used. GENERIC INSTRUCTIONS FOR THE PCRE C LIBRARY The following are generic instructions for building the PCRE C library "by hand". If you are going to use CMake, this section does not apply to you; you can skip ahead to the CMake section. (1) Copy or rename the file config.h.generic as config.h, and edit the macro settings that it contains to whatever is appropriate for your environment. In particular, you can alter the definition of the NEWLINE macro to specify what character(s) you want to be interpreted as line terminators. In an EBCDIC environment, you MUST change NEWLINE, because its default value is 10, an ASCII LF. The usual EBCDIC newline character is 21 (0x15, NL), though in some cases it may be 37 (0x25). When you compile any of the PCRE modules, you must specify -DHAVE_CONFIG_H to your compiler so that config.h is included in the sources. An alternative approach is not to edit config.h, but to use -D on the compiler command line to make any changes that you need to the configuration options. In this case -DHAVE_CONFIG_H must not be set. NOTE: There have been occasions when the way in which certain parameters in config.h are used has changed between releases. (In the configure/make world, this is handled automatically.) When upgrading to a new release, you are strongly advised to review config.h.generic before re-using what you had previously. (2) Copy or rename the file pcre.h.generic as pcre.h. (3) EITHER: Copy or rename file pcre_chartables.c.dist as pcre_chartables.c. OR: Compile dftables.c as a stand-alone program (using -DHAVE_CONFIG_H if you have set up config.h), and then run it with the single argument "pcre_chartables.c". This generates a set of standard character tables and writes them to that file. The tables are generated using the default C locale for your system. If you want to use a locale that is specified by LC_xxx environment variables, add the -L option to the dftables command. You must use this method if you are building on a system that uses EBCDIC code. The tables in pcre_chartables.c are defaults. The caller of PCRE can specify alternative tables at run time. (4) Ensure that you have the following header files: pcre_internal.h ucp.h (5) For an 8-bit library, compile the following source files, setting -DHAVE_CONFIG_H as a compiler option if you have set up config.h with your configuration, or else use other -D settings to change the configuration as required. pcre_byte_order.c pcre_chartables.c pcre_compile.c pcre_config.c pcre_dfa_exec.c pcre_exec.c pcre_fullinfo.c pcre_get.c pcre_globals.c pcre_jit_compile.c pcre_maketables.c pcre_newline.c pcre_ord2utf8.c pcre_refcount.c pcre_string_utils.c pcre_study.c pcre_tables.c pcre_ucd.c pcre_valid_utf8.c pcre_version.c pcre_xclass.c Make sure that you include -I. in the compiler command (or equivalent for an unusual compiler) so that all included PCRE header files are first sought in the current directory. Otherwise you run the risk of picking up a previously-installed file from somewhere else. Note that you must still compile pcre_jit_compile.c, even if you have not defined SUPPORT_JIT in config.h, because when JIT support is not configured, dummy functions are compiled. When JIT support IS configured, pcre_jit_compile.c #includes sources from the sljit subdirectory, where there should be 16 files, all of whose names begin with "sljit". (6) Now link all the compiled code into an object library in whichever form your system keeps such libraries. This is the basic PCRE C 8-bit library. If your system has static and shared libraries, you may have to do this once for each type. (7) If you want to build a 16-bit library (as well as, or instead of the 8-bit or 32-bit libraries) repeat steps 5-6 with the following files: pcre16_byte_order.c pcre16_chartables.c pcre16_compile.c pcre16_config.c pcre16_dfa_exec.c pcre16_exec.c pcre16_fullinfo.c pcre16_get.c pcre16_globals.c pcre16_jit_compile.c pcre16_maketables.c pcre16_newline.c pcre16_ord2utf16.c pcre16_refcount.c pcre16_string_utils.c pcre16_study.c pcre16_tables.c pcre16_ucd.c pcre16_utf16_utils.c pcre16_valid_utf16.c pcre16_version.c pcre16_xclass.c (8) If you want to build a 32-bit library (as well as, or instead of the 8-bit or 16-bit libraries) repeat steps 5-6 with the following files: pcre32_byte_order.c pcre32_chartables.c pcre32_compile.c pcre32_config.c pcre32_dfa_exec.c pcre32_exec.c pcre32_fullinfo.c pcre32_get.c pcre32_globals.c pcre32_jit_compile.c pcre32_maketables.c pcre32_newline.c pcre32_ord2utf32.c pcre32_refcount.c pcre32_string_utils.c pcre32_study.c pcre32_tables.c pcre32_ucd.c pcre32_utf32_utils.c pcre32_valid_utf32.c pcre32_version.c pcre32_xclass.c (9) If you want to build the POSIX wrapper functions (which apply only to the 8-bit library), ensure that you have the pcreposix.h file and then compile pcreposix.c (remembering -DHAVE_CONFIG_H if necessary). Link the result (on its own) as the pcreposix library. (10) The pcretest program can be linked with any combination of the 8-bit, 16-bit and 32-bit libraries (depending on what you selected in config.h). Compile pcretest.c and pcre_printint.c (again, don't forget -DHAVE_CONFIG_H) and link them together with the appropriate library/ies. If you compiled an 8-bit library, pcretest also needs the pcreposix wrapper library unless you compiled it with -DNOPOSIX. (11) Run pcretest on the testinput files in the testdata directory, and check that the output matches the corresponding testoutput files. There are comments about what each test does in the section entitled "Testing PCRE" in the README file. If you compiled more than one of the 8-bit, 16-bit and 32-bit libraries, you need to run pcretest with the -16 option to do 16-bit tests and with the -32 option to do 32-bit tests. Some tests are relevant only when certain build-time options are selected. For example, test 4 is for UTF-8/UTF-16/UTF-32 support, and will not run if you have built PCRE without it. See the comments at the start of each testinput file. If you have a suitable Unix-like shell, the RunTest script will run the appropriate tests for you. The command "RunTest list" will output a list of all the tests. Note that the supplied files are in Unix format, with just LF characters as line terminators. You may need to edit them to change this if your system uses a different convention. If you are using Windows, you probably should use the wintestinput3 file instead of testinput3 (and the corresponding output file). This is a locale test; wintestinput3 sets the locale to "french" rather than "fr_FR", and there some minor output differences. (12) If you have built PCRE with SUPPORT_JIT, the JIT features will be tested by the testdata files. However, you might also like to build and run the freestanding JIT test program, pcre_jit_test.c. (13) If you want to use the pcregrep command, compile and link pcregrep.c; it uses only the basic 8-bit PCRE library (it does not need the pcreposix library). THE C++ WRAPPER FUNCTIONS The PCRE distribution also contains some C++ wrapper functions and tests, applicable to the 8-bit library, which were contributed by Google Inc. On a system that can use "configure" and "make", the functions are automatically built into a library called pcrecpp. It should be straightforward to compile the .cc files manually on other systems. The files called xxx_unittest.cc are test programs for each of the corresponding xxx.cc files. BUILDING FOR VIRTUAL PASCAL A script for building PCRE using Borland's C++ compiler for use with VPASCAL was contributed by Alexander Tokarev. Stefan Weber updated the script and added additional files. The following files in the distribution are for building PCRE for use with VP/Borland: makevp_c.txt, makevp_l.txt, makevp.bat, pcregexp.pas. STACK SIZE IN WINDOWS ENVIRONMENTS The default processor stack size of 1Mb in some Windows environments is too small for matching patterns that need much recursion. In particular, test 2 may fail because of this. Normally, running out of stack causes a crash, but there have been cases where the test program has just died silently. See your linker documentation for how to increase stack size if you experience problems. The Linux default of 8Mb is a reasonable choice for the stack, though even that can be too small for some pattern/subject combinations. PCRE has a compile configuration option to disable the use of stack for recursion so that heap is used instead. However, pattern matching is significantly slower when this is done. There is more about stack usage in the "pcrestack" documentation. LINKING PROGRAMS IN WINDOWS ENVIRONMENTS If you want to statically link a program against a PCRE library in the form of a non-dll .a file, you must define PCRE_STATIC before including pcre.h or pcrecpp.h, otherwise the pcre_malloc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results. CALLING CONVENTIONS IN WINDOWS ENVIRONMENTS It is possible to compile programs to use different calling conventions using MSVC. Search the web for "calling conventions" for more information. To make it easier to change the calling convention for the exported functions in the PCRE library, the macro PCRE_CALL_CONVENTION is present in all the external definitions. It can be set externally when compiling (e.g. in CFLAGS). If it is not set, it defaults to empty; the default calling convention is then used (which is what is wanted most of the time). COMMENTS ABOUT WIN32 BUILDS (see also "BUILDING PCRE ON WINDOWS WITH CMAKE") There are two ways of building PCRE using the "configure, make, make install" paradigm on Windows systems: using MinGW or using Cygwin. These are not at all the same thing; they are completely different from each other. There is also support for building using CMake, which some users find a more straightforward way of building PCRE under Windows. The MinGW home page (http://www.mingw.org/) says this: MinGW: A collection of freely available and freely distributable Windows specific header files and import libraries combined with GNU toolsets that allow one to produce native Windows programs that do not rely on any 3rd-party C runtime DLLs. The Cygwin home page (http://www.cygwin.com/) says this: Cygwin is a Linux-like environment for Windows. It consists of two parts: . A DLL (cygwin1.dll) which acts as a Linux API emulation layer providing substantial Linux API functionality . A collection of tools which provide Linux look and feel. The Cygwin DLL currently works with all recent, commercially released x86 32 bit and 64 bit versions of Windows, with the exception of Windows CE. On both MinGW and Cygwin, PCRE should build correctly using: ./configure && make && make install This should create two libraries called libpcre and libpcreposix, and, if you have enabled building the C++ wrapper, a third one called libpcrecpp. These are independent libraries: when you link with libpcreposix or libpcrecpp you must also link with libpcre, which contains the basic functions. (Some earlier releases of PCRE included the basic libpcre functions in libpcreposix. This no longer happens.) A user submitted a special-purpose patch that makes it easy to create "pcre.dll" under mingw32 using the "msys" environment. It provides "pcre.dll" as a special target. If you use this target, no other files are built, and in particular, the pcretest and pcregrep programs are not built. An example of how this might be used is: ./configure --enable-utf --disable-cpp CFLAGS="-03 -s"; make pcre.dll Using Cygwin's compiler generates libraries and executables that depend on cygwin1.dll. If a library that is generated this way is distributed, cygwin1.dll has to be distributed as well. Since cygwin1.dll is under the GPL licence, this forces not only PCRE to be under the GPL, but also the entire application. A distributor who wants to keep their own code proprietary must purchase an appropriate Cygwin licence. MinGW has no such restrictions. The MinGW compiler generates a library or executable that can run standalone on Windows without any third party dll or licensing issues. But there is more complication: If a Cygwin user uses the -mno-cygwin Cygwin gcc flag, what that really does is to tell Cygwin's gcc to use the MinGW gcc. Cygwin's gcc is only acting as a front end to MinGW's gcc (if you install Cygwin's gcc, you get both Cygwin's gcc and MinGW's gcc). So, a user can: . Build native binaries by using MinGW or by getting Cygwin and using -mno-cygwin. . Build binaries that depend on cygwin1.dll by using Cygwin with the normal compiler flags. The test files that are supplied with PCRE are in UNIX format, with LF characters as line terminators. Unless your PCRE library uses a default newline option that includes LF as a valid newline, it may be necessary to change the line terminators in the test files to get some of the tests to work. BUILDING PCRE ON WINDOWS WITH CMAKE CMake is an alternative configuration facility that can be used instead of "configure". CMake creates project files (make files, solution files, etc.) tailored to numerous development environments, including Visual Studio, Borland, Msys, MinGW, NMake, and Unix. If possible, use short paths with no spaces in the names for your CMake installation and your PCRE source and build directories. The following instructions were contributed by a PCRE user. If they are not followed exactly, errors may occur. In the event that errors do occur, it is recommended that you delete the CMake cache before attempting to repeat the CMake build process. In the CMake GUI, the cache can be deleted by selecting "File > Delete Cache". 1. Install the latest CMake version available from http://www.cmake.org/, and ensure that cmake\bin is on your path. 2. Unzip (retaining folder structure) the PCRE source tree into a source directory such as C:\pcre. You should ensure your local date and time is not earlier than the file dates in your source dir if the release is very new. 3. Create a new, empty build directory, preferably a subdirectory of the source dir. For example, C:\pcre\pcre-xx\build. 4. Run cmake-gui from the Shell envirornment of your build tool, for example, Msys for Msys/MinGW or Visual Studio Command Prompt for VC/VC++. Do not try to start Cmake from the Windows Start menu, as this can lead to errors. 5. Enter C:\pcre\pcre-xx and C:\pcre\pcre-xx\build for the source and build directories, respectively. 6. Hit the "Configure" button. 7. Select the particular IDE / build tool that you are using (Visual Studio, MSYS makefiles, MinGW makefiles, etc.) 8. The GUI will then list several configuration options. This is where you can enable UTF-8 support or other PCRE optional features. 9. Hit "Configure" again. The adjacent "Generate" button should now be active. 10. Hit "Generate". 11. The build directory should now contain a usable build system, be it a solution file for Visual Studio, makefiles for MinGW, etc. Exit from cmake-gui and use the generated build system with your compiler or IDE. E.g., for MinGW you can run "make", or for Visual Studio, open the PCRE solution, select the desired configuration (Debug, or Release, etc.) and build the ALL_BUILD project. 12. If during configuration with cmake-gui you've elected to build the test programs, you can execute them by building the test project. E.g., for MinGW: "make test"; for Visual Studio build the RUN_TESTS project. The most recent build configuration is targeted by the tests. A summary of test results is presented. Complete test output is subsequently available for review in Testing\Temporary under your build dir. USE OF RELATIVE PATHS WITH CMAKE ON WINDOWS A PCRE user comments as follows: I thought that others may want to know the current state of CMAKE_USE_RELATIVE_PATHS support on Windows. Here it is: -- AdditionalIncludeDirectories is only partially modified (only the first path - see below) -- Only some of the contained file paths are modified - shown below for pcre.vcproj -- It properly modifies I am sure CMake people can fix that if they want to. Until then one will need to replace existing absolute paths in project files with relative paths manually (e.g. from VS) - relative to project file location. I did just that before being told to try CMAKE_USE_RELATIVE_PATHS. Not a big deal. AdditionalIncludeDirectories="E:\builds\pcre\build;E:\builds\pcre\pcre-7.5;" AdditionalIncludeDirectories=".;E:\builds\pcre\pcre-7.5;" RelativePath="pcre.h" RelativePath="pcre_chartables.c" RelativePath="pcre_chartables.c.rule" TESTING WITH RUNTEST.BAT If configured with CMake, building the test project ("make test" or building ALL_TESTS in Visual Studio) creates (and runs) pcre_test.bat (and depending on your configuration options, possibly other test programs) in the build directory. Pcre_test.bat runs RunTest.Bat with correct source and exe paths. For manual testing with RunTest.bat, provided the build dir is a subdirectory of the source directory: Open command shell window. Chdir to the location of your pcretest.exe and pcregrep.exe programs. Call RunTest.bat with "..\RunTest.Bat" or "..\..\RunTest.bat" as appropriate. To run only a particular test with RunTest.Bat provide a test number argument. Otherwise: 1. Copy RunTest.bat into the directory where pcretest.exe and pcregrep.exe have been created. 2. Edit RunTest.bat to indentify the full or relative location of the pcre source (wherein which the testdata folder resides), e.g.: set srcdir=C:\pcre\pcre-8.20 3. In a Windows command environment, chdir to the location of your bat and exe programs. 4. Run RunTest.bat. Test outputs will automatically be compared to expected results, and discrepancies will be identified in the console output. To independently test the just-in-time compiler, run pcre_jit_test.exe. To test pcrecpp, run pcrecpp_unittest.exe, pcre_stringpiece_unittest.exe and pcre_scanner_unittest.exe. BUILDING UNDER WINDOWS CE WITH VISUAL STUDIO 200x Vincent Richomme sent a zip archive of files to help with this process. They can be found in the file "pcre-vsbuild.zip" in the Contrib directory of the FTP site. BUILDING UNDER WINDOWS WITH BCC5.5 Michael Roy sent these comments about building PCRE under Windows with BCC5.5: Some of the core BCC libraries have a version of PCRE from 1998 built in, which can lead to pcre_exec() giving an erroneous PCRE_ERROR_NULL from a version mismatch. I'm including an easy workaround below, if you'd like to include it in the non-unix instructions: When linking a project with BCC5.5, pcre.lib must be included before any of the libraries cw32.lib, cw32i.lib, cw32mt.lib, and cw32mti.lib on the command line. BUILDING USING BORLAND C++ BUILDER 2007 (CB2007) AND HIGHER A PCRE user sent these comments about this environment (see also the comment from another user that follows them): The XE versions of C++ Builder come with a RegularExpressionsCore class which contain a version of TPerlRegEx. However, direct use of the C PCRE library may be desirable. The default makevp.bat, however, supplied with PCRE builds a version of PCRE that is not usable with any version of C++ Builder because the compiler ships with an embedded version of PCRE, version 2.01 from 1998! [See also the note about BCC5.5 above.] If you want to use PCRE you'll need to rename the functions (pcre_compile to pcre_compile_bcc, etc) or do as I have done and just use the 16 bit versions. I'm using std::wstring everywhere anyway. Since the embedded version of PCRE does not have the 16 bit function names, there is no conflict. Building PCRE using a C++ Builder static library project file (recommended): 1. Rename or remove pcre.h, pcreposi.h, and pcreposix.h from your C++ Builder original include path. 2. Download PCRE from pcre.org and extract to a directory. 3. Rename pcre_chartables.c.dist to pcre_chartables.c, pcre.h.generic to pcre.h, and config.h.generic to config.h. 4. Edit pcre.h and pcre_config.c so that they include config.h. 5. Edit config.h like so: Comment out the following lines: #define PACKAGE "pcre" #define PACKAGE_BUGREPORT "" #define PACKAGE_NAME "PCRE" #define PACKAGE_STRING "PCRE 8.32" #define PACKAGE_TARNAME "pcre" #define PACKAGE_URL "" #define PACKAGE_VERSION "8.32" Add the following lines: #ifndef SUPPORT_UTF #define SUPPORT_UTF 100 // any value is fine #endif #ifndef SUPPORT_UCP #define SUPPORT_UCP 101 // any value is fine #endif #ifndef SUPPORT_UCP #define SUPPORT_PCRE16 102 // any value is fine #endif #ifndef SUPPORT_UTF8 #define SUPPORT_UTF8 103 // any value is fine #endif 6. Build a C++ Builder project using the IDE. Go to File / New / Other and choose Static Library. You can name it pcre.cbproj or whatever. Now set your paths by going to Project / Options. Set the Include path. Do this from the "Base" option to apply to both Release and Debug builds. Now add the following files to the project: pcre.h pcre16_byte_order.c pcre16_chartables.c pcre16_compile.c pcre16_config.c pcre16_dfa_exec.c pcre16_exec.c pcre16_fullinfo.c pcre16_get.c pcre16_globals.c pcre16_maketables.c pcre16_newline.c pcre16_ord2utf16.c pcre16_printint.c pcre16_refcount.c pcre16_string_utils.c pcre16_study.c pcre16_tables.c pcre16_ucd.c pcre16_utf16_utils.c pcre16_valid_utf16.c pcre16_version.c pcre16_xclass.c //Optional pcre_version.c 7. After compiling the .lib file, copy the .lib and header files to a project you want to use PCRE with. Enjoy. Optional ... Building PCRE using the makevp.bat file: 1. Edit makevp_c.txt and makevp_l.txt and change all the names to the 16 bit versions. 2. Edit makevp.bat and set the path to C++ Builder. Run makevp.bat. Another PCRE user added this comment: Another approach I successfully used for some years with BCB 5 and 6 was to make sure that include and library paths of PCRE are configured before the default paths of the IDE in the dialogs where one can manage those paths. Afterwards one can open the project files using a text editor and manually add the self created library for pcre itself, pcrecpp doesn't ship with the IDE, in the library nodes where the IDE manages its own libraries to link against in front of the IDE-own libraries. This way one can use the default PCRE function names without getting access violations on runtime. BUILDING PCRE ON OPENVMS Stephen Hoffman sent the following, in December 2012: "Here is a very short write-up on the OpenVMS port and here is a zip with the OpenVMS files, and with one modified testing-related PCRE file." This is a port of PCRE 8.32. Earlier, Dan Mooney sent the following comments about building PCRE on OpenVMS. They relate to an older version of PCRE that used fewer source files, so the exact commands will need changing. See the current list of source files above. "It was quite easy to compile and link the library. I don't have a formal make file but the attached file [reproduced below] contains the OpenVMS DCL commands I used to build the library. I had to add #define POSIX_MALLOC_THRESHOLD 10 to pcre.h since it was not defined anywhere. The library was built on: O/S: HP OpenVMS v7.3-1 Compiler: Compaq C v6.5-001-48BCD Linker: vA13-01 The test results did not match 100% due to the issues you mention in your documentation regarding isprint(), iscntrl(), isgraph() and ispunct(). I modified some of the character tables temporarily and was able to get the results to match. Tests using the fr locale did not match since I don't have that locale loaded. The study size was always reported to be 3 less than the value in the standard test output files." ========================= $! This DCL procedure builds PCRE on OpenVMS $! $! I followed the instructions in the non-unix-use file in the distribution. $! $ COMPILE == "CC/LIST/NOMEMBER_ALIGNMENT/PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES $ COMPILE DFTABLES.C $ LINK/EXE=DFTABLES.EXE DFTABLES.OBJ $ RUN DFTABLES.EXE/OUTPUT=CHARTABLES.C $ COMPILE MAKETABLES.C $ COMPILE GET.C $ COMPILE STUDY.C $! I had to set POSIX_MALLOC_THRESHOLD to 10 in PCRE.H since the symbol $! did not seem to be defined anywhere. $! I edited pcre.h and added #DEFINE SUPPORT_UTF8 to enable UTF8 support. $ COMPILE PCRE.C $ LIB/CREATE PCRE MAKETABLES.OBJ, GET.OBJ, STUDY.OBJ, PCRE.OBJ $! I had to set POSIX_MALLOC_THRESHOLD to 10 in PCRE.H since the symbol $! did not seem to be defined anywhere. $ COMPILE PCREPOSIX.C $ LIB/CREATE PCREPOSIX PCREPOSIX.OBJ $ COMPILE PCRETEST.C $ LINK/EXE=PCRETEST.EXE PCRETEST.OBJ, PCRE/LIB, PCREPOSIX/LIB $! C programs that want access to command line arguments must be $! defined as a symbol $ PCRETEST :== "$ SYS$ROADSUSERS:[DMOONEY.REGEXP]PCRETEST.EXE" $! Arguments must be enclosed in quotes. $ PCRETEST "-C" $! Test results: $! $! The test results did not match 100%. The functions isprint(), iscntrl(), $! isgraph() and ispunct() on OpenVMS must not produce the same results $! as the system that built the test output files provided with the $! distribution. $! $! The study size did not match and was always 3 less on OpenVMS. $! $! Locale could not be set to fr $! ========================= BUILDING PCRE ON STRATUS OPENVOS These notes on the port of PCRE to VOS (lightly edited) were supplied by Ashutosh Warikoo, whose email address has the local part awarikoo and the domain nse.co.in. The port was for version 7.9 in August 2009. 1. Building PCRE I built pcre on OpenVOS Release 17.0.1at using GNU Tools 3.4a without any problems. I used the following packages to build PCRE: ftp://ftp.stratus.com/pub/vos/posix/ga/posix.save.evf.gz Please read and follow the instructions that come with these packages. To start the build of pcre, from the root of the package type: ./build.sh 2. Installing PCRE Once you have successfully built PCRE, login to the SysAdmin group, switch to the root user, and type [ !create_dir (master_disk)>usr --if needed ] [ !create_dir (master_disk)>usr>local --if needed ] !gmake install This installs PCRE and its man pages into /usr/local. You can add (master_disk)>usr>local>bin to your command search paths, or if you are in BASH, add /usr/local/bin to the PATH environment variable. 4. Restrictions This port requires readline library optionally. However during the build I faced some yet unexplored errors while linking with readline. As it was an optional component I chose to disable it. 5. Known Problems I ran the test suite, but you will have to be your own judge of whether this command, and this port, suits your purposes. If you find any problems that appear to be related to the port itself, please let me know. Please see the build.log file in the root of the package also. BUILDING PCRE ON NATIVE Z/OS AND Z/VM z/OS and z/VM are operating systems for mainframe computers, produced by IBM. The character code used is EBCDIC, not ASCII or Unicode. In z/OS, UNIX APIs and applications can be supported through UNIX System Services, and in such an environment PCRE can be built in the same way as in other systems. However, in native z/OS (without UNIX System Services) and in z/VM, special ports are required. PCRE1 version 8.39 is available in file 882 on this site: http://www.cbttape.org Everything, source and executable, is in EBCDIC and native z/OS file formats. However, this software is not maintained and will not be upgraded. If you are new to PCRE you should be looking at PCRE2 (version 10.30 or later). =============================== Last Updated: 13 September 2017 =============================== ================================================ FILE: src/pcre/doc/html/README.txt ================================================ README file for PCRE (Perl-compatible regular expression library) ----------------------------------------------------------------- NOTE: This set of files relates to PCRE releases that use the original API, with library names libpcre, libpcre16, and libpcre32. January 2015 saw the first release of a new API, known as PCRE2, with release numbers starting at 10.00 and library names libpcre2-8, libpcre2-16, and libpcre2-32. The old libraries (now called PCRE1) are still being maintained for bug fixes, but there will be no new development. New projects are advised to use the new PCRE2 libraries. The latest release of PCRE1 is always available in three alternative formats from: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-xxx.tar.gz ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-xxx.tar.bz2 ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-xxx.zip There is a mailing list for discussion about the development of PCRE at pcre-dev@exim.org. You can access the archives and subscribe or manage your subscription here: https://lists.exim.org/mailman/listinfo/pcre-dev Please read the NEWS file if you are upgrading from a previous release. The contents of this README file are: The PCRE APIs Documentation for PCRE Contributions by users of PCRE Building PCRE on non-Unix-like systems Building PCRE without using autotools Building PCRE using autotools Retrieving configuration information Shared libraries Cross-compiling using autotools Using HP's ANSI C++ compiler (aCC) Compiling in Tru64 using native compilers Using Sun's compilers for Solaris Using PCRE from MySQL Making new tarballs Testing PCRE Character tables File manifest The PCRE APIs ------------- PCRE is written in C, and it has its own API. There are three sets of functions, one for the 8-bit library, which processes strings of bytes, one for the 16-bit library, which processes strings of 16-bit values, and one for the 32-bit library, which processes strings of 32-bit values. The distribution also includes a set of C++ wrapper functions (see the pcrecpp man page for details), courtesy of Google Inc., which can be used to call the 8-bit PCRE library from C++. Other C++ wrappers have been created from time to time. See, for example: https://github.com/YasserAsmi/regexp, which aims to be simple and similar in style to the C API. The distribution also contains a set of C wrapper functions (again, just for the 8-bit library) that are based on the POSIX regular expression API (see the pcreposix man page). These end up in the library called libpcreposix. Note that this just provides a POSIX calling interface to PCRE; the regular expressions themselves still follow Perl syntax and semantics. The POSIX API is restricted, and does not give full access to all of PCRE's facilities. The header file for the POSIX-style functions is called pcreposix.h. The official POSIX name is regex.h, but I did not want to risk possible problems with existing files of that name by distributing it that way. To use PCRE with an existing program that uses the POSIX API, pcreposix.h will have to be renamed or pointed at by a link. If you are using the POSIX interface to PCRE and there is already a POSIX regex library installed on your system, as well as worrying about the regex.h header file (as mentioned above), you must also take care when linking programs to ensure that they link with PCRE's libpcreposix library. Otherwise they may pick up the POSIX functions of the same name from the other library. One way of avoiding this confusion is to compile PCRE with the addition of -Dregcomp=PCREregcomp (and similarly for the other POSIX functions) to the compiler flags (CFLAGS if you are using "configure" -- see below). This has the effect of renaming the functions so that the names no longer clash. Of course, you have to do the same thing for your applications, or write them using the new names. Documentation for PCRE ---------------------- If you install PCRE in the normal way on a Unix-like system, you will end up with a set of man pages whose names all start with "pcre". The one that is just called "pcre" lists all the others. In addition to these man pages, the PCRE documentation is supplied in two other forms: 1. There are files called doc/pcre.txt, doc/pcregrep.txt, and doc/pcretest.txt in the source distribution. The first of these is a concatenation of the text forms of all the section 3 man pages except the listing of pcredemo.c and those that summarize individual functions. The other two are the text forms of the section 1 man pages for the pcregrep and pcretest commands. These text forms are provided for ease of scanning with text editors or similar tools. They are installed in /share/doc/pcre, where is the installation prefix (defaulting to /usr/local). 2. A set of files containing all the documentation in HTML form, hyperlinked in various ways, and rooted in a file called index.html, is distributed in doc/html and installed in /share/doc/pcre/html. Users of PCRE have contributed files containing the documentation for various releases in CHM format. These can be found in the Contrib directory of the FTP site (see next section). Contributions by users of PCRE ------------------------------ You can find contributions from PCRE users in the directory ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/Contrib There is a README file giving brief descriptions of what they are. Some are complete in themselves; others are pointers to URLs containing relevant files. Some of this material is likely to be well out-of-date. Several of the earlier contributions provided support for compiling PCRE on various flavours of Windows (I myself do not use Windows). Nowadays there is more Windows support in the standard distribution, so these contibutions have been archived. A PCRE user maintains downloadable Windows binaries of the pcregrep and pcretest programs here: http://www.rexegg.com/pcregrep-pcretest.html Building PCRE on non-Unix-like systems -------------------------------------- For a non-Unix-like system, please read the comments in the file NON-AUTOTOOLS-BUILD, though if your system supports the use of "configure" and "make" you may be able to build PCRE using autotools in the same way as for many Unix-like systems. PCRE can also be configured using the GUI facility provided by CMake's cmake-gui command. This creates Makefiles, solution files, etc. The file NON-AUTOTOOLS-BUILD has information about CMake. PCRE has been compiled on many different operating systems. It should be straightforward to build PCRE on any system that has a Standard C compiler and library, because it uses only Standard C functions. Building PCRE without using autotools ------------------------------------- The use of autotools (in particular, libtool) is problematic in some environments, even some that are Unix or Unix-like. See the NON-AUTOTOOLS-BUILD file for ways of building PCRE without using autotools. Building PCRE using autotools ----------------------------- If you are using HP's ANSI C++ compiler (aCC), please see the special note in the section entitled "Using HP's ANSI C++ compiler (aCC)" below. The following instructions assume the use of the widely used "configure; make; make install" (autotools) process. To build PCRE on system that supports autotools, first run the "configure" command from the PCRE distribution directory, with your current directory set to the directory where you want the files to be created. This command is a standard GNU "autoconf" configuration script, for which generic instructions are supplied in the file INSTALL. Most commonly, people build PCRE within its own distribution directory, and in this case, on many systems, just running "./configure" is sufficient. However, the usual methods of changing standard defaults are available. For example: CFLAGS='-O2 -Wall' ./configure --prefix=/opt/local This command specifies that the C compiler should be run with the flags '-O2 -Wall' instead of the default, and that "make install" should install PCRE under /opt/local instead of the default /usr/local. If you want to build in a different directory, just run "configure" with that directory as current. For example, suppose you have unpacked the PCRE source into /source/pcre/pcre-xxx, but you want to build it in /build/pcre/pcre-xxx: cd /build/pcre/pcre-xxx /source/pcre/pcre-xxx/configure PCRE is written in C and is normally compiled as a C library. However, it is possible to build it as a C++ library, though the provided building apparatus does not have any features to support this. There are some optional features that can be included or omitted from the PCRE library. They are also documented in the pcrebuild man page. . By default, both shared and static libraries are built. You can change this by adding one of these options to the "configure" command: --disable-shared --disable-static (See also "Shared libraries on Unix-like systems" below.) . By default, only the 8-bit library is built. If you add --enable-pcre16 to the "configure" command, the 16-bit library is also built. If you add --enable-pcre32 to the "configure" command, the 32-bit library is also built. If you want only the 16-bit or 32-bit library, use --disable-pcre8 to disable building the 8-bit library. . If you are building the 8-bit library and want to suppress the building of the C++ wrapper library, you can add --disable-cpp to the "configure" command. Otherwise, when "configure" is run without --disable-pcre8, it will try to find a C++ compiler and C++ header files, and if it succeeds, it will try to build the C++ wrapper. . If you want to include support for just-in-time compiling, which can give large performance improvements on certain platforms, add --enable-jit to the "configure" command. This support is available only for certain hardware architectures. If you try to enable it on an unsupported architecture, there will be a compile time error. . When JIT support is enabled, pcregrep automatically makes use of it, unless you add --disable-pcregrep-jit to the "configure" command. . If you want to make use of the support for UTF-8 Unicode character strings in the 8-bit library, or UTF-16 Unicode character strings in the 16-bit library, or UTF-32 Unicode character strings in the 32-bit library, you must add --enable-utf to the "configure" command. Without it, the code for handling UTF-8, UTF-16 and UTF-8 is not included in the relevant library. Even when --enable-utf is included, the use of a UTF encoding still has to be enabled by an option at run time. When PCRE is compiled with this option, its input can only either be ASCII or UTF-8/16/32, even when running on EBCDIC platforms. It is not possible to use both --enable-utf and --enable-ebcdic at the same time. . There are no separate options for enabling UTF-8, UTF-16 and UTF-32 independently because that would allow ridiculous settings such as requesting UTF-16 support while building only the 8-bit library. However, the option --enable-utf8 is retained for backwards compatibility with earlier releases that did not support 16-bit or 32-bit character strings. It is synonymous with --enable-utf. It is not possible to configure one library with UTF support and the other without in the same configuration. . If, in addition to support for UTF-8/16/32 character strings, you want to include support for the \P, \p, and \X sequences that recognize Unicode character properties, you must add --enable-unicode-properties to the "configure" command. This adds about 30K to the size of the library (in the form of a property table); only the basic two-letter properties such as Lu are supported. . You can build PCRE to recognize either CR or LF or the sequence CRLF or any of the preceding, or any of the Unicode newline sequences as indicating the end of a line. Whatever you specify at build time is the default; the caller of PCRE can change the selection at run time. The default newline indicator is a single LF character (the Unix standard). You can specify the default newline indicator by adding --enable-newline-is-cr or --enable-newline-is-lf or --enable-newline-is-crlf or --enable-newline-is-anycrlf or --enable-newline-is-any to the "configure" command, respectively. If you specify --enable-newline-is-cr or --enable-newline-is-crlf, some of the standard tests will fail, because the lines in the test files end with LF. Even if the files are edited to change the line endings, there are likely to be some failures. With --enable-newline-is-anycrlf or --enable-newline-is-any, many tests should succeed, but there may be some failures. . By default, the sequence \R in a pattern matches any Unicode line ending sequence. This is independent of the option specifying what PCRE considers to be the end of a line (see above). However, the caller of PCRE can restrict \R to match only CR, LF, or CRLF. You can make this the default by adding --enable-bsr-anycrlf to the "configure" command (bsr = "backslash R"). . When called via the POSIX interface, PCRE uses malloc() to get additional storage for processing capturing parentheses if there are more than 10 of them in a pattern. You can increase this threshold by setting, for example, --with-posix-malloc-threshold=20 on the "configure" command. . PCRE has a counter that limits the depth of nesting of parentheses in a pattern. This limits the amount of system stack that a pattern uses when it is compiled. The default is 250, but you can change it by setting, for example, --with-parens-nest-limit=500 . PCRE has a counter that can be set to limit the amount of resources it uses when matching a pattern. If the limit is exceeded during a match, the match fails. The default is ten million. You can change the default by setting, for example, --with-match-limit=500000 on the "configure" command. This is just the default; individual calls to pcre_exec() can supply their own value. There is more discussion on the pcreapi man page. . There is a separate counter that limits the depth of recursive function calls during a matching process. This also has a default of ten million, which is essentially "unlimited". You can change the default by setting, for example, --with-match-limit-recursion=500000 Recursive function calls use up the runtime stack; running out of stack can cause programs to crash in strange ways. There is a discussion about stack sizes in the pcrestack man page. . The default maximum compiled pattern size is around 64K. You can increase this by adding --with-link-size=3 to the "configure" command. In the 8-bit library, PCRE then uses three bytes instead of two for offsets to different parts of the compiled pattern. In the 16-bit library, --with-link-size=3 is the same as --with-link-size=4, which (in both libraries) uses four-byte offsets. Increasing the internal link size reduces performance. In the 32-bit library, the only supported link size is 4. . You can build PCRE so that its internal match() function that is called from pcre_exec() does not call itself recursively. Instead, it uses memory blocks obtained from the heap via the special functions pcre_stack_malloc() and pcre_stack_free() to save data that would otherwise be saved on the stack. To build PCRE like this, use --disable-stack-for-recursion on the "configure" command. PCRE runs more slowly in this mode, but it may be necessary in environments with limited stack sizes. This applies only to the normal execution of the pcre_exec() function; if JIT support is being successfully used, it is not relevant. Equally, it does not apply to pcre_dfa_exec(), which does not use deeply nested recursion. There is a discussion about stack sizes in the pcrestack man page. . For speed, PCRE uses four tables for manipulating and identifying characters whose code point values are less than 256. By default, it uses a set of tables for ASCII encoding that is part of the distribution. If you specify --enable-rebuild-chartables a program called dftables is compiled and run in the default C locale when you obey "make". It builds a source file called pcre_chartables.c. If you do not specify this option, pcre_chartables.c is created as a copy of pcre_chartables.c.dist. See "Character tables" below for further information. . It is possible to compile PCRE for use on systems that use EBCDIC as their character code (as opposed to ASCII/Unicode) by specifying --enable-ebcdic This automatically implies --enable-rebuild-chartables (see above). However, when PCRE is built this way, it always operates in EBCDIC. It cannot support both EBCDIC and UTF-8/16/32. There is a second option, --enable-ebcdic-nl25, which specifies that the code value for the EBCDIC NL character is 0x25 instead of the default 0x15. . In environments where valgrind is installed, if you specify --enable-valgrind PCRE will use valgrind annotations to mark certain memory regions as unaddressable. This allows it to detect invalid memory accesses, and is mostly useful for debugging PCRE itself. . In environments where the gcc compiler is used and lcov version 1.6 or above is installed, if you specify --enable-coverage the build process implements a code coverage report for the test suite. The report is generated by running "make coverage". If ccache is installed on your system, it must be disabled when building PCRE for coverage reporting. You can do this by setting the environment variable CCACHE_DISABLE=1 before running "make" to build PCRE. There is more information about coverage reporting in the "pcrebuild" documentation. . The pcregrep program currently supports only 8-bit data files, and so requires the 8-bit PCRE library. It is possible to compile pcregrep to use libz and/or libbz2, in order to read .gz and .bz2 files (respectively), by specifying one or both of --enable-pcregrep-libz --enable-pcregrep-libbz2 Of course, the relevant libraries must be installed on your system. . The default size (in bytes) of the internal buffer used by pcregrep can be set by, for example: --with-pcregrep-bufsize=51200 The value must be a plain integer. The default is 20480. . It is possible to compile pcretest so that it links with the libreadline or libedit libraries, by specifying, respectively, --enable-pcretest-libreadline or --enable-pcretest-libedit If this is done, when pcretest's input is from a terminal, it reads it using the readline() function. This provides line-editing and history facilities. Note that libreadline is GPL-licenced, so if you distribute a binary of pcretest linked in this way, there may be licensing issues. These can be avoided by linking with libedit (which has a BSD licence) instead. Enabling libreadline causes the -lreadline option to be added to the pcretest build. In many operating environments with a sytem-installed readline library this is sufficient. However, in some environments (e.g. if an unmodified distribution version of readline is in use), it may be necessary to specify something like LIBS="-lncurses" as well. This is because, to quote the readline INSTALL, "Readline uses the termcap functions, but does not link with the termcap or curses library itself, allowing applications which link with readline the to choose an appropriate library." If you get error messages about missing functions tgetstr, tgetent, tputs, tgetflag, or tgoto, this is the problem, and linking with the ncurses library should fix it. The "configure" script builds the following files for the basic C library: . Makefile the makefile that builds the library . config.h build-time configuration options for the library . pcre.h the public PCRE header file . pcre-config script that shows the building settings such as CFLAGS that were set for "configure" . libpcre.pc ) data for the pkg-config command . libpcre16.pc ) . libpcre32.pc ) . libpcreposix.pc ) . libtool script that builds shared and/or static libraries Versions of config.h and pcre.h are distributed in the PCRE tarballs under the names config.h.generic and pcre.h.generic. These are provided for those who have to built PCRE without using "configure" or CMake. If you use "configure" or CMake, the .generic versions are not used. When building the 8-bit library, if a C++ compiler is found, the following files are also built: . libpcrecpp.pc data for the pkg-config command . pcrecpparg.h header file for calling PCRE via the C++ wrapper . pcre_stringpiece.h header for the C++ "stringpiece" functions The "configure" script also creates config.status, which is an executable script that can be run to recreate the configuration, and config.log, which contains compiler output from tests that "configure" runs. Once "configure" has run, you can run "make". This builds the the libraries libpcre, libpcre16 and/or libpcre32, and a test program called pcretest. If you enabled JIT support with --enable-jit, a test program called pcre_jit_test is built as well. If the 8-bit library is built, libpcreposix and the pcregrep command are also built, and if a C++ compiler was found on your system, and you did not disable it with --disable-cpp, "make" builds the C++ wrapper library, which is called libpcrecpp, as well as some test programs called pcrecpp_unittest, pcre_scanner_unittest, and pcre_stringpiece_unittest. The command "make check" runs all the appropriate tests. Details of the PCRE tests are given below in a separate section of this document. You can use "make install" to install PCRE into live directories on your system. The following are installed (file names are all relative to the that is set when "configure" is run): Commands (bin): pcretest pcregrep (if 8-bit support is enabled) pcre-config Libraries (lib): libpcre16 (if 16-bit support is enabled) libpcre32 (if 32-bit support is enabled) libpcre (if 8-bit support is enabled) libpcreposix (if 8-bit support is enabled) libpcrecpp (if 8-bit and C++ support is enabled) Configuration information (lib/pkgconfig): libpcre16.pc libpcre32.pc libpcre.pc libpcreposix.pc libpcrecpp.pc (if C++ support is enabled) Header files (include): pcre.h pcreposix.h pcre_scanner.h ) pcre_stringpiece.h ) if C++ support is enabled pcrecpp.h ) pcrecpparg.h ) Man pages (share/man/man{1,3}): pcregrep.1 pcretest.1 pcre-config.1 pcre.3 pcre*.3 (lots more pages, all starting "pcre") HTML documentation (share/doc/pcre/html): index.html *.html (lots more pages, hyperlinked from index.html) Text file documentation (share/doc/pcre): AUTHORS COPYING ChangeLog LICENCE NEWS README pcre.txt (a concatenation of the man(3) pages) pcretest.txt the pcretest man page pcregrep.txt the pcregrep man page pcre-config.txt the pcre-config man page If you want to remove PCRE from your system, you can run "make uninstall". This removes all the files that "make install" installed. However, it does not remove any directories, because these are often shared with other programs. Retrieving configuration information ------------------------------------ Running "make install" installs the command pcre-config, which can be used to recall information about the PCRE configuration and installation. For example: pcre-config --version prints the version number, and pcre-config --libs outputs information about where the library is installed. This command can be included in makefiles for programs that use PCRE, saving the programmer from having to remember too many details. The pkg-config command is another system for saving and retrieving information about installed libraries. Instead of separate commands for each library, a single command is used. For example: pkg-config --cflags pcre The data is held in *.pc files that are installed in a directory called /lib/pkgconfig. Shared libraries ---------------- The default distribution builds PCRE as shared libraries and static libraries, as long as the operating system supports shared libraries. Shared library support relies on the "libtool" script which is built as part of the "configure" process. The libtool script is used to compile and link both shared and static libraries. They are placed in a subdirectory called .libs when they are newly built. The programs pcretest and pcregrep are built to use these uninstalled libraries (by means of wrapper scripts in the case of shared libraries). When you use "make install" to install shared libraries, pcregrep and pcretest are automatically re-built to use the newly installed shared libraries before being installed themselves. However, the versions left in the build directory still use the uninstalled libraries. To build PCRE using static libraries only you must use --disable-shared when configuring it. For example: ./configure --prefix=/usr/gnu --disable-shared Then run "make" in the usual way. Similarly, you can use --disable-static to build only shared libraries. Cross-compiling using autotools ------------------------------- You can specify CC and CFLAGS in the normal way to the "configure" command, in order to cross-compile PCRE for some other host. However, you should NOT specify --enable-rebuild-chartables, because if you do, the dftables.c source file is compiled and run on the local host, in order to generate the inbuilt character tables (the pcre_chartables.c file). This will probably not work, because dftables.c needs to be compiled with the local compiler, not the cross compiler. When --enable-rebuild-chartables is not specified, pcre_chartables.c is created by making a copy of pcre_chartables.c.dist, which is a default set of tables that assumes ASCII code. Cross-compiling with the default tables should not be a problem. If you need to modify the character tables when cross-compiling, you should move pcre_chartables.c.dist out of the way, then compile dftables.c by hand and run it on the local host to make a new version of pcre_chartables.c.dist. Then when you cross-compile PCRE this new version of the tables will be used. Using HP's ANSI C++ compiler (aCC) ---------------------------------- Unless C++ support is disabled by specifying the "--disable-cpp" option of the "configure" script, you must include the "-AA" option in the CXXFLAGS environment variable in order for the C++ components to compile correctly. Also, note that the aCC compiler on PA-RISC platforms may have a defect whereby needed libraries fail to get included when specifying the "-AA" compiler option. If you experience unresolved symbols when linking the C++ programs, use the workaround of specifying the following environment variable prior to running the "configure" script: CXXLDFLAGS="-lstd_v2 -lCsup_v2" Compiling in Tru64 using native compilers ----------------------------------------- The following error may occur when compiling with native compilers in the Tru64 operating system: CXX libpcrecpp_la-pcrecpp.lo cxx: Error: /usr/lib/cmplrs/cxx/V7.1-006/include/cxx/iosfwd, line 58: #error directive: "cannot include iosfwd -- define __USE_STD_IOSTREAM to override default - see section 7.1.2 of the C++ Using Guide" #error "cannot include iosfwd -- define __USE_STD_IOSTREAM to override default - see section 7.1.2 of the C++ Using Guide" This may be followed by other errors, complaining that 'namespace "std" has no member'. The solution to this is to add the line #define __USE_STD_IOSTREAM 1 to the config.h file. Using Sun's compilers for Solaris --------------------------------- A user reports that the following configurations work on Solaris 9 sparcv9 and Solaris 9 x86 (32-bit): Solaris 9 sparcv9: ./configure --disable-cpp CC=/bin/cc CFLAGS="-m64 -g" Solaris 9 x86: ./configure --disable-cpp CC=/bin/cc CFLAGS="-g" Using PCRE from MySQL --------------------- On systems where both PCRE and MySQL are installed, it is possible to make use of PCRE from within MySQL, as an alternative to the built-in pattern matching. There is a web page that tells you how to do this: http://www.mysqludf.org/lib_mysqludf_preg/index.php Making new tarballs ------------------- The command "make dist" creates three PCRE tarballs, in tar.gz, tar.bz2, and zip formats. The command "make distcheck" does the same, but then does a trial build of the new distribution to ensure that it works. If you have modified any of the man page sources in the doc directory, you should first run the PrepareRelease script before making a distribution. This script creates the .txt and HTML forms of the documentation from the man pages. Testing PCRE ------------ To test the basic PCRE library on a Unix-like system, run the RunTest script. There is another script called RunGrepTest that tests the options of the pcregrep command. If the C++ wrapper library is built, three test programs called pcrecpp_unittest, pcre_scanner_unittest, and pcre_stringpiece_unittest are also built. When JIT support is enabled, another test program called pcre_jit_test is built. Both the scripts and all the program tests are run if you obey "make check" or "make test". For other environments, see the instructions in NON-AUTOTOOLS-BUILD. The RunTest script runs the pcretest test program (which is documented in its own man page) on each of the relevant testinput files in the testdata directory, and compares the output with the contents of the corresponding testoutput files. RunTest uses a file called testtry to hold the main output from pcretest. Other files whose names begin with "test" are used as working files in some tests. Some tests are relevant only when certain build-time options were selected. For example, the tests for UTF-8/16/32 support are run only if --enable-utf was used. RunTest outputs a comment when it skips a test. Many of the tests that are not skipped are run up to three times. The second run forces pcre_study() to be called for all patterns except for a few in some tests that are marked "never study" (see the pcretest program for how this is done). If JIT support is available, the non-DFA tests are run a third time, this time with a forced pcre_study() with the PCRE_STUDY_JIT_COMPILE option. This testing can be suppressed by putting "nojit" on the RunTest command line. The entire set of tests is run once for each of the 8-bit, 16-bit and 32-bit libraries that are enabled. If you want to run just one set of tests, call RunTest with either the -8, -16 or -32 option. If valgrind is installed, you can run the tests under it by putting "valgrind" on the RunTest command line. To run pcretest on just one or more specific test files, give their numbers as arguments to RunTest, for example: RunTest 2 7 11 You can also specify ranges of tests such as 3-6 or 3- (meaning 3 to the end), or a number preceded by ~ to exclude a test. For example: Runtest 3-15 ~10 This runs tests 3 to 15, excluding test 10, and just ~13 runs all the tests except test 13. Whatever order the arguments are in, the tests are always run in numerical order. You can also call RunTest with the single argument "list" to cause it to output a list of tests. The first test file can be fed directly into the perltest.pl script to check that Perl gives the same results. The only difference you should see is in the first few lines, where the Perl version is given instead of the PCRE version. The second set of tests check pcre_fullinfo(), pcre_study(), pcre_copy_substring(), pcre_get_substring(), pcre_get_substring_list(), error detection, and run-time flags that are specific to PCRE, as well as the POSIX wrapper API. It also uses the debugging flags to check some of the internals of pcre_compile(). If you build PCRE with a locale setting that is not the standard C locale, the character tables may be different (see next paragraph). In some cases, this may cause failures in the second set of tests. For example, in a locale where the isprint() function yields TRUE for characters in the range 128-255, the use of [:isascii:] inside a character class defines a different set of characters, and this shows up in this test as a difference in the compiled code, which is being listed for checking. Where the comparison test output contains [\x00-\x7f] the test will contain [\x00-\xff], and similarly in some other cases. This is not a bug in PCRE. The third set of tests checks pcre_maketables(), the facility for building a set of character tables for a specific locale and using them instead of the default tables. The tests make use of the "fr_FR" (French) locale. Before running the test, the script checks for the presence of this locale by running the "locale" command. If that command fails, or if it doesn't include "fr_FR" in the list of available locales, the third test cannot be run, and a comment is output to say why. If running this test produces instances of the error ** Failed to set locale "fr_FR" in the comparison output, it means that locale is not available on your system, despite being listed by "locale". This does not mean that PCRE is broken. [If you are trying to run this test on Windows, you may be able to get it to work by changing "fr_FR" to "french" everywhere it occurs. Alternatively, use RunTest.bat. The version of RunTest.bat included with PCRE 7.4 and above uses Windows versions of test 2. More info on using RunTest.bat is included in the document entitled NON-UNIX-USE.] The fourth and fifth tests check the UTF-8/16/32 support and error handling and internal UTF features of PCRE that are not relevant to Perl, respectively. The sixth and seventh tests do the same for Unicode character properties support. The eighth, ninth, and tenth tests check the pcre_dfa_exec() alternative matching function, in non-UTF-8/16/32 mode, UTF-8/16/32 mode, and UTF-8/16/32 mode with Unicode property support, respectively. The eleventh test checks some internal offsets and code size features; it is run only when the default "link size" of 2 is set (in other cases the sizes change) and when Unicode property support is enabled. The twelfth test is run only when JIT support is available, and the thirteenth test is run only when JIT support is not available. They test some JIT-specific features such as information output from pcretest about JIT compilation. The fourteenth, fifteenth, and sixteenth tests are run only in 8-bit mode, and the seventeenth, eighteenth, and nineteenth tests are run only in 16/32-bit mode. These are tests that generate different output in the two modes. They are for general cases, UTF-8/16/32 support, and Unicode property support, respectively. The twentieth test is run only in 16/32-bit mode. It tests some specific 16/32-bit features of the DFA matching engine. The twenty-first and twenty-second tests are run only in 16/32-bit mode, when the link size is set to 2 for the 16-bit library. They test reloading pre-compiled patterns. The twenty-third and twenty-fourth tests are run only in 16-bit mode. They are for general cases, and UTF-16 support, respectively. The twenty-fifth and twenty-sixth tests are run only in 32-bit mode. They are for general cases, and UTF-32 support, respectively. Character tables ---------------- For speed, PCRE uses four tables for manipulating and identifying characters whose code point values are less than 256. The final argument of the pcre_compile() function is a pointer to a block of memory containing the concatenated tables. A call to pcre_maketables() can be used to generate a set of tables in the current locale. If the final argument for pcre_compile() is passed as NULL, a set of default tables that is built into the binary is used. The source file called pcre_chartables.c contains the default set of tables. By default, this is created as a copy of pcre_chartables.c.dist, which contains tables for ASCII coding. However, if --enable-rebuild-chartables is specified for ./configure, a different version of pcre_chartables.c is built by the program dftables (compiled from dftables.c), which uses the ANSI C character handling functions such as isalnum(), isalpha(), isupper(), islower(), etc. to build the table sources. This means that the default C locale which is set for your system will control the contents of these default tables. You can change the default tables by editing pcre_chartables.c and then re-building PCRE. If you do this, you should take care to ensure that the file does not get automatically re-generated. The best way to do this is to move pcre_chartables.c.dist out of the way and replace it with your customized tables. When the dftables program is run as a result of --enable-rebuild-chartables, it uses the default C locale that is set on your system. It does not pay attention to the LC_xxx environment variables. In other words, it uses the system's default locale rather than whatever the compiling user happens to have set. If you really do want to build a source set of character tables in a locale that is specified by the LC_xxx variables, you can run the dftables program by hand with the -L option. For example: ./dftables -L pcre_chartables.c.special The first two 256-byte tables provide lower casing and case flipping functions, respectively. The next table consists of three 32-byte bit maps which identify digits, "word" characters, and white space, respectively. These are used when building 32-byte bit maps that represent character classes for code points less than 256. The final 256-byte table has bits indicating various character types, as follows: 1 white space character 2 letter 4 decimal digit 8 hexadecimal digit 16 alphanumeric or '_' 128 regular expression metacharacter or binary zero You should not alter the set of characters that contain the 128 bit, as that will cause PCRE to malfunction. File manifest ------------- The distribution should contain the files listed below. Where a file name is given as pcre[16|32]_xxx it means that there are three files, one with the name pcre_xxx, one with the name pcre16_xx, and a third with the name pcre32_xxx. (A) Source files of the PCRE library functions and their headers: dftables.c auxiliary program for building pcre_chartables.c when --enable-rebuild-chartables is specified pcre_chartables.c.dist a default set of character tables that assume ASCII coding; used, unless --enable-rebuild-chartables is specified, by copying to pcre[16]_chartables.c pcreposix.c ) pcre[16|32]_byte_order.c ) pcre[16|32]_compile.c ) pcre[16|32]_config.c ) pcre[16|32]_dfa_exec.c ) pcre[16|32]_exec.c ) pcre[16|32]_fullinfo.c ) pcre[16|32]_get.c ) sources for the functions in the library, pcre[16|32]_globals.c ) and some internal functions that they use pcre[16|32]_jit_compile.c ) pcre[16|32]_maketables.c ) pcre[16|32]_newline.c ) pcre[16|32]_refcount.c ) pcre[16|32]_string_utils.c ) pcre[16|32]_study.c ) pcre[16|32]_tables.c ) pcre[16|32]_ucd.c ) pcre[16|32]_version.c ) pcre[16|32]_xclass.c ) pcre_ord2utf8.c ) pcre_valid_utf8.c ) pcre16_ord2utf16.c ) pcre16_utf16_utils.c ) pcre16_valid_utf16.c ) pcre32_utf32_utils.c ) pcre32_valid_utf32.c ) pcre[16|32]_printint.c ) debugging function that is used by pcretest, ) and can also be #included in pcre_compile() pcre.h.in template for pcre.h when built by "configure" pcreposix.h header for the external POSIX wrapper API pcre_internal.h header for internal use sljit/* 16 files that make up the JIT compiler ucp.h header for Unicode property handling config.h.in template for config.h, which is built by "configure" pcrecpp.h public header file for the C++ wrapper pcrecpparg.h.in template for another C++ header file pcre_scanner.h public header file for C++ scanner functions pcrecpp.cc ) pcre_scanner.cc ) source for the C++ wrapper library pcre_stringpiece.h.in template for pcre_stringpiece.h, the header for the C++ stringpiece functions pcre_stringpiece.cc source for the C++ stringpiece functions (B) Source files for programs that use PCRE: pcredemo.c simple demonstration of coding calls to PCRE pcregrep.c source of a grep utility that uses PCRE pcretest.c comprehensive test program (C) Auxiliary files: 132html script to turn "man" pages into HTML AUTHORS information about the author of PCRE ChangeLog log of changes to the code CleanTxt script to clean nroff output for txt man pages Detrail script to remove trailing spaces HACKING some notes about the internals of PCRE INSTALL generic installation instructions LICENCE conditions for the use of PCRE COPYING the same, using GNU's standard name Makefile.in ) template for Unix Makefile, which is built by ) "configure" Makefile.am ) the automake input that was used to create ) Makefile.in NEWS important changes in this release NON-UNIX-USE the previous name for NON-AUTOTOOLS-BUILD NON-AUTOTOOLS-BUILD notes on building PCRE without using autotools PrepareRelease script to make preparations for "make dist" README this file RunTest a Unix shell script for running tests RunGrepTest a Unix shell script for pcregrep tests aclocal.m4 m4 macros (generated by "aclocal") config.guess ) files used by libtool, config.sub ) used only when building a shared library configure a configuring shell script (built by autoconf) configure.ac ) the autoconf input that was used to build ) "configure" and config.h depcomp ) script to find program dependencies, generated by ) automake doc/*.3 man page sources for PCRE doc/*.1 man page sources for pcregrep and pcretest doc/index.html.src the base HTML page doc/html/* HTML documentation doc/pcre.txt plain text version of the man pages doc/pcretest.txt plain text documentation of test program doc/perltest.txt plain text documentation of Perl test program install-sh a shell script for installing files libpcre16.pc.in template for libpcre16.pc for pkg-config libpcre32.pc.in template for libpcre32.pc for pkg-config libpcre.pc.in template for libpcre.pc for pkg-config libpcreposix.pc.in template for libpcreposix.pc for pkg-config libpcrecpp.pc.in template for libpcrecpp.pc for pkg-config ltmain.sh file used to build a libtool script missing ) common stub for a few missing GNU programs while ) installing, generated by automake mkinstalldirs script for making install directories perltest.pl Perl test program pcre-config.in source of script which retains PCRE information pcre_jit_test.c test program for the JIT compiler pcrecpp_unittest.cc ) pcre_scanner_unittest.cc ) test programs for the C++ wrapper pcre_stringpiece_unittest.cc ) testdata/testinput* test data for main library tests testdata/testoutput* expected test results testdata/grep* input and output for pcregrep tests testdata/* other supporting test files (D) Auxiliary files for cmake support cmake/COPYING-CMAKE-SCRIPTS cmake/FindPackageHandleStandardArgs.cmake cmake/FindEditline.cmake cmake/FindReadline.cmake CMakeLists.txt config-cmake.h.in (E) Auxiliary files for VPASCAL makevp.bat makevp_c.txt makevp_l.txt pcregexp.pas (F) Auxiliary files for building PCRE "by hand" pcre.h.generic ) a version of the public PCRE header file ) for use in non-"configure" environments config.h.generic ) a version of config.h for use in non-"configure" ) environments (F) Miscellaneous RunTest.bat a script for running tests under Windows Philip Hazel Email local part: ph10 Email domain: cam.ac.uk Last updated: 10 February 2015 ================================================ FILE: src/pcre/doc/html/index.html ================================================ PCRE specification

    Perl-compatible Regular Expressions (PCRE)

    The HTML documentation for PCRE consists of a number of pages that are listed below in alphabetical order. If you are new to PCRE, please read the first one first.

    pcre   Introductory page
    pcre-config   Information about the installation configuration
    pcre16   Discussion of the 16-bit PCRE library
    pcre32   Discussion of the 32-bit PCRE library
    pcreapi   PCRE's native API
    pcrebuild   Building PCRE
    pcrecallout   The callout facility
    pcrecompat   Compability with Perl
    pcrecpp   The C++ wrapper for the PCRE library
    pcredemo   A demonstration C program that uses the PCRE library
    pcregrep   The pcregrep command
    pcrejit   Discussion of the just-in-time optimization support
    pcrelimits   Details of size and other limits
    pcrematching   Discussion of the two matching algorithms
    pcrepartial   Using PCRE for partial matching
    pcrepattern   Specification of the regular expressions supported by PCRE
    pcreperform   Some comments on performance
    pcreposix   The POSIX API to the PCRE 8-bit library
    pcreprecompile   How to save and re-use compiled patterns
    pcresample   Discussion of the pcredemo program
    pcrestack   Discussion of PCRE's stack usage
    pcresyntax   Syntax quick-reference summary
    pcretest   The pcretest command for testing PCRE
    pcreunicode   Discussion of Unicode and UTF-8/UTF-16/UTF-32 support

    There are also individual pages that summarize the interface for each function in the library. There is a single page for each triple of 8-bit/16-bit/32-bit functions.

    pcre_assign_jit_stack   Assign stack for JIT matching
    pcre_compile   Compile a regular expression
    pcre_compile2   Compile a regular expression (alternate interface)
    pcre_config   Show build-time configuration options
    pcre_copy_named_substring   Extract named substring into given buffer
    pcre_copy_substring   Extract numbered substring into given buffer
    pcre_dfa_exec   Match a compiled pattern to a subject string (DFA algorithm; not Perl compatible)
    pcre_exec   Match a compiled pattern to a subject string (Perl compatible)
    pcre_free_study   Free study data
    pcre_free_substring   Free extracted substring
    pcre_free_substring_list   Free list of extracted substrings
    pcre_fullinfo   Extract information about a pattern
    pcre_get_named_substring   Extract named substring into new memory
    pcre_get_stringnumber   Convert captured string name to number
    pcre_get_stringtable_entries   Find table entries for given string name
    pcre_get_substring   Extract numbered substring into new memory
    pcre_get_substring_list   Extract all substrings into new memory
    pcre_jit_exec   Fast path interface to JIT matching
    pcre_jit_stack_alloc   Create a stack for JIT matching
    pcre_jit_stack_free   Free a JIT matching stack
    pcre_maketables   Build character tables in current locale
    pcre_pattern_to_host_byte_order   Convert compiled pattern to host byte order if necessary
    pcre_refcount   Maintain reference count in compiled pattern
    pcre_study   Study a compiled pattern
    pcre_utf16_to_host_byte_order   Convert UTF-16 string to host byte order if necessary
    pcre_utf32_to_host_byte_order   Convert UTF-32 string to host byte order if necessary
    pcre_version   Return PCRE version and release date
    ================================================ FILE: src/pcre/doc/html/pcre-config.html ================================================ pcre-config specification

    pcre-config man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SYNOPSIS

    pcre-config [--prefix] [--exec-prefix] [--version] [--libs] [--libs16] [--libs32] [--libs-cpp] [--libs-posix] [--cflags] [--cflags-posix]


    DESCRIPTION

    pcre-config returns the configuration of the installed PCRE libraries and the options required to compile a program to use them. Some of the options apply only to the 8-bit, or 16-bit, or 32-bit libraries, respectively, and are not available if only one of those libraries has been built. If an unavailable option is encountered, the "usage" information is output.


    OPTIONS

    --prefix Writes the directory prefix used in the PCRE installation for architecture independent files (/usr on many systems, /usr/local on some systems) to the standard output.

    --exec-prefix Writes the directory prefix used in the PCRE installation for architecture dependent files (normally the same as --prefix) to the standard output.

    --version Writes the version number of the installed PCRE libraries to the standard output.

    --libs Writes to the standard output the command line options required to link with the 8-bit PCRE library (-lpcre on many systems).

    --libs16 Writes to the standard output the command line options required to link with the 16-bit PCRE library (-lpcre16 on many systems).

    --libs32 Writes to the standard output the command line options required to link with the 32-bit PCRE library (-lpcre32 on many systems).

    --libs-cpp Writes to the standard output the command line options required to link with PCRE's C++ wrapper library (-lpcrecpp -lpcre on many systems).

    --libs-posix Writes to the standard output the command line options required to link with PCRE's POSIX API wrapper library (-lpcreposix -lpcre on many systems).

    --cflags Writes to the standard output the command line options required to compile files that use PCRE (this may include some -I options, but is blank on many systems).

    --cflags-posix Writes to the standard output the command line options required to compile files that use PCRE's POSIX API wrapper library (this may include some -I options, but is blank on many systems).


    SEE ALSO

    pcre(3)


    AUTHOR

    This manual page was originally written by Mark Baker for the Debian GNU/Linux system. It has been subsequently revised as a generic PCRE man page.


    REVISION

    Last updated: 24 June 2012

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre.html ================================================ pcre specification

    pcre man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    PLEASE TAKE NOTE

    This document relates to PCRE releases that use the original API, with library names libpcre, libpcre16, and libpcre32. January 2015 saw the first release of a new API, known as PCRE2, with release numbers starting at 10.00 and library names libpcre2-8, libpcre2-16, and libpcre2-32. The old libraries (now called PCRE1) are still being maintained for bug fixes, but there will be no new development. New projects are advised to use the new PCRE2 libraries.


    INTRODUCTION

    The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl, with just a few differences. Some features that appeared in Python and PCRE before they appeared in Perl are also available using the Python syntax, there is some support for one or two .NET and Oniguruma syntax items, and there is an option for requesting some minor changes that give better JavaScript compatibility.

    Starting with release 8.30, it is possible to compile two separate PCRE libraries: the original, which supports 8-bit character strings (including UTF-8 strings), and a second library that supports 16-bit character strings (including UTF-16 strings). The build process allows either one or both to be built. The majority of the work to make this possible was done by Zoltan Herczeg.

    Starting with release 8.32 it is possible to compile a third separate PCRE library that supports 32-bit character strings (including UTF-32 strings). The build process allows any combination of the 8-, 16- and 32-bit libraries. The work to make this possible was done by Christian Persch.

    The three libraries contain identical sets of functions, except that the names in the 16-bit library start with pcre16_ instead of pcre_, and the names in the 32-bit library start with pcre32_ instead of pcre_. To avoid over-complication and reduce the documentation maintenance load, most of the documentation describes the 8-bit library, with the differences for the 16-bit and 32-bit libraries described separately in the pcre16 and pcre32 pages. References to functions or structures of the form pcre[16|32]_xxx should be read as meaning "pcre_xxx when using the 8-bit library, pcre16_xxx when using the 16-bit library, or pcre32_xxx when using the 32-bit library".

    The current implementation of PCRE corresponds approximately with Perl 5.12, including support for UTF-8/16/32 encoded strings and Unicode general category properties. However, UTF-8/16/32 and Unicode support has to be explicitly enabled; it is not the default. The Unicode tables correspond to Unicode release 6.3.0.

    In addition to the Perl-compatible matching function, PCRE contains an alternative function that matches the same compiled patterns in a different way. In certain circumstances, the alternative function has some advantages. For a discussion of the two matching algorithms, see the pcrematching page.

    PCRE is written in C and released as a C library. A number of people have written wrappers and interfaces of various kinds. In particular, Google Inc. have provided a comprehensive C++ wrapper for the 8-bit library. This is now included as part of the PCRE distribution. The pcrecpp page has details of this interface. Other people's contributions can be found in the Contrib directory at the primary FTP site, which is: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre

    Details of exactly which Perl regular expression features are and are not supported by PCRE are given in separate documents. See the pcrepattern and pcrecompat pages. There is a syntax summary in the pcresyntax page.

    Some features of PCRE can be included, excluded, or changed when the library is built. The pcre_config() function makes it possible for a client to discover which features are available. The features themselves are described in the pcrebuild page. Documentation about building PCRE for various operating systems can be found in the README and NON-AUTOTOOLS_BUILD files in the source distribution.

    The libraries contains a number of undocumented internal functions and data tables that are used by more than one of the exported external functions, but which are not intended for use by external callers. Their names all begin with "_pcre_" or "_pcre16_" or "_pcre32_", which hopefully will not provoke any name clashes. In some environments, it is possible to control which external symbols are exported when a shared library is built, and in these cases the undocumented symbols are not exported.


    SECURITY CONSIDERATIONS

    If you are using PCRE in a non-UTF application that permits users to supply arbitrary patterns for compilation, you should be aware of a feature that allows users to turn on UTF support from within a pattern, provided that PCRE was built with UTF support. For example, an 8-bit pattern that begins with "(*UTF8)" or "(*UTF)" turns on UTF-8 mode, which interprets patterns and subjects as strings of UTF-8 characters instead of individual 8-bit characters. This causes both the pattern and any data against which it is matched to be checked for UTF-8 validity. If the data string is very long, such a check might use sufficiently many resources as to cause your application to lose performance.

    One way of guarding against this possibility is to use the pcre_fullinfo() function to check the compiled pattern's options for UTF. Alternatively, from release 8.33, you can set the PCRE_NEVER_UTF option at compile time. This causes an compile time error if a pattern contains a UTF-setting sequence.

    If your application is one that supports UTF, be aware that validity checking can take time. If the same data string is to be matched many times, you can use the PCRE_NO_UTF[8|16|32]_CHECK option for the second and subsequent matches to save redundant checks.

    Another way that performance can be hit is by running a pattern that has a very large search tree against a string that will never match. Nested unlimited repeats in a pattern are a common example. PCRE provides some protection against this: see the PCRE_EXTRA_MATCH_LIMIT feature in the pcreapi page.


    USER DOCUMENTATION

    The user documentation for PCRE comprises a number of different sections. In the "man" format, each of these is a separate "man page". In the HTML format, each is a separate page, linked from the index page. In the plain text format, the descriptions of the pcregrep and pcretest programs are in files called pcregrep.txt and pcretest.txt, respectively. The remaining sections, except for the pcredemo section (which is a program listing), are concatenated in pcre.txt, for ease of searching. The sections are as follows:

      pcre              this document
      pcre-config       show PCRE installation configuration information
      pcre16            details of the 16-bit library
      pcre32            details of the 32-bit library
      pcreapi           details of PCRE's native C API
      pcrebuild         building PCRE
      pcrecallout       details of the callout feature
      pcrecompat        discussion of Perl compatibility
      pcrecpp           details of the C++ wrapper for the 8-bit library
      pcredemo          a demonstration C program that uses PCRE
      pcregrep          description of the pcregrep command (8-bit only)
      pcrejit           discussion of the just-in-time optimization support
      pcrelimits        details of size and other limits
      pcrematching      discussion of the two matching algorithms
      pcrepartial       details of the partial matching facility
      pcrepattern       syntax and semantics of supported regular expressions
      pcreperform       discussion of performance issues
      pcreposix         the POSIX-compatible C API for the 8-bit library
      pcreprecompile    details of saving and re-using precompiled patterns
      pcresample        discussion of the pcredemo program
      pcrestack         discussion of stack usage
      pcresyntax        quick syntax reference
      pcretest          description of the pcretest testing command
      pcreunicode       discussion of Unicode and UTF-8/16/32 support
    
    In the "man" and HTML formats, there is also a short page for each C library function, listing its arguments and results.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.

    Putting an actual email address here seems to have been a spam magnet, so I've taken it away. If you want to email me, use my two initials, followed by the two digits 10, at the domain cam.ac.uk.


    REVISION

    Last updated: 10 February 2015
    Copyright © 1997-2015 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre16.html ================================================ pcre16 specification

    pcre16 man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    #include <pcre.h>


    PCRE 16-BIT API BASIC FUNCTIONS

    pcre16 *pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre16 *pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre16_extra *pcre16_study(const pcre16 *code, int options, const char **errptr);

    void pcre16_free_study(pcre16_extra *extra);

    int pcre16_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize);

    int pcre16_dfa_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);


    PCRE 16-BIT API STRING EXTRACTION FUNCTIONS

    int pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_UCHAR16 *buffer, int buffersize);

    int pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR16 *buffer, int buffersize);

    int pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_SPTR16 *stringptr);

    int pcre16_get_stringnumber(const pcre16 *code, " PCRE_SPTR16 name);

    int pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 name, PCRE_UCHAR16 **first, PCRE_UCHAR16 **last);

    int pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR16 *stringptr);

    int pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 **listptr);

    void pcre16_free_substring(PCRE_SPTR16 stringptr);

    void pcre16_free_substring_list(PCRE_SPTR16 *stringptr);


    PCRE 16-BIT API AUXILIARY FUNCTIONS

    pcre16_jit_stack *pcre16_jit_stack_alloc(int startsize, int maxsize);

    void pcre16_jit_stack_free(pcre16_jit_stack *stack);

    void pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *data);

    const unsigned char *pcre16_maketables(void);

    int pcre16_fullinfo(const pcre16 *code, const pcre16_extra *extra, int what, void *where);

    int pcre16_refcount(pcre16 *code, int adjust);

    int pcre16_config(int what, void *where);

    const char *pcre16_version(void);

    int pcre16_pattern_to_host_byte_order(pcre16 *code, pcre16_extra *extra, const unsigned char *tables);


    PCRE 16-BIT API INDIRECTED FUNCTIONS

    void *(*pcre16_malloc)(size_t);

    void (*pcre16_free)(void *);

    void *(*pcre16_stack_malloc)(size_t);

    void (*pcre16_stack_free)(void *);

    int (*pcre16_callout)(pcre16_callout_block *);


    PCRE 16-BIT API 16-BIT-ONLY FUNCTION

    int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input, int length, int *byte_order, int keep_boms);


    THE PCRE 16-BIT LIBRARY

    Starting with release 8.30, it is possible to compile a PCRE library that supports 16-bit character strings, including UTF-16 strings, as well as or instead of the original 8-bit library. The majority of the work to make this possible was done by Zoltan Herczeg. The two libraries contain identical sets of functions, used in exactly the same way. Only the names of the functions and the data types of their arguments and results are different. To avoid over-complication and reduce the documentation maintenance load, most of the PCRE documentation describes the 8-bit library, with only occasional references to the 16-bit library. This page describes what is different when you use the 16-bit library.

    WARNING: A single application can be linked with both libraries, but you must take care when processing any particular pattern to use functions from just one library. For example, if you want to study a pattern that was compiled with pcre16_compile(), you must do so with pcre16_study(), not pcre_study(), and you must free the study data with pcre16_free_study().


    THE HEADER FILE

    There is only one header file, pcre.h. It contains prototypes for all the functions in all libraries, as well as definitions of flags, structures, error codes, etc.


    THE LIBRARY NAME

    In Unix-like systems, the 16-bit library is called libpcre16, and can normally be accesss by adding -lpcre16 to the command for linking an application that uses PCRE.


    STRING TYPES

    In the 8-bit library, strings are passed to PCRE library functions as vectors of bytes with the C type "char *". In the 16-bit library, strings are passed as vectors of unsigned 16-bit quantities. The macro PCRE_UCHAR16 specifies an appropriate data type, and PCRE_SPTR16 is defined as "const PCRE_UCHAR16 *". In very many environments, "short int" is a 16-bit data type. When PCRE is built, it defines PCRE_UCHAR16 as "unsigned short int", but checks that it really is a 16-bit data type. If it is not, the build fails with an error message telling the maintainer to modify the definition appropriately.


    STRUCTURE TYPES

    The types of the opaque structures that are used for compiled 16-bit patterns and JIT stacks are pcre16 and pcre16_jit_stack respectively. The type of the user-accessible structure that is returned by pcre16_study() is pcre16_extra, and the type of the structure that is used for passing data to a callout function is pcre16_callout_block. These structures contain the same fields, with the same names, as their 8-bit counterparts. The only difference is that pointers to character strings are 16-bit instead of 8-bit types.


    16-BIT FUNCTIONS

    For every function in the 8-bit library there is a corresponding function in the 16-bit library with a name that starts with pcre16_ instead of pcre_. The prototypes are listed above. In addition, there is one extra function, pcre16_utf16_to_host_byte_order(). This is a utility function that converts a UTF-16 character string to host byte order if necessary. The other 16-bit functions expect the strings they are passed to be in host byte order.

    The input and output arguments of pcre16_utf16_to_host_byte_order() may point to the same address, that is, conversion in place is supported. The output buffer must be at least as long as the input.

    The length argument specifies the number of 16-bit data units in the input string; a negative value specifies a zero-terminated string.

    If byte_order is NULL, it is assumed that the string starts off in host byte order. This may be changed by byte-order marks (BOMs) anywhere in the string (commonly as the first character).

    If byte_order is not NULL, a non-zero value of the integer to which it points means that the input starts off in host byte order, otherwise the opposite order is assumed. Again, BOMs in the string can change this. The final byte order is passed back at the end of processing.

    If keep_boms is not zero, byte-order mark characters (0xfeff) are copied into the output string. Otherwise they are discarded.

    The result of the function is the number of 16-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated.


    SUBJECT STRING OFFSETS

    The lengths and starting offsets of subject strings must be specified in 16-bit data units, and the offsets within subject strings that are returned by the matching functions are in also 16-bit units rather than bytes.


    NAMED SUBPATTERNS

    The name-to-number translation table that is maintained for named subpatterns uses 16-bit characters. The pcre16_get_stringtable_entries() function returns the length of each entry in the table as the number of 16-bit data units.


    OPTION NAMES

    There are two new general option names, PCRE_UTF16 and PCRE_NO_UTF16_CHECK, which correspond to PCRE_UTF8 and PCRE_NO_UTF8_CHECK in the 8-bit library. In fact, these new options define the same bits in the options word. There is a discussion about the validity of UTF-16 strings in the pcreunicode page.

    For the pcre16_config() function there is an option PCRE_CONFIG_UTF16 that returns 1 if UTF-16 support is configured, otherwise 0. If this option is given to pcre_config() or pcre32_config(), or if the PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF32 option is given to pcre16_config(), the result is the PCRE_ERROR_BADOPTION error.


    CHARACTER CODES

    In 16-bit mode, when PCRE_UTF16 is not set, character values are treated in the same way as in 8-bit, non UTF-8 mode, except, of course, that they can range from 0 to 0xffff instead of 0 to 0xff. Character types for characters less than 0xff can therefore be influenced by the locale in the same way as before. Characters greater than 0xff have only one case, and no "type" (such as letter or digit).

    In UTF-16 mode, the character code is Unicode, in the range 0 to 0x10ffff, with the exception of values in the range 0xd800 to 0xdfff because those are "surrogate" values that are used in pairs to encode values greater than 0xffff.

    A UTF-16 string can indicate its endianness by special code knows as a byte-order mark (BOM). The PCRE functions do not handle this, expecting strings to be in host byte order. A utility function called pcre16_utf16_to_host_byte_order() is provided to help with this (see above).


    ERROR NAMES

    The errors PCRE_ERROR_BADUTF16_OFFSET and PCRE_ERROR_SHORTUTF16 correspond to their 8-bit counterparts. The error PCRE_ERROR_BADMODE is given when a compiled pattern is passed to a function that processes patterns in the other mode, for example, if a pattern compiled with pcre_compile() is passed to pcre16_exec().

    There are new error codes whose names begin with PCRE_UTF16_ERR for invalid UTF-16 strings, corresponding to the PCRE_UTF8_ERR codes for UTF-8 strings that are described in the section entitled "Reason codes for invalid UTF-8 strings" in the main pcreapi page. The UTF-16 errors are:

      PCRE_UTF16_ERR1  Missing low surrogate at end of string
      PCRE_UTF16_ERR2  Invalid low surrogate follows high surrogate
      PCRE_UTF16_ERR3  Isolated low surrogate
      PCRE_UTF16_ERR4  Non-character
    


    ERROR TEXTS

    If there is an error while compiling a pattern, the error text that is passed back by pcre16_compile() or pcre16_compile2() is still an 8-bit character string, zero-terminated.


    CALLOUTS

    The subject and mark fields in the callout block that is passed to a callout function point to 16-bit vectors.


    TESTING

    The pcretest program continues to operate with 8-bit input and output files, but it can be used for testing the 16-bit library. If it is run with the command line option -16, patterns and subject strings are converted from 8-bit to 16-bit before being passed to PCRE, and the 16-bit library functions are used instead of the 8-bit ones. Returned 16-bit strings are converted to 8-bit for output. If both the 8-bit and the 32-bit libraries were not compiled, pcretest defaults to 16-bit and the -16 option is ignored.

    When PCRE is being built, the RunTest script that is called by "make check" uses the pcretest -C option to discover which of the 8-bit, 16-bit and 32-bit libraries has been built, and runs the tests appropriately.


    NOT SUPPORTED IN 16-BIT MODE

    Not all the features of the 8-bit library are available with the 16-bit library. The C++ and POSIX wrapper functions support only the 8-bit library, and the pcregrep program is at present 8-bit only.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 12 May 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre32.html ================================================ pcre32 specification

    pcre32 man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    #include <pcre.h>


    PCRE 32-BIT API BASIC FUNCTIONS

    pcre32 *pcre32_compile(PCRE_SPTR32 pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre32 *pcre32_compile2(PCRE_SPTR32 pattern, int options, int *errorcodeptr, const unsigned char *tableptr);

    pcre32_extra *pcre32_study(const pcre32 *code, int options, const char **errptr);

    void pcre32_free_study(pcre32_extra *extra);

    int pcre32_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize);

    int pcre32_dfa_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);


    PCRE 32-BIT API STRING EXTRACTION FUNCTIONS

    int pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_UCHAR32 *buffer, int buffersize);

    int pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR32 *buffer, int buffersize);

    int pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_SPTR32 *stringptr);

    int pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 name);

    int pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 name, PCRE_UCHAR32 **first, PCRE_UCHAR32 **last);

    int pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR32 *stringptr);

    int pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 **listptr);

    void pcre32_free_substring(PCRE_SPTR32 stringptr);

    void pcre32_free_substring_list(PCRE_SPTR32 *stringptr);


    PCRE 32-BIT API AUXILIARY FUNCTIONS

    pcre32_jit_stack *pcre32_jit_stack_alloc(int startsize, int maxsize);

    void pcre32_jit_stack_free(pcre32_jit_stack *stack);

    void pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *data);

    const unsigned char *pcre32_maketables(void);

    int pcre32_fullinfo(const pcre32 *code, const pcre32_extra *extra, int what, void *where);

    int pcre32_refcount(pcre32 *code, int adjust);

    int pcre32_config(int what, void *where);

    const char *pcre32_version(void);

    int pcre32_pattern_to_host_byte_order(pcre32 *code, pcre32_extra *extra, const unsigned char *tables);


    PCRE 32-BIT API INDIRECTED FUNCTIONS

    void *(*pcre32_malloc)(size_t);

    void (*pcre32_free)(void *);

    void *(*pcre32_stack_malloc)(size_t);

    void (*pcre32_stack_free)(void *);

    int (*pcre32_callout)(pcre32_callout_block *);


    PCRE 32-BIT API 32-BIT-ONLY FUNCTION

    int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *output, PCRE_SPTR32 input, int length, int *byte_order, int keep_boms);


    THE PCRE 32-BIT LIBRARY

    Starting with release 8.32, it is possible to compile a PCRE library that supports 32-bit character strings, including UTF-32 strings, as well as or instead of the original 8-bit library. This work was done by Christian Persch, based on the work done by Zoltan Herczeg for the 16-bit library. All three libraries contain identical sets of functions, used in exactly the same way. Only the names of the functions and the data types of their arguments and results are different. To avoid over-complication and reduce the documentation maintenance load, most of the PCRE documentation describes the 8-bit library, with only occasional references to the 16-bit and 32-bit libraries. This page describes what is different when you use the 32-bit library.

    WARNING: A single application can be linked with all or any of the three libraries, but you must take care when processing any particular pattern to use functions from just one library. For example, if you want to study a pattern that was compiled with pcre32_compile(), you must do so with pcre32_study(), not pcre_study(), and you must free the study data with pcre32_free_study().


    THE HEADER FILE

    There is only one header file, pcre.h. It contains prototypes for all the functions in all libraries, as well as definitions of flags, structures, error codes, etc.


    THE LIBRARY NAME

    In Unix-like systems, the 32-bit library is called libpcre32, and can normally be accesss by adding -lpcre32 to the command for linking an application that uses PCRE.


    STRING TYPES

    In the 8-bit library, strings are passed to PCRE library functions as vectors of bytes with the C type "char *". In the 32-bit library, strings are passed as vectors of unsigned 32-bit quantities. The macro PCRE_UCHAR32 specifies an appropriate data type, and PCRE_SPTR32 is defined as "const PCRE_UCHAR32 *". In very many environments, "unsigned int" is a 32-bit data type. When PCRE is built, it defines PCRE_UCHAR32 as "unsigned int", but checks that it really is a 32-bit data type. If it is not, the build fails with an error message telling the maintainer to modify the definition appropriately.


    STRUCTURE TYPES

    The types of the opaque structures that are used for compiled 32-bit patterns and JIT stacks are pcre32 and pcre32_jit_stack respectively. The type of the user-accessible structure that is returned by pcre32_study() is pcre32_extra, and the type of the structure that is used for passing data to a callout function is pcre32_callout_block. These structures contain the same fields, with the same names, as their 8-bit counterparts. The only difference is that pointers to character strings are 32-bit instead of 8-bit types.


    32-BIT FUNCTIONS

    For every function in the 8-bit library there is a corresponding function in the 32-bit library with a name that starts with pcre32_ instead of pcre_. The prototypes are listed above. In addition, there is one extra function, pcre32_utf32_to_host_byte_order(). This is a utility function that converts a UTF-32 character string to host byte order if necessary. The other 32-bit functions expect the strings they are passed to be in host byte order.

    The input and output arguments of pcre32_utf32_to_host_byte_order() may point to the same address, that is, conversion in place is supported. The output buffer must be at least as long as the input.

    The length argument specifies the number of 32-bit data units in the input string; a negative value specifies a zero-terminated string.

    If byte_order is NULL, it is assumed that the string starts off in host byte order. This may be changed by byte-order marks (BOMs) anywhere in the string (commonly as the first character).

    If byte_order is not NULL, a non-zero value of the integer to which it points means that the input starts off in host byte order, otherwise the opposite order is assumed. Again, BOMs in the string can change this. The final byte order is passed back at the end of processing.

    If keep_boms is not zero, byte-order mark characters (0xfeff) are copied into the output string. Otherwise they are discarded.

    The result of the function is the number of 32-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated.


    SUBJECT STRING OFFSETS

    The lengths and starting offsets of subject strings must be specified in 32-bit data units, and the offsets within subject strings that are returned by the matching functions are in also 32-bit units rather than bytes.


    NAMED SUBPATTERNS

    The name-to-number translation table that is maintained for named subpatterns uses 32-bit characters. The pcre32_get_stringtable_entries() function returns the length of each entry in the table as the number of 32-bit data units.


    OPTION NAMES

    There are two new general option names, PCRE_UTF32 and PCRE_NO_UTF32_CHECK, which correspond to PCRE_UTF8 and PCRE_NO_UTF8_CHECK in the 8-bit library. In fact, these new options define the same bits in the options word. There is a discussion about the validity of UTF-32 strings in the pcreunicode page.

    For the pcre32_config() function there is an option PCRE_CONFIG_UTF32 that returns 1 if UTF-32 support is configured, otherwise 0. If this option is given to pcre_config() or pcre16_config(), or if the PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF16 option is given to pcre32_config(), the result is the PCRE_ERROR_BADOPTION error.


    CHARACTER CODES

    In 32-bit mode, when PCRE_UTF32 is not set, character values are treated in the same way as in 8-bit, non UTF-8 mode, except, of course, that they can range from 0 to 0x7fffffff instead of 0 to 0xff. Character types for characters less than 0xff can therefore be influenced by the locale in the same way as before. Characters greater than 0xff have only one case, and no "type" (such as letter or digit).

    In UTF-32 mode, the character code is Unicode, in the range 0 to 0x10ffff, with the exception of values in the range 0xd800 to 0xdfff because those are "surrogate" values that are ill-formed in UTF-32.

    A UTF-32 string can indicate its endianness by special code knows as a byte-order mark (BOM). The PCRE functions do not handle this, expecting strings to be in host byte order. A utility function called pcre32_utf32_to_host_byte_order() is provided to help with this (see above).


    ERROR NAMES

    The error PCRE_ERROR_BADUTF32 corresponds to its 8-bit counterpart. The error PCRE_ERROR_BADMODE is given when a compiled pattern is passed to a function that processes patterns in the other mode, for example, if a pattern compiled with pcre_compile() is passed to pcre32_exec().

    There are new error codes whose names begin with PCRE_UTF32_ERR for invalid UTF-32 strings, corresponding to the PCRE_UTF8_ERR codes for UTF-8 strings that are described in the section entitled "Reason codes for invalid UTF-8 strings" in the main pcreapi page. The UTF-32 errors are:

      PCRE_UTF32_ERR1  Surrogate character (range from 0xd800 to 0xdfff)
      PCRE_UTF32_ERR2  Non-character
      PCRE_UTF32_ERR3  Character > 0x10ffff
    


    ERROR TEXTS

    If there is an error while compiling a pattern, the error text that is passed back by pcre32_compile() or pcre32_compile2() is still an 8-bit character string, zero-terminated.


    CALLOUTS

    The subject and mark fields in the callout block that is passed to a callout function point to 32-bit vectors.


    TESTING

    The pcretest program continues to operate with 8-bit input and output files, but it can be used for testing the 32-bit library. If it is run with the command line option -32, patterns and subject strings are converted from 8-bit to 32-bit before being passed to PCRE, and the 32-bit library functions are used instead of the 8-bit ones. Returned 32-bit strings are converted to 8-bit for output. If both the 8-bit and the 16-bit libraries were not compiled, pcretest defaults to 32-bit and the -32 option is ignored.

    When PCRE is being built, the RunTest script that is called by "make check" uses the pcretest -C option to discover which of the 8-bit, 16-bit and 32-bit libraries has been built, and runs the tests appropriately.


    NOT SUPPORTED IN 32-BIT MODE

    Not all the features of the 8-bit library are available with the 32-bit library. The C++ and POSIX wrapper functions support only the 8-bit library, and the pcregrep program is at present 8-bit only.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 12 May 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_assign_jit_stack.html ================================================ pcre_assign_jit_stack specification

    pcre_assign_jit_stack man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    void pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *data);

    void pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *data);

    void pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *data);


    DESCRIPTION

    This function provides control over the memory used as a stack at run-time by a call to pcre[16|32]_exec() with a pattern that has been successfully compiled with JIT optimization. The arguments are:

      extra     the data pointer returned by pcre[16|32]_study()
      callback  a callback function
      data      a JIT stack or a value to be passed to the callback
                  function
    

    If callback is NULL and data is NULL, an internal 32K block on the machine stack is used.

    If callback is NULL and data is not NULL, data must be a valid JIT stack, the result of calling pcre[16|32]_jit_stack_alloc().

    If callback not NULL, it is called with data as an argument at the start of matching, in order to set up a JIT stack. If the result is NULL, the internal 32K stack is used; otherwise the return value must be a valid JIT stack, the result of calling pcre[16|32]_jit_stack_alloc().

    You may safely assign the same JIT stack to multiple patterns, as long as they are all matched in the same thread. In a multithread application, each thread must use its own JIT stack. For more details, see the pcrejit page.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_compile.html ================================================ pcre_compile specification

    pcre_compile man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre16 *pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre32 *pcre32_compile(PCRE_SPTR32 pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);


    DESCRIPTION

    This function compiles a regular expression into an internal form. It is the same as pcre[16|32]_compile2(), except for the absence of the errorcodeptr argument. Its arguments are:

      pattern       A zero-terminated string containing the
                      regular expression to be compiled
      options       Zero or more option bits
      errptr        Where to put an error message
      erroffset     Offset in pattern where error was found
      tableptr      Pointer to character tables, or NULL to
                      use the built-in default
    
    The option bits are:
      PCRE_ANCHORED           Force pattern anchoring
      PCRE_AUTO_CALLOUT       Compile automatic callouts
      PCRE_BSR_ANYCRLF        \R matches only CR, LF, or CRLF
      PCRE_BSR_UNICODE        \R matches all Unicode line endings
      PCRE_CASELESS           Do caseless matching
      PCRE_DOLLAR_ENDONLY     $ not to match newline at end
      PCRE_DOTALL             . matches anything including NL
      PCRE_DUPNAMES           Allow duplicate names for subpatterns
      PCRE_EXTENDED           Ignore white space and # comments
      PCRE_EXTRA              PCRE extra features
                                (not much use currently)
      PCRE_FIRSTLINE          Force matching to be before newline
      PCRE_JAVASCRIPT_COMPAT  JavaScript compatibility
      PCRE_MULTILINE          ^ and $ match newlines within data
      PCRE_NEVER_UTF          Lock out UTF, e.g. via (*UTF)
      PCRE_NEWLINE_ANY        Recognize any Unicode newline sequence
      PCRE_NEWLINE_ANYCRLF    Recognize CR, LF, and CRLF as newline
                                sequences
      PCRE_NEWLINE_CR         Set CR as the newline sequence
      PCRE_NEWLINE_CRLF       Set CRLF as the newline sequence
      PCRE_NEWLINE_LF         Set LF as the newline sequence
      PCRE_NO_AUTO_CAPTURE    Disable numbered capturing paren-
                                theses (named ones available)
      PCRE_NO_AUTO_POSSESS    Disable auto-possessification
      PCRE_NO_START_OPTIMIZE  Disable match-time start optimizations
      PCRE_NO_UTF16_CHECK     Do not check the pattern for UTF-16
                                validity (only relevant if
                                PCRE_UTF16 is set)
      PCRE_NO_UTF32_CHECK     Do not check the pattern for UTF-32
                                validity (only relevant if
                                PCRE_UTF32 is set)
      PCRE_NO_UTF8_CHECK      Do not check the pattern for UTF-8
                                validity (only relevant if
                                PCRE_UTF8 is set)
      PCRE_UCP                Use Unicode properties for \d, \w, etc.
      PCRE_UNGREEDY           Invert greediness of quantifiers
      PCRE_UTF16              Run in pcre16_compile() UTF-16 mode
      PCRE_UTF32              Run in pcre32_compile() UTF-32 mode
      PCRE_UTF8               Run in pcre_compile() UTF-8 mode
    
    PCRE must be built with UTF support in order to use PCRE_UTF8/16/32 and PCRE_NO_UTF8/16/32_CHECK, and with UCP support if PCRE_UCP is used.

    The yield of the function is a pointer to a private data structure that contains the compiled pattern, or NULL if an error was detected. Note that compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_compile2.html ================================================ pcre_compile2 specification

    pcre_compile2 man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    pcre *pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre16 *pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre32 *pcre32_compile2(PCRE_SPTR32 pattern, int options, " int *errorcodeptr const char **errptr, int *erroffset, const unsigned char *tableptr);


    DESCRIPTION

    This function compiles a regular expression into an internal form. It is the same as pcre[16|32]_compile(), except for the addition of the errorcodeptr argument. The arguments are:

      pattern       A zero-terminated string containing the
                      regular expression to be compiled
      options       Zero or more option bits
      errorcodeptr  Where to put an error code
      errptr        Where to put an error message
      erroffset     Offset in pattern where error was found
      tableptr      Pointer to character tables, or NULL to
                      use the built-in default
    
    The option bits are:
      PCRE_ANCHORED           Force pattern anchoring
      PCRE_AUTO_CALLOUT       Compile automatic callouts
      PCRE_BSR_ANYCRLF        \R matches only CR, LF, or CRLF
      PCRE_BSR_UNICODE        \R matches all Unicode line endings
      PCRE_CASELESS           Do caseless matching
      PCRE_DOLLAR_ENDONLY     $ not to match newline at end
      PCRE_DOTALL             . matches anything including NL
      PCRE_DUPNAMES           Allow duplicate names for subpatterns
      PCRE_EXTENDED           Ignore white space and # comments
      PCRE_EXTRA              PCRE extra features
                                (not much use currently)
      PCRE_FIRSTLINE          Force matching to be before newline
      PCRE_JAVASCRIPT_COMPAT  JavaScript compatibility
      PCRE_MULTILINE          ^ and $ match newlines within data
      PCRE_NEVER_UTF          Lock out UTF, e.g. via (*UTF)
      PCRE_NEWLINE_ANY        Recognize any Unicode newline sequence
      PCRE_NEWLINE_ANYCRLF    Recognize CR, LF, and CRLF as newline
                                sequences
      PCRE_NEWLINE_CR         Set CR as the newline sequence
      PCRE_NEWLINE_CRLF       Set CRLF as the newline sequence
      PCRE_NEWLINE_LF         Set LF as the newline sequence
      PCRE_NO_AUTO_CAPTURE    Disable numbered capturing paren-
                                theses (named ones available)
      PCRE_NO_AUTO_POSSESS    Disable auto-possessification
      PCRE_NO_START_OPTIMIZE  Disable match-time start optimizations
      PCRE_NO_UTF16_CHECK     Do not check the pattern for UTF-16
                                validity (only relevant if
                                PCRE_UTF16 is set)
      PCRE_NO_UTF32_CHECK     Do not check the pattern for UTF-32
                                validity (only relevant if
                                PCRE_UTF32 is set)
      PCRE_NO_UTF8_CHECK      Do not check the pattern for UTF-8
                                validity (only relevant if
                                PCRE_UTF8 is set)
      PCRE_UCP                Use Unicode properties for \d, \w, etc.
      PCRE_UNGREEDY           Invert greediness of quantifiers
      PCRE_UTF16              Run pcre16_compile() in UTF-16 mode
      PCRE_UTF32              Run pcre32_compile() in UTF-32 mode
      PCRE_UTF8               Run pcre_compile() in UTF-8 mode
    
    PCRE must be built with UTF support in order to use PCRE_UTF8/16/32 and PCRE_NO_UTF8/16/32_CHECK, and with UCP support if PCRE_UCP is used.

    The yield of the function is a pointer to a private data structure that contains the compiled pattern, or NULL if an error was detected. Note that compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_config.html ================================================ pcre_config specification

    pcre_config man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_config(int what, void *where);

    int pcre16_config(int what, void *where);

    int pcre32_config(int what, void *where);


    DESCRIPTION

    This function makes it possible for a client program to find out which optional features are available in the version of the PCRE library it is using. The arguments are as follows:

      what     A code specifying what information is required
      where    Points to where to put the data
    
    The where argument must point to an integer variable, except for PCRE_CONFIG_MATCH_LIMIT, PCRE_CONFIG_MATCH_LIMIT_RECURSION, and PCRE_CONFIG_PARENS_LIMIT, when it must point to an unsigned long integer, and for PCRE_CONFIG_JITTARGET, when it must point to a const char*. The available codes are:
      PCRE_CONFIG_JIT           Availability of just-in-time compiler
                                  support (1=yes 0=no)
      PCRE_CONFIG_JITTARGET     String containing information about the
                                  target architecture for the JIT compiler,
                                  or NULL if there is no JIT support
      PCRE_CONFIG_LINK_SIZE     Internal link size: 2, 3, or 4
      PCRE_CONFIG_PARENS_LIMIT  Parentheses nesting limit
      PCRE_CONFIG_MATCH_LIMIT   Internal resource limit
      PCRE_CONFIG_MATCH_LIMIT_RECURSION
                                Internal recursion depth limit
      PCRE_CONFIG_NEWLINE       Value of the default newline sequence:
                                    13 (0x000d)    for CR
                                    10 (0x000a)    for LF
                                  3338 (0x0d0a)    for CRLF
                                    -2             for ANYCRLF
                                    -1             for ANY
      PCRE_CONFIG_BSR           Indicates what \R matches by default:
                                     0             all Unicode line endings
                                     1             CR, LF, or CRLF only
      PCRE_CONFIG_POSIX_MALLOC_THRESHOLD
                                Threshold of return slots, above which
                                  malloc() is used by the POSIX API
      PCRE_CONFIG_STACKRECURSE  Recursion implementation (1=stack 0=heap)
      PCRE_CONFIG_UTF16         Availability of UTF-16 support (1=yes
                                   0=no); option for pcre16_config()
      PCRE_CONFIG_UTF32         Availability of UTF-32 support (1=yes
                                   0=no); option for pcre32_config()
      PCRE_CONFIG_UTF8          Availability of UTF-8 support (1=yes 0=no);
                                  option for pcre_config()
      PCRE_CONFIG_UNICODE_PROPERTIES
                                Availability of Unicode property support
                                  (1=yes 0=no)
    
    The function yields 0 on success or PCRE_ERROR_BADOPTION otherwise. That error is also given if PCRE_CONFIG_UTF16 or PCRE_CONFIG_UTF32 is passed to pcre_config(), if PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF32 is passed to pcre16_config(), or if PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF16 is passed to pcre32_config().

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_copy_named_substring.html ================================================ pcre_copy_named_substring specification

    pcre_copy_named_substring man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize);

    int pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_UCHAR16 *buffer, int buffersize);

    int pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_UCHAR32 *buffer, int buffersize);


    DESCRIPTION

    This is a convenience function for extracting a captured substring, identified by name, into a given buffer. The arguments are:

      code          Pattern that was successfully matched
      subject       Subject that has been successfully matched
      ovector       Offset vector that pcre[16|32]_exec() used
      stringcount   Value returned by pcre[16|32]_exec()
      stringname    Name of the required substring
      buffer        Buffer to receive the string
      buffersize    Size of buffer
    
    The yield is the length of the substring, PCRE_ERROR_NOMEMORY if the buffer was too small, or PCRE_ERROR_NOSUBSTRING if the string name is invalid.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_copy_substring.html ================================================ pcre_copy_substring specification

    pcre_copy_substring man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize);

    int pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR16 *buffer, int buffersize);

    int pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR32 *buffer, int buffersize);


    DESCRIPTION

    This is a convenience function for extracting a captured substring into a given buffer. The arguments are:

      subject       Subject that has been successfully matched
      ovector       Offset vector that pcre[16|32]_exec() used
      stringcount   Value returned by pcre[16|32]_exec()
      stringnumber  Number of the required substring
      buffer        Buffer to receive the string
      buffersize    Size of buffer
    
    The yield is the length of the string, PCRE_ERROR_NOMEMORY if the buffer was too small, or PCRE_ERROR_NOSUBSTRING if the string number is invalid.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_dfa_exec.html ================================================ pcre_dfa_exec specification

    pcre_dfa_exec man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);

    int pcre16_dfa_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);

    int pcre32_dfa_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);


    DESCRIPTION

    This function matches a compiled regular expression against a given subject string, using an alternative matching algorithm that scans the subject string just once (not Perl-compatible). Note that the main, Perl-compatible, matching function is pcre[16|32]_exec(). The arguments for this function are:

      code         Points to the compiled pattern
      extra        Points to an associated pcre[16|32]_extra structure,
                     or is NULL
      subject      Points to the subject string
      length       Length of the subject string
      startoffset  Offset in the subject at which to start matching
      options      Option bits
      ovector      Points to a vector of ints for result offsets
      ovecsize     Number of elements in the vector
      workspace    Points to a vector of ints used as working space
      wscount      Number of elements in the vector
    
    The units for length and startoffset are bytes for pcre_exec(), 16-bit data items for pcre16_exec(), and 32-bit items for pcre32_exec(). The options are:
      PCRE_ANCHORED          Match only at the first position
      PCRE_BSR_ANYCRLF       \R matches only CR, LF, or CRLF
      PCRE_BSR_UNICODE       \R matches all Unicode line endings
      PCRE_NEWLINE_ANY       Recognize any Unicode newline sequence
      PCRE_NEWLINE_ANYCRLF   Recognize CR, LF, & CRLF as newline sequences
      PCRE_NEWLINE_CR        Recognize CR as the only newline sequence
      PCRE_NEWLINE_CRLF      Recognize CRLF as the only newline sequence
      PCRE_NEWLINE_LF        Recognize LF as the only newline sequence
      PCRE_NOTBOL            Subject is not the beginning of a line
      PCRE_NOTEOL            Subject is not the end of a line
      PCRE_NOTEMPTY          An empty string is not a valid match
      PCRE_NOTEMPTY_ATSTART  An empty string at the start of the subject
                               is not a valid match
      PCRE_NO_START_OPTIMIZE Do not do "start-match" optimizations
      PCRE_NO_UTF16_CHECK    Do not check the subject for UTF-16
                               validity (only relevant if PCRE_UTF16
                               was set at compile time)
      PCRE_NO_UTF32_CHECK    Do not check the subject for UTF-32
                               validity (only relevant if PCRE_UTF32
                               was set at compile time)
      PCRE_NO_UTF8_CHECK     Do not check the subject for UTF-8
                               validity (only relevant if PCRE_UTF8
                               was set at compile time)
      PCRE_PARTIAL           ) Return PCRE_ERROR_PARTIAL for a partial
      PCRE_PARTIAL_SOFT      )   match if no full matches are found
      PCRE_PARTIAL_HARD      Return PCRE_ERROR_PARTIAL for a partial match
                               even if there is a full match as well
      PCRE_DFA_SHORTEST      Return only the shortest match
      PCRE_DFA_RESTART       Restart after a partial match
    
    There are restrictions on what may appear in a pattern when using this matching function. Details are given in the pcrematching documentation. For details of partial matching, see the pcrepartial page.

    A pcre[16|32]_extra structure contains the following fields:

      flags            Bits indicating which fields are set
      study_data       Opaque data from pcre[16|32]_study()
      match_limit      Limit on internal resource use
      match_limit_recursion  Limit on internal recursion depth
      callout_data     Opaque data passed back to callouts
      tables           Points to character tables or is NULL
      mark             For passing back a *MARK pointer
      executable_jit   Opaque data from JIT compilation
    
    The flag bits are PCRE_EXTRA_STUDY_DATA, PCRE_EXTRA_MATCH_LIMIT, PCRE_EXTRA_MATCH_LIMIT_RECURSION, PCRE_EXTRA_CALLOUT_DATA, PCRE_EXTRA_TABLES, PCRE_EXTRA_MARK and PCRE_EXTRA_EXECUTABLE_JIT. For this matching function, the match_limit and match_limit_recursion fields are not used, and must not be set. The PCRE_EXTRA_EXECUTABLE_JIT flag and the corresponding variable are ignored.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_exec.html ================================================ pcre_exec specification

    pcre_exec man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize);

    int pcre16_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize);

    int pcre32_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize);


    DESCRIPTION

    This function matches a compiled regular expression against a given subject string, using a matching algorithm that is similar to Perl's. It returns offsets to captured substrings. Its arguments are:

      code         Points to the compiled pattern
      extra        Points to an associated pcre[16|32]_extra structure,
                     or is NULL
      subject      Points to the subject string
      length       Length of the subject string
      startoffset  Offset in the subject at which to start matching
      options      Option bits
      ovector      Points to a vector of ints for result offsets
      ovecsize     Number of elements in the vector (a multiple of 3)
    
    The units for length and startoffset are bytes for pcre_exec(), 16-bit data items for pcre16_exec(), and 32-bit items for pcre32_exec(). The options are:
      PCRE_ANCHORED          Match only at the first position
      PCRE_BSR_ANYCRLF       \R matches only CR, LF, or CRLF
      PCRE_BSR_UNICODE       \R matches all Unicode line endings
      PCRE_NEWLINE_ANY       Recognize any Unicode newline sequence
      PCRE_NEWLINE_ANYCRLF   Recognize CR, LF, & CRLF as newline sequences
      PCRE_NEWLINE_CR        Recognize CR as the only newline sequence
      PCRE_NEWLINE_CRLF      Recognize CRLF as the only newline sequence
      PCRE_NEWLINE_LF        Recognize LF as the only newline sequence
      PCRE_NOTBOL            Subject string is not the beginning of a line
      PCRE_NOTEOL            Subject string is not the end of a line
      PCRE_NOTEMPTY          An empty string is not a valid match
      PCRE_NOTEMPTY_ATSTART  An empty string at the start of the subject
                               is not a valid match
      PCRE_NO_START_OPTIMIZE Do not do "start-match" optimizations
      PCRE_NO_UTF16_CHECK    Do not check the subject for UTF-16
                               validity (only relevant if PCRE_UTF16
                               was set at compile time)
      PCRE_NO_UTF32_CHECK    Do not check the subject for UTF-32
                               validity (only relevant if PCRE_UTF32
                               was set at compile time)
      PCRE_NO_UTF8_CHECK     Do not check the subject for UTF-8
                               validity (only relevant if PCRE_UTF8
                               was set at compile time)
      PCRE_PARTIAL           ) Return PCRE_ERROR_PARTIAL for a partial
      PCRE_PARTIAL_SOFT      )   match if no full matches are found
      PCRE_PARTIAL_HARD      Return PCRE_ERROR_PARTIAL for a partial match
                               if that is found before a full match
    
    For details of partial matching, see the pcrepartial page. A pcre_extra structure contains the following fields:
      flags            Bits indicating which fields are set
      study_data       Opaque data from pcre[16|32]_study()
      match_limit      Limit on internal resource use
      match_limit_recursion  Limit on internal recursion depth
      callout_data     Opaque data passed back to callouts
      tables           Points to character tables or is NULL
      mark             For passing back a *MARK pointer
      executable_jit   Opaque data from JIT compilation
    
    The flag bits are PCRE_EXTRA_STUDY_DATA, PCRE_EXTRA_MATCH_LIMIT, PCRE_EXTRA_MATCH_LIMIT_RECURSION, PCRE_EXTRA_CALLOUT_DATA, PCRE_EXTRA_TABLES, PCRE_EXTRA_MARK and PCRE_EXTRA_EXECUTABLE_JIT.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_free_study.html ================================================ pcre_free_study specification

    pcre_free_study man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    void pcre_free_study(pcre_extra *extra);

    void pcre16_free_study(pcre16_extra *extra);

    void pcre32_free_study(pcre32_extra *extra);


    DESCRIPTION

    This function is used to free the memory used for the data generated by a call to pcre[16|32]_study() when it is no longer needed. The argument must be the result of such a call.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_free_substring.html ================================================ pcre_free_substring specification

    pcre_free_substring man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    void pcre_free_substring(const char *stringptr);

    void pcre16_free_substring(PCRE_SPTR16 stringptr);

    void pcre32_free_substring(PCRE_SPTR32 stringptr);


    DESCRIPTION

    This is a convenience function for freeing the store obtained by a previous call to pcre[16|32]_get_substring() or pcre[16|32]_get_named_substring(). Its only argument is a pointer to the string.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_free_substring_list.html ================================================ pcre_free_substring_list specification

    pcre_free_substring_list man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    void pcre_free_substring_list(const char **stringptr);

    void pcre16_free_substring_list(PCRE_SPTR16 *stringptr);

    void pcre32_free_substring_list(PCRE_SPTR32 *stringptr);


    DESCRIPTION

    This is a convenience function for freeing the store obtained by a previous call to pcre[16|32]_get_substring_list(). Its only argument is a pointer to the list of string pointers.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_fullinfo.html ================================================ pcre_fullinfo specification

    pcre_fullinfo man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_fullinfo(const pcre *code, const pcre_extra *extra, int what, void *where);

    int pcre16_fullinfo(const pcre16 *code, const pcre16_extra *extra, int what, void *where);

    int pcre32_fullinfo(const pcre32 *code, const pcre32_extra *extra, int what, void *where);


    DESCRIPTION

    This function returns information about a compiled pattern. Its arguments are:

      code                      Compiled regular expression
      extra                     Result of pcre[16|32]_study() or NULL
      what                      What information is required
      where                     Where to put the information
    
    The following information is available:
      PCRE_INFO_BACKREFMAX      Number of highest back reference
      PCRE_INFO_CAPTURECOUNT    Number of capturing subpatterns
      PCRE_INFO_DEFAULT_TABLES  Pointer to default tables
      PCRE_INFO_FIRSTBYTE       Fixed first data unit for a match, or
                                  -1 for start of string
                                     or after newline, or
                                  -2 otherwise
      PCRE_INFO_FIRSTTABLE      Table of first data units (after studying)
      PCRE_INFO_HASCRORLF       Return 1 if explicit CR or LF matches exist
      PCRE_INFO_JCHANGED        Return 1 if (?J) or (?-J) was used
      PCRE_INFO_JIT             Return 1 after successful JIT compilation
      PCRE_INFO_JITSIZE         Size of JIT compiled code
      PCRE_INFO_LASTLITERAL     Literal last data unit required
      PCRE_INFO_MINLENGTH       Lower bound length of matching strings
      PCRE_INFO_MATCHEMPTY      Return 1 if the pattern can match an empty string,
                                   0 otherwise
      PCRE_INFO_MATCHLIMIT      Match limit if set, otherwise PCRE_RROR_UNSET
      PCRE_INFO_MAXLOOKBEHIND   Length (in characters) of the longest lookbehind assertion
      PCRE_INFO_NAMECOUNT       Number of named subpatterns
      PCRE_INFO_NAMEENTRYSIZE   Size of name table entry
      PCRE_INFO_NAMETABLE       Pointer to name table
      PCRE_INFO_OKPARTIAL       Return 1 if partial matching can be tried
                                  (always returns 1 after release 8.00)
      PCRE_INFO_OPTIONS         Option bits used for compilation
      PCRE_INFO_SIZE            Size of compiled pattern
      PCRE_INFO_STUDYSIZE       Size of study data
      PCRE_INFO_FIRSTCHARACTER      Fixed first data unit for a match
      PCRE_INFO_FIRSTCHARACTERFLAGS Returns
                                      1 if there is a first data character set, which can
                                        then be retrieved using PCRE_INFO_FIRSTCHARACTER,
                                      2 if the first character is at the start of the data
                                        string or after a newline, and
                                      0 otherwise
      PCRE_INFO_RECURSIONLIMIT    Recursion limit if set, otherwise PCRE_ERROR_UNSET
      PCRE_INFO_REQUIREDCHAR      Literal last data unit required
      PCRE_INFO_REQUIREDCHARFLAGS Returns 1 if the last data character is set (which can then
                                  be retrieved using PCRE_INFO_REQUIREDCHAR); 0 otherwise
    
    The where argument must point to an integer variable, except for the following what values:
      PCRE_INFO_DEFAULT_TABLES  const uint8_t *
      PCRE_INFO_FIRSTCHARACTER  uint32_t
      PCRE_INFO_FIRSTTABLE      const uint8_t *
      PCRE_INFO_JITSIZE         size_t
      PCRE_INFO_MATCHLIMIT      uint32_t
      PCRE_INFO_NAMETABLE       PCRE_SPTR16           (16-bit library)
      PCRE_INFO_NAMETABLE       PCRE_SPTR32           (32-bit library)
      PCRE_INFO_NAMETABLE       const unsigned char * (8-bit library)
      PCRE_INFO_OPTIONS         unsigned long int
      PCRE_INFO_SIZE            size_t
      PCRE_INFO_STUDYSIZE       size_t
      PCRE_INFO_RECURSIONLIMIT  uint32_t
      PCRE_INFO_REQUIREDCHAR    uint32_t
    
    The yield of the function is zero on success or:
      PCRE_ERROR_NULL           the argument code was NULL
                                the argument where was NULL
      PCRE_ERROR_BADMAGIC       the "magic number" was not found
      PCRE_ERROR_BADOPTION      the value of what was invalid
      PCRE_ERROR_UNSET          the option was not set
    

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_get_named_substring.html ================================================ pcre_get_named_substring specification

    pcre_get_named_substring man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr);

    int pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_SPTR16 *stringptr);

    int pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_SPTR32 *stringptr);


    DESCRIPTION

    This is a convenience function for extracting a captured substring by name. The arguments are:

      code          Compiled pattern
      subject       Subject that has been successfully matched
      ovector       Offset vector that pcre[16|32]_exec() used
      stringcount   Value returned by pcre[16|32]_exec()
      stringname    Name of the required substring
      stringptr     Where to put the string pointer
    
    The memory in which the substring is placed is obtained by calling pcre[16|32]_malloc(). The convenience function pcre[16|32]_free_substring() can be used to free it when it is no longer needed. The yield of the function is the length of the extracted substring, PCRE_ERROR_NOMEMORY if sufficient memory could not be obtained, or PCRE_ERROR_NOSUBSTRING if the string name is invalid.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_get_stringnumber.html ================================================ pcre_get_stringnumber specification

    pcre_get_stringnumber man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_get_stringnumber(const pcre *code, const char *name);

    int pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 name);

    int pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 name);


    DESCRIPTION

    This convenience function finds the number of a named substring capturing parenthesis in a compiled pattern. Its arguments are:

      code    Compiled regular expression
      name    Name whose number is required
    
    The yield of the function is the number of the parenthesis if the name is found, or PCRE_ERROR_NOSUBSTRING otherwise. When duplicate names are allowed (PCRE_DUPNAMES is set), it is not defined which of the numbers is returned by pcre[16|32]_get_stringnumber(). You can obtain the complete list by calling pcre[16|32]_get_stringtable_entries().

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_get_stringtable_entries.html ================================================ pcre_get_stringtable_entries specification

    pcre_get_stringtable_entries man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_get_stringtable_entries(const pcre *code, const char *name, char **first, char **last);

    int pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 name, PCRE_UCHAR16 **first, PCRE_UCHAR16 **last);

    int pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 name, PCRE_UCHAR32 **first, PCRE_UCHAR32 **last);


    DESCRIPTION

    This convenience function finds, for a compiled pattern, the first and last entries for a given name in the table that translates capturing parenthesis names into numbers. When names are required to be unique (PCRE_DUPNAMES is not set), it is usually easier to use pcre[16|32]_get_stringnumber() instead.

      code    Compiled regular expression
      name    Name whose entries required
      first   Where to return a pointer to the first entry
      last    Where to return a pointer to the last entry
    
    The yield of the function is the length of each entry, or PCRE_ERROR_NOSUBSTRING if none are found.

    There is a complete description of the PCRE native API, including the format of the table entries, in the pcreapi page, and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_get_substring.html ================================================ pcre_get_substring specification

    pcre_get_substring man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr);

    int pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR16 *stringptr);

    int pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR32 *stringptr);


    DESCRIPTION

    This is a convenience function for extracting a captured substring. The arguments are:

      subject       Subject that has been successfully matched
      ovector       Offset vector that pcre[16|32]_exec() used
      stringcount   Value returned by pcre[16|32]_exec()
      stringnumber  Number of the required substring
      stringptr     Where to put the string pointer
    
    The memory in which the substring is placed is obtained by calling pcre[16|32]_malloc(). The convenience function pcre[16|32]_free_substring() can be used to free it when it is no longer needed. The yield of the function is the length of the substring, PCRE_ERROR_NOMEMORY if sufficient memory could not be obtained, or PCRE_ERROR_NOSUBSTRING if the string number is invalid.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_get_substring_list.html ================================================ pcre_get_substring_list specification

    pcre_get_substring_list man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr);

    int pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 **listptr);

    int pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 **listptr);


    DESCRIPTION

    This is a convenience function for extracting a list of all the captured substrings. The arguments are:

      subject       Subject that has been successfully matched
      ovector       Offset vector that pcre[16|32]_exec used
      stringcount   Value returned by pcre[16|32]_exec
      listptr       Where to put a pointer to the list
    
    The memory in which the substrings and the list are placed is obtained by calling pcre[16|32]_malloc(). The convenience function pcre[16|32]_free_substring_list() can be used to free it when it is no longer needed. A pointer to a list of pointers is put in the variable whose address is in listptr. The list is terminated by a NULL pointer. The yield of the function is zero on success or PCRE_ERROR_NOMEMORY if sufficient memory could not be obtained.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_jit_exec.html ================================================ pcre_jit_exec specification

    pcre_jit_exec man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_jit_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, pcre_jit_stack *jstack);

    int pcre16_jit_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize, pcre_jit_stack *jstack);

    int pcre32_jit_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize, pcre_jit_stack *jstack);


    DESCRIPTION

    This function matches a compiled regular expression that has been successfully studied with one of the JIT options against a given subject string, using a matching algorithm that is similar to Perl's. It is a "fast path" interface to JIT, and it bypasses some of the sanity checks that pcre_exec() applies. It returns offsets to captured substrings. Its arguments are:

      code         Points to the compiled pattern
      extra        Points to an associated pcre[16|32]_extra structure,
                     or is NULL
      subject      Points to the subject string
      length       Length of the subject string, in bytes
      startoffset  Offset in bytes in the subject at which to
                     start matching
      options      Option bits
      ovector      Points to a vector of ints for result offsets
      ovecsize     Number of elements in the vector (a multiple of 3)
      jstack       Pointer to a JIT stack
    
    The allowed options are:
      PCRE_NOTBOL            Subject string is not the beginning of a line
      PCRE_NOTEOL            Subject string is not the end of a line
      PCRE_NOTEMPTY          An empty string is not a valid match
      PCRE_NOTEMPTY_ATSTART  An empty string at the start of the subject
                               is not a valid match
      PCRE_NO_UTF16_CHECK    Do not check the subject for UTF-16
                               validity (only relevant if PCRE_UTF16
                               was set at compile time)
      PCRE_NO_UTF32_CHECK    Do not check the subject for UTF-32
                               validity (only relevant if PCRE_UTF32
                               was set at compile time)
      PCRE_NO_UTF8_CHECK     Do not check the subject for UTF-8
                               validity (only relevant if PCRE_UTF8
                               was set at compile time)
      PCRE_PARTIAL           ) Return PCRE_ERROR_PARTIAL for a partial
      PCRE_PARTIAL_SOFT      )   match if no full matches are found
      PCRE_PARTIAL_HARD      Return PCRE_ERROR_PARTIAL for a partial match
                               if that is found before a full match
    
    However, the PCRE_NO_UTF[8|16|32]_CHECK options have no effect, as this check is never applied. For details of partial matching, see the pcrepartial page. A pcre_extra structure contains the following fields:
      flags            Bits indicating which fields are set
      study_data       Opaque data from pcre[16|32]_study()
      match_limit      Limit on internal resource use
      match_limit_recursion  Limit on internal recursion depth
      callout_data     Opaque data passed back to callouts
      tables           Points to character tables or is NULL
      mark             For passing back a *MARK pointer
      executable_jit   Opaque data from JIT compilation
    
    The flag bits are PCRE_EXTRA_STUDY_DATA, PCRE_EXTRA_MATCH_LIMIT, PCRE_EXTRA_MATCH_LIMIT_RECURSION, PCRE_EXTRA_CALLOUT_DATA, PCRE_EXTRA_TABLES, PCRE_EXTRA_MARK and PCRE_EXTRA_EXECUTABLE_JIT.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the JIT API in the pcrejit page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_jit_stack_alloc.html ================================================ pcre_jit_stack_alloc specification

    pcre_jit_stack_alloc man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    pcre_jit_stack *pcre_jit_stack_alloc(int startsize, int maxsize);

    pcre16_jit_stack *pcre16_jit_stack_alloc(int startsize, int maxsize);

    pcre32_jit_stack *pcre32_jit_stack_alloc(int startsize, int maxsize);


    DESCRIPTION

    This function is used to create a stack for use by the code compiled by the JIT optimization of pcre[16|32]_study(). The arguments are a starting size for the stack, and a maximum size to which it is allowed to grow. The result can be passed to the JIT run-time code by pcre[16|32]_assign_jit_stack(), or that function can set up a callback for obtaining a stack. A maximum stack size of 512K to 1M should be more than enough for any pattern. For more details, see the pcrejit page.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_jit_stack_free.html ================================================ pcre_jit_stack_free specification

    pcre_jit_stack_free man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    void pcre_jit_stack_free(pcre_jit_stack *stack);

    void pcre16_jit_stack_free(pcre16_jit_stack *stack);

    void pcre32_jit_stack_free(pcre32_jit_stack *stack);


    DESCRIPTION

    This function is used to free a JIT stack that was created by pcre[16|32]_jit_stack_alloc() when it is no longer needed. For more details, see the pcrejit page.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_maketables.html ================================================ pcre_maketables specification

    pcre_maketables man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    const unsigned char *pcre_maketables(void);

    const unsigned char *pcre16_maketables(void);

    const unsigned char *pcre32_maketables(void);


    DESCRIPTION

    This function builds a set of character tables for character values less than 256. These can be passed to pcre[16|32]_compile() to override PCRE's internal, built-in tables (which were made by pcre[16|32]_maketables() when PCRE was compiled). You might want to do this if you are using a non-standard locale. The function yields a pointer to the tables.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_pattern_to_host_byte_order.html ================================================ pcre_pattern_to_host_byte_order specification

    pcre_pattern_to_host_byte_order man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_pattern_to_host_byte_order(pcre *code, pcre_extra *extra, const unsigned char *tables);

    int pcre16_pattern_to_host_byte_order(pcre16 *code, pcre16_extra *extra, const unsigned char *tables);

    int pcre32_pattern_to_host_byte_order(pcre32 *code, pcre32_extra *extra, const unsigned char *tables);


    DESCRIPTION

    This function ensures that the bytes in 2-byte and 4-byte values in a compiled pattern are in the correct order for the current host. It is useful when a pattern that has been compiled on one host is transferred to another that might have different endianness. The arguments are:

      code         A compiled regular expression
      extra        Points to an associated pcre[16|32]_extra structure,
                     or is NULL
      tables       Pointer to character tables, or NULL to
                     set the built-in default
    
    The result is 0 for success, a negative PCRE_ERROR_xxx value otherwise.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_refcount.html ================================================ pcre_refcount specification

    pcre_refcount man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre_refcount(pcre *code, int adjust);

    int pcre16_refcount(pcre16 *code, int adjust);

    int pcre32_refcount(pcre32 *code, int adjust);


    DESCRIPTION

    This function is used to maintain a reference count inside a data block that contains a compiled pattern. Its arguments are:

      code                      Compiled regular expression
      adjust                    Adjustment to reference value
    
    The yield of the function is the adjusted reference value, which is constrained to lie between 0 and 65535.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_study.html ================================================ pcre_study specification

    pcre_study man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    pcre_extra *pcre_study(const pcre *code, int options, const char **errptr);

    pcre16_extra *pcre16_study(const pcre16 *code, int options, const char **errptr);

    pcre32_extra *pcre32_study(const pcre32 *code, int options, const char **errptr);


    DESCRIPTION

    This function studies a compiled pattern, to see if additional information can be extracted that might speed up matching. Its arguments are:

      code       A compiled regular expression
      options    Options for pcre[16|32]_study()
      errptr     Where to put an error message
    
    If the function succeeds, it returns a value that can be passed to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() via their extra arguments.

    If the function returns NULL, either it could not find any additional information, or there was an error. You can tell the difference by looking at the error value. It is NULL in first case.

    The only option is PCRE_STUDY_JIT_COMPILE. It requests just-in-time compilation if possible. If PCRE has been compiled without JIT support, this option is ignored. See the pcrejit page for further details.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_utf16_to_host_byte_order.html ================================================ pcre_utf16_to_host_byte_order specification

    pcre_utf16_to_host_byte_order man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input, int length, int *host_byte_order, int keep_boms);


    DESCRIPTION

    This function, which exists only in the 16-bit library, converts a UTF-16 string to the correct order for the current host, taking account of any byte order marks (BOMs) within the string. Its arguments are:

      output           pointer to output buffer, may be the same as input
      input            pointer to input buffer
      length           number of 16-bit units in the input, or negative for
                         a zero-terminated string
      host_byte_order  a NULL value or a non-zero value pointed to means
                         start in host byte order
      keep_boms        if non-zero, BOMs are copied to the output string
    
    The result of the function is the number of 16-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated.

    If host_byte_order is not NULL, it is set to indicate the byte order that is current at the end of the string.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_utf32_to_host_byte_order.html ================================================ pcre_utf32_to_host_byte_order specification

    pcre_utf32_to_host_byte_order man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *output, PCRE_SPTR32 input, int length, int *host_byte_order, int keep_boms);


    DESCRIPTION

    This function, which exists only in the 32-bit library, converts a UTF-32 string to the correct order for the current host, taking account of any byte order marks (BOMs) within the string. Its arguments are:

      output           pointer to output buffer, may be the same as input
      input            pointer to input buffer
      length           number of 32-bit units in the input, or negative for
                         a zero-terminated string
      host_byte_order  a NULL value or a non-zero value pointed to means
                         start in host byte order
      keep_boms        if non-zero, BOMs are copied to the output string
    
    The result of the function is the number of 32-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated.

    If host_byte_order is not NULL, it is set to indicate the byte order that is current at the end of the string.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcre_version.html ================================================ pcre_version specification

    pcre_version man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SYNOPSIS

    #include <pcre.h>

    const char *pcre_version(void);

    const char *pcre16_version(void);

    const char *pcre32_version(void);


    DESCRIPTION

    This function (even in the 16-bit and 32-bit libraries) returns a zero-terminated, 8-bit character string that gives the version number of the PCRE library and the date of its release.

    There is a complete description of the PCRE native API in the pcreapi page and a description of the POSIX API in the pcreposix page.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcreapi.html ================================================ pcreapi specification

    pcreapi man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    #include <pcre.h>


    PCRE NATIVE API BASIC FUNCTIONS

    pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre *pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre_extra *pcre_study(const pcre *code, int options, const char **errptr);

    void pcre_free_study(pcre_extra *extra);

    int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize);

    int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);


    PCRE NATIVE API STRING EXTRACTION FUNCTIONS

    int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize);

    int pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize);

    int pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr);

    int pcre_get_stringnumber(const pcre *code, const char *name);

    int pcre_get_stringtable_entries(const pcre *code, const char *name, char **first, char **last);

    int pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr);

    int pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr);

    void pcre_free_substring(const char *stringptr);

    void pcre_free_substring_list(const char **stringptr);


    PCRE NATIVE API AUXILIARY FUNCTIONS

    int pcre_jit_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, pcre_jit_stack *jstack);

    pcre_jit_stack *pcre_jit_stack_alloc(int startsize, int maxsize);

    void pcre_jit_stack_free(pcre_jit_stack *stack);

    void pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *data);

    const unsigned char *pcre_maketables(void);

    int pcre_fullinfo(const pcre *code, const pcre_extra *extra, int what, void *where);

    int pcre_refcount(pcre *code, int adjust);

    int pcre_config(int what, void *where);

    const char *pcre_version(void);

    int pcre_pattern_to_host_byte_order(pcre *code, pcre_extra *extra, const unsigned char *tables);


    PCRE NATIVE API INDIRECTED FUNCTIONS

    void *(*pcre_malloc)(size_t);

    void (*pcre_free)(void *);

    void *(*pcre_stack_malloc)(size_t);

    void (*pcre_stack_free)(void *);

    int (*pcre_callout)(pcre_callout_block *);

    int (*pcre_stack_guard)(void);


    PCRE 8-BIT, 16-BIT, AND 32-BIT LIBRARIES

    As well as support for 8-bit character strings, PCRE also supports 16-bit strings (from release 8.30) and 32-bit strings (from release 8.32), by means of two additional libraries. They can be built as well as, or instead of, the 8-bit library. To avoid too much complication, this document describes the 8-bit versions of the functions, with only occasional references to the 16-bit and 32-bit libraries.

    The 16-bit and 32-bit functions operate in the same way as their 8-bit counterparts; they just use different data types for their arguments and results, and their names start with pcre16_ or pcre32_ instead of pcre_. For every option that has UTF8 in its name (for example, PCRE_UTF8), there are corresponding 16-bit and 32-bit names with UTF8 replaced by UTF16 or UTF32, respectively. This facility is in fact just cosmetic; the 16-bit and 32-bit option names define the same bit values.

    References to bytes and UTF-8 in this document should be read as references to 16-bit data units and UTF-16 when using the 16-bit library, or 32-bit data units and UTF-32 when using the 32-bit library, unless specified otherwise. More details of the specific differences for the 16-bit and 32-bit libraries are given in the pcre16 and pcre32 pages.


    PCRE API OVERVIEW

    PCRE has its own native API, which is described in this document. There are also some wrapper functions (for the 8-bit library only) that correspond to the POSIX regular expression API, but they do not give access to all the functionality. They are described in the pcreposix documentation. Both of these APIs define a set of C function calls. A C++ wrapper (again for the 8-bit library only) is also distributed with PCRE. It is documented in the pcrecpp page.

    The native API C function prototypes are defined in the header file pcre.h, and on Unix-like systems the (8-bit) library itself is called libpcre. It can normally be accessed by adding -lpcre to the command for linking an application that uses PCRE. The header file defines the macros PCRE_MAJOR and PCRE_MINOR to contain the major and minor release numbers for the library. Applications can use these to include support for different releases of PCRE.

    In a Windows environment, if you want to statically link an application program against a non-dll pcre.a file, you must define PCRE_STATIC before including pcre.h or pcrecpp.h, because otherwise the pcre_malloc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results.

    The functions pcre_compile(), pcre_compile2(), pcre_study(), and pcre_exec() are used for compiling and matching regular expressions in a Perl-compatible manner. A sample program that demonstrates the simplest way of using them is provided in the file called pcredemo.c in the PCRE source distribution. A listing of this program is given in the pcredemo documentation, and the pcresample documentation describes how to compile and run it.

    Just-in-time compiler support is an optional feature of PCRE that can be built in appropriate hardware environments. It greatly speeds up the matching performance of many patterns. Simple programs can easily request that it be used if available, by setting an option that is ignored when it is not relevant. More complicated programs might need to make use of the functions pcre_jit_stack_alloc(), pcre_jit_stack_free(), and pcre_assign_jit_stack() in order to control the JIT code's memory usage.

    From release 8.32 there is also a direct interface for JIT execution, which gives improved performance. The JIT-specific functions are discussed in the pcrejit documentation.

    A second matching function, pcre_dfa_exec(), which is not Perl-compatible, is also provided. This uses a different algorithm for the matching. The alternative algorithm finds all possible matches (at a given point in the subject), and scans the subject just once (unless there are lookbehind assertions). However, this algorithm does not return captured substrings. A description of the two matching algorithms and their advantages and disadvantages is given in the pcrematching documentation.

    In addition to the main compiling and matching functions, there are convenience functions for extracting captured substrings from a subject string that is matched by pcre_exec(). They are:

      pcre_copy_substring()
      pcre_copy_named_substring()
      pcre_get_substring()
      pcre_get_named_substring()
      pcre_get_substring_list()
      pcre_get_stringnumber()
      pcre_get_stringtable_entries()
    
    pcre_free_substring() and pcre_free_substring_list() are also provided, to free the memory used for extracted strings.

    The function pcre_maketables() is used to build a set of character tables in the current locale for passing to pcre_compile(), pcre_exec(), or pcre_dfa_exec(). This is an optional facility that is provided for specialist use. Most commonly, no special tables are passed, in which case internal tables that are generated when PCRE is built are used.

    The function pcre_fullinfo() is used to find out information about a compiled pattern. The function pcre_version() returns a pointer to a string containing the version of PCRE and its date of release.

    The function pcre_refcount() maintains a reference count in a data block containing a compiled pattern. This is provided for the benefit of object-oriented applications.

    The global variables pcre_malloc and pcre_free initially contain the entry points of the standard malloc() and free() functions, respectively. PCRE calls the memory management functions via these variables, so a calling program can replace them if it wishes to intercept the calls. This should be done before calling any PCRE functions.

    The global variables pcre_stack_malloc and pcre_stack_free are also indirections to memory management functions. These special functions are used only when PCRE is compiled to use the heap for remembering data, instead of recursive function calls, when running the pcre_exec() function. See the pcrebuild documentation for details of how to do this. It is a non-standard way of building PCRE, for use in environments that have limited stacks. Because of the greater use of memory management, it runs more slowly. Separate functions are provided so that special-purpose external code can be used for this case. When used, these functions always allocate memory blocks of the same size. There is a discussion about PCRE's stack usage in the pcrestack documentation.

    The global variable pcre_callout initially contains NULL. It can be set by the caller to a "callout" function, which PCRE will then call at specified points during a matching operation. Details are given in the pcrecallout documentation.

    The global variable pcre_stack_guard initially contains NULL. It can be set by the caller to a function that is called by PCRE whenever it starts to compile a parenthesized part of a pattern. When parentheses are nested, PCRE uses recursive function calls, which use up the system stack. This function is provided so that applications with restricted stacks can force a compilation error if the stack runs out. The function should return zero if all is well, or non-zero to force an error.


    NEWLINES

    PCRE supports five different conventions for indicating line breaks in strings: a single CR (carriage return) character, a single LF (linefeed) character, the two-character sequence CRLF, any of the three preceding, or any Unicode newline sequence. The Unicode newline sequences are the three just mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029).

    Each of the first three conventions is used by at least one operating system as its standard newline sequence. When PCRE is built, a default can be specified. The default default is LF, which is the Unix standard. When PCRE is run, the default can be overridden, either when a pattern is compiled, or when it is matched.

    At compile time, the newline convention can be specified by the options argument of pcre_compile(), or it can be specified by special text at the start of the pattern itself; this overrides any other settings. See the pcrepattern page for details of the special character sequences.

    In the PCRE documentation the word "newline" is used to mean "the character or pair of characters that indicate a line break". The choice of newline convention affects the handling of the dot, circumflex, and dollar metacharacters, the handling of #-comments in /x mode, and, when CRLF is a recognized line ending sequence, the match position advancement for a non-anchored pattern. There is more detail about this in the section on pcre_exec() options below.

    The choice of newline convention does not affect the interpretation of the \n or \r escape sequences, nor does it affect what \R matches, which is controlled in a similar way, but by separate options.


    MULTITHREADING

    The PCRE functions can be used in multi-threading applications, with the proviso that the memory management functions pointed to by pcre_malloc, pcre_free, pcre_stack_malloc, and pcre_stack_free, and the callout and stack-checking functions pointed to by pcre_callout and pcre_stack_guard, are shared by all threads.

    The compiled form of a regular expression is not altered during matching, so the same compiled pattern can safely be used by several threads at once.

    If the just-in-time optimization feature is being used, it needs separate memory stack areas for each thread. See the pcrejit documentation for more details.


    SAVING PRECOMPILED PATTERNS FOR LATER USE

    The compiled form of a regular expression can be saved and re-used at a later time, possibly by a different program, and even on a host other than the one on which it was compiled. Details are given in the pcreprecompile documentation, which includes a description of the pcre_pattern_to_host_byte_order() function. However, compiling a regular expression with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes.


    CHECKING BUILD-TIME OPTIONS

    int pcre_config(int what, void *where);

    The function pcre_config() makes it possible for a PCRE client to discover which optional features have been compiled into the PCRE library. The pcrebuild documentation has more details about these optional features.

    The first argument for pcre_config() is an integer, specifying which information is required; the second argument is a pointer to a variable into which the information is placed. The returned value is zero on success, or the negative error code PCRE_ERROR_BADOPTION if the value in the first argument is not recognized. The following information is available:

      PCRE_CONFIG_UTF8
    
    The output is an integer that is set to one if UTF-8 support is available; otherwise it is set to zero. This value should normally be given to the 8-bit version of this function, pcre_config(). If it is given to the 16-bit or 32-bit version of this function, the result is PCRE_ERROR_BADOPTION.
      PCRE_CONFIG_UTF16
    
    The output is an integer that is set to one if UTF-16 support is available; otherwise it is set to zero. This value should normally be given to the 16-bit version of this function, pcre16_config(). If it is given to the 8-bit or 32-bit version of this function, the result is PCRE_ERROR_BADOPTION.
      PCRE_CONFIG_UTF32
    
    The output is an integer that is set to one if UTF-32 support is available; otherwise it is set to zero. This value should normally be given to the 32-bit version of this function, pcre32_config(). If it is given to the 8-bit or 16-bit version of this function, the result is PCRE_ERROR_BADOPTION.
      PCRE_CONFIG_UNICODE_PROPERTIES
    
    The output is an integer that is set to one if support for Unicode character properties is available; otherwise it is set to zero.
      PCRE_CONFIG_JIT
    
    The output is an integer that is set to one if support for just-in-time compiling is available; otherwise it is set to zero.
      PCRE_CONFIG_JITTARGET
    
    The output is a pointer to a zero-terminated "const char *" string. If JIT support is available, the string contains the name of the architecture for which the JIT compiler is configured, for example "x86 32bit (little endian + unaligned)". If JIT support is not available, the result is NULL.
      PCRE_CONFIG_NEWLINE
    
    The output is an integer whose value specifies the default character sequence that is recognized as meaning "newline". The values that are supported in ASCII/Unicode environments are: 10 for LF, 13 for CR, 3338 for CRLF, -2 for ANYCRLF, and -1 for ANY. In EBCDIC environments, CR, ANYCRLF, and ANY yield the same values. However, the value for LF is normally 21, though some EBCDIC environments use 37. The corresponding values for CRLF are 3349 and 3365. The default should normally correspond to the standard sequence for your operating system.
      PCRE_CONFIG_BSR
    
    The output is an integer whose value indicates what character sequences the \R escape sequence matches by default. A value of 0 means that \R matches any Unicode line ending sequence; a value of 1 means that \R matches only CR, LF, or CRLF. The default can be overridden when a pattern is compiled or matched.
      PCRE_CONFIG_LINK_SIZE
    
    The output is an integer that contains the number of bytes used for internal linkage in compiled regular expressions. For the 8-bit library, the value can be 2, 3, or 4. For the 16-bit library, the value is either 2 or 4 and is still a number of bytes. For the 32-bit library, the value is either 2 or 4 and is still a number of bytes. The default value of 2 is sufficient for all but the most massive patterns, since it allows the compiled pattern to be up to 64K in size. Larger values allow larger regular expressions to be compiled, at the expense of slower matching.
      PCRE_CONFIG_POSIX_MALLOC_THRESHOLD
    
    The output is an integer that contains the threshold above which the POSIX interface uses malloc() for output vectors. Further details are given in the pcreposix documentation.
      PCRE_CONFIG_PARENS_LIMIT
    
    The output is a long integer that gives the maximum depth of nesting of parentheses (of any kind) in a pattern. This limit is imposed to cap the amount of system stack used when a pattern is compiled. It is specified when PCRE is built; the default is 250. This limit does not take into account the stack that may already be used by the calling application. For finer control over compilation stack usage, you can set a pointer to an external checking function in pcre_stack_guard.
      PCRE_CONFIG_MATCH_LIMIT
    
    The output is a long integer that gives the default limit for the number of internal matching function calls in a pcre_exec() execution. Further details are given with pcre_exec() below.
      PCRE_CONFIG_MATCH_LIMIT_RECURSION
    
    The output is a long integer that gives the default limit for the depth of recursion when calling the internal matching function in a pcre_exec() execution. Further details are given with pcre_exec() below.
      PCRE_CONFIG_STACKRECURSE
    
    The output is an integer that is set to one if internal recursion when running pcre_exec() is implemented by recursive function calls that use the stack to remember their state. This is the usual way that PCRE is compiled. The output is zero if PCRE was compiled to use blocks of data on the heap instead of recursive function calls. In this case, pcre_stack_malloc and pcre_stack_free are called to manage memory blocks on the heap, thus avoiding the use of the stack.


    COMPILING A PATTERN

    pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);

    pcre *pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr);

    Either of the functions pcre_compile() or pcre_compile2() can be called to compile a pattern into an internal form. The only difference between the two interfaces is that pcre_compile2() has an additional argument, errorcodeptr, via which a numerical error code can be returned. To avoid too much repetition, we refer just to pcre_compile() below, but the information applies equally to pcre_compile2().

    The pattern is a C string terminated by a binary zero, and is passed in the pattern argument. A pointer to a single block of memory that is obtained via pcre_malloc is returned. This contains the compiled code and related data. The pcre type is defined for the returned block; this is a typedef for a structure whose contents are not externally defined. It is up to the caller to free the memory (via pcre_free) when it is no longer required.

    Although the compiled code of a PCRE regex is relocatable, that is, it does not depend on memory location, the complete pcre data block is not fully relocatable, because it may contain a copy of the tableptr argument, which is an address (see below).

    The options argument contains various bit settings that affect the compilation. It should be zero if no options are required. The available options are described below. Some of them (in particular, those that are compatible with Perl, but some others as well) can also be set and unset from within the pattern (see the detailed description in the pcrepattern documentation). For those options that can be different in different parts of the pattern, the contents of the options argument specifies their settings at the start of compilation and execution. The PCRE_ANCHORED, PCRE_BSR_xxx, PCRE_NEWLINE_xxx, PCRE_NO_UTF8_CHECK, and PCRE_NO_START_OPTIMIZE options can be set at the time of matching as well as at compile time.

    If errptr is NULL, pcre_compile() returns NULL immediately. Otherwise, if compilation of a pattern fails, pcre_compile() returns NULL, and sets the variable pointed to by errptr to point to a textual error message. This is a static string that is part of the library. You must not try to free it. Normally, the offset from the start of the pattern to the data unit that was being processed when the error was discovered is placed in the variable pointed to by erroffset, which must not be NULL (if it is, an immediate error is given). However, for an invalid UTF-8 or UTF-16 string, the offset is that of the first data unit of the failing character.

    Some errors are not detected until the whole pattern has been scanned; in these cases, the offset passed back is the length of the pattern. Note that the offset is in data units, not characters, even in a UTF mode. It may sometimes point into the middle of a UTF-8 or UTF-16 character.

    If pcre_compile2() is used instead of pcre_compile(), and the errorcodeptr argument is not NULL, a non-zero error code number is returned via this argument in the event of an error. This is in addition to the textual error message. Error codes and messages are listed below.

    If the final argument, tableptr, is NULL, PCRE uses a default set of character tables that are built when PCRE is compiled, using the default C locale. Otherwise, tableptr must be an address that is the result of a call to pcre_maketables(). This value is stored with the compiled pattern, and used again by pcre_exec() and pcre_dfa_exec() when the pattern is matched. For more discussion, see the section on locale support below.

    This code fragment shows a typical straightforward call to pcre_compile():

      pcre *re;
      const char *error;
      int erroffset;
      re = pcre_compile(
        "^A.*Z",          /* the pattern */
        0,                /* default options */
        &error,           /* for error message */
        &erroffset,       /* for error offset */
        NULL);            /* use default character tables */
    
    The following names for option bits are defined in the pcre.h header file:
      PCRE_ANCHORED
    
    If this bit is set, the pattern is forced to be "anchored", that is, it is constrained to match only at the first matching point in the string that is being searched (the "subject string"). This effect can also be achieved by appropriate constructs in the pattern itself, which is the only way to do it in Perl.
      PCRE_AUTO_CALLOUT
    
    If this bit is set, pcre_compile() automatically inserts callout items, all with number 255, before each pattern item. For discussion of the callout facility, see the pcrecallout documentation.
      PCRE_BSR_ANYCRLF
      PCRE_BSR_UNICODE
    
    These options (which are mutually exclusive) control what the \R escape sequence matches. The choice is either to match only CR, LF, or CRLF, or to match any Unicode newline sequence. The default is specified when PCRE is built. It can be overridden from within the pattern, or by setting an option when a compiled pattern is matched.
      PCRE_CASELESS
    
    If this bit is set, letters in the pattern match both upper and lower case letters. It is equivalent to Perl's /i option, and it can be changed within a pattern by a (?i) option setting. In UTF-8 mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF-8 support.
      PCRE_DOLLAR_ENDONLY
    
    If this bit is set, a dollar metacharacter in the pattern matches only at the end of the subject string. Without this option, a dollar also matches immediately before a newline at the end of the string (but not before any other newlines). The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. There is no equivalent to this option in Perl, and no way to set it within a pattern.
      PCRE_DOTALL
    
    If this bit is set, a dot metacharacter in the pattern matches a character of any value, including one that indicates a newline. However, it only ever matches one character, even if newlines are coded as CRLF. Without this option, a dot does not match when the current position is at a newline. This option is equivalent to Perl's /s option, and it can be changed within a pattern by a (?s) option setting. A negative class such as [^a] always matches newline characters, independent of the setting of this option.
      PCRE_DUPNAMES
    
    If this bit is set, names used to identify capturing subpatterns need not be unique. This can be helpful for certain types of pattern when it is known that only one instance of the named subpattern can ever be matched. There are more details of named subpatterns below; see also the pcrepattern documentation.
      PCRE_EXTENDED
    
    If this bit is set, most white space characters in the pattern are totally ignored except when escaped or inside a character class. However, white space is not allowed within sequences such as (?> that introduce various parenthesized subpatterns, nor within a numerical quantifier such as {1,3}. However, ignorable white space is permitted between an item and a following quantifier and between a quantifier and a following + that indicates possessiveness.

    White space did not used to include the VT character (code 11), because Perl did not treat this character as white space. However, Perl changed at release 5.18, so PCRE followed at release 8.34, and VT is now treated as white space.

    PCRE_EXTENDED also causes characters between an unescaped # outside a character class and the next newline, inclusive, to be ignored. PCRE_EXTENDED is equivalent to Perl's /x option, and it can be changed within a pattern by a (?x) option setting.

    Which characters are interpreted as newlines is controlled by the options passed to pcre_compile() or by a special sequence at the start of the pattern, as described in the section entitled "Newline conventions" in the pcrepattern documentation. Note that the end of this type of comment is a literal newline sequence in the pattern; escape sequences that happen to represent a newline do not count.

    This option makes it possible to include comments inside complicated patterns. Note, however, that this applies only to data characters. White space characters may never appear within special character sequences in a pattern, for example within the sequence (?( that introduces a conditional subpattern.

      PCRE_EXTRA
    
    This option was invented in order to turn on additional functionality of PCRE that is incompatible with Perl, but it is currently of very little use. When set, any backslash in a pattern that is followed by a letter that has no special meaning causes an error, thus reserving these combinations for future expansion. By default, as in Perl, a backslash followed by a letter with no special meaning is treated as a literal. (Perl can, however, be persuaded to give an error for this, by running it with the -w option.) There are at present no other features controlled by this option. It can also be set by a (?X) option setting within a pattern.
      PCRE_FIRSTLINE
    
    If this option is set, an unanchored pattern is required to match before or at the first newline in the subject string, though the matched text may continue over the newline.
      PCRE_JAVASCRIPT_COMPAT
    
    If this option is set, PCRE's behaviour is changed in some ways so that it is compatible with JavaScript rather than Perl. The changes are as follows:

    (1) A lone closing square bracket in a pattern causes a compile-time error, because this is illegal in JavaScript (by default it is treated as a data character). Thus, the pattern AB]CD becomes illegal when this option is set.

    (2) At run time, a back reference to an unset subpattern group matches an empty string (by default this causes the current matching alternative to fail). A pattern such as (\1)(a) succeeds when this option is set (assuming it can find an "a" in the subject), whereas it fails by default, for Perl compatibility.

    (3) \U matches an upper case "U" character; by default \U causes a compile time error (Perl uses \U to upper case subsequent characters).

    (4) \u matches a lower case "u" character unless it is followed by four hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, \u causes a compile time error (Perl uses it to upper case the following character).

    (5) \x matches a lower case "x" character unless it is followed by two hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, as in Perl, a hexadecimal number is always expected after \x, but it may have zero, one, or two digits (so, for example, \xz matches a binary zero character followed by z).

      PCRE_MULTILINE
    
    By default, for the purposes of matching "start of line" and "end of line", PCRE treats the subject string as consisting of a single line of characters, even if it actually contains newlines. The "start of line" metacharacter (^) matches only at the start of the string, and the "end of line" metacharacter ($) matches only at the end of the string, or before a terminating newline (except when PCRE_DOLLAR_ENDONLY is set). Note, however, that unless PCRE_DOTALL is set, the "any character" metacharacter (.) does not match at a newline. This behaviour (for ^, $, and dot) is the same as Perl.

    When PCRE_MULTILINE it is set, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern, setting PCRE_MULTILINE has no effect.

      PCRE_NEVER_UTF
    
    This option locks out interpretation of the pattern as UTF-8 (or UTF-16 or UTF-32 in the 16-bit and 32-bit libraries). In particular, it prevents the creator of the pattern from switching to UTF interpretation by starting the pattern with (*UTF). This may be useful in applications that process patterns from external sources. The combination of PCRE_UTF8 and PCRE_NEVER_UTF also causes an error.
      PCRE_NEWLINE_CR
      PCRE_NEWLINE_LF
      PCRE_NEWLINE_CRLF
      PCRE_NEWLINE_ANYCRLF
      PCRE_NEWLINE_ANY
    
    These options override the default newline definition that was chosen when PCRE was built. Setting the first or the second specifies that a newline is indicated by a single character (CR or LF, respectively). Setting PCRE_NEWLINE_CRLF specifies that a newline is indicated by the two-character CRLF sequence. Setting PCRE_NEWLINE_ANYCRLF specifies that any of the three preceding sequences should be recognized. Setting PCRE_NEWLINE_ANY specifies that any Unicode newline sequence should be recognized.

    In an ASCII/Unicode environment, the Unicode newline sequences are the three just mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029). For the 8-bit library, the last two are recognized only in UTF-8 mode.

    When PCRE is compiled to run in an EBCDIC (mainframe) environment, the code for CR is 0x0d, the same as ASCII. However, the character code for LF is normally 0x15, though in some EBCDIC environments 0x25 is used. Whichever of these is not LF is made to correspond to Unicode's NEL character. EBCDIC codes are all less than 256. For more details, see the pcrebuild documentation.

    The newline setting in the options word uses three bits that are treated as a number, giving eight possibilities. Currently only six are used (default plus the five values above). This means that if you set more than one newline option, the combination may or may not be sensible. For example, PCRE_NEWLINE_CR with PCRE_NEWLINE_LF is equivalent to PCRE_NEWLINE_CRLF, but other combinations may yield unused numbers and cause an error.

    The only time that a line break in a pattern is specially recognized when compiling is when PCRE_EXTENDED is set. CR and LF are white space characters, and so are ignored in this mode. Also, an unescaped # outside a character class indicates a comment that lasts until after the next line break sequence. In other circumstances, line break sequences in patterns are treated as literal data.

    The newline option that is set at compile time becomes the default that is used for pcre_exec() and pcre_dfa_exec(), but it can be overridden.

      PCRE_NO_AUTO_CAPTURE
    
    If this option is set, it disables the use of numbered capturing parentheses in the pattern. Any opening parenthesis that is not followed by ? behaves as if it were followed by ?: but named parentheses can still be used for capturing (and they acquire numbers in the usual way). There is no equivalent of this option in Perl.
      PCRE_NO_AUTO_POSSESS
    
    If this option is set, it disables "auto-possessification". This is an optimization that, for example, turns a+b into a++b in order to avoid backtracks into a+ that can never be successful. However, if callouts are in use, auto-possessification means that some of them are never taken. You can set this option if you want the matching functions to do a full unoptimized search and run all the callouts, but it is mainly provided for testing purposes.
      PCRE_NO_START_OPTIMIZE
    
    This is an option that acts at matching time; that is, it is really an option for pcre_exec() or pcre_dfa_exec(). If it is set at compile time, it is remembered with the compiled pattern and assumed at matching time. This is necessary if you want to use JIT execution, because the JIT compiler needs to know whether or not this option is set. For details see the discussion of PCRE_NO_START_OPTIMIZE below.
      PCRE_UCP
    
    This option changes the way PCRE processes \B, \b, \D, \d, \S, \s, \W, \w, and some of the POSIX character classes. By default, only ASCII characters are recognized, but if PCRE_UCP is set, Unicode properties are used instead to classify characters. More details are given in the section on generic character types in the pcrepattern page. If you set PCRE_UCP, matching one of the items it affects takes much longer. The option is available only if PCRE has been compiled with Unicode property support.
      PCRE_UNGREEDY
    
    This option inverts the "greediness" of the quantifiers so that they are not greedy by default, but become greedy if followed by "?". It is not compatible with Perl. It can also be set by a (?U) option setting within the pattern.
      PCRE_UTF8
    
    This option causes PCRE to regard both the pattern and the subject as strings of UTF-8 characters instead of single-byte strings. However, it is available only when PCRE is built to include UTF support. If not, the use of this option provokes an error. Details of how this option changes the behaviour of PCRE are given in the pcreunicode page.
      PCRE_NO_UTF8_CHECK
    
    When PCRE_UTF8 is set, the validity of the pattern as a UTF-8 string is automatically checked. There is a discussion about the validity of UTF-8 strings in the pcreunicode page. If an invalid UTF-8 sequence is found, pcre_compile() returns an error. If you already know that your pattern is valid, and you want to skip this check for performance reasons, you can set the PCRE_NO_UTF8_CHECK option. When it is set, the effect of passing an invalid UTF-8 string as a pattern is undefined. It may cause your program to crash or loop. Note that this option can also be passed to pcre_exec() and pcre_dfa_exec(), to suppress the validity checking of subject strings only. If the same string is being matched many times, the option can be safely set for the second and subsequent matchings to improve performance.


    COMPILATION ERROR CODES

    The following table lists the error codes than may be returned by pcre_compile2(), along with the error messages that may be returned by both compiling functions. Note that error messages are always 8-bit ASCII strings, even in 16-bit or 32-bit mode. As PCRE has developed, some error codes have fallen out of use. To avoid confusion, they have not been re-used.

       0  no error
       1  \ at end of pattern
       2  \c at end of pattern
       3  unrecognized character follows \
       4  numbers out of order in {} quantifier
       5  number too big in {} quantifier
       6  missing terminating ] for character class
       7  invalid escape sequence in character class
       8  range out of order in character class
       9  nothing to repeat
      10  [this code is not in use]
      11  internal error: unexpected repeat
      12  unrecognized character after (? or (?-
      13  POSIX named classes are supported only within a class
      14  missing )
      15  reference to non-existent subpattern
      16  erroffset passed as NULL
      17  unknown option bit(s) set
      18  missing ) after comment
      19  [this code is not in use]
      20  regular expression is too large
      21  failed to get memory
      22  unmatched parentheses
      23  internal error: code overflow
      24  unrecognized character after (?<
      25  lookbehind assertion is not fixed length
      26  malformed number or name after (?(
      27  conditional group contains more than two branches
      28  assertion expected after (?(
      29  (?R or (?[+-]digits must be followed by )
      30  unknown POSIX class name
      31  POSIX collating elements are not supported
      32  this version of PCRE is compiled without UTF support
      33  [this code is not in use]
      34  character value in \x{} or \o{} is too large
      35  invalid condition (?(0)
      36  \C not allowed in lookbehind assertion
      37  PCRE does not support \L, \l, \N{name}, \U, or \u
      38  number after (?C is > 255
      39  closing ) for (?C expected
      40  recursive call could loop indefinitely
      41  unrecognized character after (?P
      42  syntax error in subpattern name (missing terminator)
      43  two named subpatterns have the same name
      44  invalid UTF-8 string (specifically UTF-8)
      45  support for \P, \p, and \X has not been compiled
      46  malformed \P or \p sequence
      47  unknown property name after \P or \p
      48  subpattern name is too long (maximum 32 characters)
      49  too many named subpatterns (maximum 10000)
      50  [this code is not in use]
      51  octal value is greater than \377 in 8-bit non-UTF-8 mode
      52  internal error: overran compiling workspace
      53  internal error: previously-checked referenced subpattern
            not found
      54  DEFINE group contains more than one branch
      55  repeating a DEFINE group is not allowed
      56  inconsistent NEWLINE options
      57  \g is not followed by a braced, angle-bracketed, or quoted
            name/number or by a plain number
      58  a numbered reference must not be zero
      59  an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)
      60  (*VERB) not recognized or malformed
      61  number is too big
      62  subpattern name expected
      63  digit expected after (?+
      64  ] is an invalid data character in JavaScript compatibility mode
      65  different names for subpatterns of the same number are
            not allowed
      66  (*MARK) must have an argument
      67  this version of PCRE is not compiled with Unicode property
            support
      68  \c must be followed by an ASCII character
      69  \k is not followed by a braced, angle-bracketed, or quoted name
      70  internal error: unknown opcode in find_fixedlength()
      71  \N is not supported in a class
      72  too many forward references
      73  disallowed Unicode code point (>= 0xd800 && <= 0xdfff)
      74  invalid UTF-16 string (specifically UTF-16)
      75  name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)
      76  character value in \u.... sequence is too large
      77  invalid UTF-32 string (specifically UTF-32)
      78  setting UTF is disabled by the application
      79  non-hex character in \x{} (closing brace missing?)
      80  non-octal character in \o{} (closing brace missing?)
      81  missing opening brace after \o
      82  parentheses are too deeply nested
      83  invalid range in character class
      84  group name must start with a non-digit
      85  parentheses are too deeply nested (stack check)
    
    The numbers 32 and 10000 in errors 48 and 49 are defaults; different values may be used if the limits were changed when PCRE was built.


    STUDYING A PATTERN

    pcre_extra *pcre_study(const pcre *code, int options, const char **errptr);

    If a compiled pattern is going to be used several times, it is worth spending more time analyzing it in order to speed up the time taken for matching. The function pcre_study() takes a pointer to a compiled pattern as its first argument. If studying the pattern produces additional information that will help speed up matching, pcre_study() returns a pointer to a pcre_extra block, in which the study_data field points to the results of the study.

    The returned value from pcre_study() can be passed directly to pcre_exec() or pcre_dfa_exec(). However, a pcre_extra block also contains other fields that can be set by the caller before the block is passed; these are described below in the section on matching a pattern.

    If studying the pattern does not produce any useful information, pcre_study() returns NULL by default. In that circumstance, if the calling program wants to pass any of the other fields to pcre_exec() or pcre_dfa_exec(), it must set up its own pcre_extra block. However, if pcre_study() is called with the PCRE_STUDY_EXTRA_NEEDED option, it returns a pcre_extra block even if studying did not find any additional information. It may still return NULL, however, if an error occurs in pcre_study().

    The second argument of pcre_study() contains option bits. There are three further options in addition to PCRE_STUDY_EXTRA_NEEDED:

      PCRE_STUDY_JIT_COMPILE
      PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
      PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
    
    If any of these are set, and the just-in-time compiler is available, the pattern is further compiled into machine code that executes much faster than the pcre_exec() interpretive matching function. If the just-in-time compiler is not available, these options are ignored. All undefined bits in the options argument must be zero.

    JIT compilation is a heavyweight optimization. It can take some time for patterns to be analyzed, and for one-off matches and simple patterns the benefit of faster execution might be offset by a much slower study time. Not all patterns can be optimized by the JIT compiler. For those that cannot be handled, matching automatically falls back to the pcre_exec() interpreter. For more details, see the pcrejit documentation.

    The third argument for pcre_study() is a pointer for an error message. If studying succeeds (even if no data is returned), the variable it points to is set to NULL. Otherwise it is set to point to a textual error message. This is a static string that is part of the library. You must not try to free it. You should test the error pointer for NULL after calling pcre_study(), to be sure that it has run successfully.

    When you are finished with a pattern, you can free the memory used for the study data by calling pcre_free_study(). This function was added to the API for release 8.20. For earlier versions, the memory could be freed with pcre_free(), just like the pattern itself. This will still work in cases where JIT optimization is not used, but it is advisable to change to the new function when convenient.

    This is a typical way in which pcre_study() is used (except that in a real application there should be tests for errors):

      int rc;
      pcre *re;
      pcre_extra *sd;
      re = pcre_compile("pattern", 0, &error, &erroroffset, NULL);
      sd = pcre_study(
        re,             /* result of pcre_compile() */
        0,              /* no options */
        &error);        /* set to NULL or points to a message */
      rc = pcre_exec(   /* see below for details of pcre_exec() options */
        re, sd, "subject", 7, 0, 0, ovector, 30);
      ...
      pcre_free_study(sd);
      pcre_free(re);
    
    Studying a pattern does two things: first, a lower bound for the length of subject string that is needed to match the pattern is computed. This does not mean that there are any strings of that length that match, but it does guarantee that no shorter strings match. The value is used to avoid wasting time by trying to match strings that are shorter than the lower bound. You can find out the value in a calling program via the pcre_fullinfo() function.

    Studying a pattern is also useful for non-anchored patterns that do not have a single fixed starting character. A bitmap of possible starting bytes is created. This speeds up finding a position in the subject at which to start matching. (In 16-bit mode, the bitmap is used for 16-bit values less than 256. In 32-bit mode, the bitmap is used for 32-bit values less than 256.)

    These two optimizations apply to both pcre_exec() and pcre_dfa_exec(), and the information is also used by the JIT compiler. The optimizations can be disabled by setting the PCRE_NO_START_OPTIMIZE option. You might want to do this if your pattern contains callouts or (*MARK) and you want to make use of these facilities in cases where matching fails.

    PCRE_NO_START_OPTIMIZE can be specified at either compile time or execution time. However, if PCRE_NO_START_OPTIMIZE is passed to pcre_exec(), (that is, after any JIT compilation has happened) JIT execution is disabled. For JIT execution to work with PCRE_NO_START_OPTIMIZE, the option must be set at compile time.

    There is a longer discussion of PCRE_NO_START_OPTIMIZE below.


    LOCALE SUPPORT

    PCRE handles caseless matching, and determines whether characters are letters, digits, or whatever, by reference to a set of tables, indexed by character code point. When running in UTF-8 mode, or in the 16- or 32-bit libraries, this applies only to characters with code points less than 256. By default, higher-valued code points never match escapes such as \w or \d. However, if PCRE is built with Unicode property support, all characters can be tested with \p and \P, or, alternatively, the PCRE_UCP option can be set when a pattern is compiled; this causes \w and friends to use Unicode property support instead of the built-in tables.

    The use of locales with Unicode is discouraged. If you are handling characters with code points greater than 128, you should either use Unicode support, or use locales, but not try to mix the two.

    PCRE contains an internal set of tables that are used when the final argument of pcre_compile() is NULL. These are sufficient for many applications. Normally, the internal tables recognize only ASCII characters. However, when PCRE is built, it is possible to cause the internal tables to be rebuilt in the default "C" locale of the local system, which may cause them to be different.

    The internal tables can always be overridden by tables supplied by the application that calls PCRE. These may be created in a different locale from the default. As more and more applications change to using Unicode, the need for this locale support is expected to die away.

    External tables are built by calling the pcre_maketables() function, which has no arguments, in the relevant locale. The result can then be passed to pcre_compile() as often as necessary. For example, to build and use tables that are appropriate for the French locale (where accented characters with values greater than 128 are treated as letters), the following code could be used:

      setlocale(LC_CTYPE, "fr_FR");
      tables = pcre_maketables();
      re = pcre_compile(..., tables);
    
    The locale name "fr_FR" is used on Linux and other Unix-like systems; if you are using Windows, the name for the French locale is "french".

    When pcre_maketables() runs, the tables are built in memory that is obtained via pcre_malloc. It is the caller's responsibility to ensure that the memory containing the tables remains available for as long as it is needed.

    The pointer that is passed to pcre_compile() is saved with the compiled pattern, and the same tables are used via this pointer by pcre_study() and also by pcre_exec() and pcre_dfa_exec(). Thus, for any single pattern, compilation, studying and matching all happen in the same locale, but different patterns can be processed in different locales.

    It is possible to pass a table pointer or NULL (indicating the use of the internal tables) to pcre_exec() or pcre_dfa_exec() (see the discussion below in the section on matching a pattern). This facility is provided for use with pre-compiled patterns that have been saved and reloaded. Character tables are not saved with patterns, so if a non-standard table was used at compile time, it must be provided again when the reloaded pattern is matched. Attempting to use this facility to match a pattern in a different locale from the one in which it was compiled is likely to lead to anomalous (usually incorrect) results.


    INFORMATION ABOUT A PATTERN

    int pcre_fullinfo(const pcre *code, const pcre_extra *extra, int what, void *where);

    The pcre_fullinfo() function returns information about a compiled pattern. It replaces the pcre_info() function, which was removed from the library at version 8.30, after more than 10 years of obsolescence.

    The first argument for pcre_fullinfo() is a pointer to the compiled pattern. The second argument is the result of pcre_study(), or NULL if the pattern was not studied. The third argument specifies which piece of information is required, and the fourth argument is a pointer to a variable to receive the data. The yield of the function is zero for success, or one of the following negative numbers:

      PCRE_ERROR_NULL           the argument code was NULL
                                the argument where was NULL
      PCRE_ERROR_BADMAGIC       the "magic number" was not found
      PCRE_ERROR_BADENDIANNESS  the pattern was compiled with different
                                endianness
      PCRE_ERROR_BADOPTION      the value of what was invalid
      PCRE_ERROR_UNSET          the requested field is not set
    
    The "magic number" is placed at the start of each compiled pattern as an simple check against passing an arbitrary memory pointer. The endianness error can occur if a compiled pattern is saved and reloaded on a different host. Here is a typical call of pcre_fullinfo(), to obtain the length of the compiled pattern:
      int rc;
      size_t length;
      rc = pcre_fullinfo(
        re,               /* result of pcre_compile() */
        sd,               /* result of pcre_study(), or NULL */
        PCRE_INFO_SIZE,   /* what is required */
        &length);         /* where to put the data */
    
    The possible values for the third argument are defined in pcre.h, and are as follows:
      PCRE_INFO_BACKREFMAX
    
    Return the number of the highest back reference in the pattern. The fourth argument should point to an int variable. Zero is returned if there are no back references.
      PCRE_INFO_CAPTURECOUNT
    
    Return the number of capturing subpatterns in the pattern. The fourth argument should point to an int variable.
      PCRE_INFO_DEFAULT_TABLES
    
    Return a pointer to the internal default character tables within PCRE. The fourth argument should point to an unsigned char * variable. This information call is provided for internal use by the pcre_study() function. External callers can cause PCRE to use its internal tables by passing a NULL table pointer.
      PCRE_INFO_FIRSTBYTE (deprecated)
    
    Return information about the first data unit of any matched string, for a non-anchored pattern. The name of this option refers to the 8-bit library, where data units are bytes. The fourth argument should point to an int variable. Negative values are used for special cases. However, this means that when the 32-bit library is in non-UTF-32 mode, the full 32-bit range of characters cannot be returned. For this reason, this value is deprecated; use PCRE_INFO_FIRSTCHARACTERFLAGS and PCRE_INFO_FIRSTCHARACTER instead.

    If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), its value is returned. In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library the value can be up to 0x10ffff.

    If there is no fixed first value, and if either

    (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or

    (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored),

    -1 is returned, indicating that the pattern matches only at the start of a subject string or after any newline within the string. Otherwise -2 is returned. For anchored patterns, -2 is returned.

      PCRE_INFO_FIRSTCHARACTER
    
    Return the value of the first data unit (non-UTF character) of any matched string in the situation where PCRE_INFO_FIRSTCHARACTERFLAGS returns 1; otherwise return 0. The fourth argument should point to an uint_t variable.

    In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff, and up to 0xffffffff when not using UTF-32 mode.

      PCRE_INFO_FIRSTCHARACTERFLAGS
    
    Return information about the first data unit of any matched string, for a non-anchored pattern. The fourth argument should point to an int variable.

    If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), 1 is returned, and the character value can be retrieved using PCRE_INFO_FIRSTCHARACTER. If there is no fixed first value, and if either

    (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or

    (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored),

    2 is returned, indicating that the pattern matches only at the start of a subject string or after any newline within the string. Otherwise 0 is returned. For anchored patterns, 0 is returned.

      PCRE_INFO_FIRSTTABLE
    
    If the pattern was studied, and this resulted in the construction of a 256-bit table indicating a fixed set of values for the first data unit in any matching string, a pointer to the table is returned. Otherwise NULL is returned. The fourth argument should point to an unsigned char * variable.
      PCRE_INFO_HASCRORLF
    
    Return 1 if the pattern contains any explicit matches for CR or LF characters, otherwise 0. The fourth argument should point to an int variable. An explicit match is either a literal CR or LF character, or \r or \n.
      PCRE_INFO_JCHANGED
    
    Return 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise 0. The fourth argument should point to an int variable. (?J) and (?-J) set and unset the local PCRE_DUPNAMES option, respectively.
      PCRE_INFO_JIT
    
    Return 1 if the pattern was studied with one of the JIT options, and just-in-time compiling was successful. The fourth argument should point to an int variable. A return value of 0 means that JIT support is not available in this version of PCRE, or that the pattern was not studied with a JIT option, or that the JIT compiler could not handle this particular pattern. See the pcrejit documentation for details of what can and cannot be handled.
      PCRE_INFO_JITSIZE
    
    If the pattern was successfully studied with a JIT option, return the size of the JIT compiled code, otherwise return zero. The fourth argument should point to a size_t variable.
      PCRE_INFO_LASTLITERAL
    
    Return the value of the rightmost literal data unit that must exist in any matched string, other than at its start, if such a value has been recorded. The fourth argument should point to an int variable. If there is no such value, -1 is returned. For anchored patterns, a last literal value is recorded only if it follows something of variable length. For example, for the pattern /^a\d+z\d+/ the returned value is "z", but for /^a\dz\d/ the returned value is -1.

    Since for the 32-bit library using the non-UTF-32 mode, this function is unable to return the full 32-bit range of characters, this value is deprecated; instead the PCRE_INFO_REQUIREDCHARFLAGS and PCRE_INFO_REQUIREDCHAR values should be used.

      PCRE_INFO_MATCH_EMPTY
    
    Return 1 if the pattern can match an empty string, otherwise 0. The fourth argument should point to an int variable.
      PCRE_INFO_MATCHLIMIT
    
    If the pattern set a match limit by including an item of the form (*LIMIT_MATCH=nnnn) at the start, the value is returned. The fourth argument should point to an unsigned 32-bit integer. If no such value has been set, the call to pcre_fullinfo() returns the error PCRE_ERROR_UNSET.
      PCRE_INFO_MAXLOOKBEHIND
    
    Return the number of characters (NB not data units) in the longest lookbehind assertion in the pattern. This information is useful when doing multi-segment matching using the partial matching facilities. Note that the simple assertions \b and \B require a one-character lookbehind. \A also registers a one-character lookbehind, though it does not actually inspect the previous character. This is to ensure that at least one character from the old segment is retained when a new segment is processed. Otherwise, if there are no lookbehinds in the pattern, \A might match incorrectly at the start of a new segment.
      PCRE_INFO_MINLENGTH
    
    If the pattern was studied and a minimum length for matching subject strings was computed, its value is returned. Otherwise the returned value is -1. The value is a number of characters, which in UTF mode may be different from the number of data units. The fourth argument should point to an int variable. A non-negative value is a lower bound to the length of any matching string. There may not be any strings of that length that do actually match, but every string that does match is at least that long.
      PCRE_INFO_NAMECOUNT
      PCRE_INFO_NAMEENTRYSIZE
      PCRE_INFO_NAMETABLE
    
    PCRE supports the use of named as well as numbered capturing parentheses. The names are just an additional way of identifying the parentheses, which still acquire numbers. Several convenience functions such as pcre_get_named_substring() are provided for extracting captured substrings by name. It is also possible to extract the data directly, by first converting the name to a number in order to access the correct pointers in the output vector (described with pcre_exec() below). To do the conversion, you need to use the name-to-number map, which is described by these three values.

    The map consists of a number of fixed-size entries. PCRE_INFO_NAMECOUNT gives the number of entries, and PCRE_INFO_NAMEENTRYSIZE gives the size of each entry; both of these return an int value. The entry size depends on the length of the longest name. PCRE_INFO_NAMETABLE returns a pointer to the first entry of the table. This is a pointer to char in the 8-bit library, where the first two bytes of each entry are the number of the capturing parenthesis, most significant byte first. In the 16-bit library, the pointer points to 16-bit data units, the first of which contains the parenthesis number. In the 32-bit library, the pointer points to 32-bit data units, the first of which contains the parenthesis number. The rest of the entry is the corresponding name, zero terminated.

    The names are in alphabetical order. If (?| is used to create multiple groups with the same number, as described in the section on duplicate subpattern numbers in the pcrepattern page, the groups may be given the same name, but there is only one entry in the table. Different names for groups of the same number are not permitted. Duplicate names for subpatterns with different numbers are permitted, but only if PCRE_DUPNAMES is set. They appear in the table in the order in which they were found in the pattern. In the absence of (?| this is the order of increasing number; when (?| is used this is not necessarily the case because later subpatterns may have lower numbers.

    As a simple example of the name/number table, consider the following pattern after compilation by the 8-bit library (assume PCRE_EXTENDED is set, so white space - including newlines - is ignored):

      (?<date> (?<year>(\d\d)?\d\d) - (?<month>\d\d) - (?<day>\d\d) )
    
    There are four named subpatterns, so the table has four entries, and each entry in the table is eight bytes long. The table is as follows, with non-printing bytes shows in hexadecimal, and undefined bytes shown as ??:
      00 01 d  a  t  e  00 ??
      00 05 d  a  y  00 ?? ??
      00 04 m  o  n  t  h  00
      00 02 y  e  a  r  00 ??
    
    When writing code to extract data from named subpatterns using the name-to-number map, remember that the length of the entries is likely to be different for each compiled pattern.
      PCRE_INFO_OKPARTIAL
    
    Return 1 if the pattern can be used for partial matching with pcre_exec(), otherwise 0. The fourth argument should point to an int variable. From release 8.00, this always returns 1, because the restrictions that previously applied to partial matching have been lifted. The pcrepartial documentation gives details of partial matching.
      PCRE_INFO_OPTIONS
    
    Return a copy of the options with which the pattern was compiled. The fourth argument should point to an unsigned long int variable. These option bits are those specified in the call to pcre_compile(), modified by any top-level option settings at the start of the pattern itself. In other words, they are the options that will be in force when matching starts. For example, if the pattern /(?im)abc(?-i)d/ is compiled with the PCRE_EXTENDED option, the result is PCRE_CASELESS, PCRE_MULTILINE, and PCRE_EXTENDED.

    A pattern is automatically anchored by PCRE if all of its top-level alternatives begin with one of the following:

      ^     unless PCRE_MULTILINE is set
      \A    always
      \G    always
      .*    if PCRE_DOTALL is set and there are no back references to the subpattern in which .* appears
    
    For such patterns, the PCRE_ANCHORED bit is set in the options returned by pcre_fullinfo().
      PCRE_INFO_RECURSIONLIMIT
    
    If the pattern set a recursion limit by including an item of the form (*LIMIT_RECURSION=nnnn) at the start, the value is returned. The fourth argument should point to an unsigned 32-bit integer. If no such value has been set, the call to pcre_fullinfo() returns the error PCRE_ERROR_UNSET.
      PCRE_INFO_SIZE
    
    Return the size of the compiled pattern in bytes (for all three libraries). The fourth argument should point to a size_t variable. This value does not include the size of the pcre structure that is returned by pcre_compile(). The value that is passed as the argument to pcre_malloc() when pcre_compile() is getting memory in which to place the compiled data is the value returned by this option plus the size of the pcre structure. Studying a compiled pattern, with or without JIT, does not alter the value returned by this option.
      PCRE_INFO_STUDYSIZE
    
    Return the size in bytes (for all three libraries) of the data block pointed to by the study_data field in a pcre_extra block. If pcre_extra is NULL, or there is no study data, zero is returned. The fourth argument should point to a size_t variable. The study_data field is set by pcre_study() to record information that will speed up matching (see the section entitled "Studying a pattern" above). The format of the study_data block is private, but its length is made available via this option so that it can be saved and restored (see the pcreprecompile documentation for details).
      PCRE_INFO_REQUIREDCHARFLAGS
    
    Returns 1 if there is a rightmost literal data unit that must exist in any matched string, other than at its start. The fourth argument should point to an int variable. If there is no such value, 0 is returned. If returning 1, the character value itself can be retrieved using PCRE_INFO_REQUIREDCHAR.

    For anchored patterns, a last literal value is recorded only if it follows something of variable length. For example, for the pattern /^a\d+z\d+/ the returned value 1 (with "z" returned from PCRE_INFO_REQUIREDCHAR), but for /^a\dz\d/ the returned value is 0.

      PCRE_INFO_REQUIREDCHAR
    
    Return the value of the rightmost literal data unit that must exist in any matched string, other than at its start, if such a value has been recorded. The fourth argument should point to an uint32_t variable. If there is no such value, 0 is returned.


    REFERENCE COUNTS

    int pcre_refcount(pcre *code, int adjust);

    The pcre_refcount() function is used to maintain a reference count in the data block that contains a compiled pattern. It is provided for the benefit of applications that operate in an object-oriented manner, where different parts of the application may be using the same compiled pattern, but you want to free the block when they are all done.

    When a pattern is compiled, the reference count field is initialized to zero. It is changed only by calling this function, whose action is to add the adjust value (which may be positive or negative) to it. The yield of the function is the new value. However, the value of the count is constrained to lie between 0 and 65535, inclusive. If the new value is outside these limits, it is forced to the appropriate limit value.

    Except when it is zero, the reference count is not correctly preserved if a pattern is compiled on one host and then transferred to a host whose byte-order is different. (This seems a highly unlikely scenario.)


    MATCHING A PATTERN: THE TRADITIONAL FUNCTION

    int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize);

    The function pcre_exec() is called to match a subject string against a compiled pattern, which is passed in the code argument. If the pattern was studied, the result of the study should be passed in the extra argument. You can call pcre_exec() with the same code and extra arguments as many times as you like, in order to match different subject strings with the same pattern.

    This function is the main matching facility of the library, and it operates in a Perl-like manner. For specialist use there is also an alternative matching function, which is described below in the section about the pcre_dfa_exec() function.

    In most applications, the pattern will have been compiled (and optionally studied) in the same process that calls pcre_exec(). However, it is possible to save compiled patterns and study data, and then use them later in different processes, possibly even on different hosts. For a discussion about this, see the pcreprecompile documentation.

    Here is an example of a simple call to pcre_exec():

      int rc;
      int ovector[30];
      rc = pcre_exec(
        re,             /* result of pcre_compile() */
        NULL,           /* we didn't study the pattern */
        "some string",  /* the subject string */
        11,             /* the length of the subject string */
        0,              /* start at offset 0 in the subject */
        0,              /* default options */
        ovector,        /* vector of integers for substring information */
        30);            /* number of elements (NOT size in bytes) */
    


    Extra data for pcre_exec()

    If the extra argument is not NULL, it must point to a pcre_extra data block. The pcre_study() function returns such a block (when it doesn't return NULL), but you can also create one for yourself, and pass additional information in it. The pcre_extra block contains the following fields (not necessarily in this order):

      unsigned long int flags;
      void *study_data;
      void *executable_jit;
      unsigned long int match_limit;
      unsigned long int match_limit_recursion;
      void *callout_data;
      const unsigned char *tables;
      unsigned char **mark;
    
    In the 16-bit version of this structure, the mark field has type "PCRE_UCHAR16 **".

    In the 32-bit version of this structure, the mark field has type "PCRE_UCHAR32 **".

    The flags field is used to specify which of the other fields are set. The flag bits are:

      PCRE_EXTRA_CALLOUT_DATA
      PCRE_EXTRA_EXECUTABLE_JIT
      PCRE_EXTRA_MARK
      PCRE_EXTRA_MATCH_LIMIT
      PCRE_EXTRA_MATCH_LIMIT_RECURSION
      PCRE_EXTRA_STUDY_DATA
      PCRE_EXTRA_TABLES
    
    Other flag bits should be set to zero. The study_data field and sometimes the executable_jit field are set in the pcre_extra block that is returned by pcre_study(), together with the appropriate flag bits. You should not set these yourself, but you may add to the block by setting other fields and their corresponding flag bits.

    The match_limit field provides a means of preventing PCRE from using up a vast amount of resources when running patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is a pattern that uses nested unlimited repeats.

    Internally, pcre_exec() uses a function called match(), which it calls repeatedly (sometimes recursively). The limit set by match_limit is imposed on the number of times this function is called during a match, which has the effect of limiting the amount of backtracking that can take place. For patterns that are not anchored, the count restarts from zero for each position in the subject string.

    When pcre_exec() is called with a pattern that was successfully studied with a JIT option, the way that the matching is executed is entirely different. However, there is still the possibility of runaway matching that goes on for a very long time, and so the match_limit value is also used in this case (but in a different way) to limit how long the matching can continue.

    The default value for the limit can be set when PCRE is built; the default default is 10 million, which handles all but the most extreme cases. You can override the default by suppling pcre_exec() with a pcre_extra block in which match_limit is set, and PCRE_EXTRA_MATCH_LIMIT is set in the flags field. If the limit is exceeded, pcre_exec() returns PCRE_ERROR_MATCHLIMIT.

    A value for the match limit may also be supplied by an item at the start of a pattern of the form

      (*LIMIT_MATCH=d)
    
    where d is a decimal number. However, such a setting is ignored unless d is less than the limit set by the caller of pcre_exec() or, if no such limit is set, less than the default.

    The match_limit_recursion field is similar to match_limit, but instead of limiting the total number of times that match() is called, it limits the depth of recursion. The recursion depth is a smaller number than the total number of calls, because not all calls to match() are recursive. This limit is of use only if it is set smaller than match_limit.

    Limiting the recursion depth limits the amount of machine stack that can be used, or, when PCRE has been compiled to use memory on the heap instead of the stack, the amount of heap memory that can be used. This limit is not relevant, and is ignored, when matching is done using JIT compiled code.

    The default value for match_limit_recursion can be set when PCRE is built; the default default is the same value as the default for match_limit. You can override the default by suppling pcre_exec() with a pcre_extra block in which match_limit_recursion is set, and PCRE_EXTRA_MATCH_LIMIT_RECURSION is set in the flags field. If the limit is exceeded, pcre_exec() returns PCRE_ERROR_RECURSIONLIMIT.

    A value for the recursion limit may also be supplied by an item at the start of a pattern of the form

      (*LIMIT_RECURSION=d)
    
    where d is a decimal number. However, such a setting is ignored unless d is less than the limit set by the caller of pcre_exec() or, if no such limit is set, less than the default.

    The callout_data field is used in conjunction with the "callout" feature, and is described in the pcrecallout documentation.

    The tables field is provided for use with patterns that have been pre-compiled using custom character tables, saved to disc or elsewhere, and then reloaded, because the tables that were used to compile a pattern are not saved with it. See the pcreprecompile documentation for a discussion of saving compiled patterns for later use. If NULL is passed using this mechanism, it forces PCRE's internal tables to be used.

    Warning: The tables that pcre_exec() uses must be the same as those that were used when the pattern was compiled. If this is not the case, the behaviour of pcre_exec() is undefined. Therefore, when a pattern is compiled and matched in the same process, this field should never be set. In this (the most common) case, the correct table pointer is automatically passed with the compiled pattern from pcre_compile() to pcre_exec().

    If PCRE_EXTRA_MARK is set in the flags field, the mark field must be set to point to a suitable variable. If the pattern contains any backtracking control verbs such as (*MARK:NAME), and the execution ends up with a name to pass back, a pointer to the name string (zero terminated) is placed in the variable pointed to by the mark field. The names are within the compiled pattern; if you wish to retain such a name you must copy it before freeing the memory of a compiled pattern. If there is no name to pass back, the variable pointed to by the mark field is set to NULL. For details of the backtracking control verbs, see the section entitled "Backtracking control" in the pcrepattern documentation.


    Option bits for pcre_exec()

    The unused bits of the options argument for pcre_exec() must be zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NEWLINE_xxx, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_NO_START_OPTIMIZE, PCRE_NO_UTF8_CHECK, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT.

    If the pattern was successfully studied with one of the just-in-time (JIT) compile options, the only supported options for JIT execution are PCRE_NO_UTF8_CHECK, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. If an unsupported option is used, JIT execution is disabled and the normal interpretive code in pcre_exec() is run.

      PCRE_ANCHORED
    
    The PCRE_ANCHORED option limits pcre_exec() to matching at the first matching position. If a pattern was compiled with PCRE_ANCHORED, or turned out to be anchored by virtue of its contents, it cannot be made unachored at matching time.
      PCRE_BSR_ANYCRLF
      PCRE_BSR_UNICODE
    
    These options (which are mutually exclusive) control what the \R escape sequence matches. The choice is either to match only CR, LF, or CRLF, or to match any Unicode newline sequence. These options override the choice that was made or defaulted when the pattern was compiled.
      PCRE_NEWLINE_CR
      PCRE_NEWLINE_LF
      PCRE_NEWLINE_CRLF
      PCRE_NEWLINE_ANYCRLF
      PCRE_NEWLINE_ANY
    
    These options override the newline definition that was chosen or defaulted when the pattern was compiled. For details, see the description of pcre_compile() above. During matching, the newline choice affects the behaviour of the dot, circumflex, and dollar metacharacters. It may also alter the way the match position is advanced after a match failure for an unanchored pattern.

    When PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANYCRLF, or PCRE_NEWLINE_ANY is set, and a match attempt for an unanchored pattern fails when the current position is at a CRLF sequence, and the pattern contains no explicit matches for CR or LF characters, the match position is advanced by two characters instead of one, in other words, to after the CRLF.

    The above rule is a compromise that makes the most common cases work as expected. For example, if the pattern is .+A (and the PCRE_DOTALL option is not set), it does not match the string "\r\nA" because, after failing at the start, it skips both the CR and the LF before retrying. However, the pattern [\r\n]A does match that string, because it contains an explicit CR or LF reference, and so advances only by one character after the first failure.

    An explicit match for CR of LF is either a literal appearance of one of those characters, or one of the \r or \n escape sequences. Implicit matches such as [^X] do not count, nor does \s (which includes CR and LF in the characters that it matches).

    Notwithstanding the above, anomalous effects may still occur when CRLF is a valid newline sequence and explicit \r or \n escapes appear in the pattern.

      PCRE_NOTBOL
    
    This option specifies that first character of the subject string is not the beginning of a line, so the circumflex metacharacter should not match before it. Setting this without PCRE_MULTILINE (at compile time) causes circumflex never to match. This option affects only the behaviour of the circumflex metacharacter. It does not affect \A.
      PCRE_NOTEOL
    
    This option specifies that the end of the subject string is not the end of a line, so the dollar metacharacter should not match it nor (except in multiline mode) a newline immediately before it. Setting this without PCRE_MULTILINE (at compile time) causes dollar never to match. This option affects only the behaviour of the dollar metacharacter. It does not affect \Z or \z.
      PCRE_NOTEMPTY
    
    An empty string is not considered to be a valid match if this option is set. If there are alternatives in the pattern, they are tried. If all the alternatives match the empty string, the entire match fails. For example, if the pattern
      a?b?
    
    is applied to a string not beginning with "a" or "b", it matches an empty string at the start of the subject. With PCRE_NOTEMPTY set, this match is not valid, so PCRE searches further into the string for occurrences of "a" or "b".
      PCRE_NOTEMPTY_ATSTART
    
    This is like PCRE_NOTEMPTY, except that an empty string match that is not at the start of the subject is permitted. If the pattern is anchored, such a match can occur only if the pattern contains \K.

    Perl has no direct equivalent of PCRE_NOTEMPTY or PCRE_NOTEMPTY_ATSTART, but it does make a special case of a pattern match of the empty string within its split() function, and when using the /g modifier. It is possible to emulate Perl's behaviour after matching a null string by first trying the match again at the same offset with PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED, and then if that fails, by advancing the starting offset (see below) and trying an ordinary match again. There is some code that demonstrates how to do this in the pcredemo sample program. In the most general case, you have to check to see if the newline convention recognizes CRLF as a newline, and if so, and the current character is CR followed by LF, advance the starting offset by two characters instead of one.

      PCRE_NO_START_OPTIMIZE
    
    There are a number of optimizations that pcre_exec() uses at the start of a match, in order to speed up the process. For example, if it is known that an unanchored match must start with a specific character, it searches the subject for that character, and fails immediately if it cannot find it, without actually running the main matching function. This means that a special item such as (*COMMIT) at the start of a pattern is not considered until after a suitable starting point for the match has been found. Also, when callouts or (*MARK) items are in use, these "start-up" optimizations can cause them to be skipped if the pattern is never actually used. The start-up optimizations are in effect a pre-scan of the subject that takes place before the pattern is run.

    The PCRE_NO_START_OPTIMIZE option disables the start-up optimizations, possibly causing performance to suffer, but ensuring that in cases where the result is "no match", the callouts do occur, and that items such as (*COMMIT) and (*MARK) are considered at every possible starting position in the subject string. If PCRE_NO_START_OPTIMIZE is set at compile time, it cannot be unset at matching time. The use of PCRE_NO_START_OPTIMIZE at matching time (that is, passing it to pcre_exec()) disables JIT execution; in this situation, matching is always done using interpretively.

    Setting PCRE_NO_START_OPTIMIZE can change the outcome of a matching operation. Consider the pattern

      (*COMMIT)ABC
    
    When this is compiled, PCRE records the fact that a match must start with the character "A". Suppose the subject string is "DEFABC". The start-up optimization scans along the subject, finds "A" and runs the first match attempt from there. The (*COMMIT) item means that the pattern must match the current starting position, which in this case, it does. However, if the same match is run with PCRE_NO_START_OPTIMIZE set, the initial scan along the subject string does not happen. The first match attempt is run starting from "D" and when this fails, (*COMMIT) prevents any further matches being tried, so the overall result is "no match". If the pattern is studied, more start-up optimizations may be used. For example, a minimum length for the subject may be recorded. Consider the pattern
      (*MARK:A)(X|Y)
    
    The minimum length for a match is one character. If the subject is "ABC", there will be attempts to match "ABC", "BC", "C", and then finally an empty string. If the pattern is studied, the final attempt does not take place, because PCRE knows that the subject is too short, and so the (*MARK) is never encountered. In this case, studying the pattern does not affect the overall match result, which is still "no match", but it does affect the auxiliary information that is returned.
      PCRE_NO_UTF8_CHECK
    
    When PCRE_UTF8 is set at compile time, the validity of the subject as a UTF-8 string is automatically checked when pcre_exec() is subsequently called. The entire string is checked before any other processing takes place. The value of startoffset is also checked to ensure that it points to the start of a UTF-8 character. There is a discussion about the validity of UTF-8 strings in the pcreunicode page. If an invalid sequence of bytes is found, pcre_exec() returns the error PCRE_ERROR_BADUTF8 or, if PCRE_PARTIAL_HARD is set and the problem is a truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8. In both cases, information about the precise nature of the error may also be returned (see the descriptions of these errors in the section entitled \fIError return values from\fP pcre_exec() below). If startoffset contains a value that does not point to the start of a UTF-8 character (or to the end of the subject), PCRE_ERROR_BADUTF8_OFFSET is returned.

    If you already know that your subject is valid, and you want to skip these checks for performance reasons, you can set the PCRE_NO_UTF8_CHECK option when calling pcre_exec(). You might want to do this for the second and subsequent calls to pcre_exec() if you are making repeated calls to find all the matches in a single subject string. However, you should be sure that the value of startoffset points to the start of a character (or the end of the subject). When PCRE_NO_UTF8_CHECK is set, the effect of passing an invalid string as a subject or an invalid value of startoffset is undefined. Your program may crash or loop.

      PCRE_PARTIAL_HARD
      PCRE_PARTIAL_SOFT
    
    These options turn on the partial matching feature. For backwards compatibility, PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. A partial match occurs if the end of the subject string is reached successfully, but there are not enough subject characters to complete the match. If this happens when PCRE_PARTIAL_SOFT (but not PCRE_PARTIAL_HARD) is set, matching continues by testing any remaining alternatives. Only if no complete match can be found is PCRE_ERROR_PARTIAL returned instead of PCRE_ERROR_NOMATCH. In other words, PCRE_PARTIAL_SOFT says that the caller is prepared to handle a partial match, but only if no complete match can be found.

    If PCRE_PARTIAL_HARD is set, it overrides PCRE_PARTIAL_SOFT. In this case, if a partial match is found, pcre_exec() immediately returns PCRE_ERROR_PARTIAL, without considering any other alternatives. In other words, when PCRE_PARTIAL_HARD is set, a partial match is considered to be more important that an alternative complete match.

    In both cases, the portion of the string that was inspected when the partial match was found is set as the first matching string. There is a more detailed discussion of partial and multi-segment matching, with examples, in the pcrepartial documentation.


    The string to be matched by pcre_exec()

    The subject string is passed to pcre_exec() as a pointer in subject, a length in length, and a starting offset in startoffset. The units for length and startoffset are bytes for the 8-bit library, 16-bit data items for the 16-bit library, and 32-bit data items for the 32-bit library.

    If startoffset is negative or greater than the length of the subject, pcre_exec() returns PCRE_ERROR_BADOFFSET. When the starting offset is zero, the search for a match starts at the beginning of the subject, and this is by far the most common case. In UTF-8 or UTF-16 mode, the offset must point to the start of a character, or the end of the subject (in UTF-32 mode, one data unit equals one character, so all offsets are valid). Unlike the pattern string, the subject may contain binary zeroes.

    A non-zero starting offset is useful when searching for another match in the same subject by calling pcre_exec() again after a previous success. Setting startoffset differs from just passing over a shortened string and setting PCRE_NOTBOL in the case of a pattern that begins with any kind of lookbehind. For example, consider the pattern

      \Biss\B
    
    which finds occurrences of "iss" in the middle of words. (\B matches only if the current position in the subject is not a word boundary.) When applied to the string "Mississipi" the first call to pcre_exec() finds the first occurrence. If pcre_exec() is called again with just the remainder of the subject, namely "issipi", it does not match, because \B is always false at the start of the subject, which is deemed to be a word boundary. However, if pcre_exec() is passed the entire string again, but with startoffset set to 4, it finds the second occurrence of "iss" because it is able to look behind the starting point to discover that it is preceded by a letter.

    Finding all the matches in a subject is tricky when the pattern can match an empty string. It is possible to emulate Perl's /g behaviour by first trying the match again at the same offset, with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED options, and then if that fails, advancing the starting offset and trying an ordinary match again. There is some code that demonstrates how to do this in the pcredemo sample program. In the most general case, you have to check to see if the newline convention recognizes CRLF as a newline, and if so, and the current character is CR followed by LF, advance the starting offset by two characters instead of one.

    If a non-zero starting offset is passed when the pattern is anchored, one attempt to match at the given offset is made. This can only succeed if the pattern does not require the match to be at the start of the subject.


    How pcre_exec() returns captured substrings

    In general, a pattern matches a certain portion of the subject, and in addition, further substrings from the subject may be picked out by parts of the pattern. Following the usage in Jeffrey Friedl's book, this is called "capturing" in what follows, and the phrase "capturing subpattern" is used for a fragment of a pattern that picks out a substring. PCRE supports several other kinds of parenthesized subpattern that do not cause substrings to be captured.

    Captured substrings are returned to the caller via a vector of integers whose address is passed in ovector. The number of elements in the vector is passed in ovecsize, which must be a non-negative number. Note: this argument is NOT the size of ovector in bytes.

    The first two-thirds of the vector is used to pass back captured substrings, each substring using a pair of integers. The remaining third of the vector is used as workspace by pcre_exec() while matching capturing subpatterns, and is not available for passing back information. The number passed in ovecsize should always be a multiple of three. If it is not, it is rounded down.

    When a match is successful, information about captured substrings is returned in pairs of integers, starting at the beginning of ovector, and continuing up to two-thirds of its length at the most. The first element of each pair is set to the offset of the first character in a substring, and the second is set to the offset of the first character after the end of a substring. These values are always data unit offsets, even in UTF mode. They are byte offsets in the 8-bit library, 16-bit data item offsets in the 16-bit library, and 32-bit data item offsets in the 32-bit library. Note: they are not character counts.

    The first pair of integers, ovector[0] and ovector[1], identify the portion of the subject string matched by the entire pattern. The next pair is used for the first capturing subpattern, and so on. The value returned by pcre_exec() is one more than the highest numbered pair that has been set. For example, if two substrings have been captured, the returned value is 3. If there are no capturing subpatterns, the return value from a successful match is 1, indicating that just the first pair of offsets has been set.

    If a capturing subpattern is matched repeatedly, it is the last portion of the string that it matched that is returned.

    If the vector is too small to hold all the captured substring offsets, it is used as far as possible (up to two-thirds of its length), and the function returns a value of zero. If neither the actual string matched nor any captured substrings are of interest, pcre_exec() may be called with ovector passed as NULL and ovecsize as zero. However, if the pattern contains back references and the ovector is not big enough to remember the related substrings, PCRE has to get additional memory for use during matching. Thus it is usually advisable to supply an ovector of reasonable size.

    There are some cases where zero is returned (indicating vector overflow) when in fact the vector is exactly the right size for the final match. For example, consider the pattern

      (a)(?:(b)c|bd)
    
    If a vector of 6 elements (allowing for only 1 captured substring) is given with subject string "abd", pcre_exec() will try to set the second captured string, thereby recording a vector overflow, before failing to match "c" and backing up to try the second alternative. The zero return, however, does correctly indicate that the maximum number of slots (namely 2) have been filled. In similar cases where there is temporary overflow, but the final number of used slots is actually less than the maximum, a non-zero value is returned.

    The pcre_fullinfo() function can be used to find out how many capturing subpatterns there are in a compiled pattern. The smallest size for ovector that will allow for n captured substrings, in addition to the offsets of the substring matched by the whole pattern, is (n+1)*3.

    It is possible for capturing subpattern number n+1 to match some part of the subject when subpattern n has not been used at all. For example, if the string "abc" is matched against the pattern (a|(z))(bc) the return from the function is 4, and subpatterns 1 and 3 are matched, but 2 is not. When this happens, both values in the offset pairs corresponding to unused subpatterns are set to -1.

    Offset values that correspond to unused subpatterns at the end of the expression are also set to -1. For example, if the string "abc" is matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are not matched. The return from the function is 2, because the highest used capturing subpattern number is 1, and the offsets for for the second and third capturing subpatterns (assuming the vector is large enough, of course) are set to -1.

    Note: Elements in the first two-thirds of ovector that do not correspond to capturing parentheses in the pattern are never changed. That is, if a pattern contains n capturing parentheses, no more than ovector[0] to ovector[2n+1] are set by pcre_exec(). The other elements (in the first two-thirds) retain whatever values they previously had.

    Some convenience functions are provided for extracting the captured substrings as separate strings. These are described below.


    Error return values from pcre_exec()

    If pcre_exec() fails, it returns a negative number. The following are defined in the header file:

      PCRE_ERROR_NOMATCH        (-1)
    
    The subject string did not match the pattern.
      PCRE_ERROR_NULL           (-2)
    
    Either code or subject was passed as NULL, or ovector was NULL and ovecsize was not zero.
      PCRE_ERROR_BADOPTION      (-3)
    
    An unrecognized bit was set in the options argument.
      PCRE_ERROR_BADMAGIC       (-4)
    
    PCRE stores a 4-byte "magic number" at the start of the compiled code, to catch the case when it is passed a junk pointer and to detect when a pattern that was compiled in an environment of one endianness is run in an environment with the other endianness. This is the error that PCRE gives when the magic number is not present.
      PCRE_ERROR_UNKNOWN_OPCODE (-5)
    
    While running the pattern match, an unknown item was encountered in the compiled pattern. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern.
      PCRE_ERROR_NOMEMORY       (-6)
    
    If a pattern contains back references, but the ovector that is passed to pcre_exec() is not big enough to remember the referenced substrings, PCRE gets a block of memory at the start of matching to use for this purpose. If the call via pcre_malloc() fails, this error is given. The memory is automatically freed at the end of matching.

    This error is also given if pcre_stack_malloc() fails in pcre_exec(). This can happen only when PCRE has been compiled with --disable-stack-for-recursion.

      PCRE_ERROR_NOSUBSTRING    (-7)
    
    This error is used by the pcre_copy_substring(), pcre_get_substring(), and pcre_get_substring_list() functions (see below). It is never returned by pcre_exec().
      PCRE_ERROR_MATCHLIMIT     (-8)
    
    The backtracking limit, as specified by the match_limit field in a pcre_extra structure (or defaulted) was reached. See the description above.
      PCRE_ERROR_CALLOUT        (-9)
    
    This error is never generated by pcre_exec() itself. It is provided for use by callout functions that want to yield a distinctive error code. See the pcrecallout documentation for details.
      PCRE_ERROR_BADUTF8        (-10)
    
    A string that contains an invalid UTF-8 byte sequence was passed as a subject, and the PCRE_NO_UTF8_CHECK option was not set. If the size of the output vector (ovecsize) is at least 2, the byte offset to the start of the the invalid UTF-8 character is placed in the first element, and a reason code is placed in the second element. The reason codes are listed in the following section. For backward compatibility, if PCRE_PARTIAL_HARD is set and the problem is a truncated UTF-8 character at the end of the subject (reason codes 1 to 5), PCRE_ERROR_SHORTUTF8 is returned instead of PCRE_ERROR_BADUTF8.
      PCRE_ERROR_BADUTF8_OFFSET (-11)
    
    The UTF-8 byte sequence that was passed as a subject was checked and found to be valid (the PCRE_NO_UTF8_CHECK option was not set), but the value of startoffset did not point to the beginning of a UTF-8 character or the end of the subject.
      PCRE_ERROR_PARTIAL        (-12)
    
    The subject string did not match, but it did match partially. See the pcrepartial documentation for details of partial matching.
      PCRE_ERROR_BADPARTIAL     (-13)
    
    This code is no longer in use. It was formerly returned when the PCRE_PARTIAL option was used with a compiled pattern containing items that were not supported for partial matching. From release 8.00 onwards, there are no restrictions on partial matching.
      PCRE_ERROR_INTERNAL       (-14)
    
    An unexpected internal error has occurred. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern.
      PCRE_ERROR_BADCOUNT       (-15)
    
    This error is given if the value of the ovecsize argument is negative.
      PCRE_ERROR_RECURSIONLIMIT (-21)
    
    The internal recursion limit, as specified by the match_limit_recursion field in a pcre_extra structure (or defaulted) was reached. See the description above.
      PCRE_ERROR_BADNEWLINE     (-23)
    
    An invalid combination of PCRE_NEWLINE_xxx options was given.
      PCRE_ERROR_BADOFFSET      (-24)
    
    The value of startoffset was negative or greater than the length of the subject, that is, the value in length.
      PCRE_ERROR_SHORTUTF8      (-25)
    
    This error is returned instead of PCRE_ERROR_BADUTF8 when the subject string ends with a truncated UTF-8 character and the PCRE_PARTIAL_HARD option is set. Information about the failure is returned as for PCRE_ERROR_BADUTF8. It is in fact sufficient to detect this case, but this special error code for PCRE_PARTIAL_HARD precedes the implementation of returned information; it is retained for backwards compatibility.
      PCRE_ERROR_RECURSELOOP    (-26)
    
    This error is returned when pcre_exec() detects a recursion loop within the pattern. Specifically, it means that either the whole pattern or a subpattern has been called recursively for the second time at the same position in the subject string. Some simple patterns that might do this are detected and faulted at compile time, but more complicated cases, in particular mutual recursions between two different subpatterns, cannot be detected until run time.
      PCRE_ERROR_JIT_STACKLIMIT (-27)
    
    This error is returned when a pattern that was successfully studied using a JIT compile option is being matched, but the memory available for the just-in-time processing stack is not large enough. See the pcrejit documentation for more details.
      PCRE_ERROR_BADMODE        (-28)
    
    This error is given if a pattern that was compiled by the 8-bit library is passed to a 16-bit or 32-bit library function, or vice versa.
      PCRE_ERROR_BADENDIANNESS  (-29)
    
    This error is given if a pattern that was compiled and saved is reloaded on a host with different endianness. The utility function pcre_pattern_to_host_byte_order() can be used to convert such a pattern so that it runs on the new host.
      PCRE_ERROR_JIT_BADOPTION
    
    This error is returned when a pattern that was successfully studied using a JIT compile option is being matched, but the matching mode (partial or complete match) does not correspond to any JIT compilation mode. When the JIT fast path function is used, this error may be also given for invalid options. See the pcrejit documentation for more details.
      PCRE_ERROR_BADLENGTH      (-32)
    
    This error is given if pcre_exec() is called with a negative value for the length argument.

    Error numbers -16 to -20, -22, and 30 are not used by pcre_exec().


    Reason codes for invalid UTF-8 strings

    This section applies only to the 8-bit library. The corresponding information for the 16-bit and 32-bit libraries is given in the pcre16 and pcre32 pages.

    When pcre_exec() returns either PCRE_ERROR_BADUTF8 or PCRE_ERROR_SHORTUTF8, and the size of the output vector (ovecsize) is at least 2, the offset of the start of the invalid UTF-8 character is placed in the first output vector element (ovector[0]) and a reason code is placed in the second element (ovector[1]). The reason codes are given names in the pcre.h header file:

      PCRE_UTF8_ERR1
      PCRE_UTF8_ERR2
      PCRE_UTF8_ERR3
      PCRE_UTF8_ERR4
      PCRE_UTF8_ERR5
    
    The string ends with a truncated UTF-8 character; the code specifies how many bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8 characters to be no longer than 4 bytes, the encoding scheme (originally defined by RFC 2279) allows for up to 6 bytes, and this is checked first; hence the possibility of 4 or 5 missing bytes.
      PCRE_UTF8_ERR6
      PCRE_UTF8_ERR7
      PCRE_UTF8_ERR8
      PCRE_UTF8_ERR9
      PCRE_UTF8_ERR10
    
    The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of the character do not have the binary value 0b10 (that is, either the most significant bit is 0, or the next bit is 1).
      PCRE_UTF8_ERR11
      PCRE_UTF8_ERR12
    
    A character that is valid by the RFC 2279 rules is either 5 or 6 bytes long; these code points are excluded by RFC 3629.
      PCRE_UTF8_ERR13
    
    A 4-byte character has a value greater than 0x10fff; these code points are excluded by RFC 3629.
      PCRE_UTF8_ERR14
    
    A 3-byte character has a value in the range 0xd800 to 0xdfff; this range of code points are reserved by RFC 3629 for use with UTF-16, and so are excluded from UTF-8.
      PCRE_UTF8_ERR15
      PCRE_UTF8_ERR16
      PCRE_UTF8_ERR17
      PCRE_UTF8_ERR18
      PCRE_UTF8_ERR19
    
    A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes for a value that can be represented by fewer bytes, which is invalid. For example, the two bytes 0xc0, 0xae give the value 0x2e, whose correct coding uses just one byte.
      PCRE_UTF8_ERR20
    
    The two most significant bits of the first byte of a character have the binary value 0b10 (that is, the most significant bit is 1 and the second is 0). Such a byte can only validly occur as the second or subsequent byte of a multi-byte character.
      PCRE_UTF8_ERR21
    
    The first byte of a character has the value 0xfe or 0xff. These values can never occur in a valid UTF-8 string.
      PCRE_UTF8_ERR22
    
    This error code was formerly used when the presence of a so-called "non-character" caused an error. Unicode corrigendum #9 makes it clear that such characters should not cause a string to be rejected, and so this code is no longer in use and is never returned.


    EXTRACTING CAPTURED SUBSTRINGS BY NUMBER

    int pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize);

    int pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr);

    int pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr);

    Captured substrings can be accessed directly by using the offsets returned by pcre_exec() in ovector. For convenience, the functions pcre_copy_substring(), pcre_get_substring(), and pcre_get_substring_list() are provided for extracting captured substrings as new, separate, zero-terminated strings. These functions identify substrings by number. The next section describes functions for extracting named substrings.

    A substring that contains a binary zero is correctly extracted and has a further zero added on the end, but the result is not, of course, a C string. However, you can process such a string by referring to the length that is returned by pcre_copy_substring() and pcre_get_substring(). Unfortunately, the interface to pcre_get_substring_list() is not adequate for handling strings containing binary zeros, because the end of the final string is not independently indicated.

    The first three arguments are the same for all three of these functions: subject is the subject string that has just been successfully matched, ovector is a pointer to the vector of integer offsets that was passed to pcre_exec(), and stringcount is the number of substrings that were captured by the match, including the substring that matched the entire regular expression. This is the value returned by pcre_exec() if it is greater than zero. If pcre_exec() returned zero, indicating that it ran out of space in ovector, the value passed as stringcount should be the number of elements in the vector divided by three.

    The functions pcre_copy_substring() and pcre_get_substring() extract a single substring, whose number is given as stringnumber. A value of zero extracts the substring that matched the entire pattern, whereas higher values extract the captured substrings. For pcre_copy_substring(), the string is placed in buffer, whose length is given by buffersize, while for pcre_get_substring() a new block of memory is obtained via pcre_malloc, and its address is returned via stringptr. The yield of the function is the length of the string, not including the terminating zero, or one of these error codes:

      PCRE_ERROR_NOMEMORY       (-6)
    
    The buffer was too small for pcre_copy_substring(), or the attempt to get memory failed for pcre_get_substring().
      PCRE_ERROR_NOSUBSTRING    (-7)
    
    There is no substring whose number is stringnumber.

    The pcre_get_substring_list() function extracts all available substrings and builds a list of pointers to them. All this is done in a single block of memory that is obtained via pcre_malloc. The address of the memory block is returned via listptr, which is also the start of the list of string pointers. The end of the list is marked by a NULL pointer. The yield of the function is zero if all went well, or the error code

      PCRE_ERROR_NOMEMORY       (-6)
    
    if the attempt to get the memory block failed.

    When any of these functions encounter a substring that is unset, which can happen when capturing subpattern number n+1 matches some part of the subject, but subpattern n has not been used at all, they return an empty string. This can be distinguished from a genuine zero-length substring by inspecting the appropriate offset in ovector, which is negative for unset substrings.

    The two convenience functions pcre_free_substring() and pcre_free_substring_list() can be used to free the memory returned by a previous call of pcre_get_substring() or pcre_get_substring_list(), respectively. They do nothing more than call the function pointed to by pcre_free, which of course could be called directly from a C program. However, PCRE is used in some situations where it is linked via a special interface to another programming language that cannot use pcre_free directly; it is for these cases that the functions are provided.


    EXTRACTING CAPTURED SUBSTRINGS BY NAME

    int pcre_get_stringnumber(const pcre *code, const char *name);

    int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize);

    int pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr);

    To extract a substring by name, you first have to find associated number. For example, for this pattern

      (a+)b(?<xxx>\d+)...
    
    the number of the subpattern called "xxx" is 2. If the name is known to be unique (PCRE_DUPNAMES was not set), you can find the number from the name by calling pcre_get_stringnumber(). The first argument is the compiled pattern, and the second is the name. The yield of the function is the subpattern number, or PCRE_ERROR_NOSUBSTRING (-7) if there is no subpattern of that name.

    Given the number, you can extract the substring directly, or use one of the functions described in the previous section. For convenience, there are also two functions that do the whole job.

    Most of the arguments of pcre_copy_named_substring() and pcre_get_named_substring() are the same as those for the similarly named functions that extract by number. As these are described in the previous section, they are not re-described here. There are just two differences:

    First, instead of a substring number, a substring name is given. Second, there is an extra argument, given at the start, which is a pointer to the compiled pattern. This is needed in order to gain access to the name-to-number translation table.

    These functions call pcre_get_stringnumber(), and if it succeeds, they then call pcre_copy_substring() or pcre_get_substring(), as appropriate. NOTE: If PCRE_DUPNAMES is set and there are duplicate names, the behaviour may not be what you want (see the next section).

    Warning: If the pattern uses the (?| feature to set up multiple subpatterns with the same number, as described in the section on duplicate subpattern numbers in the pcrepattern page, you cannot use names to distinguish the different subpatterns, because names are not included in the compiled code. The matching process uses only numbers. For this reason, the use of different names for subpatterns of the same number causes an error at compile time.


    DUPLICATE SUBPATTERN NAMES

    int pcre_get_stringtable_entries(const pcre *code, const char *name, char **first, char **last);

    When a pattern is compiled with the PCRE_DUPNAMES option, names for subpatterns are not required to be unique. (Duplicate names are always allowed for subpatterns with the same number, created by using the (?| feature. Indeed, if such subpatterns are named, they are required to use the same names.)

    Normally, patterns with duplicate names are such that in any one match, only one of the named subpatterns participates. An example is shown in the pcrepattern documentation.

    When duplicates are present, pcre_copy_named_substring() and pcre_get_named_substring() return the first substring corresponding to the given name that is set. If none are set, PCRE_ERROR_NOSUBSTRING (-7) is returned; no data is returned. The pcre_get_stringnumber() function returns one of the numbers that are associated with the name, but it is not defined which it is.

    If you want to get full details of all captured substrings for a given name, you must use the pcre_get_stringtable_entries() function. The first argument is the compiled pattern, and the second is the name. The third and fourth are pointers to variables which are updated by the function. After it has run, they point to the first and last entries in the name-to-number table for the given name. The function itself returns the length of each entry, or PCRE_ERROR_NOSUBSTRING (-7) if there are none. The format of the table is described above in the section entitled Information about a pattern above. Given all the relevant entries for the name, you can extract each of their numbers, and hence the captured data, if any.


    FINDING ALL POSSIBLE MATCHES

    The traditional matching function uses a similar algorithm to Perl, which stops when it finds the first match, starting at a given point in the subject. If you want to find all possible matches, or the longest possible match, consider using the alternative matching function (see below) instead. If you cannot use the alternative function, but still need to find all possible matches, you can kludge it up by making use of the callout facility, which is described in the pcrecallout documentation.

    What you have to do is to insert a callout right at the end of the pattern. When your callout function is called, extract and save the current matched substring. Then return 1, which forces pcre_exec() to backtrack and try other alternatives. Ultimately, when it runs out of matches, pcre_exec() will yield PCRE_ERROR_NOMATCH.


    OBTAINING AN ESTIMATE OF STACK USAGE

    Matching certain patterns using pcre_exec() can use a lot of process stack, which in certain environments can be rather limited in size. Some users find it helpful to have an estimate of the amount of stack that is used by pcre_exec(), to help them set recursion limits, as described in the pcrestack documentation. The estimate that is output by pcretest when called with the -m and -C options is obtained by calling pcre_exec with the values NULL, NULL, NULL, -999, and -999 for its first five arguments.

    Normally, if its first argument is NULL, pcre_exec() immediately returns the negative error code PCRE_ERROR_NULL, but with this special combination of arguments, it returns instead a negative number whose absolute value is the approximate stack frame size in bytes. (A negative number is used so that it is clear that no match has happened.) The value is approximate because in some cases, recursive calls to pcre_exec() occur when there are one or two additional variables on the stack.

    If PCRE has been compiled to use the heap instead of the stack for recursion, the value returned is the size of each block that is obtained from the heap.


    MATCHING A PATTERN: THE ALTERNATIVE FUNCTION

    int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount);

    The function pcre_dfa_exec() is called to match a subject string against a compiled pattern, using a matching algorithm that scans the subject string just once, and does not backtrack. This has different characteristics to the normal algorithm, and is not compatible with Perl. Some of the features of PCRE patterns are not supported. Nevertheless, there are times when this kind of matching can be useful. For a discussion of the two matching algorithms, and a list of features that pcre_dfa_exec() does not support, see the pcrematching documentation.

    The arguments for the pcre_dfa_exec() function are the same as for pcre_exec(), plus two extras. The ovector argument is used in a different way, and this is described below. The other common arguments are used in the same way as for pcre_exec(), so their description is not repeated here.

    The two additional arguments provide workspace for the function. The workspace vector should contain at least 20 elements. It is used for keeping track of multiple paths through the pattern tree. More workspace will be needed for patterns and subjects where there are a lot of potential matches.

    Here is an example of a simple call to pcre_dfa_exec():

      int rc;
      int ovector[10];
      int wspace[20];
      rc = pcre_dfa_exec(
        re,             /* result of pcre_compile() */
        NULL,           /* we didn't study the pattern */
        "some string",  /* the subject string */
        11,             /* the length of the subject string */
        0,              /* start at offset 0 in the subject */
        0,              /* default options */
        ovector,        /* vector of integers for substring information */
        10,             /* number of elements (NOT size in bytes) */
        wspace,         /* working space vector */
        20);            /* number of elements (NOT size in bytes) */
    


    Option bits for pcre_dfa_exec()

    The unused bits of the options argument for pcre_dfa_exec() must be zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NEWLINE_xxx, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_NO_UTF8_CHECK, PCRE_BSR_ANYCRLF, PCRE_BSR_UNICODE, PCRE_NO_START_OPTIMIZE, PCRE_PARTIAL_HARD, PCRE_PARTIAL_SOFT, PCRE_DFA_SHORTEST, and PCRE_DFA_RESTART. All but the last four of these are exactly the same as for pcre_exec(), so their description is not repeated here.

      PCRE_PARTIAL_HARD
      PCRE_PARTIAL_SOFT
    
    These have the same general effect as they do for pcre_exec(), but the details are slightly different. When PCRE_PARTIAL_HARD is set for pcre_dfa_exec(), it returns PCRE_ERROR_PARTIAL if the end of the subject is reached and there is still at least one matching possibility that requires additional characters. This happens even if some complete matches have also been found. When PCRE_PARTIAL_SOFT is set, the return code PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if the end of the subject is reached, there have been no complete matches, but there is still at least one matching possibility. The portion of the string that was inspected when the longest partial match was found is set as the first matching string in both cases. There is a more detailed discussion of partial and multi-segment matching, with examples, in the pcrepartial documentation.
      PCRE_DFA_SHORTEST
    
    Setting the PCRE_DFA_SHORTEST option causes the matching algorithm to stop as soon as it has found one match. Because of the way the alternative algorithm works, this is necessarily the shortest possible match at the first possible matching point in the subject string.
      PCRE_DFA_RESTART
    
    When pcre_dfa_exec() returns a partial match, it is possible to call it again, with additional subject characters, and have it continue with the same match. The PCRE_DFA_RESTART option requests this action; when it is set, the workspace and wscount options must reference the same vector as before because data about the match so far is left in them after a partial match. There is more discussion of this facility in the pcrepartial documentation.


    Successful returns from pcre_dfa_exec()

    When pcre_dfa_exec() succeeds, it may have matched more than one substring in the subject. Note, however, that all the matches from one run of the function start at the same point in the subject. The shorter matches are all initial substrings of the longer matches. For example, if the pattern

      <.*>
    
    is matched against the string
      This is <something> <something else> <something further> no more
    
    the three matched strings are
      <something>
      <something> <something else>
      <something> <something else> <something further>
    
    On success, the yield of the function is a number greater than zero, which is the number of matched substrings. The substrings themselves are returned in ovector. Each string uses two elements; the first is the offset to the start, and the second is the offset to the end. In fact, all the strings have the same start offset. (Space could have been saved by giving this only once, but it was decided to retain some compatibility with the way pcre_exec() returns data, even though the meaning of the strings is different.)

    The strings are returned in reverse order of length; that is, the longest matching string is given first. If there were too many matches to fit into ovector, the yield of the function is zero, and the vector is filled with the longest matches. Unlike pcre_exec(), pcre_dfa_exec() can use the entire ovector for returning matched strings.

    NOTE: PCRE's "auto-possessification" optimization usually applies to character repeats at the end of a pattern (as well as internally). For example, the pattern "a\d+" is compiled as if it were "a\d++" because there is no point even considering the possibility of backtracking into the repeated digits. For DFA matching, this means that only one possible match is found. If you really do want multiple matches in such cases, either use an ungreedy repeat ("a\d+?") or set the PCRE_NO_AUTO_POSSESS option when compiling.


    Error returns from pcre_dfa_exec()

    The pcre_dfa_exec() function returns a negative number when it fails. Many of the errors are the same as for pcre_exec(), and these are described above. There are in addition the following errors that are specific to pcre_dfa_exec():

      PCRE_ERROR_DFA_UITEM      (-16)
    
    This return is given if pcre_dfa_exec() encounters an item in the pattern that it does not support, for instance, the use of \C or a back reference.
      PCRE_ERROR_DFA_UCOND      (-17)
    
    This return is given if pcre_dfa_exec() encounters a condition item that uses a back reference for the condition, or a test for recursion in a specific group. These are not supported.
      PCRE_ERROR_DFA_UMLIMIT    (-18)
    
    This return is given if pcre_dfa_exec() is called with an extra block that contains a setting of the match_limit or match_limit_recursion fields. This is not supported (these fields are meaningless for DFA matching).
      PCRE_ERROR_DFA_WSSIZE     (-19)
    
    This return is given if pcre_dfa_exec() runs out of space in the workspace vector.
      PCRE_ERROR_DFA_RECURSE    (-20)
    
    When a recursive subpattern is processed, the matching function calls itself recursively, using private vectors for ovector and workspace. This error is given if the output vector is not large enough. This should be extremely rare, as a vector of size 1000 is used.
      PCRE_ERROR_DFA_BADRESTART (-30)
    
    When pcre_dfa_exec() is called with the PCRE_DFA_RESTART option, some plausibility checks are made on the contents of the workspace, which should contain data about the previous partial match. If any of these checks fail, this error is given.


    SEE ALSO

    pcre16(3), pcre32(3), pcrebuild(3), pcrecallout(3), pcrecpp(3)(3), pcrematching(3), pcrepartial(3), pcreposix(3), pcreprecompile(3), pcresample(3), pcrestack(3).


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 18 December 2015
    Copyright © 1997-2015 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrebuild.html ================================================ pcrebuild specification

    pcrebuild man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    BUILDING PCRE

    PCRE is distributed with a configure script that can be used to build the library in Unix-like environments using the applications known as Autotools. Also in the distribution are files to support building using CMake instead of configure. The text file README contains general information about building with Autotools (some of which is repeated below), and also has some comments about building on various operating systems. There is a lot more information about building PCRE without using Autotools (including information about using CMake and building "by hand") in the text file called NON-AUTOTOOLS-BUILD. You should consult this file as well as the README file if you are building in a non-Unix-like environment.


    PCRE BUILD-TIME OPTIONS

    The rest of this document describes the optional features of PCRE that can be selected when the library is compiled. It assumes use of the configure script, where the optional features are selected or deselected by providing options to configure before running the make command. However, the same options can be selected in both Unix-like and non-Unix-like environments using the GUI facility of cmake-gui if you are using CMake instead of configure to build PCRE.

    If you are not using Autotools or CMake, option selection can be done by editing the config.h file, or by passing parameter settings to the compiler, as described in NON-AUTOTOOLS-BUILD.

    The complete list of options for configure (which includes the standard ones such as the selection of the installation directory) can be obtained by running

      ./configure --help
    
    The following sections include descriptions of options whose names begin with --enable or --disable. These settings specify changes to the defaults for the configure command. Because of the way that configure works, --enable and --disable always come in pairs, so the complementary option always exists as well, but as it specifies the default, it is not described.


    BUILDING 8-BIT, 16-BIT AND 32-BIT LIBRARIES

    By default, a library called libpcre is built, containing functions that take string arguments contained in vectors of bytes, either as single-byte characters, or interpreted as UTF-8 strings. You can also build a separate library, called libpcre16, in which strings are contained in vectors of 16-bit data units and interpreted either as single-unit characters or UTF-16 strings, by adding

      --enable-pcre16
    
    to the configure command. You can also build yet another separate library, called libpcre32, in which strings are contained in vectors of 32-bit data units and interpreted either as single-unit characters or UTF-32 strings, by adding
      --enable-pcre32
    
    to the configure command. If you do not want the 8-bit library, add
      --disable-pcre8
    
    as well. At least one of the three libraries must be built. Note that the C++ and POSIX wrappers are for the 8-bit library only, and that pcregrep is an 8-bit program. None of these are built if you select only the 16-bit or 32-bit libraries.


    BUILDING SHARED AND STATIC LIBRARIES

    The Autotools PCRE building process uses libtool to build both shared and static libraries by default. You can suppress one of these by adding one of

      --disable-shared
      --disable-static
    
    to the configure command, as required.


    C++ SUPPORT

    By default, if the 8-bit library is being built, the configure script will search for a C++ compiler and C++ header files. If it finds them, it automatically builds the C++ wrapper library (which supports only 8-bit strings). You can disable this by adding

      --disable-cpp
    
    to the configure command.


    UTF-8, UTF-16 AND UTF-32 SUPPORT

    To build PCRE with support for UTF Unicode character strings, add

      --enable-utf
    
    to the configure command. This setting applies to all three libraries, adding support for UTF-8 to the 8-bit library, support for UTF-16 to the 16-bit library, and support for UTF-32 to the to the 32-bit library. There are no separate options for enabling UTF-8, UTF-16 and UTF-32 independently because that would allow ridiculous settings such as requesting UTF-16 support while building only the 8-bit library. It is not possible to build one library with UTF support and another without in the same configuration. (For backwards compatibility, --enable-utf8 is a synonym of --enable-utf.)

    Of itself, this setting does not make PCRE treat strings as UTF-8, UTF-16 or UTF-32. As well as compiling PCRE with this option, you also have have to set the PCRE_UTF8, PCRE_UTF16 or PCRE_UTF32 option (as appropriate) when you call one of the pattern compiling functions.

    If you set --enable-utf when compiling in an EBCDIC environment, PCRE expects its input to be either ASCII or UTF-8 (depending on the run-time option). It is not possible to support both EBCDIC and UTF-8 codes in the same version of the library. Consequently, --enable-utf and --enable-ebcdic are mutually exclusive.


    UNICODE CHARACTER PROPERTY SUPPORT

    UTF support allows the libraries to process character codepoints up to 0x10ffff in the strings that they handle. On its own, however, it does not provide any facilities for accessing the properties of such characters. If you want to be able to use the pattern escapes \P, \p, and \X, which refer to Unicode character properties, you must add

      --enable-unicode-properties
    
    to the configure command. This implies UTF support, even if you have not explicitly requested it.

    Including Unicode property support adds around 30K of tables to the PCRE library. Only the general category properties such as Lu and Nd are supported. Details are given in the pcrepattern documentation.


    JUST-IN-TIME COMPILER SUPPORT

    Just-in-time compiler support is included in the build by specifying

      --enable-jit
    
    This support is available only for certain hardware architectures. If this option is set for an unsupported architecture, a compile time error occurs. See the pcrejit documentation for a discussion of JIT usage. When JIT support is enabled, pcregrep automatically makes use of it, unless you add
      --disable-pcregrep-jit
    
    to the "configure" command.


    CODE VALUE OF NEWLINE

    By default, PCRE interprets the linefeed (LF) character as indicating the end of a line. This is the normal newline character on Unix-like systems. You can compile PCRE to use carriage return (CR) instead, by adding

      --enable-newline-is-cr
    
    to the configure command. There is also a --enable-newline-is-lf option, which explicitly specifies linefeed as the newline character.

    Alternatively, you can specify that line endings are to be indicated by the two character sequence CRLF. If you want this, add
      --enable-newline-is-crlf
    
    to the configure command. There is a fourth option, specified by
      --enable-newline-is-anycrlf
    
    which causes PCRE to recognize any of the three sequences CR, LF, or CRLF as indicating a line ending. Finally, a fifth option, specified by
      --enable-newline-is-any
    
    causes PCRE to recognize any Unicode newline sequence.

    Whatever line ending convention is selected when PCRE is built can be overridden when the library functions are called. At build time it is conventional to use the standard for your operating system.


    WHAT \R MATCHES

    By default, the sequence \R in a pattern matches any Unicode newline sequence, whatever has been selected as the line ending sequence. If you specify

      --enable-bsr-anycrlf
    
    the default is changed so that \R matches only CR, LF, or CRLF. Whatever is selected when PCRE is built can be overridden when the library functions are called.


    POSIX MALLOC USAGE

    When the 8-bit library is called through the POSIX interface (see the pcreposix documentation), additional working storage is required for holding the pointers to capturing substrings, because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using malloc() for each call. The default threshold above which the stack is no longer used is 10; it can be changed by adding a setting such as

      --with-posix-malloc-threshold=20
    
    to the configure command.


    HANDLING VERY LARGE PATTERNS

    Within a compiled pattern, offset values are used to point from one part to another (for example, from an opening parenthesis to an alternation metacharacter). By default, in the 8-bit and 16-bit libraries, two-byte values are used for these offsets, leading to a maximum size for a compiled pattern of around 64K. This is sufficient to handle all but the most gigantic patterns. Nevertheless, some people do want to process truly enormous patterns, so it is possible to compile PCRE to use three-byte or four-byte offsets by adding a setting such as

      --with-link-size=3
    
    to the configure command. The value given must be 2, 3, or 4. For the 16-bit library, a value of 3 is rounded up to 4. In these libraries, using longer offsets slows down the operation of PCRE because it has to load additional data when handling them. For the 32-bit library the value is always 4 and cannot be overridden; the value of --with-link-size is ignored.


    AVOIDING EXCESSIVE STACK USAGE

    When matching with the pcre_exec() function, PCRE implements backtracking by making recursive calls to an internal function called match(). In environments where the size of the stack is limited, this can severely limit PCRE's operation. (The Unix environment does not usually suffer from this problem, but it may sometimes be necessary to increase the maximum stack size. There is a discussion in the pcrestack documentation.) An alternative approach to recursion that uses memory from the heap to remember data, instead of using recursive function calls, has been implemented to work round the problem of limited stack size. If you want to build a version of PCRE that works this way, add

      --disable-stack-for-recursion
    
    to the configure command. With this configuration, PCRE will use the pcre_stack_malloc and pcre_stack_free variables to call memory management functions. By default these point to malloc() and free(), but you can replace the pointers so that your own functions are used instead.

    Separate functions are provided rather than using pcre_malloc and pcre_free because the usage is very predictable: the block sizes requested are always the same, and the blocks are always freed in reverse order. A calling program might be able to implement optimized functions that perform better than malloc() and free(). PCRE runs noticeably more slowly when built in this way. This option affects only the pcre_exec() function; it is not relevant for pcre_dfa_exec().


    LIMITING PCRE RESOURCE USAGE

    Internally, PCRE has a function called match(), which it calls repeatedly (sometimes recursively) when matching a pattern with the pcre_exec() function. By controlling the maximum number of times this function may be called during a single matching operation, a limit can be placed on the resources used by a single call to pcre_exec(). The limit can be changed at run time, as described in the pcreapi documentation. The default is 10 million, but this can be changed by adding a setting such as

      --with-match-limit=500000
    
    to the configure command. This setting has no effect on the pcre_dfa_exec() matching function.

    In some environments it is desirable to limit the depth of recursive calls of match() more strictly than the total number of calls, in order to restrict the maximum amount of stack (or heap, if --disable-stack-for-recursion is specified) that is used. A second limit controls this; it defaults to the value that is set for --with-match-limit, which imposes no additional constraints. However, you can set a lower limit by adding, for example,

      --with-match-limit-recursion=10000
    
    to the configure command. This value can also be overridden at run time.


    CREATING CHARACTER TABLES AT BUILD TIME

    PCRE uses fixed tables for processing characters whose code values are less than 256. By default, PCRE is built with a set of tables that are distributed in the file pcre_chartables.c.dist. These tables are for ASCII codes only. If you add

      --enable-rebuild-chartables
    
    to the configure command, the distributed tables are no longer used. Instead, a program called dftables is compiled and run. This outputs the source for new set of tables, created in the default locale of your C run-time system. (This method of replacing the tables does not work if you are cross compiling, because dftables is run on the local host. If you need to create alternative tables when cross compiling, you will have to do so "by hand".)


    USING EBCDIC CODE

    PCRE assumes by default that it will run in an environment where the character code is ASCII (or Unicode, which is a superset of ASCII). This is the case for most computer operating systems. PCRE can, however, be compiled to run in an EBCDIC environment by adding

      --enable-ebcdic
    
    to the configure command. This setting implies --enable-rebuild-chartables. You should only use it if you know that you are in an EBCDIC environment (for example, an IBM mainframe operating system). The --enable-ebcdic option is incompatible with --enable-utf.

    The EBCDIC character that corresponds to an ASCII LF is assumed to have the value 0x15 by default. However, in some EBCDIC environments, 0x25 is used. In such an environment you should use

      --enable-ebcdic-nl25
    
    as well as, or instead of, --enable-ebcdic. The EBCDIC character for CR has the same value as in ASCII, namely, 0x0d. Whichever of 0x15 and 0x25 is not chosen as LF is made to correspond to the Unicode NEL character (which, in Unicode, is 0x85).

    The options that select newline behaviour, such as --enable-newline-is-cr, and equivalent run-time options, refer to these character values in an EBCDIC environment.


    PCREGREP OPTIONS FOR COMPRESSED FILE SUPPORT

    By default, pcregrep reads all files as plain text. You can build it so that it recognizes files whose names end in .gz or .bz2, and reads them with libz or libbz2, respectively, by adding one or both of

      --enable-pcregrep-libz
      --enable-pcregrep-libbz2
    
    to the configure command. These options naturally require that the relevant libraries are installed on your system. Configuration will fail if they are not.


    PCREGREP BUFFER SIZE

    pcregrep uses an internal buffer to hold a "window" on the file it is scanning, in order to be able to output "before" and "after" lines when it finds a match. The size of the buffer is controlled by a parameter whose default value is 20K. The buffer itself is three times this size, but because of the way it is used for holding "before" lines, the longest line that is guaranteed to be processable is the parameter size. You can change the default parameter value by adding, for example,

      --with-pcregrep-bufsize=50K
    
    to the configure command. The caller of \fPpcregrep\fP can, however, override this value by specifying a run-time option.


    PCRETEST OPTION FOR LIBREADLINE SUPPORT

    If you add

      --enable-pcretest-libreadline
    
    to the configure command, pcretest is linked with the libreadline library, and when its input is from a terminal, it reads it using the readline() function. This provides line-editing and history facilities. Note that libreadline is GPL-licensed, so if you distribute a binary of pcretest linked in this way, there may be licensing issues.

    Setting this option causes the -lreadline option to be added to the pcretest build. In many operating environments with a sytem-installed libreadline this is sufficient. However, in some environments (e.g. if an unmodified distribution version of readline is in use), some extra configuration may be necessary. The INSTALL file for libreadline says this:

      "Readline uses the termcap functions, but does not link with the
      termcap or curses library itself, allowing applications which link
      with readline the to choose an appropriate library."
    
    If your environment has not been set up so that an appropriate library is automatically included, you may need to add something like
      LIBS="-ncurses"
    
    immediately before the configure command.


    DEBUGGING WITH VALGRIND SUPPORT

    By adding the

      --enable-valgrind
    
    option to to the configure command, PCRE will use valgrind annotations to mark certain memory regions as unaddressable. This allows it to detect invalid memory accesses, and is mostly useful for debugging PCRE itself.


    CODE COVERAGE REPORTING

    If your C compiler is gcc, you can build a version of PCRE that can generate a code coverage report for its test suite. To enable this, you must install lcov version 1.6 or above. Then specify

      --enable-coverage
    
    to the configure command and build PCRE in the usual way.

    Note that using ccache (a caching C compiler) is incompatible with code coverage reporting. If you have configured ccache to run automatically on your system, you must set the environment variable

      CCACHE_DISABLE=1
    
    before running make to build PCRE, so that ccache is not used.

    When --enable-coverage is used, the following addition targets are added to the Makefile:

      make coverage
    
    This creates a fresh coverage report for the PCRE test suite. It is equivalent to running "make coverage-reset", "make coverage-baseline", "make check", and then "make coverage-report".
      make coverage-reset
    
    This zeroes the coverage counters, but does nothing else.
      make coverage-baseline
    
    This captures baseline coverage information.
      make coverage-report
    
    This creates the coverage report.
      make coverage-clean-report
    
    This removes the generated coverage report without cleaning the coverage data itself.
      make coverage-clean-data
    
    This removes the captured coverage data without removing the coverage files created at compile time (*.gcno).
      make coverage-clean
    
    This cleans all coverage data including the generated coverage report. For more information about code coverage, see the gcov and lcov documentation.


    SEE ALSO

    pcreapi(3), pcre16, pcre32, pcre_config(3).


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 12 May 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrecallout.html ================================================ pcrecallout specification

    pcrecallout man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SYNOPSIS

    #include <pcre.h>

    int (*pcre_callout)(pcre_callout_block *);

    int (*pcre16_callout)(pcre16_callout_block *);

    int (*pcre32_callout)(pcre32_callout_block *);


    DESCRIPTION

    PCRE provides a feature called "callout", which is a means of temporarily passing control to the caller of PCRE in the middle of pattern matching. The caller of PCRE provides an external function by putting its entry point in the global variable pcre_callout (pcre16_callout for the 16-bit library, pcre32_callout for the 32-bit library). By default, this variable contains NULL, which disables all calling out.

    Within a regular expression, (?C) indicates the points at which the external function is to be called. Different callout points can be identified by putting a number less than 256 after the letter C. The default value is zero. For example, this pattern has two callout points:

      (?C1)abc(?C2)def
    
    If the PCRE_AUTO_CALLOUT option bit is set when a pattern is compiled, PCRE automatically inserts callouts, all with number 255, before each item in the pattern. For example, if PCRE_AUTO_CALLOUT is used with the pattern
      A(\d{2}|--)
    
    it is processed as if it were

    (?C255)A(?C255)((?C255)\d{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255)

    Notice that there is a callout before and after each parenthesis and alternation bar. If the pattern contains a conditional group whose condition is an assertion, an automatic callout is inserted immediately before the condition. Such a callout may also be inserted explicitly, for example:
      (?(?C9)(?=a)ab|de)
    
    This applies only to assertion conditions (because they are themselves independent groups).

    Automatic callouts can be used for tracking the progress of pattern matching. The pcretest program has a pattern qualifier (/C) that sets automatic callouts; when it is used, the output indicates how the pattern is being matched. This is useful information when you are trying to optimize the performance of a particular pattern.


    MISSING CALLOUTS

    You should be aware that, because of optimizations in the way PCRE compiles and matches patterns, callouts sometimes do not happen exactly as you might expect.

    At compile time, PCRE "auto-possessifies" repeated items when it knows that what follows cannot be part of the repeat. For example, a+[bc] is compiled as if it were a++[bc]. The pcretest output when this pattern is anchored and then applied with automatic callouts to the string "aaaa" is:

      --->aaaa
       +0 ^        ^
       +1 ^        a+
       +3 ^   ^    [bc]
      No match
    
    This indicates that when matching [bc] fails, there is no backtracking into a+ and therefore the callouts that would be taken for the backtracks do not occur. You can disable the auto-possessify feature by passing PCRE_NO_AUTO_POSSESS to pcre_compile(), or starting the pattern with (*NO_AUTO_POSSESS). If this is done in pcretest (using the /O qualifier), the output changes to this:
      --->aaaa
       +0 ^        ^
       +1 ^        a+
       +3 ^   ^    [bc]
       +3 ^  ^     [bc]
       +3 ^ ^      [bc]
       +3 ^^       [bc]
      No match
    
    This time, when matching [bc] fails, the matcher backtracks into a+ and tries again, repeatedly, until a+ itself fails.

    Other optimizations that provide fast "no match" results also affect callouts. For example, if the pattern is

      ab(?C4)cd
    
    PCRE knows that any matching string must contain the letter "d". If the subject string is "abyz", the lack of "d" means that matching doesn't ever start, and the callout is never reached. However, with "abyd", though the result is still no match, the callout is obeyed.

    If the pattern is studied, PCRE knows the minimum length of a matching string, and will immediately give a "no match" return without actually running a match if the subject is not long enough, or, for unanchored patterns, if it has been scanned far enough.

    You can disable these optimizations by passing the PCRE_NO_START_OPTIMIZE option to the matching function, or by starting the pattern with (*NO_START_OPT). This slows down the matching process, but does ensure that callouts such as the example above are obeyed.


    THE CALLOUT INTERFACE

    During matching, when PCRE reaches a callout point, the external function defined by pcre_callout or pcre[16|32]_callout is called (if it is set). This applies to both normal and DFA matching. The only argument to the callout function is a pointer to a pcre_callout or pcre[16|32]_callout block. These structures contains the following fields:

      int           version;
      int           callout_number;
      int          *offset_vector;
      const char   *subject;           (8-bit version)
      PCRE_SPTR16   subject;           (16-bit version)
      PCRE_SPTR32   subject;           (32-bit version)
      int           subject_length;
      int           start_match;
      int           current_position;
      int           capture_top;
      int           capture_last;
      void         *callout_data;
      int           pattern_position;
      int           next_item_length;
      const unsigned char *mark;       (8-bit version)
      const PCRE_UCHAR16  *mark;       (16-bit version)
      const PCRE_UCHAR32  *mark;       (32-bit version)
    
    The version field is an integer containing the version number of the block format. The initial version was 0; the current version is 2. The version number will change again in future if additional fields are added, but the intention is never to remove any of the existing fields.

    The callout_number field contains the number of the callout, as compiled into the pattern (that is, the number after ?C for manual callouts, and 255 for automatically generated callouts).

    The offset_vector field is a pointer to the vector of offsets that was passed by the caller to the matching function. When pcre_exec() or pcre[16|32]_exec() is used, the contents can be inspected, in order to extract substrings that have been matched so far, in the same way as for extracting substrings after a match has completed. For the DFA matching functions, this field is not useful.

    The subject and subject_length fields contain copies of the values that were passed to the matching function.

    The start_match field normally contains the offset within the subject at which the current match attempt started. However, if the escape sequence \K has been encountered, this value is changed to reflect the modified starting point. If the pattern is not anchored, the callout function may be called several times from the same point in the pattern for different starting points in the subject.

    The current_position field contains the offset within the subject of the current match pointer.

    When the pcre_exec() or pcre[16|32]_exec() is used, the capture_top field contains one more than the number of the highest numbered captured substring so far. If no substrings have been captured, the value of capture_top is one. This is always the case when the DFA functions are used, because they do not support captured substrings.

    The capture_last field contains the number of the most recently captured substring. However, when a recursion exits, the value reverts to what it was outside the recursion, as do the values of all captured substrings. If no substrings have been captured, the value of capture_last is -1. This is always the case for the DFA matching functions.

    The callout_data field contains a value that is passed to a matching function specifically so that it can be passed back in callouts. It is passed in the callout_data field of a pcre_extra or pcre[16|32]_extra data structure. If no such data was passed, the value of callout_data in a callout block is NULL. There is a description of the pcre_extra structure in the pcreapi documentation.

    The pattern_position field is present from version 1 of the callout structure. It contains the offset to the next item to be matched in the pattern string.

    The next_item_length field is present from version 1 of the callout structure. It contains the length of the next item to be matched in the pattern string. When the callout immediately precedes an alternation bar, a closing parenthesis, or the end of the pattern, the length is zero. When the callout precedes an opening parenthesis, the length is that of the entire subpattern.

    The pattern_position and next_item_length fields are intended to help in distinguishing between different automatic callouts, which all have the same callout number. However, they are set for all callouts.

    The mark field is present from version 2 of the callout structure. In callouts from pcre_exec() or pcre[16|32]_exec() it contains a pointer to the zero-terminated name of the most recently passed (*MARK), (*PRUNE), or (*THEN) item in the match, or NULL if no such items have been passed. Instances of (*PRUNE) or (*THEN) without a name do not obliterate a previous (*MARK). In callouts from the DFA matching functions this field always contains NULL.


    RETURN VALUES

    The external callout function returns an integer to PCRE. If the value is zero, matching proceeds as normal. If the value is greater than zero, matching fails at the current point, but the testing of other matching possibilities goes ahead, just as if a lookahead assertion had failed. If the value is less than zero, the match is abandoned, the matching function returns the negative value.

    Negative values should normally be chosen from the set of PCRE_ERROR_xxx values. In particular, PCRE_ERROR_NOMATCH forces a standard "no match" failure. The error number PCRE_ERROR_CALLOUT is reserved for use by callout functions; it will never be used by PCRE itself.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 12 November 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrecompat.html ================================================ pcrecompat specification

    pcrecompat man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    DIFFERENCES BETWEEN PCRE AND PERL

    This document describes the differences in the ways that PCRE and Perl handle regular expressions. The differences described here are with respect to Perl versions 5.10 and above.

    1. PCRE has only a subset of Perl's Unicode support. Details of what it does have are given in the pcreunicode page.

    2. PCRE allows repeat quantifiers only on parenthesized assertions, but they do not mean what you might think. For example, (?!a){3} does not assert that the next three characters are not "a". It just asserts that the next character is not "a" three times (in principle: PCRE optimizes this to run the assertion just once). Perl allows repeat quantifiers on other assertions such as \b, but these do not seem to have any use.

    3. Capturing subpatterns that occur inside negative lookahead assertions are counted, but their entries in the offsets vector are never set. Perl sometimes (but not always) sets its numerical variables from inside negative assertions.

    4. Though binary zero characters are supported in the subject string, they are not allowed in a pattern string because it is passed as a normal C string, terminated by zero. The escape sequence \0 can be used in the pattern to represent a binary zero.

    5. The following Perl escape sequences are not supported: \l, \u, \L, \U, and \N when followed by a character name or Unicode value. (\N on its own, matching a non-newline character, is supported.) In fact these are implemented by Perl's general string-handling and are not part of its pattern matching engine. If any of these are encountered by PCRE, an error is generated by default. However, if the PCRE_JAVASCRIPT_COMPAT option is set, \U and \u are interpreted as JavaScript interprets them.

    6. The Perl escape sequences \p, \P, and \X are supported only if PCRE is built with Unicode character property support. The properties that can be tested with \p and \P are limited to the general category properties such as Lu and Nd, script names such as Greek or Han, and the derived properties Any and L&. PCRE does support the Cs (surrogate) property, which Perl does not; the Perl documentation says "Because Perl hides the need for the user to understand the internal representation of Unicode characters, there is no need to implement the somewhat messy concept of surrogates."

    7. PCRE does support the \Q...\E escape for quoting substrings. Characters in between are treated as literals. This is slightly different from Perl in that $ and @ are also handled as literals inside the quotes. In Perl, they cause variable interpolation (but of course PCRE does not have variables). Note the following examples:

        Pattern            PCRE matches      Perl matches
    
        \Qabc$xyz\E        abc$xyz           abc followed by the contents of $xyz
        \Qabc\$xyz\E       abc\$xyz          abc\$xyz
        \Qabc\E\$\Qxyz\E   abc$xyz           abc$xyz
    
    The \Q...\E sequence is recognized both inside and outside character classes.

    8. Fairly obviously, PCRE does not support the (?{code}) and (??{code}) constructions. However, there is support for recursive patterns. This is not available in Perl 5.8, but it is in Perl 5.10. Also, the PCRE "callout" feature allows an external function to be called during pattern matching. See the pcrecallout documentation for details.

    9. Subpatterns that are called as subroutines (whether or not recursively) are always treated as atomic groups in PCRE. This is like Python, but unlike Perl. Captured values that are set outside a subroutine call can be reference from inside in PCRE, but not in Perl. There is a discussion that explains these differences in more detail in the section on recursion differences from Perl in the pcrepattern page.

    10. If any of the backtracking control verbs are used in a subpattern that is called as a subroutine (whether or not recursively), their effect is confined to that subpattern; it does not extend to the surrounding pattern. This is not always the case in Perl. In particular, if (*THEN) is present in a group that is called as a subroutine, its action is limited to that group, even if the group does not contain any | characters. Note that such subpatterns are processed as anchored at the point where they are tested.

    11. If a pattern contains more than one backtracking control verb, the first one that is backtracked onto acts. For example, in the pattern A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure in C triggers (*PRUNE). Perl's behaviour is more complex; in many cases it is the same as PCRE, but there are examples where it differs.

    12. Most backtracking verbs in assertions have their normal actions. They are not confined to the assertion.

    13. There are some differences that are concerned with the settings of captured strings when part of a pattern is repeated. For example, matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE it is set to "b".

    14. PCRE's handling of duplicate subpattern numbers and duplicate subpattern names is not as general as Perl's. This is a consequence of the fact the PCRE works internally just with numbers, using an external table to translate between numbers and names. In particular, a pattern such as (?|(?<a>A)|(?<b>B), where the two capturing parentheses have the same number but different names, is not supported, and causes an error at compile time. If it were allowed, it would not be possible to distinguish which parentheses matched, because both names map to capturing subpattern number 1. To avoid this confusing situation, an error is given at compile time.

    15. Perl recognizes comments in some places that PCRE does not, for example, between the ( and ? at the start of a subpattern. If the /x modifier is set, Perl allows white space between ( and ? (though current Perls warn that this is deprecated) but PCRE never does, even if the PCRE_EXTENDED option is set.

    16. Perl, when in warning mode, gives warnings for character classes such as [A-\d] or [a-[:digit:]]. It then treats the hyphens as literals. PCRE has no warning features, so it gives an error in these cases because they are almost certainly user mistakes.

    17. In PCRE, the upper/lower case character properties Lu and Ll are not affected when case-independent matching is specified. For example, \p{Lu} always matches an upper case letter. I think Perl has changed in this respect; in the release at the time of writing (5.16), \p{Lu} and \p{Ll} match all letters, regardless of case, when case independence is specified.

    18. PCRE provides some extensions to the Perl regular expression facilities. Perl 5.10 includes new features that are not in earlier versions of Perl, some of which (such as named parentheses) have been in PCRE for some time. This list is with respect to Perl 5.10:

    (a) Although lookbehind assertions in PCRE must match fixed length strings, each alternative branch of a lookbehind assertion can match a different length of string. Perl requires them all to have the same length.

    (b) If PCRE_DOLLAR_ENDONLY is set and PCRE_MULTILINE is not set, the $ meta-character matches only at the very end of the string.

    (c) If PCRE_EXTRA is set, a backslash followed by a letter with no special meaning is faulted. Otherwise, like Perl, the backslash is quietly ignored. (Perl can be made to issue a warning.)

    (d) If PCRE_UNGREEDY is set, the greediness of the repetition quantifiers is inverted, that is, by default they are not greedy, but if followed by a question mark they are.

    (e) PCRE_ANCHORED can be used at matching time to force a pattern to be tried only at the first matching position in the subject string.

    (f) The PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, and PCRE_NO_AUTO_CAPTURE options for pcre_exec() have no Perl equivalents.

    (g) The \R escape sequence can be restricted to match only CR, LF, or CRLF by the PCRE_BSR_ANYCRLF option.

    (h) The callout facility is PCRE-specific.

    (i) The partial matching facility is PCRE-specific.

    (j) Patterns compiled by PCRE can be saved and re-used at a later time, even on different hosts that have the other endianness. However, this does not apply to optimized data created by the just-in-time compiler.

    (k) The alternative matching functions (pcre_dfa_exec(), pcre16_dfa_exec() and pcre32_dfa_exec(),) match in a different way and are not Perl-compatible.

    (l) PCRE recognizes some special sequences such as (*CR) at the start of a pattern that set overall options that cannot be changed within the pattern.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 10 November 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrecpp.html ================================================ pcrecpp specification

    pcrecpp man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SYNOPSIS OF C++ WRAPPER

    #include <pcrecpp.h>


    DESCRIPTION

    The C++ wrapper for PCRE was provided by Google Inc. Some additional functionality was added by Giuseppe Maxia. This brief man page was constructed from the notes in the pcrecpp.h file, which should be consulted for further details. Note that the C++ wrapper supports only the original 8-bit PCRE library. There is no 16-bit or 32-bit support at present.


    MATCHING INTERFACE

    The "FullMatch" operation checks that supplied text matches a supplied pattern exactly. If pointer arguments are supplied, it copies matched sub-strings that match sub-patterns into them.

      Example: successful match
         pcrecpp::RE re("h.*o");
         re.FullMatch("hello");
    
      Example: unsuccessful match (requires full match):
         pcrecpp::RE re("e");
         !re.FullMatch("hello");
    
      Example: creating a temporary RE object:
         pcrecpp::RE("h.*o").FullMatch("hello");
    
    You can pass in a "const char*" or a "string" for "text". The examples below tend to use a const char*. You can, as in the different examples above, store the RE object explicitly in a variable or use a temporary RE object. The examples below use one mode or the other arbitrarily. Either could correctly be used for any of these examples.

    You must supply extra pointer arguments to extract matched subpieces.

      Example: extracts "ruby" into "s" and 1234 into "i"
         int i;
         string s;
         pcrecpp::RE re("(\\w+):(\\d+)");
         re.FullMatch("ruby:1234", &s, &i);
    
      Example: does not try to extract any extra sub-patterns
         re.FullMatch("ruby:1234", &s);
    
      Example: does not try to extract into NULL
         re.FullMatch("ruby:1234", NULL, &i);
    
      Example: integer overflow causes failure
         !re.FullMatch("ruby:1234567891234", NULL, &i);
    
      Example: fails because there aren't enough sub-patterns:
         !pcrecpp::RE("\\w+:\\d+").FullMatch("ruby:1234", &s);
    
      Example: fails because string cannot be stored in integer
         !pcrecpp::RE("(.*)").FullMatch("ruby", &i);
    
    The provided pointer arguments can be pointers to any scalar numeric type, or one of:
       string        (matched piece is copied to string)
       StringPiece   (StringPiece is mutated to point to matched piece)
       T             (where "bool T::ParseFrom(const char*, int)" exists)
       NULL          (the corresponding matched sub-pattern is not copied)
    
    The function returns true iff all of the following conditions are satisfied:
      a. "text" matches "pattern" exactly;
    
      b. The number of matched sub-patterns is >= number of supplied
         pointers;
    
      c. The "i"th argument has a suitable type for holding the
         string captured as the "i"th sub-pattern. If you pass in
         void * NULL for the "i"th argument, or a non-void * NULL
         of the correct type, or pass fewer arguments than the
         number of sub-patterns, "i"th captured sub-pattern is
         ignored.
    
    CAVEAT: An optional sub-pattern that does not exist in the matched string is assigned the empty string. Therefore, the following will return false (because the empty string is not a valid number):
       int number;
       pcrecpp::RE::FullMatch("abc", "[a-z]+(\\d+)?", &number);
    
    The matching interface supports at most 16 arguments per call. If you need more, consider using the more general interface pcrecpp::RE::DoMatch. See pcrecpp.h for the signature for DoMatch.

    NOTE: Do not use no_arg, which is used internally to mark the end of a list of optional arguments, as a placeholder for missing arguments, as this can lead to segfaults.


    QUOTING METACHARACTERS

    You can use the "QuoteMeta" operation to insert backslashes before all potentially meaningful characters in a string. The returned string, used as a regular expression, will exactly match the original string.

      Example:
         string quoted = RE::QuoteMeta(unquoted);
    
    Note that it's legal to escape a character even if it has no special meaning in a regular expression -- so this function does that. (This also makes it identical to the perl function of the same name; see "perldoc -f quotemeta".) For example, "1.5-2.0?" becomes "1\.5\-2\.0\?".


    PARTIAL MATCHES

    You can use the "PartialMatch" operation when you want the pattern to match any substring of the text.

      Example: simple search for a string:
         pcrecpp::RE("ell").PartialMatch("hello");
    
      Example: find first number in a string:
         int number;
         pcrecpp::RE re("(\\d+)");
         re.PartialMatch("x*100 + 20", &number);
         assert(number == 100);
    


    UTF-8 AND THE MATCHING INTERFACE

    By default, pattern and text are plain text, one byte per character. The UTF8 flag, passed to the constructor, causes both pattern and string to be treated as UTF-8 text, still a byte stream but potentially multiple bytes per character. In practice, the text is likelier to be UTF-8 than the pattern, but the match returned may depend on the UTF8 flag, so always use it when matching UTF8 text. For example, "." will match one byte normally but with UTF8 set may match up to three bytes of a multi-byte character.

      Example:
         pcrecpp::RE_Options options;
         options.set_utf8();
         pcrecpp::RE re(utf8_pattern, options);
         re.FullMatch(utf8_string);
    
      Example: using the convenience function UTF8():
         pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8());
         re.FullMatch(utf8_string);
    
    NOTE: The UTF8 flag is ignored if pcre was not configured with the
          --enable-utf8 flag.
    


    PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE

    PCRE defines some modifiers to change the behavior of the regular expression engine. The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle to pass such modifiers to a RE class. Currently, the following modifiers are supported:

       modifier              description               Perl corresponding
    
       PCRE_CASELESS         case insensitive match      /i
       PCRE_MULTILINE        multiple lines match        /m
       PCRE_DOTALL           dot matches newlines        /s
       PCRE_DOLLAR_ENDONLY   $ matches only at end       N/A
       PCRE_EXTRA            strict escape parsing       N/A
       PCRE_EXTENDED         ignore white spaces         /x
       PCRE_UTF8             handles UTF8 chars          built-in
       PCRE_UNGREEDY         reverses * and *?           N/A
       PCRE_NO_AUTO_CAPTURE  disables capturing parens   N/A (*)
    
    (*) Both Perl and PCRE allow non capturing parentheses by means of the "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not capture, while (ab|cd) does.

    For a full account on how each modifier works, please check the PCRE API reference page.

    For each modifier, there are two member functions whose name is made out of the modifier in lowercase, without the "PCRE_" prefix. For instance, PCRE_CASELESS is handled by

      bool caseless()
    
    which returns true if the modifier is set, and
      RE_Options & set_caseless(bool)
    
    which sets or unsets the modifier. Moreover, PCRE_EXTRA_MATCH_LIMIT can be accessed through the set_match_limit() and match_limit() member functions. Setting match_limit to a non-zero value will limit the execution of pcre to keep it from doing bad things like blowing the stack or taking an eternity to return a result. A value of 5000 is good enough to stop stack blowup in a 2MB thread stack. Setting match_limit to zero disables match limiting. Alternatively, you can call match_limit_recursion() which uses PCRE_EXTRA_MATCH_LIMIT_RECURSION to limit how much PCRE recurses. match_limit() limits the number of matches PCRE does; match_limit_recursion() limits the depth of internal recursion, and therefore the amount of stack that is used.

    Normally, to pass one or more modifiers to a RE class, you declare a RE_Options object, set the appropriate options, and pass this object to a RE constructor. Example:

       RE_Options opt;
       opt.set_caseless(true);
       if (RE("HELLO", opt).PartialMatch("hello world")) ...
    
    RE_options has two constructors. The default constructor takes no arguments and creates a set of flags that are off by default. The optional parameter option_flags is to facilitate transfer of legacy code from C programs. This lets you do
       RE(pattern,
         RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str);
    
    However, new code is better off doing
       RE(pattern,
         RE_Options().set_caseless(true).set_multiline(true))
           .PartialMatch(str);
    
    If you are going to pass one of the most used modifiers, there are some convenience functions that return a RE_Options class with the appropriate modifier already set: CASELESS(), UTF8(), MULTILINE(), DOTALL(), and EXTENDED().

    If you need to set several options at once, and you don't want to go through the pains of declaring a RE_Options object and setting several options, there is a parallel method that give you such ability on the fly. You can concatenate several set_xxxxx() member functions, since each of them returns a reference to its class object. For example, to pass PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one statement, you may write:

       RE(" ^ xyz \\s+ .* blah$",
         RE_Options()
           .set_caseless(true)
           .set_extended(true)
           .set_multiline(true)).PartialMatch(sometext);
    
    


    SCANNING TEXT INCREMENTALLY

    The "Consume" operation may be useful if you want to repeatedly match regular expressions at the front of a string and skip over them as they match. This requires use of the "StringPiece" type, which represents a sub-range of a real string. Like RE, StringPiece is defined in the pcrecpp namespace.

      Example: read lines of the form "var = value" from a string.
         string contents = ...;                 // Fill string somehow
         pcrecpp::StringPiece input(contents);  // Wrap in a StringPiece
    
         string var;
         int value;
         pcrecpp::RE re("(\\w+) = (\\d+)\n");
         while (re.Consume(&input, &var, &value)) {
           ...;
         }
    
    Each successful call to "Consume" will set "var/value", and also advance "input" so it points past the matched text.

    The "FindAndConsume" operation is similar to "Consume" but does not anchor your match at the beginning of the string. For example, you could extract all words from a string by repeatedly calling

      pcrecpp::RE("(\\w+)").FindAndConsume(&input, &word)
    


    PARSING HEX/OCTAL/C-RADIX NUMBERS

    By default, if you pass a pointer to a numeric value, the corresponding text is interpreted as a base-10 number. You can instead wrap the pointer with a call to one of the operators Hex(), Octal(), or CRadix() to interpret the text in another base. The CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) prefixes, but defaults to base-10.

      Example:
        int a, b, c, d;
        pcrecpp::RE re("(.*) (.*) (.*) (.*)");
        re.FullMatch("100 40 0100 0x40",
                     pcrecpp::Octal(&a), pcrecpp::Hex(&b),
                     pcrecpp::CRadix(&c), pcrecpp::CRadix(&d));
    
    will leave 64 in a, b, c, and d.


    REPLACING PARTS OF STRINGS

    You can replace the first match of "pattern" in "str" with "rewrite". Within "rewrite", backslash-escaped digits (\1 to \9) can be used to insert text matching corresponding parenthesized group from the pattern. \0 in "rewrite" refers to the entire matching text. For example:

      string s = "yabba dabba doo";
      pcrecpp::RE("b+").Replace("d", &s);
    
    will leave "s" containing "yada dabba doo". The result is true if the pattern matches and a replacement occurs, false otherwise.

    GlobalReplace is like Replace except that it replaces all occurrences of the pattern in the string with the rewrite. Replacements are not subject to re-matching. For example:

      string s = "yabba dabba doo";
      pcrecpp::RE("b+").GlobalReplace("d", &s);
    
    will leave "s" containing "yada dada doo". It returns the number of replacements made.

    Extract is like Replace, except that if the pattern matches, "rewrite" is copied into "out" (an additional argument) with substitutions. The non-matching portions of "text" are ignored. Returns true iff a match occurred and the extraction happened successfully; if no match occurs, the string is left unaffected.


    AUTHOR

    The C++ wrapper was contributed by Google Inc.
    Copyright © 2007 Google Inc.


    REVISION

    Last updated: 08 January 2012

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcredemo.html ================================================ pcredemo specification

    pcredemo man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    /*************************************************
    *           PCRE DEMONSTRATION PROGRAM           *
    *************************************************/
    
    /* This is a demonstration program to illustrate the most straightforward ways
    of calling the PCRE regular expression library from a C program. See the
    pcresample documentation for a short discussion ("man pcresample" if you have
    the PCRE man pages installed).
    
    In Unix-like environments, if PCRE is installed in your standard system
    libraries, you should be able to compile this program using this command:
    
    gcc -Wall pcredemo.c -lpcre -o pcredemo
    
    If PCRE is not installed in a standard place, it is likely to be installed with
    support for the pkg-config mechanism. If you have pkg-config, you can compile
    this program using this command:
    
    gcc -Wall pcredemo.c `pkg-config --cflags --libs libpcre` -o pcredemo
    
    If you do not have pkg-config, you may have to use this:
    
    gcc -Wall pcredemo.c -I/usr/local/include -L/usr/local/lib \
      -R/usr/local/lib -lpcre -o pcredemo
    
    Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and
    library files for PCRE are installed on your system. Only some operating
    systems (e.g. Solaris) use the -R option.
    
    Building under Windows:
    
    If you want to statically link this program against a non-dll .a file, you must
    define PCRE_STATIC before including pcre.h, otherwise the pcre_malloc() and
    pcre_free() exported functions will be declared __declspec(dllimport), with
    unwanted results. So in this environment, uncomment the following line. */
    
    /* #define PCRE_STATIC */
    
    #include <stdio.h>
    #include <string.h>
    #include <pcre.h>
    
    #define OVECCOUNT 30    /* should be a multiple of 3 */
    
    
    int main(int argc, char **argv)
    {
    pcre *re;
    const char *error;
    char *pattern;
    char *subject;
    unsigned char *name_table;
    unsigned int option_bits;
    int erroffset;
    int find_all;
    int crlf_is_newline;
    int namecount;
    int name_entry_size;
    int ovector[OVECCOUNT];
    int subject_length;
    int rc, i;
    int utf8;
    
    
    /**************************************************************************
    * First, sort out the command line. There is only one possible option at  *
    * the moment, "-g" to request repeated matching to find all occurrences,  *
    * like Perl's /g option. We set the variable find_all to a non-zero value *
    * if the -g option is present. Apart from that, there must be exactly two *
    * arguments.                                                              *
    **************************************************************************/
    
    find_all = 0;
    for (i = 1; i < argc; i++)
      {
      if (strcmp(argv[i], "-g") == 0) find_all = 1;
        else break;
      }
    
    /* After the options, we require exactly two arguments, which are the pattern,
    and the subject string. */
    
    if (argc - i != 2)
      {
      printf("Two arguments required: a regex and a subject string\n");
      return 1;
      }
    
    pattern = argv[i];
    subject = argv[i+1];
    subject_length = (int)strlen(subject);
    
    
    /*************************************************************************
    * Now we are going to compile the regular expression pattern, and handle *
    * and errors that are detected.                                          *
    *************************************************************************/
    
    re = pcre_compile(
      pattern,              /* the pattern */
      0,                    /* default options */
      &error,               /* for error message */
      &erroffset,           /* for error offset */
      NULL);                /* use default character tables */
    
    /* Compilation failed: print the error message and exit */
    
    if (re == NULL)
      {
      printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
      return 1;
      }
    
    
    /*************************************************************************
    * If the compilation succeeded, we call PCRE again, in order to do a     *
    * pattern match against the subject string. This does just ONE match. If *
    * further matching is needed, it will be done below.                     *
    *************************************************************************/
    
    rc = pcre_exec(
      re,                   /* the compiled pattern */
      NULL,                 /* no extra data - we didn't study the pattern */
      subject,              /* the subject string */
      subject_length,       /* the length of the subject */
      0,                    /* start at offset 0 in the subject */
      0,                    /* default options */
      ovector,              /* output vector for substring information */
      OVECCOUNT);           /* number of elements in the output vector */
    
    /* Matching failed: handle error cases */
    
    if (rc < 0)
      {
      switch(rc)
        {
        case PCRE_ERROR_NOMATCH: printf("No match\n"); break;
        /*
        Handle other special cases if you like
        */
        default: printf("Matching error %d\n", rc); break;
        }
      pcre_free(re);     /* Release memory used for the compiled pattern */
      return 1;
      }
    
    /* Match succeded */
    
    printf("\nMatch succeeded at offset %d\n", ovector[0]);
    
    
    /*************************************************************************
    * We have found the first match within the subject string. If the output *
    * vector wasn't big enough, say so. Then output any substrings that were *
    * captured.                                                              *
    *************************************************************************/
    
    /* The output vector wasn't big enough */
    
    if (rc == 0)
      {
      rc = OVECCOUNT/3;
      printf("ovector only has room for %d captured substrings\n", rc - 1);
      }
    
    /* Show substrings stored in the output vector by number. Obviously, in a real
    application you might want to do things other than print them. */
    
    for (i = 0; i < rc; i++)
      {
      char *substring_start = subject + ovector[2*i];
      int substring_length = ovector[2*i+1] - ovector[2*i];
      printf("%2d: %.*s\n", i, substring_length, substring_start);
      }
    
    
    /**************************************************************************
    * That concludes the basic part of this demonstration program. We have    *
    * compiled a pattern, and performed a single match. The code that follows *
    * shows first how to access named substrings, and then how to code for    *
    * repeated matches on the same subject.                                   *
    **************************************************************************/
    
    /* See if there are any named substrings, and if so, show them by name. First
    we have to extract the count of named parentheses from the pattern. */
    
    (void)pcre_fullinfo(
      re,                   /* the compiled pattern */
      NULL,                 /* no extra data - we didn't study the pattern */
      PCRE_INFO_NAMECOUNT,  /* number of named substrings */
      &namecount);          /* where to put the answer */
    
    if (namecount <= 0) printf("No named substrings\n"); else
      {
      unsigned char *tabptr;
      printf("Named substrings\n");
    
      /* Before we can access the substrings, we must extract the table for
      translating names to numbers, and the size of each entry in the table. */
    
      (void)pcre_fullinfo(
        re,                       /* the compiled pattern */
        NULL,                     /* no extra data - we didn't study the pattern */
        PCRE_INFO_NAMETABLE,      /* address of the table */
        &name_table);             /* where to put the answer */
    
      (void)pcre_fullinfo(
        re,                       /* the compiled pattern */
        NULL,                     /* no extra data - we didn't study the pattern */
        PCRE_INFO_NAMEENTRYSIZE,  /* size of each entry in the table */
        &name_entry_size);        /* where to put the answer */
    
      /* Now we can scan the table and, for each entry, print the number, the name,
      and the substring itself. */
    
      tabptr = name_table;
      for (i = 0; i < namecount; i++)
        {
        int n = (tabptr[0] << 8) | tabptr[1];
        printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,
          ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]);
        tabptr += name_entry_size;
        }
      }
    
    
    /*************************************************************************
    * If the "-g" option was given on the command line, we want to continue  *
    * to search for additional matches in the subject string, in a similar   *
    * way to the /g option in Perl. This turns out to be trickier than you   *
    * might think because of the possibility of matching an empty string.    *
    * What happens is as follows:                                            *
    *                                                                        *
    * If the previous match was NOT for an empty string, we can just start   *
    * the next match at the end of the previous one.                         *
    *                                                                        *
    * If the previous match WAS for an empty string, we can't do that, as it *
    * would lead to an infinite loop. Instead, a special call of pcre_exec() *
    * is made with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set.    *
    * The first of these tells PCRE that an empty string at the start of the *
    * subject is not a valid match; other possibilities must be tried. The   *
    * second flag restricts PCRE to one match attempt at the initial string  *
    * position. If this match succeeds, an alternative to the empty string   *
    * match has been found, and we can print it and proceed round the loop,  *
    * advancing by the length of whatever was found. If this match does not  *
    * succeed, we still stay in the loop, advancing by just one character.   *
    * In UTF-8 mode, which can be set by (*UTF8) in the pattern, this may be *
    * more than one byte.                                                    *
    *                                                                        *
    * However, there is a complication concerned with newlines. When the     *
    * newline convention is such that CRLF is a valid newline, we must       *
    * advance by two characters rather than one. The newline convention can  *
    * be set in the regex by (*CR), etc.; if not, we must find the default.  *
    *************************************************************************/
    
    if (!find_all)     /* Check for -g */
      {
      pcre_free(re);   /* Release the memory used for the compiled pattern */
      return 0;        /* Finish unless -g was given */
      }
    
    /* Before running the loop, check for UTF-8 and whether CRLF is a valid newline
    sequence. First, find the options with which the regex was compiled; extract
    the UTF-8 state, and mask off all but the newline options. */
    
    (void)pcre_fullinfo(re, NULL, PCRE_INFO_OPTIONS, &option_bits);
    utf8 = option_bits & PCRE_UTF8;
    option_bits &= PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_CRLF|
                   PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF;
    
    /* If no newline options were set, find the default newline convention from the
    build configuration. */
    
    if (option_bits == 0)
      {
      int d;
      (void)pcre_config(PCRE_CONFIG_NEWLINE, &d);
      /* Note that these values are always the ASCII ones, even in
      EBCDIC environments. CR = 13, NL = 10. */
      option_bits = (d == 13)? PCRE_NEWLINE_CR :
              (d == 10)? PCRE_NEWLINE_LF :
              (d == (13<<8 | 10))? PCRE_NEWLINE_CRLF :
              (d == -2)? PCRE_NEWLINE_ANYCRLF :
              (d == -1)? PCRE_NEWLINE_ANY : 0;
      }
    
    /* See if CRLF is a valid newline sequence. */
    
    crlf_is_newline =
         option_bits == PCRE_NEWLINE_ANY ||
         option_bits == PCRE_NEWLINE_CRLF ||
         option_bits == PCRE_NEWLINE_ANYCRLF;
    
    /* Loop for second and subsequent matches */
    
    for (;;)
      {
      int options = 0;                 /* Normally no options */
      int start_offset = ovector[1];   /* Start at end of previous match */
    
      /* If the previous match was for an empty string, we are finished if we are
      at the end of the subject. Otherwise, arrange to run another match at the
      same point to see if a non-empty match can be found. */
    
      if (ovector[0] == ovector[1])
        {
        if (ovector[0] == subject_length) break;
        options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED;
        }
    
      /* Run the next matching operation */
    
      rc = pcre_exec(
        re,                   /* the compiled pattern */
        NULL,                 /* no extra data - we didn't study the pattern */
        subject,              /* the subject string */
        subject_length,       /* the length of the subject */
        start_offset,         /* starting offset in the subject */
        options,              /* options */
        ovector,              /* output vector for substring information */
        OVECCOUNT);           /* number of elements in the output vector */
    
      /* This time, a result of NOMATCH isn't an error. If the value in "options"
      is zero, it just means we have found all possible matches, so the loop ends.
      Otherwise, it means we have failed to find a non-empty-string match at a
      point where there was a previous empty-string match. In this case, we do what
      Perl does: advance the matching position by one character, and continue. We
      do this by setting the "end of previous match" offset, because that is picked
      up at the top of the loop as the point at which to start again.
    
      There are two complications: (a) When CRLF is a valid newline sequence, and
      the current position is just before it, advance by an extra byte. (b)
      Otherwise we must ensure that we skip an entire UTF-8 character if we are in
      UTF-8 mode. */
    
      if (rc == PCRE_ERROR_NOMATCH)
        {
        if (options == 0) break;                    /* All matches found */
        ovector[1] = start_offset + 1;              /* Advance one byte */
        if (crlf_is_newline &&                      /* If CRLF is newline & */
            start_offset < subject_length - 1 &&    /* we are at CRLF, */
            subject[start_offset] == '\r' &&
            subject[start_offset + 1] == '\n')
          ovector[1] += 1;                          /* Advance by one more. */
        else if (utf8)                              /* Otherwise, ensure we */
          {                                         /* advance a whole UTF-8 */
          while (ovector[1] < subject_length)       /* character. */
            {
            if ((subject[ovector[1]] & 0xc0) != 0x80) break;
            ovector[1] += 1;
            }
          }
        continue;    /* Go round the loop again */
        }
    
      /* Other matching errors are not recoverable. */
    
      if (rc < 0)
        {
        printf("Matching error %d\n", rc);
        pcre_free(re);    /* Release memory used for the compiled pattern */
        return 1;
        }
    
      /* Match succeded */
    
      printf("\nMatch succeeded again at offset %d\n", ovector[0]);
    
      /* The match succeeded, but the output vector wasn't big enough. */
    
      if (rc == 0)
        {
        rc = OVECCOUNT/3;
        printf("ovector only has room for %d captured substrings\n", rc - 1);
        }
    
      /* As before, show substrings stored in the output vector by number, and then
      also any named substrings. */
    
      for (i = 0; i < rc; i++)
        {
        char *substring_start = subject + ovector[2*i];
        int substring_length = ovector[2*i+1] - ovector[2*i];
        printf("%2d: %.*s\n", i, substring_length, substring_start);
        }
    
      if (namecount <= 0) printf("No named substrings\n"); else
        {
        unsigned char *tabptr = name_table;
        printf("Named substrings\n");
        for (i = 0; i < namecount; i++)
          {
          int n = (tabptr[0] << 8) | tabptr[1];
          printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,
            ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]);
          tabptr += name_entry_size;
          }
        }
      }      /* End of loop to find second and subsequent matches */
    
    printf("\n");
    pcre_free(re);       /* Release memory used for the compiled pattern */
    return 0;
    }
    
    /* End of pcredemo.c */
    

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcregrep.html ================================================ pcregrep specification

    pcregrep man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SYNOPSIS

    pcregrep [options] [long options] [pattern] [path1 path2 ...]


    DESCRIPTION

    pcregrep searches files for character patterns, in the same way as other grep commands do, but it uses the PCRE regular expression library to support patterns that are compatible with the regular expressions of Perl 5. See pcresyntax(3) for a quick-reference summary of pattern syntax, or pcrepattern(3) for a full description of the syntax and semantics of the regular expressions that PCRE supports.

    Patterns, whether supplied on the command line or in a separate file, are given without delimiters. For example:

      pcregrep Thursday /etc/motd
    
    If you attempt to use delimiters (for example, by surrounding a pattern with slashes, as is common in Perl scripts), they are interpreted as part of the pattern. Quotes can of course be used to delimit patterns on the command line because they are interpreted by the shell, and indeed quotes are required if a pattern contains white space or shell metacharacters.

    The first argument that follows any option settings is treated as the single pattern to be matched when neither -e nor -f is present. Conversely, when one or both of these options are used to specify patterns, all arguments are treated as path names. At least one of -e, -f, or an argument pattern must be provided.

    If no files are specified, pcregrep reads the standard input. The standard input can also be referenced by a name consisting of a single hyphen. For example:

      pcregrep some-pattern /file1 - /file3
    
    By default, each line that matches a pattern is copied to the standard output, and if there is more than one file, the file name is output at the start of each line, followed by a colon. However, there are options that can change how pcregrep behaves. In particular, the -M option makes it possible to search for patterns that span line boundaries. What defines a line boundary is controlled by the -N (--newline) option.

    The amount of memory used for buffering files that are being scanned is controlled by a parameter that can be set by the --buffer-size option. The default value for this parameter is specified when pcregrep is built, with the default default being 20K. A block of memory three times this size is used (to allow for buffering "before" and "after" lines). An error occurs if a line overflows the buffer.

    Patterns can be no longer than 8K or BUFSIZ bytes, whichever is the greater. BUFSIZ is defined in <stdio.h>. When there is more than one pattern (specified by the use of -e and/or -f), each pattern is applied to each line in the order in which they are defined, except that all the -e patterns are tried before the -f patterns.

    By default, as soon as one pattern matches a line, no further patterns are considered. However, if --colour (or --color) is used to colour the matching substrings, or if --only-matching, --file-offsets, or --line-offsets is used to output only the part of the line that matched (either shown literally, or as an offset), scanning resumes immediately following the match, so that further matches on the same line can be found. If there are multiple patterns, they are all tried on the remainder of the line, but patterns that follow the one that matched are not tried on the earlier part of the line.

    This behaviour means that the order in which multiple patterns are specified can affect the output when one of the above options is used. This is no longer the same behaviour as GNU grep, which now manages to display earlier matches for later patterns (as long as there is no overlap).

    Patterns that can match an empty string are accepted, but empty string matches are never recognized. An example is the pattern "(super)?(man)?", in which all components are optional. This pattern finds all occurrences of both "super" and "man"; the output differs from matching with "super|man" when only the matching substrings are being shown.

    If the LC_ALL or LC_CTYPE environment variable is set, pcregrep uses the value to set a locale when calling the PCRE library. The --locale option can be used to override this.


    SUPPORT FOR COMPRESSED FILES

    It is possible to compile pcregrep so that it uses libz or libbz2 to read files whose names end in .gz or .bz2, respectively. You can find out whether your binary has support for one or both of these file types by running it with the --help option. If the appropriate support is not present, files are treated as plain text. The standard input is always so treated.


    BINARY FILES

    By default, a file that contains a binary zero byte within the first 1024 bytes is identified as a binary file, and is processed specially. (GNU grep also identifies binary files in this manner.) See the --binary-files option for a means of changing the way binary files are handled.


    OPTIONS

    The order in which some of the options appear can affect the output. For example, both the -h and -l options affect the printing of file names. Whichever comes later in the command line will be the one that takes effect. Similarly, except where noted below, if an option is given twice, the later setting is used. Numerical values for options may be followed by K or M, to signify multiplication by 1024 or 1024*1024 respectively.

    -- This terminates the list of options. It is useful if the next item on the command line starts with a hyphen but is not an option. This allows for the processing of patterns and filenames that start with hyphens.

    -A number, --after-context=number Output number lines of context after each matching line. If filenames and/or line numbers are being output, a hyphen separator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file. The value of number is expected to be relatively small. However, pcregrep guarantees to have up to 8K of following text available for context output.

    -a, --text Treat binary files as text. This is equivalent to --binary-files=text.

    -B number, --before-context=number Output number lines of context before each matching line. If filenames and/or line numbers are being output, a hyphen separator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file. The value of number is expected to be relatively small. However, pcregrep guarantees to have up to 8K of preceding text available for context output.

    --binary-files=word Specify how binary files are to be processed. If the word is "binary" (the default), pattern matching is performed on binary files, but the only output is "Binary file <name> matches" when a match succeeds. If the word is "text", which is equivalent to the -a or --text option, binary files are processed in the same way as any other file. In this case, when a match succeeds, the output may be binary garbage, which can have nasty effects if sent to a terminal. If the word is "without-match", which is equivalent to the -I option, binary files are not processed at all; they are assumed not to be of interest.

    --buffer-size=number Set the parameter that controls how much memory is used for buffering files that are being scanned.

    -C number, --context=number Output number lines of context both before and after each matching line. This is equivalent to setting both -A and -B to the same value.

    -c, --count Do not output individual lines from the files that are being scanned; instead output the number of lines that would otherwise have been shown. If no lines are selected, the number zero is output. If several files are are being scanned, a count is output for each of them. However, if the --files-with-matches option is also used, only those files whose counts are greater than zero are listed. When -c is used, the -A, -B, and -C options are ignored.

    --colour, --color If this option is given without any data, it is equivalent to "--colour=auto". If data is required, it must be given in the same shell item, separated by an equals sign.

    --colour=value, --color=value This option specifies under what circumstances the parts of a line that matched a pattern should be coloured in the output. By default, the output is not coloured. The value (which is optional, see above) may be "never", "always", or "auto". In the latter case, colouring happens only if the standard output is connected to a terminal. More resources are used when colouring is enabled, because pcregrep has to search for all possible matches in a line, not just one, in order to colour them all.

    The colour that is used can be specified by setting the environment variable PCREGREP_COLOUR or PCREGREP_COLOR. The value of this variable should be a string of two numbers, separated by a semicolon. They are copied directly into the control string for setting colour on a terminal, so it is your responsibility to ensure that they make sense. If neither of the environment variables is set, the default is "1;31", which gives red.

    -D action, --devices=action If an input path is not a regular file or a directory, "action" specifies how it is to be processed. Valid values are "read" (the default) or "skip" (silently skip the path).

    -d action, --directories=action If an input path is a directory, "action" specifies how it is to be processed. Valid values are "read" (the default in non-Windows environments, for compatibility with GNU grep), "recurse" (equivalent to the -r option), or "skip" (silently skip the path, the default in Windows environments). In the "read" case, directories are read as if they were ordinary files. In some operating systems the effect of reading a directory like this is an immediate end-of-file; in others it may provoke an error.

    -e pattern, --regex=pattern, --regexp=pattern Specify a pattern to be matched. This option can be used multiple times in order to specify several patterns. It can also be used as a way of specifying a single pattern that starts with a hyphen. When -e is used, no argument pattern is taken from the command line; all arguments are treated as file names. There is no limit to the number of patterns. They are applied to each line in the order in which they are defined until one matches.

    If -f is used with -e, the command line patterns are matched first, followed by the patterns from the file(s), independent of the order in which these options are specified. Note that multiple use of -e is not the same as a single pattern with alternatives. For example, X|Y finds the first character in a line that is X or Y, whereas if the two patterns are given separately, with X first, pcregrep finds X if it is present, even if it follows Y in the line. It finds Y only if there is no X in the line. This matters only if you are using -o or --colo(u)r to show the part(s) of the line that matched.

    --exclude=pattern Files (but not directories) whose names match the pattern are skipped without being processed. This applies to all files, whether listed on the command line, obtained from --file-list, or by scanning a directory. The pattern is a PCRE regular expression, and is matched against the final component of the file name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times in order to specify multiple patterns. If a file name matches both an --include and an --exclude pattern, it is excluded. There is no short form for this option.

    --exclude-from=filename Treat each non-empty line of the file as the data for an --exclude option. What constitutes a newline when reading the file is the operating system's default. The --newline option has no effect on this option. This option may be given more than once in order to specify a number of files to read.

    --exclude-dir=pattern Directories whose names match the pattern are skipped without being processed, whatever the setting of the --recursive option. This applies to all directories, whether listed on the command line, obtained from --file-list, or by scanning a parent directory. The pattern is a PCRE regular expression, and is matched against the final component of the directory name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times in order to specify more than one pattern. If a directory matches both --include-dir and --exclude-dir, it is excluded. There is no short form for this option.

    -F, --fixed-strings Interpret each data-matching pattern as a list of fixed strings, separated by newlines, instead of as a regular expression. What constitutes a newline for this purpose is controlled by the --newline option. The -w (match as a word) and -x (match whole line) options can be used with -F. They apply to each of the fixed strings. A line is selected if any of the fixed strings are found in it (subject to -w or -x, if present). This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the --include or --exclude options.

    -f filename, --file=filename Read patterns from the file, one per line, and match them against each line of input. What constitutes a newline when reading the file is the operating system's default. The --newline option has no effect on this option. Trailing white space is removed from each line, and blank lines are ignored. An empty file contains no patterns and therefore matches nothing. See also the comments about multiple patterns versus a single pattern with alternatives in the description of -e above.

    If this option is given more than once, all the specified files are read. A data line is output if any of the patterns match it. A filename can be given as "-" to refer to the standard input. When -f is used, patterns specified on the command line using -e may also be present; they are tested before the file's patterns. However, no other pattern is taken from the command line; all arguments are treated as the names of paths to be searched.

    --file-list=filename Read a list of files and/or directories that are to be scanned from the given file, one per line. Trailing white space is removed from each line, and blank lines are ignored. These paths are processed before any that are listed on the command line. The filename can be given as "-" to refer to the standard input. If --file and --file-list are both specified as "-", patterns are read first. This is useful only when the standard input is a terminal, from which further lines (the list of files) can be read after an end-of-file indication. If this option is given more than once, all the specified files are read.

    --file-offsets Instead of showing lines or parts of lines that match, show each match as an offset from the start of the file and a length, separated by a comma. In this mode, no context is shown. That is, the -A, -B, and -C options are ignored. If there is more than one match in a line, each of them is shown separately. This option is mutually exclusive with --line-offsets and --only-matching.

    -H, --with-filename Force the inclusion of the filename at the start of output lines when searching a single file. By default, the filename is not shown in this case. For matching lines, the filename is followed by a colon; for context lines, a hyphen separator is used. If a line number is also being output, it follows the file name.

    -h, --no-filename Suppress the output filenames when searching multiple files. By default, filenames are shown when multiple files are searched. For matching lines, the filename is followed by a colon; for context lines, a hyphen separator is used. If a line number is also being output, it follows the file name.

    --help Output a help message, giving brief details of the command options and file type support, and then exit. Anything else on the command line is ignored.

    -I Treat binary files as never matching. This is equivalent to --binary-files=without-match.

    -i, --ignore-case Ignore upper/lower case distinctions during comparisons.

    --include=pattern If any --include patterns are specified, the only files that are processed are those that match one of the patterns (and do not match an --exclude pattern). This option does not affect directories, but it applies to all files, whether listed on the command line, obtained from --file-list, or by scanning a directory. The pattern is a PCRE regular expression, and is matched against the final component of the file name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times. If a file name matches both an --include and an --exclude pattern, it is excluded. There is no short form for this option.

    --include-from=filename Treat each non-empty line of the file as the data for an --include option. What constitutes a newline for this purpose is the operating system's default. The --newline option has no effect on this option. This option may be given any number of times; all the files are read.

    --include-dir=pattern If any --include-dir patterns are specified, the only directories that are processed are those that match one of the patterns (and do not match an --exclude-dir pattern). This applies to all directories, whether listed on the command line, obtained from --file-list, or by scanning a parent directory. The pattern is a PCRE regular expression, and is matched against the final component of the directory name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times. If a directory matches both --include-dir and --exclude-dir, it is excluded. There is no short form for this option.

    -L, --files-without-match Instead of outputting lines from the files, just output the names of the files that do not contain any lines that would have been output. Each file name is output once, on a separate line.

    -l, --files-with-matches Instead of outputting lines from the files, just output the names of the files containing lines that would have been output. Each file name is output once, on a separate line. Searching normally stops as soon as a matching line is found in a file. However, if the -c (count) option is also used, matching continues in order to obtain the correct count, and those files that have at least one match are listed along with their counts. Using this option with -c is a way of suppressing the listing of files with no matches.

    --label=name This option supplies a name to be used for the standard input when file names are being output. If not supplied, "(standard input)" is used. There is no short form for this option.

    --line-buffered When this option is given, input is read and processed line by line, and the output is flushed after each write. By default, input is read in large chunks, unless pcregrep can determine that it is reading from a terminal (which is currently possible only in Unix-like environments). Output to terminal is normally automatically flushed by the operating system. This option can be useful when the input or output is attached to a pipe and you do not want pcregrep to buffer up large amounts of data. However, its use will affect performance, and the -M (multiline) option ceases to work.

    --line-offsets Instead of showing lines or parts of lines that match, show each match as a line number, the offset from the start of the line, and a length. The line number is terminated by a colon (as usual; see the -n option), and the offset and length are separated by a comma. In this mode, no context is shown. That is, the -A, -B, and -C options are ignored. If there is more than one match in a line, each of them is shown separately. This option is mutually exclusive with --file-offsets and --only-matching.

    --locale=locale-name This option specifies a locale to be used for pattern matching. It overrides the value in the LC_ALL or LC_CTYPE environment variables. If no locale is specified, the PCRE library's default (usually the "C" locale) is used. There is no short form for this option.

    --match-limit=number Processing some regular expression patterns can require a very large amount of memory, leading in some cases to a program crash if not enough is available. Other patterns may take a very long time to search for all possible matching strings. The pcre_exec() function that is called by pcregrep to do the matching has two parameters that can limit the resources that it uses.

    The --match-limit option provides a means of limiting resource usage when processing patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is a pattern that uses nested unlimited repeats. Internally, PCRE uses a function called match() which it calls repeatedly (sometimes recursively). The limit set by --match-limit is imposed on the number of times this function is called during a match, which has the effect of limiting the amount of backtracking that can take place.

    The --recursion-limit option is similar to --match-limit, but instead of limiting the total number of times that match() is called, it limits the depth of recursive calls, which in turn limits the amount of memory that can be used. The recursion depth is a smaller number than the total number of calls, because not all calls to match() are recursive. This limit is of use only if it is set smaller than --match-limit.

    There are no short forms for these options. The default settings are specified when the PCRE library is compiled, with the default default being 10 million.

    -M, --multiline Allow patterns to match more than one line. When this option is given, patterns may usefully contain literal newline characters and internal occurrences of ^ and $ characters. The output for a successful match may consist of more than one line, the last of which is the one in which the match ended. If the matched string ends with a newline sequence the output ends at the end of that line.

    When this option is set, the PCRE library is called in "multiline" mode. There is a limit to the number of lines that can be matched, imposed by the way that pcregrep buffers the input file as it scans it. However, pcregrep ensures that at least 8K characters or the rest of the document (whichever is the shorter) are available for forward matching, and similarly the previous 8K characters (or all the previous characters, if fewer than 8K) are guaranteed to be available for lookbehind assertions. This option does not work when input is read line by line (see \fP--line-buffered\fP.)

    -N newline-type, --newline=newline-type The PCRE library supports five different conventions for indicating the ends of lines. They are the single-character sequences CR (carriage return) and LF (linefeed), the two-character sequence CRLF, an "anycrlf" convention, which recognizes any of the preceding three types, and an "any" convention, in which any Unicode line ending sequence is assumed to end a line. The Unicode sequences are the three just mentioned, plus VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029).

    When the PCRE library is built, a default line-ending sequence is specified. This is normally the standard sequence for the operating system. Unless otherwise specified by this option, pcregrep uses the library's default. The possible values for this option are CR, LF, CRLF, ANYCRLF, or ANY. This makes it possible to use pcregrep to scan files that have come from other environments without having to modify their line endings. If the data that is being scanned does not agree with the convention set by this option, pcregrep may behave in strange ways. Note that this option does not apply to files specified by the -f, --exclude-from, or --include-from options, which are expected to use the operating system's standard newline sequence.

    -n, --line-number Precede each output line by its line number in the file, followed by a colon for matching lines or a hyphen for context lines. If the filename is also being output, it precedes the line number. This option is forced if --line-offsets is used.

    --no-jit If the PCRE library is built with support for just-in-time compiling (which speeds up matching), pcregrep automatically makes use of this, unless it was explicitly disabled at build time. This option can be used to disable the use of JIT at run time. It is provided for testing and working round problems. It should never be needed in normal use.

    -o, --only-matching Show only the part of the line that matched a pattern instead of the whole line. In this mode, no context is shown. That is, the -A, -B, and -C options are ignored. If there is more than one match in a line, each of them is shown separately. If -o is combined with -v (invert the sense of the match to find non-matching lines), no output is generated, but the return code is set appropriately. If the matched portion of the line is empty, nothing is output unless the file name or line number are being printed, in which case they are shown on an otherwise empty line. This option is mutually exclusive with --file-offsets and --line-offsets.

    -onumber, --only-matching=number Show only the part of the line that matched the capturing parentheses of the given number. Up to 32 capturing parentheses are supported, and -o0 is equivalent to -o without a number. Because these options can be given without an argument (see above), if an argument is present, it must be given in the same shell item, for example, -o3 or --only-matching=2. The comments given for the non-argument case above also apply to this case. If the specified capturing parentheses do not exist in the pattern, or were not set in the match, nothing is output unless the file name or line number are being printed.

    If this option is given multiple times, multiple substrings are output, in the order the options are given. For example, -o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and then 3 again to be output. By default, there is no separator (but see the next option).

    --om-separator=text Specify a separating string for multiple occurrences of -o. The default is an empty string. Separating strings are never coloured.

    -q, --quiet Work quietly, that is, display nothing except error messages. The exit status indicates whether or not any matches were found.

    -r, --recursive If any given path is a directory, recursively scan the files it contains, taking note of any --include and --exclude settings. By default, a directory is read as a normal file; in some operating systems this gives an immediate end-of-file. This option is a shorthand for setting the -d option to "recurse".

    --recursion-limit=number See --match-limit above.

    -s, --no-messages Suppress error messages about non-existent or unreadable files. Such files are quietly skipped. However, the return code is still 2, even if matches were found in other files.

    -u, --utf-8 Operate in UTF-8 mode. This option is available only if PCRE has been compiled with UTF-8 support. All patterns (including those for any --exclude and --include options) and all subject lines that are scanned must be valid strings of UTF-8 characters.

    -V, --version Write the version numbers of pcregrep and the PCRE library to the standard output and then exit. Anything else on the command line is ignored.

    -v, --invert-match Invert the sense of the match, so that lines which do not match any of the patterns are the ones that are found.

    -w, --word-regex, --word-regexp Force the patterns to match only whole words. This is equivalent to having \b at the start and end of the pattern. This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the --include or --exclude options.

    -x, --line-regex, --line-regexp Force the patterns to be anchored (each must start matching at the beginning of a line) and in addition, require them to match entire lines. This is equivalent to having ^ and $ characters at the start and end of each alternative branch in every pattern. This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the --include or --exclude options.


    ENVIRONMENT VARIABLES

    The environment variables LC_ALL and LC_CTYPE are examined, in that order, for a locale. The first one that is set is used. This can be overridden by the --locale option. If no locale is set, the PCRE library's default (usually the "C" locale) is used.


    NEWLINES

    The -N (--newline) option allows pcregrep to scan files with different newline conventions from the default. Any parts of the input files that are written to the standard output are copied identically, with whatever newline sequences they have in the input. However, the setting of this option does not affect the interpretation of files specified by the -f, --exclude-from, or --include-from options, which are assumed to use the operating system's standard newline sequence, nor does it affect the way in which pcregrep writes informational messages to the standard error and output streams. For these it uses the string "\n" to indicate newlines, relying on the C I/O library to convert this to an appropriate sequence.


    OPTIONS COMPATIBILITY

    Many of the short and long forms of pcregrep's options are the same as in the GNU grep program. Any long option of the form --xxx-regexp (GNU terminology) is also available as --xxx-regex (PCRE terminology). However, the --file-list, --file-offsets, --include-dir, --line-offsets, --locale, --match-limit, -M, --multiline, -N, --newline, --om-separator, --recursion-limit, -u, and --utf-8 options are specific to pcregrep, as is the use of the --only-matching option with a capturing parentheses number.

    Although most of the common options work the same way, a few are different in pcregrep. For example, the --include option's argument is a glob for GNU grep, but a regular expression for pcregrep. If both the -c and -l options are given, GNU grep lists only file names, without counts, but pcregrep gives the counts.


    OPTIONS WITH DATA

    There are four different ways in which an option with data can be specified. If a short form option is used, the data may follow immediately, or (with one exception) in the next command line item. For example:

      -f/some/file
      -f /some/file
    
    The exception is the -o option, which may appear with or without data. Because of this, if data is present, it must follow immediately in the same item, for example -o3.

    If a long form option is used, the data may appear in the same command line item, separated by an equals character, or (with two exceptions) it may appear in the next command line item. For example:

      --file=/some/file
      --file /some/file
    
    Note, however, that if you want to supply a file name beginning with ~ as data in a shell command, and have the shell expand ~ to a home directory, you must separate the file name from the option, because the shell does not treat ~ specially unless it is at the start of an item.

    The exceptions to the above are the --colour (or --color) and --only-matching options, for which the data is optional. If one of these options does have data, it must be given in the first form, using an equals character. Otherwise pcregrep will assume that it has no data.


    MATCHING ERRORS

    It is possible to supply a regular expression that takes a very long time to fail to match certain lines. Such patterns normally involve nested indefinite repeats, for example: (a+)*\d when matched against a line of a's with no final digit. The PCRE matching function has a resource limit that causes it to abort in these circumstances. If this happens, pcregrep outputs an error message and the line that caused the problem to the standard error stream. If there are more than 20 such errors, pcregrep gives up.

    The --match-limit option of pcregrep can be used to set the overall resource limit; there is a second option called --recursion-limit that sets a limit on the amount of memory (usually stack) that is used (see the discussion of these options above).


    DIAGNOSTICS

    Exit status is 0 if any matches were found, 1 if no matches were found, and 2 for syntax errors, overlong lines, non-existent or inaccessible files (even if matches were found in other files) or too many matching errors. Using the -s option to suppress error messages about inaccessible files does not affect the return code.


    SEE ALSO

    pcrepattern(3), pcresyntax(3), pcretest(1).


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 03 April 2014
    Copyright © 1997-2014 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrejit.html ================================================ pcrejit specification

    pcrejit man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    PCRE JUST-IN-TIME COMPILER SUPPORT

    Just-in-time compiling is a heavyweight optimization that can greatly speed up pattern matching. However, it comes at the cost of extra processing before the match is performed. Therefore, it is of most benefit when the same pattern is going to be matched many times. This does not necessarily mean many calls of a matching function; if the pattern is not anchored, matching attempts may take place many times at various positions in the subject, even for a single call. Therefore, if the subject string is very long, it may still pay to use JIT for one-off matches.

    JIT support applies only to the traditional Perl-compatible matching function. It does not apply when the DFA matching function is being used. The code for this support was written by Zoltan Herczeg.


    8-BIT, 16-BIT AND 32-BIT SUPPORT

    JIT support is available for all of the 8-bit, 16-bit and 32-bit PCRE libraries. To keep this documentation simple, only the 8-bit interface is described in what follows. If you are using the 16-bit library, substitute the 16-bit functions and 16-bit structures (for example, pcre16_jit_stack instead of pcre_jit_stack). If you are using the 32-bit library, substitute the 32-bit functions and 32-bit structures (for example, pcre32_jit_stack instead of pcre_jit_stack).


    AVAILABILITY OF JIT SUPPORT

    JIT support is an optional feature of PCRE. The "configure" option --enable-jit (or equivalent CMake option) must be set when PCRE is built if you want to use JIT. The support is limited to the following hardware platforms:

      ARM v5, v7, and Thumb2
      Intel x86 32-bit and 64-bit
      MIPS 32-bit
      Power PC 32-bit and 64-bit
      SPARC 32-bit (experimental)
    
    If --enable-jit is set on an unsupported platform, compilation fails.

    A program that is linked with PCRE 8.20 or later can tell if JIT support is available by calling pcre_config() with the PCRE_CONFIG_JIT option. The result is 1 when JIT is available, and 0 otherwise. However, a simple program does not need to check this in order to use JIT. The normal API is implemented in a way that falls back to the interpretive code if JIT is not available. For programs that need the best possible performance, there is also a "fast path" API that is JIT-specific.

    If your program may sometimes be linked with versions of PCRE that are older than 8.20, but you want to use JIT when it is available, you can test the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such as PCRE_CONFIG_JIT, for compile-time control of your code. Also beware that the pcre_jit_exec() function was not available at all before 8.32, and may not be available at all if PCRE isn't compiled with --enable-jit. See the "JIT FAST PATH API" section below for details.


    SIMPLE USE OF JIT

    You have to do two things to make use of the JIT support in the simplest way:

      (1) Call pcre_study() with the PCRE_STUDY_JIT_COMPILE option for
          each compiled pattern, and pass the resulting pcre_extra block to
          pcre_exec().
    
      (2) Use pcre_free_study() to free the pcre_extra block when it is
          no longer needed, instead of just freeing it yourself. This ensures that
          any JIT data is also freed.
    
    For a program that may be linked with pre-8.20 versions of PCRE, you can insert
      #ifndef PCRE_STUDY_JIT_COMPILE
      #define PCRE_STUDY_JIT_COMPILE 0
      #endif
    
    so that no option is passed to pcre_study(), and then use something like this to free the study data:
      #ifdef PCRE_CONFIG_JIT
          pcre_free_study(study_ptr);
      #else
          pcre_free(study_ptr);
      #endif
    
    PCRE_STUDY_JIT_COMPILE requests the JIT compiler to generate code for complete matches. If you want to run partial matches using the PCRE_PARTIAL_HARD or PCRE_PARTIAL_SOFT options of pcre_exec(), you should set one or both of the following options in addition to, or instead of, PCRE_STUDY_JIT_COMPILE when you call pcre_study():
      PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
      PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
    
    If using pcre_jit_exec() and supporting a pre-8.32 version of PCRE, you can insert:
       #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
       pcre_jit_exec(...);
       #else
       pcre_exec(...)
       #endif
    
    but as described in the "JIT FAST PATH API" section below this assumes version 8.32 and later are compiled with --enable-jit, which may break.

    The JIT compiler generates different optimized code for each of the three modes (normal, soft partial, hard partial). When pcre_exec() is called, the appropriate code is run if it is available. Otherwise, the pattern is matched using interpretive code.

    In some circumstances you may need to call additional functions. These are described in the section entitled "Controlling the JIT stack" below.

    If JIT support is not available, PCRE_STUDY_JIT_COMPILE etc. are ignored, and no JIT data is created. Otherwise, the compiled pattern is passed to the JIT compiler, which turns it into machine code that executes much faster than the normal interpretive code. When pcre_exec() is passed a pcre_extra block containing a pointer to JIT code of the appropriate mode (normal or hard/soft partial), it obeys that code instead of running the interpreter. The result is identical, but the compiled JIT code runs much faster.

    There are some pcre_exec() options that are not supported for JIT execution. There are also some pattern items that JIT cannot handle. Details are given below. In both cases, execution automatically falls back to the interpretive code. If you want to know whether JIT was actually used for a particular match, you should arrange for a JIT callback function to be set up as described in the section entitled "Controlling the JIT stack" below, even if you do not need to supply a non-default JIT stack. Such a callback function is called whenever JIT code is about to be obeyed. If the execution options are not right for JIT execution, the callback function is not obeyed.

    If the JIT compiler finds an unsupported item, no JIT data is generated. You can find out if JIT execution is available after studying a pattern by calling pcre_fullinfo() with the PCRE_INFO_JIT option. A result of 1 means that JIT compilation was successful. A result of 0 means that JIT support is not available, or the pattern was not studied with PCRE_STUDY_JIT_COMPILE etc., or the JIT compiler was not able to handle the pattern.

    Once a pattern has been studied, with or without JIT, it can be used as many times as you like for matching different subject strings.


    UNSUPPORTED OPTIONS AND PATTERN ITEMS

    The only pcre_exec() options that are supported for JIT execution are PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK, PCRE_NO_UTF32_CHECK, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT.

    The only unsupported pattern items are \C (match a single data unit) when running in a UTF mode, and a callout immediately before an assertion condition in a conditional group.


    RETURN VALUES FROM JIT EXECUTION

    When a pattern is matched using JIT execution, the return values are the same as those given by the interpretive pcre_exec() code, with the addition of one new error code: PCRE_ERROR_JIT_STACKLIMIT. This means that the memory used for the JIT stack was insufficient. See "Controlling the JIT stack" below for a discussion of JIT stack usage. For compatibility with the interpretive pcre_exec() code, no more than two-thirds of the ovector argument is used for passing back captured substrings.

    The error code PCRE_ERROR_MATCHLIMIT is returned by the JIT code if searching a very large pattern tree goes on for too long, as it is in the same circumstance when JIT is not used, but the details of exactly what is counted are not the same. The PCRE_ERROR_RECURSIONLIMIT error code is never returned by JIT execution.


    SAVING AND RESTORING COMPILED PATTERNS

    The code that is generated by the JIT compiler is architecture-specific, and is also position dependent. For those reasons it cannot be saved (in a file or database) and restored later like the bytecode and other data of a compiled pattern. Saving and restoring compiled patterns is not something many people do. More detail about this facility is given in the pcreprecompile documentation. It should be possible to run pcre_study() on a saved and restored pattern, and thereby recreate the JIT data, but because JIT compilation uses significant resources, it is probably not worth doing this; you might as well recompile the original pattern.


    CONTROLLING THE JIT STACK

    When the compiled JIT code runs, it needs a block of memory to use as a stack. By default, it uses 32K on the machine stack. However, some large or complicated patterns need more than this. The error PCRE_ERROR_JIT_STACKLIMIT is given when there is not enough stack. Three functions are provided for managing blocks of memory for use as JIT stacks. There is further discussion about the use of JIT stacks in the section entitled "JIT stack FAQ" below.

    The pcre_jit_stack_alloc() function creates a JIT stack. Its arguments are a starting size and a maximum size, and it returns a pointer to an opaque structure of type pcre_jit_stack, or NULL if there is an error. The pcre_jit_stack_free() function can be used to free a stack that is no longer needed. (For the technically minded: the address space is allocated by mmap or VirtualAlloc.)

    JIT uses far less memory for recursion than the interpretive code, and a maximum stack size of 512K to 1M should be more than enough for any pattern.

    The pcre_assign_jit_stack() function specifies which stack JIT code should use. Its arguments are as follows:

      pcre_extra         *extra
      pcre_jit_callback  callback
      void               *data
    
    The extra argument must be the result of studying a pattern with PCRE_STUDY_JIT_COMPILE etc. There are three cases for the values of the other two options:
      (1) If callback is NULL and data is NULL, an internal 32K block
          on the machine stack is used.
    
      (2) If callback is NULL and data is not NULL, data must be
          a valid JIT stack, the result of calling pcre_jit_stack_alloc().
    
      (3) If callback is not NULL, it must point to a function that is
          called with data as an argument at the start of matching, in
          order to set up a JIT stack. If the return from the callback
          function is NULL, the internal 32K stack is used; otherwise the
          return value must be a valid JIT stack, the result of calling
          pcre_jit_stack_alloc().
    
    A callback function is obeyed whenever JIT code is about to be run; it is not obeyed when pcre_exec() is called with options that are incompatible for JIT execution. A callback function can therefore be used to determine whether a match operation was executed by JIT or by the interpreter.

    You may safely use the same JIT stack for more than one pattern (either by assigning directly or by callback), as long as the patterns are all matched sequentially in the same thread. In a multithread application, if you do not specify a JIT stack, or if you assign or pass back NULL from a callback, that is thread-safe, because each thread has its own machine stack. However, if you assign or pass back a non-NULL JIT stack, this must be a different stack for each thread so that the application is thread-safe.

    Strictly speaking, even more is allowed. You can assign the same non-NULL stack to any number of patterns as long as they are not used for matching by multiple threads at the same time. For example, you can assign the same stack to all compiled patterns, and use a global mutex in the callback to wait until the stack is available for use. However, this is an inefficient solution, and not recommended.

    This is a suggestion for how a multithreaded program that needs to set up non-default JIT stacks might operate:

      During thread initalization
        thread_local_var = pcre_jit_stack_alloc(...)
    
      During thread exit
        pcre_jit_stack_free(thread_local_var)
    
      Use a one-line callback function
        return thread_local_var
    
    All the functions described in this section do nothing if JIT is not available, and pcre_assign_jit_stack() does nothing unless the extra argument is non-NULL and points to a pcre_extra block that is the result of a successful study with PCRE_STUDY_JIT_COMPILE etc.


    JIT STACK FAQ

    (1) Why do we need JIT stacks?

    PCRE (and JIT) is a recursive, depth-first engine, so it needs a stack where the local data of the current node is pushed before checking its child nodes. Allocating real machine stack on some platforms is difficult. For example, the stack chain needs to be updated every time if we extend the stack on PowerPC. Although it is possible, its updating time overhead decreases performance. So we do the recursion in memory.

    (2) Why don't we simply allocate blocks of memory with malloc()?

    Modern operating systems have a nice feature: they can reserve an address space instead of allocating memory. We can safely allocate memory pages inside this address space, so the stack could grow without moving memory data (this is important because of pointers). Thus we can allocate 1M address space, and use only a single memory page (usually 4K) if that is enough. However, we can still grow up to 1M anytime if needed.

    (3) Who "owns" a JIT stack?

    The owner of the stack is the user program, not the JIT studied pattern or anything else. The user program must ensure that if a stack is used by pcre_exec(), (that is, it is assigned to the pattern currently running), that stack must not be used by any other threads (to avoid overwriting the same memory area). The best practice for multithreaded programs is to allocate a stack for each thread, and return this stack through the JIT callback function.

    (4) When should a JIT stack be freed?

    You can free a JIT stack at any time, as long as it will not be used by pcre_exec() again. When you assign the stack to a pattern, only a pointer is set. There is no reference counting or any other magic. You can free the patterns and stacks in any order, anytime. Just do not call pcre_exec() with a pattern pointing to an already freed stack, as that will cause SEGFAULT. (Also, do not free a stack currently used by pcre_exec() in another thread). You can also replace the stack for a pattern at any time. You can even free the previous stack before assigning a replacement.

    (5) Should I allocate/free a stack every time before/after calling pcre_exec()?

    No, because this is too costly in terms of resources. However, you could implement some clever idea which release the stack if it is not used in let's say two minutes. The JIT callback can help to achieve this without keeping a list of the currently JIT studied patterns.

    (6) OK, the stack is for long term memory allocation. But what happens if a pattern causes stack overflow with a stack of 1M? Is that 1M kept until the stack is freed?

    Especially on embedded sytems, it might be a good idea to release memory sometimes without freeing the stack. There is no API for this at the moment. Probably a function call which returns with the currently allocated memory for any stack and another which allows releasing memory (shrinking the stack) would be a good idea if someone needs this.

    (7) This is too much of a headache. Isn't there any better solution for JIT stack handling?

    No, thanks to Windows. If POSIX threads were used everywhere, we could throw out this complicated API.


    EXAMPLE CODE

    This is a single-threaded example that specifies a JIT stack without using a callback.

      int rc;
      int ovector[30];
      pcre *re;
      pcre_extra *extra;
      pcre_jit_stack *jit_stack;
    
      re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
      /* Check for errors */
      extra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, &error);
      jit_stack = pcre_jit_stack_alloc(32*1024, 512*1024);
      /* Check for error (NULL) */
      pcre_assign_jit_stack(extra, NULL, jit_stack);
      rc = pcre_exec(re, extra, subject, length, 0, 0, ovector, 30);
      /* Check results */
      pcre_free(re);
      pcre_free_study(extra);
      pcre_jit_stack_free(jit_stack);
    
    


    JIT FAST PATH API

    Because the API described above falls back to interpreted execution when JIT is not available, it is convenient for programs that are written for general use in many environments. However, calling JIT via pcre_exec() does have a performance impact. Programs that are written for use where JIT is known to be available, and which need the best possible performance, can instead use a "fast path" API to call JIT execution directly instead of calling pcre_exec() (obviously only for patterns that have been successfully studied by JIT).

    The fast path function is called pcre_jit_exec(), and it takes exactly the same arguments as pcre_exec(), plus one additional argument that must point to a JIT stack. The JIT stack arrangements described above do not apply. The return values are the same as for pcre_exec().

    When you call pcre_exec(), as well as testing for invalid options, a number of other sanity checks are performed on the arguments. For example, if the subject pointer is NULL, or its length is negative, an immediate error is given. Also, unless PCRE_NO_UTF[8|16|32] is set, a UTF subject string is tested for validity. In the interests of speed, these checks do not happen on the JIT fast path, and if invalid data is passed, the result is undefined.

    Bypassing the sanity checks and the pcre_exec() wrapping can give speedups of more than 10%.

    Note that the pcre_jit_exec() function is not available in versions of PCRE before 8.32 (released in November 2012). If you need to support versions that old you must either use the slower pcre_exec(), or switch between the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR.

    Due to an unfortunate implementation oversight, even in versions 8.32 and later there will be no pcre_jit_exec() stub function defined when PCRE is compiled with --disable-jit, which is the default, and there's no way to detect whether PCRE was compiled with --enable-jit via a macro.

    If you need to support versions older than 8.32, or versions that may not build with --enable-jit, you must either use the slower pcre_exec(), or switch between the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR.

    Switching between the two by checking the version assumes that all the versions being targeted are built with --enable-jit. To also support builds that may use --disable-jit either pcre_exec() must be used, or a compile-time check for JIT via pcre_config() (which assumes the runtime environment will be the same), or as the Git project decided to do, simply assume that pcre_jit_exec() is present in 8.32 or later unless a compile-time flag is provided, see the "grep: un-break building with PCRE >= 8.32 without --enable-jit" commit in git.git for an example of that.


    SEE ALSO

    pcreapi(3)


    AUTHOR

    Philip Hazel (FAQ by Zoltan Herczeg)
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 05 July 2017
    Copyright © 1997-2017 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrelimits.html ================================================ pcrelimits specification

    pcrelimits man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    SIZE AND OTHER LIMITATIONS

    There are some size limitations in PCRE but it is hoped that they will never in practice be relevant.

    The maximum length of a compiled pattern is approximately 64K data units (bytes for the 8-bit library, 16-bit units for the 16-bit library, and 32-bit units for the 32-bit library) if PCRE is compiled with the default internal linkage size, which is 2 bytes for the 8-bit and 16-bit libraries, and 4 bytes for the 32-bit library. If you want to process regular expressions that are truly enormous, you can compile PCRE with an internal linkage size of 3 or 4 (when building the 16-bit or 32-bit library, 3 is rounded up to 4). See the README file in the source distribution and the pcrebuild documentation for details. In these cases the limit is substantially larger. However, the speed of execution is slower.

    All values in repeating quantifiers must be less than 65536.

    There is no limit to the number of parenthesized subpatterns, but there can be no more than 65535 capturing subpatterns. There is, however, a limit to the depth of nesting of parenthesized subpatterns of all kinds. This is imposed in order to limit the amount of system stack used at compile time. The limit can be specified when PCRE is built; the default is 250.

    There is a limit to the number of forward references to subsequent subpatterns of around 200,000. Repeated forward references with fixed upper limits, for example, (?2){0,100} when subpattern number 2 is to the right, are included in the count. There is no limit to the number of backward references.

    The maximum length of name for a named subpattern is 32 characters, and the maximum number of named subpatterns is 10000.

    The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb is 255 for the 8-bit library and 65535 for the 16-bit and 32-bit libraries.

    The maximum length of a subject string is the largest positive number that an integer variable can hold. However, when using the traditional matching function, PCRE uses recursion to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of a subject string that can be processed by certain patterns. For a discussion of stack issues, see the pcrestack documentation.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 05 November 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrematching.html ================================================ pcrematching specification

    pcrematching man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    PCRE MATCHING ALGORITHMS

    This document describes the two different algorithms that are available in PCRE for matching a compiled regular expression against a given subject string. The "standard" algorithm is the one provided by the pcre_exec(), pcre16_exec() and pcre32_exec() functions. These work in the same as as Perl's matching function, and provide a Perl-compatible matching operation. The just-in-time (JIT) optimization that is described in the pcrejit documentation is compatible with these functions.

    An alternative algorithm is provided by the pcre_dfa_exec(), pcre16_dfa_exec() and pcre32_dfa_exec() functions; they operate in a different way, and are not Perl-compatible. This alternative has advantages and disadvantages compared with the standard algorithm, and these are described below.

    When there is only one possible way in which a given subject string can match a pattern, the two algorithms give the same answer. A difference arises, however, when there are multiple possibilities. For example, if the pattern

      ^<.*>
    
    is matched against the string
      <something> <something else> <something further>
    
    there are three possible answers. The standard algorithm finds only one of them, whereas the alternative algorithm finds all three.


    REGULAR EXPRESSIONS AS TREES

    The set of strings that are matched by a regular expression can be represented as a tree structure. An unlimited repetition in the pattern makes the tree of infinite size, but it is still a tree. Matching the pattern to a given subject string (from a given starting point) can be thought of as a search of the tree. There are two ways to search a tree: depth-first and breadth-first, and these correspond to the two matching algorithms provided by PCRE.


    THE STANDARD MATCHING ALGORITHM

    In the terminology of Jeffrey Friedl's book "Mastering Regular Expressions", the standard algorithm is an "NFA algorithm". It conducts a depth-first search of the pattern tree. That is, it proceeds along a single path through the tree, checking that the subject matches what is required. When there is a mismatch, the algorithm tries any alternatives at the current point, and if they all fail, it backs up to the previous branch point in the tree, and tries the next alternative branch at that level. This often involves backing up (moving to the left) in the subject string as well. The order in which repetition branches are tried is controlled by the greedy or ungreedy nature of the quantifier.

    If a leaf node is reached, a matching string has been found, and at that point the algorithm stops. Thus, if there is more than one possible match, this algorithm returns the first one that it finds. Whether this is the shortest, the longest, or some intermediate length depends on the way the greedy and ungreedy repetition quantifiers are specified in the pattern.

    Because it ends up with a single path through the tree, it is relatively straightforward for this algorithm to keep track of the substrings that are matched by portions of the pattern in parentheses. This provides support for capturing parentheses and back references.


    THE ALTERNATIVE MATCHING ALGORITHM

    This algorithm conducts a breadth-first search of the tree. Starting from the first matching point in the subject, it scans the subject string from left to right, once, character by character, and as it does this, it remembers all the paths through the tree that represent valid matches. In Friedl's terminology, this is a kind of "DFA algorithm", though it is not implemented as a traditional finite state machine (it keeps multiple states active simultaneously).

    Although the general principle of this matching algorithm is that it scans the subject string only once, without backtracking, there is one exception: when a lookaround assertion is encountered, the characters following or preceding the current point have to be independently inspected.

    The scan continues until either the end of the subject is reached, or there are no more unterminated paths. At this point, terminated paths represent the different matching possibilities (if there are none, the match has failed). Thus, if there is more than one possible match, this algorithm finds all of them, and in particular, it finds the longest. The matches are returned in decreasing order of length. There is an option to stop the algorithm after the first match (which is necessarily the shortest) is found.

    Note that all the matches that are found start at the same point in the subject. If the pattern

      cat(er(pillar)?)?
    
    is matched against the string "the caterpillar catchment", the result will be the three strings "caterpillar", "cater", and "cat" that start at the fifth character of the subject. The algorithm does not automatically move on to find matches that start at later positions.

    PCRE's "auto-possessification" optimization usually applies to character repeats at the end of a pattern (as well as internally). For example, the pattern "a\d+" is compiled as if it were "a\d++" because there is no point even considering the possibility of backtracking into the repeated digits. For DFA matching, this means that only one possible match is found. If you really do want multiple matches in such cases, either use an ungreedy repeat ("a\d+?") or set the PCRE_NO_AUTO_POSSESS option when compiling.

    There are a number of features of PCRE regular expressions that are not supported by the alternative matching algorithm. They are as follows:

    1. Because the algorithm finds all possible matches, the greedy or ungreedy nature of repetition quantifiers is not relevant. Greedy and ungreedy quantifiers are treated in exactly the same way. However, possessive quantifiers can make a difference when what follows could also match what is quantified, for example in a pattern like this:

      ^a++\w!
    
    This pattern matches "aaab!" but not "aaa!", which would be matched by a non-possessive quantifier. Similarly, if an atomic group is present, it is matched as if it were a standalone pattern at the current point, and the longest match is then "locked in" for the rest of the overall pattern.

    2. When dealing with multiple paths through the tree simultaneously, it is not straightforward to keep track of captured substrings for the different matching possibilities, and PCRE's implementation of this algorithm does not attempt to do this. This means that no captured substrings are available.

    3. Because no substrings are captured, back references within the pattern are not supported, and cause errors if encountered.

    4. For the same reason, conditional expressions that use a backreference as the condition or test for a specific group recursion are not supported.

    5. Because many paths through the tree may be active, the \K escape sequence, which resets the start of the match when encountered (but may be on some paths and not on others), is not supported. It causes an error if encountered.

    6. Callouts are supported, but the value of the capture_top field is always 1, and the value of the capture_last field is always -1.

    7. The \C escape sequence, which (in the standard algorithm) always matches a single data unit, even in UTF-8, UTF-16 or UTF-32 modes, is not supported in these modes, because the alternative algorithm moves through the subject string one character (not data unit) at a time, for all active paths through the tree.

    8. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not supported. (*FAIL) is supported, and behaves like a failing negative assertion.


    ADVANTAGES OF THE ALTERNATIVE ALGORITHM

    Using the alternative matching algorithm provides the following advantages:

    1. All possible matches (at a single point in the subject) are automatically found, and in particular, the longest match is found. To find more than one match using the standard algorithm, you have to do kludgy things with callouts.

    2. Because the alternative algorithm scans the subject string just once, and never needs to backtrack (except for lookbehinds), it is possible to pass very long subject strings to the matching function in several pieces, checking for partial matching each time. Although it is possible to do multi-segment matching using the standard algorithm by retaining partially matched substrings, it is more complicated. The pcrepartial documentation gives details of partial matching and discusses multi-segment matching.


    DISADVANTAGES OF THE ALTERNATIVE ALGORITHM

    The alternative algorithm suffers from a number of disadvantages:

    1. It is substantially slower than the standard algorithm. This is partly because it has to search for all possible matches, but is also because it is less susceptible to optimization.

    2. Capturing parentheses and back references are not supported.

    3. Although atomic groups are supported, their use does not provide the performance advantage that it does for the standard algorithm.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 12 November 2013
    Copyright © 1997-2012 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrepartial.html ================================================ pcrepartial specification

    pcrepartial man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    PARTIAL MATCHING IN PCRE

    In normal use of PCRE, if the subject string that is passed to a matching function matches as far as it goes, but is too short to match the entire pattern, PCRE_ERROR_NOMATCH is returned. There are circumstances where it might be helpful to distinguish this case from other cases in which there is no match.

    Consider, for example, an application where a human is required to type in data for a field with specific formatting requirements. An example might be a date in the form ddmmmyy, defined by this pattern:

      ^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$
    
    If the application sees the user's keystrokes one by one, and can check that what has been typed so far is potentially valid, it is able to raise an error as soon as a mistake is made, by beeping and not reflecting the character that has been typed, for example. This immediate feedback is likely to be a better user interface than a check that is delayed until the entire string has been entered. Partial matching can also be useful when the subject string is very long and is not all available at once.

    PCRE supports partial matching by means of the PCRE_PARTIAL_SOFT and PCRE_PARTIAL_HARD options, which can be set when calling any of the matching functions. For backwards compatibility, PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. The essential difference between the two options is whether or not a partial match is preferred to an alternative complete match, though the details differ between the two types of matching function. If both options are set, PCRE_PARTIAL_HARD takes precedence.

    If you want to use partial matching with just-in-time optimized code, you must call pcre_study(), pcre16_study() or pcre32_study() with one or both of these options:

      PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
      PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE
    
    PCRE_STUDY_JIT_COMPILE should also be set if you are going to run non-partial matches on the same pattern. If the appropriate JIT study mode has not been set for a match, the interpretive matching code is used.

    Setting a partial matching option disables two of PCRE's standard optimizations. PCRE remembers the last literal data unit in a pattern, and abandons matching immediately if it is not present in the subject string. This optimization cannot be used for a subject string that might match only partially. If the pattern was studied, PCRE knows the minimum length of a matching string, and does not bother to run the matching function on shorter strings. This optimization is also disabled for partial matching.


    PARTIAL MATCHING USING pcre_exec() OR pcre[16|32]_exec()

    A partial match occurs during a call to pcre_exec() or pcre[16|32]_exec() when the end of the subject string is reached successfully, but matching cannot continue because more characters are needed. However, at least one character in the subject must have been inspected. This character need not form part of the final matched string; lookbehind assertions and the \K escape sequence provide ways of inspecting characters before the start of a matched substring. The requirement for inspecting at least one character exists because an empty string can always be matched; without such a restriction there would always be a partial match of an empty string at the end of the subject.

    If there are at least two slots in the offsets vector when a partial match is returned, the first slot is set to the offset of the earliest character that was inspected. For convenience, the second offset points to the end of the subject so that a substring can easily be identified. If there are at least three slots in the offsets vector, the third slot is set to the offset of the character where matching started.

    For the majority of patterns, the contents of the first and third slots will be the same. However, for patterns that contain lookbehind assertions, or begin with \b or \B, characters before the one where matching started may have been inspected while carrying out the match. For example, consider this pattern:

      /(?<=abc)123/
    
    This pattern matches "123", but only if it is preceded by "abc". If the subject string is "xyzabc12", the first two offsets after a partial match are for the substring "abc12", because all these characters were inspected. However, the third offset is set to 6, because that is the offset where matching began.

    What happens when a partial match is identified depends on which of the two partial matching options are set.


    PCRE_PARTIAL_SOFT WITH pcre_exec() OR pcre[16|32]_exec()

    If PCRE_PARTIAL_SOFT is set when pcre_exec() or pcre[16|32]_exec() identifies a partial match, the partial match is remembered, but matching continues as normal, and other alternatives in the pattern are tried. If no complete match can be found, PCRE_ERROR_PARTIAL is returned instead of PCRE_ERROR_NOMATCH.

    This option is "soft" because it prefers a complete match over a partial match. All the various matching items in a pattern behave as if the subject string is potentially complete. For example, \z, \Z, and $ match at the end of the subject, as normal, and for \b and \B the end of the subject is treated as a non-alphanumeric.

    If there is more than one partial match, the first one that was found provides the data that is returned. Consider this pattern:

      /123\w+X|dogY/
    
    If this is matched against the subject string "abc123dog", both alternatives fail to match, but the end of the subject is reached during matching, so PCRE_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying "123dog" as the first partial match that was found. (In this example, there are two partial matches, because "dog" on its own partially matches the second alternative.)


    PCRE_PARTIAL_HARD WITH pcre_exec() OR pcre[16|32]_exec()

    If PCRE_PARTIAL_HARD is set for pcre_exec() or pcre[16|32]_exec(), PCRE_ERROR_PARTIAL is returned as soon as a partial match is found, without continuing to search for possible complete matches. This option is "hard" because it prefers an earlier partial match over a later complete match. For this reason, the assumption is made that the end of the supplied subject string may not be the true end of the available data, and so, if \z, \Z, \b, \B, or $ are encountered at the end of the subject, the result is PCRE_ERROR_PARTIAL, provided that at least one character in the subject has been inspected.

    Setting PCRE_PARTIAL_HARD also affects the way UTF-8 and UTF-16 subject strings are checked for validity. Normally, an invalid sequence causes the error PCRE_ERROR_BADUTF8 or PCRE_ERROR_BADUTF16. However, in the special case of a truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8 or PCRE_ERROR_SHORTUTF16 is returned when PCRE_PARTIAL_HARD is set.


    Comparing hard and soft partial matching

    The difference between the two partial matching options can be illustrated by a pattern such as:

      /dog(sbody)?/
    
    This matches either "dog" or "dogsbody", greedily (that is, it prefers the longer string if possible). If it is matched against the string "dog" with PCRE_PARTIAL_SOFT, it yields a complete match for "dog". However, if PCRE_PARTIAL_HARD is set, the result is PCRE_ERROR_PARTIAL. On the other hand, if the pattern is made ungreedy the result is different:
      /dog(sbody)??/
    
    In this case the result is always a complete match because that is found first, and matching never continues after finding a complete match. It might be easier to follow this explanation by thinking of the two patterns like this:
      /dog(sbody)?/    is the same as  /dogsbody|dog/
      /dog(sbody)??/   is the same as  /dog|dogsbody/
    
    The second pattern will never match "dogsbody", because it will always find the shorter match first.


    PARTIAL MATCHING USING pcre_dfa_exec() OR pcre[16|32]_dfa_exec()

    The DFA functions move along the subject string character by character, without backtracking, searching for all possible matches simultaneously. If the end of the subject is reached before the end of the pattern, there is the possibility of a partial match, again provided that at least one character has been inspected.

    When PCRE_PARTIAL_SOFT is set, PCRE_ERROR_PARTIAL is returned only if there have been no complete matches. Otherwise, the complete matches are returned. However, if PCRE_PARTIAL_HARD is set, a partial match takes precedence over any complete matches. The portion of the string that was inspected when the longest partial match was found is set as the first matching string, provided there are at least two slots in the offsets vector.

    Because the DFA functions always search for all possible matches, and there is no difference between greedy and ungreedy repetition, their behaviour is different from the standard functions when PCRE_PARTIAL_HARD is set. Consider the string "dog" matched against the ungreedy pattern shown above:

      /dog(sbody)??/
    
    Whereas the standard functions stop as soon as they find the complete match for "dog", the DFA functions also find the partial match for "dogsbody", and so return that when PCRE_PARTIAL_HARD is set.


    PARTIAL MATCHING AND WORD BOUNDARIES

    If a pattern ends with one of sequences \b or \B, which test for word boundaries, partial matching with PCRE_PARTIAL_SOFT can give counter-intuitive results. Consider this pattern:

      /\bcat\b/
    
    This matches "cat", provided there is a word boundary at either end. If the subject string is "the cat", the comparison of the final "t" with a following character cannot take place, so a partial match is found. However, normal matching carries on, and \b matches at the end of the subject when the last character is a letter, so a complete match is found. The result, therefore, is not PCRE_ERROR_PARTIAL. Using PCRE_PARTIAL_HARD in this case does yield PCRE_ERROR_PARTIAL, because then the partial match takes precedence.


    FORMERLY RESTRICTED PATTERNS

    For releases of PCRE prior to 8.00, because of the way certain internal optimizations were implemented in the pcre_exec() function, the PCRE_PARTIAL option (predecessor of PCRE_PARTIAL_SOFT) could not be used with all patterns. From release 8.00 onwards, the restrictions no longer apply, and partial matching with can be requested for any pattern.

    Items that were formerly restricted were repeated single characters and repeated metasequences. If PCRE_PARTIAL was set for a pattern that did not conform to the restrictions, pcre_exec() returned the error code PCRE_ERROR_BADPARTIAL (-13). This error code is no longer in use. The PCRE_INFO_OKPARTIAL call to pcre_fullinfo() to find out if a compiled pattern can be used for partial matching now always returns 1.


    EXAMPLE OF PARTIAL MATCHING USING PCRETEST

    If the escape sequence \P is present in a pcretest data line, the PCRE_PARTIAL_SOFT option is used for the match. Here is a run of pcretest that uses the date example quoted above:

        re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
      data> 25jun04\P
       0: 25jun04
       1: jun
      data> 25dec3\P
      Partial match: 23dec3
      data> 3ju\P
      Partial match: 3ju
      data> 3juj\P
      No match
      data> j\P
      No match
    
    The first data string is matched completely, so pcretest shows the matched substrings. The remaining four strings do not match the complete pattern, but the first two are partial matches. Similar output is obtained if DFA matching is used.

    If the escape sequence \P is present more than once in a pcretest data line, the PCRE_PARTIAL_HARD option is set for the match.


    MULTI-SEGMENT MATCHING WITH pcre_dfa_exec() OR pcre[16|32]_dfa_exec()

    When a partial match has been found using a DFA matching function, it is possible to continue the match by providing additional subject data and calling the function again with the same compiled regular expression, this time setting the PCRE_DFA_RESTART option. You must pass the same working space as before, because this is where details of the previous partial match are stored. Here is an example using pcretest, using the \R escape sequence to set the PCRE_DFA_RESTART option (\D specifies the use of the DFA matching function):

        re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
      data> 23ja\P\D
      Partial match: 23ja
      data> n05\R\D
       0: n05
    
    The first call has "23ja" as the subject, and requests partial matching; the second call has "n05" as the subject for the continued (restarted) match. Notice that when the match is complete, only the last part is shown; PCRE does not retain the previously partially-matched string. It is up to the calling program to do that if it needs to.

    That means that, for an unanchored pattern, if a continued match fails, it is not possible to try again at a new starting point. All this facility is capable of doing is continuing with the previous match attempt. In the previous example, if the second set of data is "ug23" the result is no match, even though there would be a match for "aug23" if the entire string were given at once. Depending on the application, this may or may not be what you want. The only way to allow for starting again at the next character is to retain the matched part of the subject and try a new complete match.

    You can set the PCRE_PARTIAL_SOFT or PCRE_PARTIAL_HARD options with PCRE_DFA_RESTART to continue partial matching over multiple segments. This facility can be used to pass very long subject strings to the DFA matching functions.


    MULTI-SEGMENT MATCHING WITH pcre_exec() OR pcre[16|32]_exec()

    From release 8.00, the standard matching functions can also be used to do multi-segment matching. Unlike the DFA functions, it is not possible to restart the previous match with a new segment of data. Instead, new data must be added to the previous subject string, and the entire match re-run, starting from the point where the partial match occurred. Earlier data can be discarded.

    It is best to use PCRE_PARTIAL_HARD in this situation, because it does not treat the end of a segment as the end of the subject when matching \z, \Z, \b, \B, and $. Consider an unanchored pattern that matches dates:

        re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/
      data> The date is 23ja\P\P
      Partial match: 23ja
    
    At this stage, an application could discard the text preceding "23ja", add on text from the next segment, and call the matching function again. Unlike the DFA matching functions, the entire matching string must always be available, and the complete matching process occurs for each call, so more memory and more processing time is needed.

    Note: If the pattern contains lookbehind assertions, or \K, or starts with \b or \B, the string that is returned for a partial match includes characters that precede the start of what would be returned for a complete match, because it contains all the characters that were inspected during the partial match.


    ISSUES WITH MULTI-SEGMENT MATCHING

    Certain types of pattern may give problems with multi-segment matching, whichever matching function is used.

    1. If the pattern contains a test for the beginning of a line, you need to pass the PCRE_NOTBOL option when the subject string for any call does start at the beginning of a line. There is also a PCRE_NOTEOL option, but in practice when doing multi-segment matching you should be using PCRE_PARTIAL_HARD, which includes the effect of PCRE_NOTEOL.

    2. Lookbehind assertions that have already been obeyed are catered for in the offsets that are returned for a partial match. However a lookbehind assertion later in the pattern could require even earlier characters to be inspected. You can handle this case by using the PCRE_INFO_MAXLOOKBEHIND option of the pcre_fullinfo() or pcre[16|32]_fullinfo() functions to obtain the length of the longest lookbehind in the pattern. This length is given in characters, not bytes. If you always retain at least that many characters before the partially matched string, all should be well. (Of course, near the start of the subject, fewer characters may be present; in that case all characters should be retained.)

    From release 8.33, there is a more accurate way of deciding which characters to retain. Instead of subtracting the length of the longest lookbehind from the earliest inspected character (offsets[0]), the match start position (offsets[2]) should be used, and the next match attempt started at the offsets[2] character by setting the startoffset argument of pcre_exec() or pcre_dfa_exec().

    For example, if the pattern "(?<=123)abc" is partially matched against the string "xx123a", the three offset values returned are 2, 6, and 5. This indicates that the matching process that gave a partial match started at offset 5, but the characters "123a" were all inspected. The maximum lookbehind for that pattern is 3, so taking that away from 5 shows that we need only keep "123a", and the next match attempt can be started at offset 3 (that is, at "a") when further characters have been added. When the match start is not the earliest inspected character, pcretest shows it explicitly:

        re> "(?<=123)abc"
      data> xx123a\P\P
      Partial match at offset 5: 123a
    

    3. Because a partial match must always contain at least one character, what might be considered a partial match of an empty string actually gives a "no match" result. For example:

        re> /c(?<=abc)x/
      data> ab\P
      No match
    
    If the next segment begins "cx", a match should be found, but this will only happen if characters from the previous segment are retained. For this reason, a "no match" result should be interpreted as "partial match of an empty string" when the pattern contains lookbehinds.

    4. Matching a subject string that is split into multiple segments may not always produce exactly the same result as matching over one single long string, especially when PCRE_PARTIAL_SOFT is used. The section "Partial Matching and Word Boundaries" above describes an issue that arises if the pattern ends with \b or \B. Another kind of difference may occur when there are multiple matching possibilities, because (for PCRE_PARTIAL_SOFT) a partial match result is given only when there are no completed matches. This means that as soon as the shortest match has been found, continuation to a new subject segment is no longer possible. Consider again this pcretest example:

        re> /dog(sbody)?/
      data> dogsb\P
       0: dog
      data> do\P\D
      Partial match: do
      data> gsb\R\P\D
       0: g
      data> dogsbody\D
       0: dogsbody
       1: dog
    
    The first data line passes the string "dogsb" to a standard matching function, setting the PCRE_PARTIAL_SOFT option. Although the string is a partial match for "dogsbody", the result is not PCRE_ERROR_PARTIAL, because the shorter string "dog" is a complete match. Similarly, when the subject is presented to a DFA matching function in several parts ("do" and "gsb" being the first two) the match stops when "dog" has been found, and it is not possible to continue. On the other hand, if "dogsbody" is presented as a single string, a DFA matching function finds both matches.

    Because of these problems, it is best to use PCRE_PARTIAL_HARD when matching multi-segment data. The example above then behaves differently:

        re> /dog(sbody)?/
      data> dogsb\P\P
      Partial match: dogsb
      data> do\P\D
      Partial match: do
      data> gsb\R\P\P\D
      Partial match: gsb
    
    5. Patterns that contain alternatives at the top level which do not all start with the same pattern item may not work as expected when PCRE_DFA_RESTART is used. For example, consider this pattern:
      1234|3789
    
    If the first part of the subject is "ABC123", a partial match of the first alternative is found at offset 3. There is no partial match for the second alternative, because such a match does not start at the same point in the subject string. Attempting to continue with the string "7890" does not yield a match because only those alternatives that match at one point in the subject are remembered. The problem arises because the start of the second alternative matches within the first alternative. There is no problem with anchored patterns or patterns such as:
      1234|ABCD
    
    where no string can be a partial match for both alternatives. This is not a problem if a standard matching function is used, because the entire match has to be rerun each time:
        re> /1234|3789/
      data> ABC123\P\P
      Partial match: 123
      data> 1237890
       0: 3789
    
    Of course, instead of using PCRE_DFA_RESTART, the same technique of re-running the entire match can also be used with the DFA matching functions. Another possibility is to work with two buffers. If a partial match at offset n in the first buffer is followed by "no match" when PCRE_DFA_RESTART is used on the second buffer, you can then try a new match starting at offset n+1 in the first buffer.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 02 July 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrepattern.html ================================================ pcrepattern specification

    pcrepattern man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    PCRE REGULAR EXPRESSION DETAILS

    The syntax and semantics of the regular expressions that are supported by PCRE are described in detail below. There is a quick-reference syntax summary in the pcresyntax page. PCRE tries to match Perl syntax and semantics as closely as it can. PCRE also supports some alternative regular expression syntax (which does not conflict with the Perl syntax) in order to provide some compatibility with regular expressions in Python, .NET, and Oniguruma.

    Perl's regular expressions are described in its own documentation, and regular expressions in general are covered in a number of books, some of which have copious examples. Jeffrey Friedl's "Mastering Regular Expressions", published by O'Reilly, covers regular expressions in great detail. This description of PCRE's regular expressions is intended as reference material.

    This document discusses the patterns that are supported by PCRE when one its main matching functions, pcre_exec() (8-bit) or pcre[16|32]_exec() (16- or 32-bit), is used. PCRE also has alternative matching functions, pcre_dfa_exec() and pcre[16|32_dfa_exec(), which match using a different algorithm that is not Perl-compatible. Some of the features discussed below are not available when DFA matching is used. The advantages and disadvantages of the alternative functions, and how they differ from the normal functions, are discussed in the pcrematching page.


    SPECIAL START-OF-PATTERN ITEMS

    A number of options that can be passed to pcre_compile() can also be set by special items at the start of a pattern. These are not Perl-compatible, but are provided to make these options accessible to pattern writers who are not able to change the program that processes the pattern. Any number of these items may appear, but they must all be together right at the start of the pattern string, and the letters must be in upper case.


    UTF support

    The original operation of PCRE was on strings of one-byte characters. However, there is now also support for UTF-8 strings in the original library, an extra library that supports 16-bit and UTF-16 character strings, and a third library that supports 32-bit and UTF-32 character strings. To use these features, PCRE must be built to include appropriate support. When using UTF strings you must either call the compiling function with the PCRE_UTF8, PCRE_UTF16, or PCRE_UTF32 option, or the pattern must start with one of these special sequences:

      (*UTF8)
      (*UTF16)
      (*UTF32)
      (*UTF)
    
    (*UTF) is a generic sequence that can be used with any of the libraries. Starting a pattern with such a sequence is equivalent to setting the relevant option. How setting a UTF mode affects pattern matching is mentioned in several places below. There is also a summary of features in the pcreunicode page.

    Some applications that allow their users to supply patterns may wish to restrict them to non-UTF data for security reasons. If the PCRE_NEVER_UTF option is set at compile time, (*UTF) etc. are not allowed, and their appearance causes an error.


    Unicode property support

    Another special sequence that may appear at the start of a pattern is (*UCP). This has the same effect as setting the PCRE_UCP option: it causes sequences such as \d and \w to use Unicode properties to determine character types, instead of recognizing only characters with codes less than 128 via a lookup table.


    Disabling auto-possessification

    If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as setting the PCRE_NO_AUTO_POSSESS option at compile time. This stops PCRE from making quantifiers possessive when what follows cannot match the repeated item. For example, by default a+b is treated as a++b. For more details, see the pcreapi documentation.


    Disabling start-up optimizations

    If a pattern starts with (*NO_START_OPT), it has the same effect as setting the PCRE_NO_START_OPTIMIZE option either at compile or matching time. This disables several optimizations for quickly reaching "no match" results. For more details, see the pcreapi documentation.


    Newline conventions

    PCRE supports five different conventions for indicating line breaks in strings: a single CR (carriage return) character, a single LF (linefeed) character, the two-character sequence CRLF, any of the three preceding, or any Unicode newline sequence. The pcreapi page has further discussion about newlines, and shows how to set the newline convention in the options arguments for the compiling and matching functions.

    It is also possible to specify a newline convention by starting a pattern string with one of the following five sequences:

      (*CR)        carriage return
      (*LF)        linefeed
      (*CRLF)      carriage return, followed by linefeed
      (*ANYCRLF)   any of the three above
      (*ANY)       all Unicode newline sequences
    
    These override the default and the options given to the compiling function. For example, on a Unix system where LF is the default newline sequence, the pattern
      (*CR)a.b
    
    changes the convention to CR. That pattern matches "a\nb" because LF is no longer a newline. If more than one of these settings is present, the last one is used.

    The newline convention affects where the circumflex and dollar assertions are true. It also affects the interpretation of the dot metacharacter when PCRE_DOTALL is not set, and the behaviour of \N. However, it does not affect what the \R escape sequence matches. By default, this is any Unicode newline sequence, for Perl compatibility. However, this can be changed; see the description of \R in the section entitled "Newline sequences" below. A change of \R setting can be combined with a change of newline convention.


    Setting match and recursion limits

    The caller of pcre_exec() can set a limit on the number of times the internal match() function is called and on the maximum depth of recursive calls. These facilities are provided to catch runaway matches that are provoked by patterns with huge matching trees (a typical example is a pattern with nested unlimited repeats) and to avoid running out of system stack by too much recursion. When one of these limits is reached, pcre_exec() gives an error return. The limits can also be set by items at the start of the pattern of the form

      (*LIMIT_MATCH=d)
      (*LIMIT_RECURSION=d)
    
    where d is any number of decimal digits. However, the value of the setting must be less than the value set (or defaulted) by the caller of pcre_exec() for it to have any effect. In other words, the pattern writer can lower the limits set by the programmer, but not raise them. If there is more than one setting of one of these limits, the lower value is used.


    EBCDIC CHARACTER CODES

    PCRE can be compiled to run in an environment that uses EBCDIC as its character code rather than ASCII or Unicode (typically a mainframe system). In the sections below, character code values are ASCII or Unicode; in an EBCDIC environment these characters may have different code values, and there are no code points greater than 255.


    CHARACTERS AND METACHARACTERS

    A regular expression is a pattern that is matched against a subject string from left to right. Most characters stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern

      The quick brown fox
    
    matches a portion of a subject string that is identical to itself. When caseless matching is specified (the PCRE_CASELESS option), letters are matched independently of case. In a UTF mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF support.

    The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of metacharacters, which do not stand for themselves but instead are interpreted in some special way.

    There are two different sets of metacharacters: those that are recognized anywhere in the pattern except within square brackets, and those that are recognized within square brackets. Outside square brackets, the metacharacters are as follows:

      \      general escape character with several uses
      ^      assert start of string (or line, in multiline mode)
      $      assert end of string (or line, in multiline mode)
      .      match any character except newline (by default)
      [      start character class definition
      |      start of alternative branch
      (      start subpattern
      )      end subpattern
      ?      extends the meaning of (
             also 0 or 1 quantifier
             also quantifier minimizer
      *      0 or more quantifier
      +      1 or more quantifier
             also "possessive quantifier"
      {      start min/max quantifier
    
    Part of a pattern that is in square brackets is called a "character class". In a character class the only metacharacters are:
      \      general escape character
      ^      negate the class, but only if the first character
      -      indicates character range
      [      POSIX character class (only if followed by POSIX syntax)
      ]      terminates the character class
    
    The following sections describe the use of each of the metacharacters.


    BACKSLASH

    The backslash character has several uses. Firstly, if it is followed by a character that is not a number or a letter, it takes away any special meaning that character may have. This use of backslash as an escape character applies both inside and outside character classes.

    For example, if you want to match a * character, you write \* in the pattern. This escaping action applies whether or not the following character would otherwise be interpreted as a metacharacter, so it is always safe to precede a non-alphanumeric with backslash to specify that it stands for itself. In particular, if you want to match a backslash, you write \\.

    In a UTF mode, only ASCII numbers and letters have any special meaning after a backslash. All other characters (in particular, those whose codepoints are greater than 127) are treated as literals.

    If a pattern is compiled with the PCRE_EXTENDED option, most white space in the pattern (other than in a character class), and characters between a # outside a character class and the next newline, inclusive, are ignored. An escaping backslash can be used to include a white space or # character as part of the pattern.

    If you want to remove the special meaning from a sequence of characters, you can do so by putting them between \Q and \E. This is different from Perl in that $ and @ are handled as literals in \Q...\E sequences in PCRE, whereas in Perl, $ and @ cause variable interpolation. Note the following examples:

      Pattern            PCRE matches   Perl matches
    
      \Qabc$xyz\E        abc$xyz        abc followed by the contents of $xyz
      \Qabc\$xyz\E       abc\$xyz       abc\$xyz
      \Qabc\E\$\Qxyz\E   abc$xyz        abc$xyz
    
    The \Q...\E sequence is recognized both inside and outside character classes. An isolated \E that is not preceded by \Q is ignored. If \Q is not followed by \E later in the pattern, the literal interpretation continues to the end of the pattern (that is, \E is assumed at the end). If the isolated \Q is inside a character class, this causes an error, because the character class is not terminated.


    Non-printing characters

    A second use of backslash provides a way of encoding non-printing characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters, apart from the binary zero that terminates a pattern, but when a pattern is being prepared by text editing, it is often easier to use one of the following escape sequences than the binary character it represents. In an ASCII or Unicode environment, these escapes are as follows:

      \a        alarm, that is, the BEL character (hex 07)
      \cx       "control-x", where x is any ASCII character
      \e        escape (hex 1B)
      \f        form feed (hex 0C)
      \n        linefeed (hex 0A)
      \r        carriage return (hex 0D)
      \t        tab (hex 09)
      \0dd      character with octal code 0dd
      \ddd      character with octal code ddd, or back reference
      \o{ddd..} character with octal code ddd..
      \xhh      character with hex code hh
      \x{hhh..} character with hex code hhh.. (non-JavaScript mode)
      \uhhhh    character with hex code hhhh (JavaScript mode only)
    
    The precise effect of \cx on ASCII characters is as follows: if x is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus \cA to \cZ become hex 01 to hex 1A (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes hex 7B (; is 3B). If the data item (byte or 16-bit value) following \c has a value greater than 127, a compile-time error occurs. This locks out non-ASCII characters in all modes.

    When PCRE is compiled in EBCDIC mode, \a, \e, \f, \n, \r, and \t generate the appropriate EBCDIC code values. The \c escape is processed as specified for Perl in the perlebcdic document. The only characters that are allowed after \c are A-Z, a-z, or one of @, [, \, ], ^, _, or ?. Any other character provokes a compile-time error. The sequence \c@ encodes character code 0; after \c the letters (in either case) encode characters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters 27-31 (hex 1B to hex 1F), and \c? becomes either 255 (hex FF) or 95 (hex 5F).

    Thus, apart from \c?, these escapes generate the same character code values as they do in an ASCII environment, though the meanings of the values mostly differ. For example, \cG always generates code value 7, which is BEL in ASCII but DEL in EBCDIC.

    The sequence \c? generates DEL (127, hex 7F) in an ASCII environment, but because 127 is not a control character in EBCDIC, Perl makes it generate the APC character. Unfortunately, there are several variants of EBCDIC. In most of them the APC character has the value 255 (hex FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If certain other characters have POSIX-BC values, PCRE makes \c? generate 95; otherwise it generates 255.

    After \0 up to two further octal digits are read. If there are fewer than two digits, just those that are present are used. Thus the sequence \0\x\015 specifies two binary zeros followed by a CR character (code value 13). Make sure you supply two digits after the initial zero if the pattern character that follows is itself an octal digit.

    The escape \o must be followed by a sequence of octal digits, enclosed in braces. An error occurs if this is not the case. This escape is a recent addition to Perl; it provides way of specifying character code points as octal numbers greater than 0777, and it also allows octal numbers and back references to be unambiguously specified.

    For greater clarity and unambiguity, it is best to avoid following \ by a digit greater than zero. Instead, use \o{} or \x{} to specify character numbers, and \g{} to specify back references. The following paragraphs describe the old, ambiguous syntax.

    The handling of a backslash followed by a digit other than 0 is complicated, and Perl has changed in recent releases, causing PCRE also to change. Outside a character class, PCRE reads the digit and any following digits as a decimal number. If the number is less than 8, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a back reference. A description of how this works is given later, following the discussion of parenthesized subpatterns.

    Inside a character class, or if the decimal number following \ is greater than 7 and there have not been that many capturing subpatterns, PCRE handles \8 and \9 as the literal characters "8" and "9", and otherwise re-reads up to three octal digits following the backslash, using them to generate a data character. Any subsequent digits stand for themselves. For example:

      \040   is another way of writing an ASCII space
      \40    is the same, provided there are fewer than 40 previous capturing subpatterns
      \7     is always a back reference
      \11    might be a back reference, or another way of writing a tab
      \011   is always a tab
      \0113  is a tab followed by the character "3"
      \113   might be a back reference, otherwise the character with octal code 113
      \377   might be a back reference, otherwise the value 255 (decimal)
      \81    is either a back reference, or the two characters "8" and "1"
    
    Note that octal values of 100 or greater that are specified using this syntax must not be introduced by a leading zero, because no more than three octal digits are ever read.

    By default, after \x that is not followed by {, from zero to two hexadecimal digits are read (letters can be in upper or lower case). Any number of hexadecimal digits may appear between \x{ and }. If a character other than a hexadecimal digit appears between \x{ and }, or if there is no terminating }, an error occurs.

    If the PCRE_JAVASCRIPT_COMPAT option is set, the interpretation of \x is as just described only when it is followed by two hexadecimal digits. Otherwise, it matches a literal "x" character. In JavaScript mode, support for code points greater than 256 is provided by \u, which must be followed by four hexadecimal digits; otherwise it matches a literal "u" character.

    Characters whose value is less than 256 can be defined by either of the two syntaxes for \x (or by \u in JavaScript mode). There is no difference in the way they are handled. For example, \xdc is exactly the same as \x{dc} (or \u00dc in JavaScript mode).


    Constraints on character values

    Characters that are specified using octal or hexadecimal numbers are limited to certain values, as follows:

      8-bit non-UTF mode    less than 0x100
      8-bit UTF-8 mode      less than 0x10ffff and a valid codepoint
      16-bit non-UTF mode   less than 0x10000
      16-bit UTF-16 mode    less than 0x10ffff and a valid codepoint
      32-bit non-UTF mode   less than 0x100000000
      32-bit UTF-32 mode    less than 0x10ffff and a valid codepoint
    
    Invalid Unicode codepoints are the range 0xd800 to 0xdfff (the so-called "surrogate" codepoints), and 0xffef.


    Escape sequences in character classes

    All the sequences that define a single character value can be used both inside and outside character classes. In addition, inside a character class, \b is interpreted as the backspace character (hex 08).

    \N is not allowed in a character class. \B, \R, and \X are not special inside a character class. Like other unrecognized escape sequences, they are treated as the literal characters "B", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set. Outside a character class, these sequences have different meanings.


    Unsupported escape sequences

    In Perl, the sequences \l, \L, \u, and \U are recognized by its string handler and used to modify the case of following characters. By default, PCRE does not support these escape sequences. However, if the PCRE_JAVASCRIPT_COMPAT option is set, \U matches a "U" character, and \u can be used to define a character by code point, as described in the previous section.


    Absolute and relative back references

    The sequence \g followed by an unsigned or a negative number, optionally enclosed in braces, is an absolute or relative back reference. A named back reference can be coded as \g{name}. Back references are discussed later, following the discussion of parenthesized subpatterns.


    Absolute and relative subroutine calls

    For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative syntax for referencing a subpattern as a "subroutine". Details are discussed later. Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not synonymous. The former is a back reference; the latter is a subroutine call.


    Generic character types

    Another use of backslash is for specifying generic character types:

      \d     any decimal digit
      \D     any character that is not a decimal digit
      \h     any horizontal white space character
      \H     any character that is not a horizontal white space character
      \s     any white space character
      \S     any character that is not a white space character
      \v     any vertical white space character
      \V     any character that is not a vertical white space character
      \w     any "word" character
      \W     any "non-word" character
    
    There is also the single sequence \N, which matches a non-newline character. This is the same as the "." metacharacter when PCRE_DOTALL is not set. Perl also uses \N to match characters by name; PCRE does not support this.

    Each pair of lower and upper case escape sequences partitions the complete set of characters into two disjoint sets. Any given character matches one, and only one, of each pair. The sequences can appear both inside and outside character classes. They each match one character of the appropriate type. If the current matching point is at the end of the subject string, all of them fail, because there is no character to match.

    For compatibility with Perl, \s did not used to match the VT character (code 11), which made it different from the the POSIX "space" class. However, Perl added VT at release 5.18, and PCRE followed suit at release 8.34. The default \s characters are now HT (9), LF (10), VT (11), FF (12), CR (13), and space (32), which are defined as white space in the "C" locale. This list may vary if locale-specific matching is taking place. For example, in some locales the "non-breaking space" character (\xA0) is recognized as white space, and in others the VT character is not.

    A "word" character is an underscore or any character that is a letter or digit. By default, the definition of letters and digits is controlled by PCRE's low-valued character tables, and may vary if locale-specific matching is taking place (see "Locale support" in the pcreapi page). For example, in a French locale such as "fr_FR" in Unix-like systems, or "french" in Windows, some character codes greater than 127 are used for accented letters, and these are then matched by \w. The use of locales with Unicode is discouraged.

    By default, characters whose code points are greater than 127 never match \d, \s, or \w, and always match \D, \S, and \W, although this may vary for characters in the range 128-255 when locale-specific matching is happening. These escape sequences retain their original meanings from before Unicode support was available, mainly for efficiency reasons. If PCRE is compiled with Unicode property support, and the PCRE_UCP option is set, the behaviour is changed so that Unicode properties are used to determine character types, as follows:

      \d  any character that matches \p{Nd} (decimal digit)
      \s  any character that matches \p{Z} or \h or \v
      \w  any character that matches \p{L} or \p{N}, plus underscore
    
    The upper case escapes match the inverse sets of characters. Note that \d matches only decimal digits, whereas \w matches any Unicode digit, as well as any Unicode letter, and underscore. Note also that PCRE_UCP affects \b, and \B because they are defined in terms of \w and \W. Matching these sequences is noticeably slower when PCRE_UCP is set.

    The sequences \h, \H, \v, and \V are features that were added to Perl at release 5.10. In contrast to the other sequences, which match only ASCII characters by default, these always match certain high-valued code points, whether or not PCRE_UCP is set. The horizontal space characters are:

      U+0009     Horizontal tab (HT)
      U+0020     Space
      U+00A0     Non-break space
      U+1680     Ogham space mark
      U+180E     Mongolian vowel separator
      U+2000     En quad
      U+2001     Em quad
      U+2002     En space
      U+2003     Em space
      U+2004     Three-per-em space
      U+2005     Four-per-em space
      U+2006     Six-per-em space
      U+2007     Figure space
      U+2008     Punctuation space
      U+2009     Thin space
      U+200A     Hair space
      U+202F     Narrow no-break space
      U+205F     Medium mathematical space
      U+3000     Ideographic space
    
    The vertical space characters are:
      U+000A     Linefeed (LF)
      U+000B     Vertical tab (VT)
      U+000C     Form feed (FF)
      U+000D     Carriage return (CR)
      U+0085     Next line (NEL)
      U+2028     Line separator
      U+2029     Paragraph separator
    
    In 8-bit, non-UTF-8 mode, only the characters with codepoints less than 256 are relevant.


    Newline sequences

    Outside a character class, by default, the escape sequence \R matches any Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent to the following:

      (?>\r\n|\n|\x0b|\f|\r|\x85)
    
    This is an example of an "atomic group", details of which are given below. This particular group matches either the two-character sequence CR followed by LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (carriage return, U+000D), or NEL (next line, U+0085). The two-character sequence is treated as a single unit that cannot be split.

    In other modes, two additional characters whose codepoints are greater than 255 are added: LS (line separator, U+2028) and PS (paragraph separator, U+2029). Unicode character property support is not needed for these characters to be recognized.

    It is possible to restrict \R to match only CR, LF, or CRLF (instead of the complete set of Unicode line endings) by setting the option PCRE_BSR_ANYCRLF either at compile time or when the pattern is matched. (BSR is an abbrevation for "backslash R".) This can be made the default when PCRE is built; if this is the case, the other behaviour can be requested via the PCRE_BSR_UNICODE option. It is also possible to specify these settings by starting a pattern string with one of the following sequences:

      (*BSR_ANYCRLF)   CR, LF, or CRLF only
      (*BSR_UNICODE)   any Unicode newline sequence
    
    These override the default and the options given to the compiling function, but they can themselves be overridden by options given to a matching function. Note that these special settings, which are not Perl-compatible, are recognized only at the very start of a pattern, and that they must be in upper case. If more than one of them is present, the last one is used. They can be combined with a change of newline convention; for example, a pattern can start with:
      (*ANY)(*BSR_ANYCRLF)
    
    They can also be combined with the (*UTF8), (*UTF16), (*UTF32), (*UTF) or (*UCP) special sequences. Inside a character class, \R is treated as an unrecognized escape sequence, and so matches the letter "R" by default, but causes an error if PCRE_EXTRA is set.


    Unicode character properties

    When PCRE is built with Unicode character property support, three additional escape sequences that match characters with specific properties are available. When in 8-bit non-UTF-8 mode, these sequences are of course limited to testing characters whose codepoints are less than 256, but they do work in this mode. The extra escape sequences are:

      \p{xx}   a character with the xx property
      \P{xx}   a character without the xx property
      \X       a Unicode extended grapheme cluster
    
    The property names represented by xx above are limited to the Unicode script names, the general category properties, "Any", which matches any character (including newline), and some special PCRE properties (described in the next section). Other Perl properties such as "InMusicalSymbols" are not currently supported by PCRE. Note that \P{Any} does not match any characters, so always causes a match failure.

    Sets of Unicode characters are defined as belonging to certain scripts. A character from one of these sets can be matched using a script name. For example:

      \p{Greek}
      \P{Han}
    
    Those that are not part of an identified script are lumped together as "Common". The current list of scripts is:

    Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hieroglyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Shavian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi.

    Each character has exactly one Unicode general category property, specified by a two-letter abbreviation. For compatibility with Perl, negation can be specified by including a circumflex between the opening brace and the property name. For example, \p{^Lu} is the same as \P{Lu}.

    If only one letter is specified with \p or \P, it includes all the general category properties that start with that letter. In this case, in the absence of negation, the curly brackets in the escape sequence are optional; these two examples have the same effect:

      \p{L}
      \pL
    
    The following general category property codes are supported:
      C     Other
      Cc    Control
      Cf    Format
      Cn    Unassigned
      Co    Private use
      Cs    Surrogate
    
      L     Letter
      Ll    Lower case letter
      Lm    Modifier letter
      Lo    Other letter
      Lt    Title case letter
      Lu    Upper case letter
    
      M     Mark
      Mc    Spacing mark
      Me    Enclosing mark
      Mn    Non-spacing mark
    
      N     Number
      Nd    Decimal number
      Nl    Letter number
      No    Other number
    
      P     Punctuation
      Pc    Connector punctuation
      Pd    Dash punctuation
      Pe    Close punctuation
      Pf    Final punctuation
      Pi    Initial punctuation
      Po    Other punctuation
      Ps    Open punctuation
    
      S     Symbol
      Sc    Currency symbol
      Sk    Modifier symbol
      Sm    Mathematical symbol
      So    Other symbol
    
      Z     Separator
      Zl    Line separator
      Zp    Paragraph separator
      Zs    Space separator
    
    The special property L& is also supported: it matches a character that has the Lu, Ll, or Lt property, in other words, a letter that is not classified as a modifier or "other".

    The Cs (Surrogate) property applies only to characters in the range U+D800 to U+DFFF. Such characters are not valid in Unicode strings and so cannot be tested by PCRE, unless UTF validity checking has been turned off (see the discussion of PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK and PCRE_NO_UTF32_CHECK in the pcreapi page). Perl does not support the Cs property.

    The long synonyms for property names that Perl supports (such as \p{Letter}) are not supported by PCRE, nor is it permitted to prefix any of these properties with "Is".

    No character that is in the Unicode table has the Cn (unassigned) property. Instead, this property is assumed for any code point that is not in the Unicode table.

    Specifying caseless matching does not affect these escape sequences. For example, \p{Lu} always matches only upper case letters. This is different from the behaviour of current versions of Perl.

    Matching characters by Unicode property is not fast, because PCRE has to do a multistage table lookup in order to find a character's property. That is why the traditional escape sequences such as \d and \w do not use Unicode properties in PCRE by default, though you can make them do so by setting the PCRE_UCP option or by starting the pattern with (*UCP).


    Extended grapheme clusters

    The \X escape matches any number of Unicode characters that form an "extended grapheme cluster", and treats the sequence as an atomic group (see below). Up to and including release 8.31, PCRE matched an earlier, simpler definition that was equivalent to

      (?>\PM\pM*)
    
    That is, it matched a character without the "mark" property, followed by zero or more characters with the "mark" property. Characters with the "mark" property are typically non-spacing accents that affect the preceding character.

    This simple definition was extended in Unicode to include more complicated kinds of composite character by giving each character a grapheme breaking property, and creating rules that use these properties to define the boundaries of extended grapheme clusters. In releases of PCRE later than 8.31, \X matches one of these clusters.

    \X always matches at least one character. Then it decides whether to add additional characters according to the following rules for ending a cluster:

    1. End at the end of the subject string.

    2. Do not end between CR and LF; otherwise end after any control character.

    3. Do not break Hangul (a Korean script) syllable sequences. Hangul characters are of five types: L, V, T, LV, and LVT. An L character may be followed by an L, V, LV, or LVT character; an LV or V character may be followed by a V or T character; an LVT or T character may be follwed only by a T character.

    4. Do not end before extending characters or spacing marks. Characters with the "mark" property always have the "extend" grapheme breaking property.

    5. Do not end after prepend characters.

    6. Otherwise, end the cluster.


    PCRE's additional properties

    As well as the standard Unicode properties described above, PCRE supports four more that make it possible to convert traditional escape sequences such as \w and \s to use Unicode properties. PCRE uses these non-standard, non-Perl properties internally when PCRE_UCP is set. However, they may also be used explicitly. These properties are:

      Xan   Any alphanumeric character
      Xps   Any POSIX space character
      Xsp   Any Perl space character
      Xwd   Any Perl "word" character
    
    Xan matches characters that have either the L (letter) or the N (number) property. Xps matches the characters tab, linefeed, vertical tab, form feed, or carriage return, and any other character that has the Z (separator) property. Xsp is the same as Xps; it used to exclude vertical tab, for Perl compatibility, but Perl changed, and so PCRE followed at release 8.34. Xwd matches the same characters as Xan, plus underscore.

    There is another non-standard property, Xuc, which matches any character that can be represented by a Universal Character Name in C++ and other programming languages. These are the characters $, @, ` (grave accent), and all characters with Unicode code points greater than or equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that most base (ASCII) characters are excluded. (Universal Character Names are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit. Note that the Xuc property does not match these sequences but the characters that they represent.)


    Resetting the match start

    The escape sequence \K causes any previously matched characters not to be included in the final matched sequence. For example, the pattern:

      foo\Kbar
    
    matches "foobar", but reports that it has matched "bar". This feature is similar to a lookbehind assertion (described below). However, in this case, the part of the subject before the real match does not have to be of fixed length, as lookbehind assertions do. The use of \K does not interfere with the setting of captured substrings. For example, when the pattern
      (foo)\Kbar
    
    matches "foobar", the first substring is still set to "foo".

    Perl documents that the use of \K within assertions is "not well defined". In PCRE, \K is acted upon when it occurs inside positive assertions, but is ignored in negative assertions. Note that when a pattern such as (?=ab\K) matches, the reported start of the match can be greater than the end of the match.


    Simple assertions

    The final use of backslash is for certain simple assertions. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described below. The backslashed assertions are:

      \b     matches at a word boundary
      \B     matches when not at a word boundary
      \A     matches at the start of the subject
      \Z     matches at the end of the subject
              also matches before a newline at the end of the subject
      \z     matches only at the end of the subject
      \G     matches at the first matching position in the subject
    
    Inside a character class, \b has a different meaning; it matches the backspace character. If any other of these assertions appears in a character class, by default it matches the corresponding literal character (for example, \B matches the letter B). However, if the PCRE_EXTRA option is set, an "invalid escape sequence" error is generated instead.

    A word boundary is a position in the subject string where the current character and the previous character do not both match \w or \W (i.e. one matches \w and the other matches \W), or the start or end of the string if the first or last character matches \w, respectively. In a UTF mode, the meanings of \w and \W can be changed by setting the PCRE_UCP option. When this is done, it also affects \b and \B. Neither PCRE nor Perl has a separate "start of word" or "end of word" metasequence. However, whatever follows \b normally determines which it is. For example, the fragment \ba matches "a" at the start of a word.

    The \A, \Z, and \z assertions differ from the traditional circumflex and dollar (described in the next section) in that they only ever match at the very start and end of the subject string, whatever options are set. Thus, they are independent of multiline mode. These three assertions are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options, which affect only the behaviour of the circumflex and dollar metacharacters. However, if the startoffset argument of pcre_exec() is non-zero, indicating that matching is to start at a point other than the beginning of the subject, \A can never match. The difference between \Z and \z is that \Z matches before a newline at the end of the string as well as at the very end, whereas \z matches only at the end.

    The \G assertion is true only when the current matching position is at the start point of the match, as specified by the startoffset argument of pcre_exec(). It differs from \A when the value of startoffset is non-zero. By calling pcre_exec() multiple times with appropriate arguments, you can mimic Perl's /g option, and it is in this kind of implementation where \G can be useful.

    Note, however, that PCRE's interpretation of \G, as the start of the current match, is subtly different from Perl's, which defines it as the end of the previous match. In Perl, these can be different when the previously matched string was empty. Because PCRE does just one match at a time, it cannot reproduce this behaviour.

    If all the alternatives of a pattern begin with \G, the expression is anchored to the starting match position, and the "anchored" flag is set in the compiled regular expression.


    CIRCUMFLEX AND DOLLAR

    The circumflex and dollar metacharacters are zero-width assertions. That is, they test for a particular condition being true without consuming any characters from the subject string.

    Outside a character class, in the default matching mode, the circumflex character is an assertion that is true only if the current matching point is at the start of the subject string. If the startoffset argument of pcre_exec() is non-zero, circumflex can never match if the PCRE_MULTILINE option is unset. Inside a character class, circumflex has an entirely different meaning (see below).

    Circumflex need not be the first character of the pattern if a number of alternatives are involved, but it should be the first thing in each alternative in which it appears if the pattern is ever to match that branch. If all possible alternatives start with a circumflex, that is, if the pattern is constrained to match only at the start of the subject, it is said to be an "anchored" pattern. (There are also other constructs that can cause a pattern to be anchored.)

    The dollar character is an assertion that is true only if the current matching point is at the end of the subject string, or immediately before a newline at the end of the string (by default). Note, however, that it does not actually match the newline. Dollar need not be the last character of the pattern if a number of alternatives are involved, but it should be the last item in any branch in which it appears. Dollar has no special meaning in a character class.

    The meaning of dollar can be changed so that it matches only at the very end of the string, by setting the PCRE_DOLLAR_ENDONLY option at compile time. This does not affect the \Z assertion.

    The meanings of the circumflex and dollar characters are changed if the PCRE_MULTILINE option is set. When this is the case, a circumflex matches immediately after internal newlines as well as at the start of the subject string. It does not match after a newline that ends the string. A dollar matches before any newlines in the string, as well as at the very end, when PCRE_MULTILINE is set. When newline is specified as the two-character sequence CRLF, isolated CR and LF characters do not indicate newlines.

    For example, the pattern /^abc$/ matches the subject string "def\nabc" (where \n represents a newline) in multiline mode, but not otherwise. Consequently, patterns that are anchored in single line mode because all branches start with ^ are not anchored in multiline mode, and a match for circumflex is possible when the startoffset argument of pcre_exec() is non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set.

    Note that the sequences \A, \Z, and \z can be used to match the start and end of the subject in both modes, and if all branches of a pattern start with \A it is always anchored, whether or not PCRE_MULTILINE is set.


    FULL STOP (PERIOD, DOT) AND \N

    Outside a character class, a dot in the pattern matches any one character in the subject string except (by default) a character that signifies the end of a line.

    When a line ending is defined as a single character, dot never matches that character; when the two-character sequence CRLF is used, dot does not match CR if it is immediately followed by LF, but otherwise it matches all characters (including isolated CRs and LFs). When any Unicode line endings are being recognized, dot does not match CR or LF or any of the other line ending characters.

    The behaviour of dot with regard to newlines can be changed. If the PCRE_DOTALL option is set, a dot matches any one character, without exception. If the two-character sequence CRLF is present in the subject string, it takes two dots to match it.

    The handling of dot is entirely independent of the handling of circumflex and dollar, the only relationship being that they both involve newlines. Dot has no special meaning in a character class.

    The escape sequence \N behaves like a dot, except that it is not affected by the PCRE_DOTALL option. In other words, it matches any character except one that signifies the end of a line. Perl also uses \N to match characters by name; PCRE does not support this.


    MATCHING A SINGLE DATA UNIT

    Outside a character class, the escape sequence \C matches any one data unit, whether or not a UTF mode is set. In the 8-bit library, one data unit is one byte; in the 16-bit library it is a 16-bit unit; in the 32-bit library it is a 32-bit unit. Unlike a dot, \C always matches line-ending characters. The feature is provided in Perl in order to match individual bytes in UTF-8 mode, but it is unclear how it can usefully be used. Because \C breaks up characters into individual data units, matching one unit with \C in a UTF mode means that the rest of the string may start with a malformed UTF character. This has undefined results, because PCRE assumes that it is dealing with valid UTF strings (and by default it checks this at the start of processing unless the PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK or PCRE_NO_UTF32_CHECK option is used).

    PCRE does not allow \C to appear in lookbehind assertions (described below) in a UTF mode, because this would make it impossible to calculate the length of the lookbehind.

    In general, the \C escape sequence is best avoided. However, one way of using it that avoids the problem of malformed UTF characters is to use a lookahead to check the length of the next character, as in this pattern, which could be used with a UTF-8 string (ignore white space and line breaks):

      (?| (?=[\x00-\x7f])(\C) |
          (?=[\x80-\x{7ff}])(\C)(\C) |
          (?=[\x{800}-\x{ffff}])(\C)(\C)(\C) |
          (?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C))
    
    A group that starts with (?| resets the capturing parentheses numbers in each alternative (see "Duplicate Subpattern Numbers" below). The assertions at the start of each branch check the next UTF-8 character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The character's individual bytes are then captured by the appropriate number of groups.


    SQUARE BRACKETS AND CHARACTER CLASSES

    An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not special by default. However, if the PCRE_JAVASCRIPT_COMPAT option is set, a lone closing square bracket causes a compile-time error. If a closing square bracket is required as a member of the class, it should be the first data character in the class (after an initial circumflex, if present) or escaped with a backslash.

    A character class matches a single character in the subject. In a UTF mode, the character may be more than one data unit long. A matched character must be in the set of characters defined by the class, unless the first character in the class definition is a circumflex, in which case the subject character must not be in the set defined by the class. If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash.

    For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient notation for specifying the characters that are in the class by enumerating those that are not. A class that starts with a circumflex is not an assertion; it still consumes a character from the subject string, and therefore it fails if the current pointer is at the end of the string.

    In UTF-8 (UTF-16, UTF-32) mode, characters with values greater than 255 (0xffff) can be included in a class as a literal string of data units, or by using the \x{ escaping mechanism.

    When caseless matching is set, any letters in a class represent both their upper case and lower case versions, so for example, a caseless [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not match "A", whereas a caseful version would. In a UTF mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching in a UTF mode for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF support.

    Characters that might indicate line breaks are never treated in any special way when matching character classes, whatever line-ending sequence is in use, and whatever setting of the PCRE_DOTALL and PCRE_MULTILINE options is used. A class such as [^a] always matches one of these characters.

    The minus (hyphen) character can be used to specify a range of characters in a character class. For example, [d-m] matches any letter between d and m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last character in the class, or immediately after a range. For example, [b-d-z] matches letters in the range b to d, a hyphen character, or z.

    It is not possible to have the literal character "]" as the end character of a range. A pattern such as [W-]46] is interpreted as a class of two characters ("W" and "-") followed by a literal string "46]", so it would match "W46]" or "-46]". However, if the "]" is escaped with a backslash it is interpreted as the end of range, so [W-\]46] is interpreted as a class containing a range followed by two other characters. The octal or hexadecimal representation of "]" can also be used to end a range.

    An error is generated if a POSIX character class (see below) or an escape sequence other than one that defines a single character appears at a point where a range ending character is expected. For example, [z-\xff] is valid, but [A-\d] and [A-[:digit:]] are not.

    Ranges operate in the collating sequence of character values. They can also be used for characters specified numerically, for example [\000-\037]. Ranges can include any characters that are valid for the current mode.

    If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, [W-c] is equivalent to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if character tables for a French locale are in use, [\xc8-\xcb] matches accented E characters in both cases. In UTF modes, PCRE supports the concept of case for characters with values greater than 128 only when it is compiled with Unicode property support.

    The character escape sequences \d, \D, \h, \H, \p, \P, \s, \S, \v, \V, \w, and \W may appear in a character class, and add the characters that they match to the class. For example, [\dABCDEF] matches any hexadecimal digit. In UTF modes, the PCRE_UCP option affects the meanings of \d, \s, \w and their upper case partners, just as it does when they appear outside a character class, as described in the section entitled "Generic character types" above. The escape sequence \b has a different meaning inside a character class; it matches the backspace character. The sequences \B, \N, \R, and \X are not special inside a character class. Like any other unrecognized escape sequences, they are treated as the literal characters "B", "N", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set.

    A circumflex can conveniently be used with the upper case character types to specify a more restricted set of characters than the matching lower case type. For example, the class [^\W_] matches any letter or digit, but not underscore, whereas [\w] includes underscore. A positive character class should be read as "something OR something OR ..." and a negative class as "NOT something AND NOT something AND NOT ...".

    The only metacharacters that are recognized in character classes are backslash, hyphen (only where it can be interpreted as specifying a range), circumflex (only at the start), opening square bracket (only when it can be interpreted as introducing a POSIX class name, or for a special compatibility feature - see the next two sections), and the terminating closing square bracket. However, escaping other non-alphanumeric characters does no harm.


    POSIX CHARACTER CLASSES

    Perl supports the POSIX notation for character classes. This uses names enclosed by [: and :] within the enclosing square brackets. PCRE also supports this notation. For example,

      [01[:alpha:]%]
    
    matches "0", "1", any alphabetic character, or "%". The supported class names are:
      alnum    letters and digits
      alpha    letters
      ascii    character codes 0 - 127
      blank    space or tab only
      cntrl    control characters
      digit    decimal digits (same as \d)
      graph    printing characters, excluding space
      lower    lower case letters
      print    printing characters, including space
      punct    printing characters, excluding letters and digits and space
      space    white space (the same as \s from PCRE 8.34)
      upper    upper case letters
      word     "word" characters (same as \w)
      xdigit   hexadecimal digits
    
    The default "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13), and space (32). If locale-specific matching is taking place, the list of space characters may be different; there may be fewer or more of them. "Space" used to be different to \s, which did not include VT, for Perl compatibility. However, Perl changed at release 5.18, and PCRE followed at release 8.34. "Space" and \s now match the same set of characters.

    The name "word" is a Perl extension, and "blank" is a GNU extension from Perl 5.8. Another Perl extension is negation, which is indicated by a ^ character after the colon. For example,

      [12[:^digit:]]
    
    matches "1", "2", or any non-digit. PCRE (and Perl) also recognize the POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not supported, and an error is given if they are encountered.

    By default, characters with values greater than 128 do not match any of the POSIX character classes. However, if the PCRE_UCP option is passed to pcre_compile(), some of the classes are changed so that Unicode character properties are used. This is achieved by replacing certain POSIX classes by other sequences, as follows:

      [:alnum:]  becomes  \p{Xan}
      [:alpha:]  becomes  \p{L}
      [:blank:]  becomes  \h
      [:digit:]  becomes  \p{Nd}
      [:lower:]  becomes  \p{Ll}
      [:space:]  becomes  \p{Xps}
      [:upper:]  becomes  \p{Lu}
      [:word:]   becomes  \p{Xwd}
    
    Negated versions, such as [:^alpha:] use \P instead of \p. Three other POSIX classes are handled specially in UCP mode:

    [:graph:] This matches characters that have glyphs that mark the page when printed. In Unicode property terms, it matches all characters with the L, M, N, P, S, or Cf properties, except for:

      U+061C           Arabic Letter Mark
      U+180E           Mongolian Vowel Separator
      U+2066 - U+2069  Various "isolate"s
    
    

    [:print:] This matches the same characters as [:graph:] plus space characters that are not controls, that is, characters with the Zs property.

    [:punct:] This matches all characters that have the Unicode P (punctuation) property, plus those characters whose code points are less than 128 that have the S (Symbol) property.

    The other POSIX classes are unchanged, and match only characters with code points less than 128.


    COMPATIBILITY FEATURE FOR WORD BOUNDARIES

    In the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word" and "end of word". PCRE treats these items as follows:

      [[:<:]]  is converted to  \b(?=\w)
      [[:>:]]  is converted to  \b(?<=\w)
    
    Only these exact character sequences are recognized. A sequence such as [a[:<:]b] provokes error for an unrecognized POSIX class name. This support is not compatible with Perl. It is provided to help migrations from other environments, and is best not used in any new patterns. Note that \b matches at the start and the end of a word (see "Simple assertions" above), and in a Perl-style pattern the preceding or following character normally shows which is wanted, without the need for the assertions that are used above in order to give exactly the POSIX behaviour.


    VERTICAL BAR

    Vertical bar characters are used to separate alternative patterns. For example, the pattern

      gilbert|sullivan
    
    matches either "gilbert" or "sullivan". Any number of alternatives may appear, and an empty alternative is permitted (matching the empty string). The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. If the alternatives are within a subpattern (defined below), "succeeds" means matching the rest of the main pattern as well as the alternative in the subpattern.


    INTERNAL OPTION SETTING

    The settings of the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and PCRE_EXTENDED options (which are Perl-compatible) can be changed from within the pattern by a sequence of Perl option letters enclosed between "(?" and ")". The option letters are

      i  for PCRE_CASELESS
      m  for PCRE_MULTILINE
      s  for PCRE_DOTALL
      x  for PCRE_EXTENDED
    
    For example, (?im) sets caseless, multiline matching. It is also possible to unset these options by preceding the letter with a hyphen, and a combined setting and unsetting such as (?im-sx), which sets PCRE_CASELESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED, is also permitted. If a letter appears both before and after the hyphen, the option is unset.

    The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA can be changed in the same way as the Perl-compatible options by using the characters J, U and X respectively.

    When one of these option changes occurs at top level (that is, not inside subpattern parentheses), the change applies to the remainder of the pattern that follows. An option change within a subpattern (see below for a description of subpatterns) affects only that part of the subpattern that follows it, so

      (a(?i)b)c
    
    matches abc and aBc and no other strings (assuming PCRE_CASELESS is not used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example,
      (a(?i)b|c)
    
    matches "ab", "aB", "c", and "C", even though when matching "C" the first branch is abandoned before the option setting. This is because the effects of option settings happen at compile time. There would be some very weird behaviour otherwise.

    Note: There are other PCRE-specific options that can be set by the application when the compiling or matching functions are called. In some cases the pattern can contain special leading sequences such as (*CRLF) to override what the application has set or what has been defaulted. Details are given in the section entitled "Newline sequences" above. There are also the (*UTF8), (*UTF16),(*UTF32), and (*UCP) leading sequences that can be used to set UTF and Unicode property modes; they are equivalent to setting the PCRE_UTF8, PCRE_UTF16, PCRE_UTF32 and the PCRE_UCP options, respectively. The (*UTF) sequence is a generic version that can be used with any of the libraries. However, the application can set the PCRE_NEVER_UTF option, which locks out the use of the (*UTF) sequences.


    SUBPATTERNS

    Subpatterns are delimited by parentheses (round brackets), which can be nested. Turning part of a pattern into a subpattern does two things:

    1. It localizes a set of alternatives. For example, the pattern

      cat(aract|erpillar|)
    
    matches "cataract", "caterpillar", or "cat". Without the parentheses, it would match "cataract", "erpillar" or an empty string.

    2. It sets up the subpattern as a capturing subpattern. This means that, when the whole pattern matches, that portion of the subject string that matched the subpattern is passed back to the caller via the ovector argument of the matching function. (This applies only to the traditional matching functions; the DFA matching functions do not support capturing.)

    Opening parentheses are counted from left to right (starting from 1) to obtain numbers for the capturing subpatterns. For example, if the string "the red king" is matched against the pattern

      the ((red|white) (king|queen))
    
    the captured substrings are "red king", "red", and "king", and are numbered 1, 2, and 3, respectively.

    The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by a question mark and a colon, the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string "the white queen" is matched against the pattern

      the ((?:red|white) (king|queen))
    
    the captured substrings are "white queen" and "queen", and are numbered 1 and 2. The maximum number of capturing subpatterns is 65535.

    As a convenient shorthand, if any option settings are required at the start of a non-capturing subpattern, the option letters may appear between the "?" and the ":". Thus the two patterns

      (?i:saturday|sunday)
      (?:(?i)saturday|sunday)
    
    match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match "SUNDAY" as well as "Saturday".


    DUPLICATE SUBPATTERN NUMBERS

    Perl 5.10 introduced a feature whereby each alternative in a subpattern uses the same numbers for its capturing parentheses. Such a subpattern starts with (?| and is itself a non-capturing subpattern. For example, consider this pattern:

      (?|(Sat)ur|(Sun))day
    
    Because the two alternatives are inside a (?| group, both sets of capturing parentheses are numbered one. Thus, when the pattern matches, you can look at captured substring number one, whichever alternative matched. This construct is useful when you want to capture part, but not all, of one of a number of alternatives. Inside a (?| group, parentheses are numbered as usual, but the number is reset at the start of each branch. The numbers of any capturing parentheses that follow the subpattern start after the highest number used in any branch. The following example is taken from the Perl documentation. The numbers underneath show in which buffer the captured content will be stored.
      # before  ---------------branch-reset----------- after
      / ( a )  (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
      # 1            2         2  3        2     3     4
    
    A back reference to a numbered subpattern uses the most recent value that is set for that number by any subpattern. The following pattern matches "abcabc" or "defdef":
      /(?|(abc)|(def))\1/
    
    In contrast, a subroutine call to a numbered subpattern always refers to the first one in the pattern with the given number. The following pattern matches "abcabc" or "defabc":
      /(?|(abc)|(def))(?1)/
    
    If a condition test for a subpattern's having matched refers to a non-unique number, the test is true if any of the subpatterns of that number have matched.

    An alternative approach to using this "branch reset" feature is to use duplicate named subpatterns, as described in the next section.


    NAMED SUBPATTERNS

    Identifying capturing parentheses by number is simple, but it can be very hard to keep track of the numbers in complicated regular expressions. Furthermore, if an expression is modified, the numbers may change. To help with this difficulty, PCRE supports the naming of subpatterns. This feature was not added to Perl until release 5.10. Python had the feature earlier, and PCRE introduced it at release 4.0, using the Python syntax. PCRE now supports both the Perl and the Python syntax. Perl allows identically numbered subpatterns to have different names, but PCRE does not.

    In PCRE, a subpattern can be named in one of three ways: (?<name>...) or (?'name'...) as in Perl, or (?P<name>...) as in Python. References to capturing parentheses from other parts of the pattern, such as back references, recursion, and conditions, can be made by name as well as by number.

    Names consist of up to 32 alphanumeric characters and underscores, but must start with a non-digit. Named capturing parentheses are still allocated numbers as well as names, exactly as if the names were not present. The PCRE API provides function calls for extracting the name-to-number translation table from a compiled pattern. There is also a convenience function for extracting a captured substring by name.

    By default, a name must be unique within a pattern, but it is possible to relax this constraint by setting the PCRE_DUPNAMES option at compile time. (Duplicate names are also always permitted for subpatterns with the same number, set up as described in the previous section.) Duplicate names can be useful for patterns where only one instance of the named parentheses can match. Suppose you want to match the name of a weekday, either as a 3-letter abbreviation or as the full name, and in both cases you want to extract the abbreviation. This pattern (ignoring the line breaks) does the job:

      (?<DN>Mon|Fri|Sun)(?:day)?|
      (?<DN>Tue)(?:sday)?|
      (?<DN>Wed)(?:nesday)?|
      (?<DN>Thu)(?:rsday)?|
      (?<DN>Sat)(?:urday)?
    
    There are five capturing substrings, but only one is ever set after a match. (An alternative way of solving this problem is to use a "branch reset" subpattern, as described in the previous section.)

    The convenience function for extracting the data by name returns the substring for the first (and in this example, the only) subpattern of that name that matched. This saves searching to find which numbered subpattern it was.

    If you make a back reference to a non-unique named subpattern from elsewhere in the pattern, the subpatterns to which the name refers are checked in the order in which they appear in the overall pattern. The first one that is set is used for the reference. For example, this pattern matches both "foofoo" and "barbar" but not "foobar" or "barfoo":

      (?:(?<n>foo)|(?<n>bar))\k<n>
    
    

    If you make a subroutine call to a non-unique named subpattern, the one that corresponds to the first occurrence of the name is used. In the absence of duplicate numbers (see the previous section) this is the one with the lowest number.

    If you use a named reference in a condition test (see the section about conditions below), either to check whether a subpattern has matched, or to check for recursion, all subpatterns with the same name are tested. If the condition is true for any one of them, the overall condition is true. This is the same behaviour as testing by number. For further details of the interfaces for handling named subpatterns, see the pcreapi documentation.

    Warning: You cannot use different names to distinguish between two subpatterns with the same number because PCRE uses only the numbers when matching. For this reason, an error is given at compile time if different names are given to subpatterns with the same number. However, you can always give the same name to subpatterns with the same number, even when PCRE_DUPNAMES is not set.


    REPETITION

    Repetition is specified by quantifiers, which can follow any of the following items:

      a literal data character
      the dot metacharacter
      the \C escape sequence
      the \X escape sequence
      the \R escape sequence
      an escape such as \d or \pL that matches a single character
      a character class
      a back reference (see next section)
      a parenthesized subpattern (including assertions)
      a subroutine call to a subpattern (recursive or otherwise)
    
    The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example:
      z{2,4}
    
    matches "zz", "zzz", or "zzzz". A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus
      [aeiou]{3,}
    
    matches at least 3 successive vowels, but may match many more, while
      \d{8}
    
    matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For example, {,6} is not a quantifier, but a literal string of four characters.

    In UTF modes, quantifiers apply to characters rather than to individual data units. Thus, for example, \x{100}{2} matches two characters, each of which is represented by a two-byte sequence in a UTF-8 string. Similarly, \X{3} matches three Unicode extended grapheme clusters, each of which may be several data units long (and they may be of different lengths).

    The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. This may be useful for subpatterns that are referenced as subroutines from elsewhere in the pattern (but see also the section entitled "Defining subpatterns for use by reference only" below). Items other than subpatterns that have a {0} quantifier are omitted from the compiled pattern.

    For convenience, the three most common quantifiers have single-character abbreviations:

      *    is equivalent to {0,}
      +    is equivalent to {1,}
      ?    is equivalent to {0,1}
    
    It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example:
      (a?)*
    
    Earlier versions of Perl and PCRE used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly broken.

    By default, the quantifiers are "greedy", that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between /* and */ and within the comment, individual * and / characters may appear. An attempt to match C comments by applying the pattern

      /\*.*\*/
    
    to the string
      /* first comment */  not comment  /* second comment */
    
    fails, because it matches the entire string owing to the greediness of the .* item.

    However, if a quantifier is followed by a question mark, it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern

      /\*.*?\*/
    
    does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in
      \d??\d
    
    which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches.

    If the PCRE_UNGREEDY option is set (an option that is not available in Perl), the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour.

    When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more memory is required for the compiled pattern, in proportion to the size of the minimum or maximum.

    If a pattern starts with .* or .{0,} and the PCRE_DOTALL option (equivalent to Perl's /s) is set, thus allowing the dot to match newlines, the pattern is implicitly anchored, because whatever follows will be tried against every character position in the subject string, so there is no point in retrying the overall match at any position after the first. PCRE normally treats such a pattern as though it were preceded by \A.

    In cases where it is known that the subject string contains no newlines, it is worth setting PCRE_DOTALL in order to obtain this optimization, or alternatively using ^ to indicate anchoring explicitly.

    However, there are some cases where the optimization cannot be used. When .* is inside capturing parentheses that are the subject of a back reference elsewhere in the pattern, a match at the start may fail where a later one succeeds. Consider, for example:

      (.*)abc\1
    
    If the subject is "xyz123abc123" the match point is the fourth character. For this reason, such a pattern is not implicitly anchored.

    Another case where implicit anchoring is not applied is when the leading .* is inside an atomic group. Once again, a match at the start may fail where a later one succeeds. Consider this pattern:

      (?>.*?a)b
    
    It matches "ab" in the subject "aab". The use of the backtracking control verbs (*PRUNE) and (*SKIP) also disable this optimization.

    When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after

      (tweedle[dume]{3}\s*)+
    
    has matched "tweedledum tweedledee" the value of the captured substring is "tweedledee". However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after
      /(a|(b))+/
    
    matches "aba" the value of the second captured substring is "b".


    ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS

    With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy") repetition, failure of what follows normally causes the repeated item to be re-evaluated to see if a different number of repeats allows the rest of the pattern to match. Sometimes it is useful to prevent this, either to change the nature of the match, or to cause it fail earlier than it otherwise might, when the author of the pattern knows there is no point in carrying on.

    Consider, for example, the pattern \d+foo when applied to the subject line

      123456bar
    
    After matching all 6 digits and then failing to match "foo", the normal action of the matcher is to try again with only 5 digits matching the \d+ item, and then with 4, and so on, before ultimately failing. "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides the means for specifying that once a subpattern has matched, it is not to be re-evaluated in this way.

    If we use atomic grouping for the previous example, the matcher gives up immediately on failing to match "foo" the first time. The notation is a kind of special parenthesis, starting with (?> as in this example:

      (?>\d+)foo
    
    This kind of parenthesis "locks up" the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal.

    An alternative description is that a subpattern of this type matches the string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string.

    Atomic grouping subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both \d+ and \d+? are prepared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\d+) can only match an entire sequence of digits.

    Atomic groups in general can of course contain arbitrarily complicated subpatterns, and can be nested. However, when the subpattern for an atomic group is just a single repeated item, as in the example above, a simpler notation, called a "possessive quantifier" can be used. This consists of an additional + character following a quantifier. Using this notation, the previous example can be rewritten as

      \d++foo
    
    Note that a possessive quantifier can be used with an entire group, for example:
      (abc|xyz){2,3}+
    
    Possessive quantifiers are always greedy; the setting of the PCRE_UNGREEDY option is ignored. They are a convenient notation for the simpler forms of atomic group. However, there is no difference in the meaning of a possessive quantifier and the equivalent atomic group, though there may be a performance difference; possessive quantifiers should be slightly faster.

    The possessive quantifier syntax is an extension to the Perl 5.8 syntax. Jeffrey Friedl originated the idea (and the name) in the first edition of his book. Mike McCloskey liked it, so implemented it when he built Sun's Java package, and PCRE copied it from there. It ultimately found its way into Perl at release 5.10.

    PCRE has an optimization that automatically "possessifies" certain simple pattern constructs. For example, the sequence A+B is treated as A++B because there is no point in backtracking into a sequence of A's when B must follow.

    When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of an atomic group is the only way to avoid some failing matches taking a very long time indeed. The pattern

      (\D+|<\d+>)*[!?]
    
    matches an unlimited number of substrings that either consist of non-digits, or digits enclosed in <>, followed by either ! or ?. When it matches, it runs quickly. However, if it is applied to
      aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    
    it takes a long time before reporting failure. This is because the string can be divided between the internal \D+ repeat and the external * repeat in a large number of ways, and all have to be tried. (The example uses [!?] rather than a single character at the end, because both PCRE and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single character that is required for a match, and fail early if it is not present in the string.) If the pattern is changed so that it uses an atomic group, like this:
      ((?>\D+)|<\d+>)*[!?]
    
    sequences of non-digits cannot be broken, and failure happens quickly.


    BACK REFERENCES

    Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing subpattern earlier (that is, to its left) in the pattern, provided there have been that many previous capturing left parentheses.

    However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pattern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. A "forward back reference" of this type can make sense when a repetition is involved and the subpattern to the right has participated in an earlier iteration.

    It is not possible to have a numerical "forward back reference" to a subpattern whose number is 10 or more using this syntax because a sequence such as \50 is interpreted as a character defined in octal. See the subsection entitled "Non-printing characters" above for further details of the handling of digits following a backslash. There is no such problem when named parentheses are used. A back reference to any subpattern is possible using named parentheses (see below).

    Another way of avoiding the ambiguity inherent in the use of digits following a backslash is to use the \g escape sequence. This escape must be followed by an unsigned number or a negative number, optionally enclosed in braces. These examples are all identical:

      (ring), \1
      (ring), \g1
      (ring), \g{1}
    
    An unsigned number specifies an absolute reference without the ambiguity that is present in the older syntax. It is also useful when literal digits follow the reference. A negative number is a relative reference. Consider this example:
      (abc(def)ghi)\g{-1}
    
    The sequence \g{-1} is a reference to the most recently started capturing subpattern before \g, that is, is it equivalent to \2 in this example. Similarly, \g{-2} would be equivalent to \1. The use of relative references can be helpful in long patterns, and also in patterns that are created by joining together fragments that contain references within themselves.

    A back reference matches whatever actually matched the capturing subpattern in the current subject string, rather than anything matching the subpattern itself (see "Subpatterns as subroutines" below for a way of doing that). So the pattern

      (sens|respons)e and \1ibility
    
    matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If caseful matching is in force at the time of the back reference, the case of letters is relevant. For example,
      ((?i)rah)\s+\1
    
    matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original capturing subpattern is matched caselessly.

    There are several different ways of writing back references to named subpatterns. The .NET syntax \k{name} and the Perl syntax \k<name> or \k'name' are supported, as is the Python syntax (?P=name). Perl 5.10's unified back reference syntax, in which \g can be used for both numeric and named references, is also supported. We could rewrite the above example in any of the following ways:

      (?<p1>(?i)rah)\s+\k<p1>
      (?'p1'(?i)rah)\s+\k{p1}
      (?P<p1>(?i)rah)\s+(?P=p1)
      (?<p1>(?i)rah)\s+\g{p1}
    
    A subpattern that is referenced by name may appear in the pattern before or after the reference.

    There may be more than one back reference to the same subpattern. If a subpattern has not actually been used in a particular match, any back references to it always fail by default. For example, the pattern

      (a|(bc))\2
    
    always fails if it starts to match "a" rather than "bc". However, if the PCRE_JAVASCRIPT_COMPAT option is set at compile time, a back reference to an unset value matches an empty string.

    Because there may be many capturing parentheses in a pattern, all digits following a backslash are taken as part of a potential back reference number. If the pattern continues with a digit character, some delimiter must be used to terminate the back reference. If the PCRE_EXTENDED option is set, this can be white space. Otherwise, the \g{ syntax or an empty comment (see "Comments" below) can be used.


    Recursive back references

    A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, (a\1) never matches. However, such references can be useful inside repeated subpatterns. For example, the pattern

      (a|b\1)+
    
    matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero.

    Back references of this type cause the group that they reference to be treated as an atomic group. Once the whole group has been matched, a subsequent matching failure cannot cause backtracking into the middle of the group.


    ASSERTIONS

    An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are described above.

    More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it. An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed.

    Assertion subpatterns are not capturing subpatterns. If such an assertion contains capturing subpatterns within it, these are counted for the purposes of numbering the capturing subpatterns in the whole pattern. However, substring capturing is carried out only for positive assertions. (Perl sometimes, but not always, does do capturing in negative assertions.)

    WARNING: If a positive assertion containing one or more capturing subpatterns succeeds, but failure to match later in the pattern causes backtracking over this assertion, the captures within the assertion are reset only if no higher numbered captures are already set. This is, unfortunately, a fundamental limitation of the current implementation, and as PCRE1 is now in maintenance-only status, it is unlikely ever to change.

    For compatibility with Perl, assertion subpatterns may be repeated; though it makes no sense to assert the same thing several times, the side effect of capturing parentheses may occasionally be useful. In practice, there only three cases:

    (1) If the quantifier is {0}, the assertion is never obeyed during matching. However, it may contain internal capturing parenthesized groups that are called from elsewhere via the subroutine mechanism.

    (2) If quantifier is {0,n} where n is greater than zero, it is treated as if it were {0,1}. At run time, the rest of the pattern match is tried with and without the assertion, the order depending on the greediness of the quantifier.

    (3) If the minimum repetition is greater than zero, the quantifier is ignored. The assertion is obeyed just once when encountered during matching.


    Lookahead assertions

    Lookahead assertions start with (?= for positive assertions and (?! for negative assertions. For example,

      \w+(?=;)
    
    matches a word followed by a semicolon, but does not include the semicolon in the match, and
      foo(?!bar)
    
    matches any occurrence of "foo" that is not followed by "bar". Note that the apparently similar pattern
      (?!foo)bar
    
    does not find an occurrence of "bar" that is preceded by something other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always true when the next three characters are "bar". A lookbehind assertion is needed to achieve the other effect.

    If you want to force a matching failure at some point in a pattern, the most convenient way to do it is with (?!) because an empty string always matches, so an assertion that requires there not to be an empty string must always fail. The backtracking control verb (*FAIL) or (*F) is a synonym for (?!).


    Lookbehind assertions

    Lookbehind assertions start with (?<= for positive assertions and (?<! for negative assertions. For example,

      (?<!foo)bar
    
    does find an occurrence of "bar" that is not preceded by "foo". The contents of a lookbehind assertion are restricted such that all the strings it matches must have a fixed length. However, if there are several top-level alternatives, they do not all have to have the same fixed length. Thus
      (?<=bullock|donkey)
    
    is permitted, but
      (?<!dogs?|cats?)
    
    causes an error at compile time. Branches that match different length strings are permitted only at the top level of a lookbehind assertion. This is an extension compared with Perl, which requires all branches to match the same length of string. An assertion such as
      (?<=ab(c|de))
    
    is not permitted, because its single top-level branch can match two different lengths, but it is acceptable to PCRE if rewritten to use two top-level branches:
      (?<=abc|abde)
    
    In some cases, the escape sequence \K (see above) can be used instead of a lookbehind assertion to get round the fixed-length restriction.

    The implementation of lookbehind assertions is, for each alternative, to temporarily move the current position back by the fixed length and then try to match. If there are insufficient characters before the current position, the assertion fails.

    In a UTF mode, PCRE does not allow the \C escape (which matches a single data unit even in a UTF mode) to appear in lookbehind assertions, because it makes it impossible to calculate the length of the lookbehind. The \X and \R escapes, which can match different numbers of data units, are also not permitted.

    "Subroutine" calls (see below) such as (?2) or (?&X) are permitted in lookbehinds, as long as the subpattern matches a fixed-length string. Recursion, however, is not supported.

    Possessive quantifiers can be used in conjunction with lookbehind assertions to specify efficient matching of fixed-length strings at the end of subject strings. Consider a simple pattern such as

      abcd$
    
    when applied to a long string that does not match. Because matching proceeds from left to right, PCRE will look for each "a" in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as
      ^.*abcd$
    
    the initial .* matches the entire string at first, but when this fails (because there is no following "a"), it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for "a" covers the entire string, from right to left, so we are no better off. However, if the pattern is written as
      ^.*+(?<=abcd)
    
    there can be no backtracking for the .*+ item; it can match only the entire string. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the match fails immediately. For long strings, this approach makes a significant difference to the processing time.


    Using multiple assertions

    Several assertions (of any sort) may occur in succession. For example,

      (?<=\d{3})(?<!999)foo
    
    matches "foo" preceded by three digits that are not "999". Notice that each of the assertions is applied independently at the same point in the subject string. First there is a check that the previous three characters are all digits, and then there is a check that the same three characters are not "999". This pattern does not match "foo" preceded by six characters, the first of which are digits and the last three of which are not "999". For example, it doesn't match "123abcfoo". A pattern to do that is
      (?<=\d{3}...)(?<!999)foo
    
    This time the first assertion looks at the preceding six characters, checking that the first three are digits, and then the second assertion checks that the preceding three characters are not "999".

    Assertions can be nested in any combination. For example,

      (?<=(?<!foo)bar)baz
    
    matches an occurrence of "baz" that is preceded by "bar" which in turn is not preceded by "foo", while
      (?<=\d{3}(?!999)...)foo
    
    is another pattern that matches "foo" preceded by three digits and any three characters that are not "999".


    CONDITIONAL SUBPATTERNS

    It is possible to cause the matching process to obey a subpattern conditionally or to choose between two alternative subpatterns, depending on the result of an assertion, or whether a specific capturing subpattern has already been matched. The two possible forms of conditional subpattern are:

      (?(condition)yes-pattern)
      (?(condition)yes-pattern|no-pattern)
    
    If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. If there are more than two alternatives in the subpattern, a compile-time error occurs. Each of the two alternatives may itself contain nested subpatterns of any form, including conditional subpatterns; the restriction to two alternatives applies only at the level of the condition. This pattern fragment is an example where the alternatives are complex:
      (?(1) (A|B|C) | (D | (?(2)E|F) | E) )
    
    

    There are four kinds of condition: references to subpatterns, references to recursion, a pseudo-condition called DEFINE, and assertions.


    Checking for a used subpattern by number

    If the text between the parentheses consists of a sequence of digits, the condition is true if a capturing subpattern of that number has previously matched. If there is more than one capturing subpattern with the same number (see the earlier section about duplicate subpattern numbers), the condition is true if any of them have matched. An alternative notation is to precede the digits with a plus or minus sign. In this case, the subpattern number is relative rather than absolute. The most recently opened parentheses can be referenced by (?(-1), the next most recent by (?(-2), and so on. Inside loops it can also make sense to refer to subsequent groups. The next parentheses to be opened can be referenced as (?(+1), and so on. (The value zero in any of these forms is not used; it provokes a compile-time error.)

    Consider the following pattern, which contains non-significant white space to make it more readable (assume the PCRE_EXTENDED option) and to divide it into three parts for ease of discussion:

      ( \( )?    [^()]+    (?(1) \) )
    
    The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a conditional subpattern that tests whether or not the first set of parentheses matched. If they did, that is, if subject started with an opening parenthesis, the condition is true, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the subpattern matches nothing. In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses.

    If you were embedding this pattern in a larger one, you could use a relative reference:

      ...other stuff... ( \( )?    [^()]+    (?(-1) \) ) ...
    
    This makes the fragment independent of the parentheses in the larger pattern.


    Checking for a used subpattern by name

    Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a used subpattern by name. For compatibility with earlier versions of PCRE, which had this facility before Perl, the syntax (?(name)...) is also recognized.

    Rewriting the above example to use a named subpattern gives this:

      (?<OPEN> \( )?    [^()]+    (?(<OPEN>) \) )
    
    If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them has matched.


    Checking for pattern recursion

    If the condition is the string (R), and there is no subpattern with the name R, the condition is true if a recursive call to the whole pattern or any subpattern has been made. If digits or a name preceded by ampersand follow the letter R, for example:

      (?(R3)...) or (?(R&name)...)
    
    the condition is true if the most recent recursion is into a subpattern whose number or name is given. This condition does not check the entire recursion stack. If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them is the most recent recursion.

    At "top level", all these recursion test conditions are false. The syntax for recursive patterns is described below.


    Defining subpatterns for use by reference only

    If the condition is the string (DEFINE), and there is no subpattern with the name DEFINE, the condition is always false. In this case, there may be only one alternative in the subpattern. It is always skipped if control reaches this point in the pattern; the idea of DEFINE is that it can be used to define subroutines that can be referenced from elsewhere. (The use of subroutines is described below.) For example, a pattern to match an IPv4 address such as "192.168.23.245" could be written like this (ignore white space and line breaks):

      (?(DEFINE) (?<byte> 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) )
      \b (?&byte) (\.(?&byte)){3} \b
    
    The first part of the pattern is a DEFINE group inside which a another group named "byte" is defined. This matches an individual component of an IPv4 address (a number less than 256). When matching takes place, this part of the pattern is skipped because DEFINE acts like a false condition. The rest of the pattern uses references to the named group to match the four dot-separated components of an IPv4 address, insisting on a word boundary at each end.


    Assertion conditions

    If the condition is not in any of the above formats, it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line:

      (?(?=[^a-z]*[a-z])
      \d{2}-[a-z]{3}-\d{2}  |  \d{2}-\d{2}-\d{2} )
    
    The condition is a positive lookahead assertion that matches an optional sequence of non-letters followed by a letter. In other words, it tests for the presence of at least one letter in the subject. If a letter is found, the subject is matched against the first alternative; otherwise it is matched against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.


    COMMENTS

    There are two ways of including comments in patterns that are processed by PCRE. In both cases, the start of the comment must not be in a character class, nor in the middle of any other sequence of related characters such as (?: or a subpattern name or number. The characters that make up a comment play no part in the pattern matching.

    The sequence (?# marks the start of a comment that continues up to the next closing parenthesis. Nested parentheses are not permitted. If the PCRE_EXTENDED option is set, an unescaped # character also introduces a comment, which in this case continues to immediately after the next newline character or character sequence in the pattern. Which characters are interpreted as newlines is controlled by the options passed to a compiling function or by a special sequence at the start of the pattern, as described in the section entitled "Newline conventions" above. Note that the end of this type of comment is a literal newline sequence in the pattern; escape sequences that happen to represent a newline do not count. For example, consider this pattern when PCRE_EXTENDED is set, and the default newline convention is in force:

      abc #comment \n still comment
    
    On encountering the # character, pcre_compile() skips along, looking for a newline in the pattern. The sequence \n is still literal at this stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so.


    RECURSIVE PATTERNS

    Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth.

    For some time, Perl has provided a facility that allows regular expressions to recurse (amongst other things). It does this by interpolating Perl code in the expression at run time, and the code can refer to the expression itself. A Perl pattern using code interpolation to solve the parentheses problem can be created like this:

      $re = qr{\( (?: (?>[^()]+) | (?p{$re}) )* \)}x;
    
    The (?p{...}) item interpolates Perl code at run time, and in this case refers recursively to the pattern in which it appears.

    Obviously, PCRE cannot support the interpolation of Perl code. Instead, it supports special syntax for recursion of the entire pattern, and also for individual subpattern recursion. After its introduction in PCRE and Python, this kind of recursion was subsequently introduced into Perl at release 5.10.

    A special item that consists of (? followed by a number greater than zero and a closing parenthesis is a recursive subroutine call of the subpattern of the given number, provided that it occurs inside that subpattern. (If not, it is a non-recursive subroutine call, which is described in the next section.) The special item (?R) or (?0) is a recursive call of the entire regular expression.

    This PCRE pattern solves the nested parentheses problem (assume the PCRE_EXTENDED option is set so that white space is ignored):

      \( ( [^()]++ | (?R) )* \)
    
    First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (that is, a correctly parenthesized substring). Finally there is a closing parenthesis. Note the use of a possessive quantifier to avoid backtracking into sequences of non-parentheses.

    If this were part of a larger pattern, you would not want to recurse the entire pattern, so instead you could use this:

      ( \( ( [^()]++ | (?1) )* \) )
    
    We have put the pattern into parentheses, and caused the recursion to refer to them instead of the whole pattern.

    In a larger pattern, keeping track of parenthesis numbers can be tricky. This is made easier by the use of relative references. Instead of (?1) in the pattern above you can write (?-2) to refer to the second most recently opened parentheses preceding the recursion. In other words, a negative number counts capturing parentheses leftwards from the point at which it is encountered.

    It is also possible to refer to subsequently opened parentheses, by writing references such as (?+2). However, these cannot be recursive because the reference is not inside the parentheses that are referenced. They are always non-recursive subroutine calls, as described in the next section.

    An alternative approach is to use named parentheses instead. The Perl syntax for this is (?&name); PCRE's earlier syntax (?P>name) is also supported. We could rewrite the above example as follows:

      (?<pn> \( ( [^()]++ | (?&pn) )* \) )
    
    If there is more than one subpattern with the same name, the earliest one is used.

    This particular example pattern that we have been looking at contains nested unlimited repeats, and so the use of a possessive quantifier for matching strings of non-parentheses is important when applying the pattern to strings that do not match. For example, when this pattern is applied to

      (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
    
    it yields "no match" quickly. However, if a possessive quantifier is not used, the match runs for a very long time indeed because there are so many different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported.

    At the end of a match, the values of capturing parentheses are those from the outermost level. If you want to obtain intermediate values, a callout function can be used (see below and the pcrecallout documentation). If the pattern above is matched against

      (ab(cd)ef)
    
    the value for the inner capturing parentheses (numbered 2) is "ef", which is the last value taken on at the top level. If a capturing subpattern is not matched at the top level, its final captured value is unset, even if it was (temporarily) set at a deeper level during the matching process.

    If there are more than 15 capturing parentheses in a pattern, PCRE has to obtain extra memory to store data during a recursion, which it does by using pcre_malloc, freeing it via pcre_free afterwards. If no memory can be obtained, the match fails with the PCRE_ERROR_NOMEMORY error.

    Do not confuse the (?R) item with the condition (R), which tests for recursion. Consider this pattern, which matches text in angle brackets, allowing for arbitrary nesting. Only digits are allowed in nested brackets (that is, when recursing), whereas any characters are permitted at the outer level.

      < (?: (?(R) \d++  | [^<>]*+) | (?R)) * >
    
    In this pattern, (?(R) is the start of a conditional subpattern, with two different alternatives for the recursive and non-recursive cases. The (?R) item is the actual recursive call.


    Differences in recursion processing between PCRE and Perl

    Recursion processing in PCRE differs from Perl in two important ways. In PCRE (like Python, but unlike Perl), a recursive subpattern call is always treated as an atomic group. That is, once it has matched some of the subject string, it is never re-entered, even if it contains untried alternatives and there is a subsequent matching failure. This can be illustrated by the following pattern, which purports to match a palindromic string that contains an odd number of characters (for example, "a", "aba", "abcba", "abcdcba"):

      ^(.|(.)(?1)\2)$
    
    The idea is that it either matches a single character, or two identical characters surrounding a sub-palindrome. In Perl, this pattern works; in PCRE it does not if the pattern is longer than three characters. Consider the subject string "abcba":

    At the top level, the first character is matched, but as it is not at the end of the string, the first alternative fails; the second alternative is taken and the recursion kicks in. The recursive call to subpattern 1 successfully matches the next character ("b"). (Note that the beginning and end of line tests are not part of the recursion).

    Back at the top level, the next character ("c") is compared with what subpattern 2 matched, which was "a". This fails. Because the recursion is treated as an atomic group, there are now no backtracking points, and so the entire match fails. (Perl is able, at this point, to re-enter the recursion and try the second alternative.) However, if the pattern is written with the alternatives in the other order, things are different:

      ^((.)(?1)\2|.)$
    
    This time, the recursing alternative is tried first, and continues to recurse until it runs out of characters, at which point the recursion fails. But this time we do have another alternative to try at the higher level. That is the big difference: in the previous case the remaining alternative is at a deeper recursion level, which PCRE cannot use.

    To change the pattern so that it matches all palindromic strings, not just those with an odd number of characters, it is tempting to change the pattern to this:

      ^((.)(?1)\2|.?)$
    
    Again, this works in Perl, but not in PCRE, and for the same reason. When a deeper recursion has matched a single character, it cannot be entered again in order to match an empty string. The solution is to separate the two cases, and write out the odd and even cases as alternatives at the higher level:
      ^(?:((.)(?1)\2|)|((.)(?3)\4|.))
    
    If you want to match typical palindromic phrases, the pattern has to ignore all non-word characters, which can be done like this:
      ^\W*+(?:((.)\W*+(?1)\W*+\2|)|((.)\W*+(?3)\W*+\4|\W*+.\W*+))\W*+$
    
    If run with the PCRE_CASELESS option, this pattern matches phrases such as "A man, a plan, a canal: Panama!" and it works well in both PCRE and Perl. Note the use of the possessive quantifier *+ to avoid backtracking into sequences of non-word characters. Without this, PCRE takes a great deal longer (ten times or more) to match typical phrases, and Perl takes so long that you think it has gone into a loop.

    WARNING: The palindrome-matching patterns above work only if the subject string does not start with a palindrome that is shorter than the entire string. For example, although "abcba" is correctly matched, if the subject is "ababa", PCRE finds the palindrome "aba" at the start, then fails at top level because the end of the string does not follow. Once again, it cannot jump back into the recursion to try other alternatives, so the entire match fails.

    The second way in which PCRE and Perl differ in their recursion processing is in the handling of captured values. In Perl, when a subpattern is called recursively or as a subpattern (see the next section), it has no access to any values that were captured outside the recursion, whereas in PCRE these values can be referenced. Consider this pattern:

      ^(.)(\1|a(?2))
    
    In PCRE, this pattern matches "bab". The first capturing parentheses match "b", then in the second group, when the back reference \1 fails to match "b", the second alternative matches "a" and then recurses. In the recursion, \1 does now match "b" and so the whole match succeeds. In Perl, the pattern fails to match because inside the recursive call \1 cannot access the externally set value.


    SUBPATTERNS AS SUBROUTINES

    If the syntax for a recursive subpattern call (either by number or by name) is used outside the parentheses to which it refers, it operates like a subroutine in a programming language. The called subpattern may be defined before or after the reference. A numbered reference can be absolute or relative, as in these examples:

      (...(absolute)...)...(?2)...
      (...(relative)...)...(?-1)...
      (...(?+1)...(relative)...
    
    An earlier example pointed out that the pattern
      (sens|respons)e and \1ibility
    
    matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If instead the pattern
      (sens|respons)e and (?1)ibility
    
    is used, it does match "sense and responsibility" as well as the other two strings. Another example is given in the discussion of DEFINE above.

    All subroutine calls, whether recursive or not, are always treated as atomic groups. That is, once a subroutine has matched some of the subject string, it is never re-entered, even if it contains untried alternatives and there is a subsequent matching failure. Any capturing parentheses that are set during the subroutine call revert to their previous values afterwards.

    Processing options such as case-independence are fixed when a subpattern is defined, so if it is used as a subroutine, such options cannot be changed for different calls. For example, consider this pattern:

      (abc)(?i:(?-1))
    
    It matches "abcabc". It does not match "abcABC" because the change of processing option does not affect the called subpattern.


    ONIGURUMA SUBROUTINE SYNTAX

    For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative syntax for referencing a subpattern as a subroutine, possibly recursively. Here are two of the examples used above, rewritten using this syntax:

      (?<pn> \( ( (?>[^()]+) | \g<pn> )* \) )
      (sens|respons)e and \g'1'ibility
    
    PCRE supports an extension to Oniguruma: if a number is preceded by a plus or a minus sign it is taken as a relative reference. For example:
      (abc)(?i:\g<-1>)
    
    Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not synonymous. The former is a back reference; the latter is a subroutine call.


    CALLOUTS

    Perl has a feature whereby using the sequence (?{...}) causes arbitrary Perl code to be obeyed in the middle of matching a regular expression. This makes it possible, amongst other things, to extract different substrings that match the same pair of parentheses when there is a repetition.

    PCRE provides a similar feature, but of course it cannot obey arbitrary Perl code. The feature is called "callout". The caller of PCRE provides an external function by putting its entry point in the global variable pcre_callout (8-bit library) or pcre[16|32]_callout (16-bit or 32-bit library). By default, this variable contains NULL, which disables all calling out.

    Within a regular expression, (?C) indicates the points at which the external function is to be called. If you want to identify different callout points, you can put a number less than 256 after the letter C. The default value is zero. For example, this pattern has two callout points:

      (?C1)abc(?C2)def
    
    If the PCRE_AUTO_CALLOUT flag is passed to a compiling function, callouts are automatically installed before each item in the pattern. They are all numbered 255. If there is a conditional group in the pattern whose condition is an assertion, an additional callout is inserted just before the condition. An explicit callout may also be set at this position, as in this example:
      (?(?C9)(?=a)abc|def)
    
    Note that this applies only to assertion conditions, not to other types of condition.

    During matching, when PCRE reaches a callout point, the external function is called. It is provided with the number of the callout, the position in the pattern, and, optionally, one item of data originally supplied by the caller of the matching function. The callout function may cause matching to proceed, to backtrack, or to fail altogether.

    By default, PCRE implements a number of optimizations at compile time and matching time, and one side-effect is that sometimes callouts are skipped. If you need all possible callouts to happen, you need to set options that disable the relevant optimizations. More details, and a complete description of the interface to the callout function, are given in the pcrecallout documentation.


    BACKTRACKING CONTROL

    Perl 5.10 introduced a number of "Special Backtracking Control Verbs", which are still described in the Perl documentation as "experimental and subject to change or removal in a future version of Perl". It goes on to say: "Their usage in production code should be noted to avoid problems during upgrades." The same remarks apply to the PCRE features described in this section.

    The new verbs make use of what was previously invalid syntax: an opening parenthesis followed by an asterisk. They are generally of the form (*VERB) or (*VERB:NAME). Some may take either form, possibly behaving differently depending on whether or not a name is present. A name is any sequence of characters that does not include a closing parenthesis. The maximum length of name is 255 in the 8-bit library and 65535 in the 16-bit and 32-bit libraries. If the name is empty, that is, if the closing parenthesis immediately follows the colon, the effect is as if the colon were not there. Any number of these verbs may occur in a pattern.

    Since these verbs are specifically related to backtracking, most of them can be used only when the pattern is to be matched using one of the traditional matching functions, because these use a backtracking algorithm. With the exception of (*FAIL), which behaves like a failing negative assertion, the backtracking control verbs cause an error if encountered by a DFA matching function.

    The behaviour of these verbs in repeated groups, assertions, and in subpatterns called as subroutines (whether or not recursively) is documented below.


    Optimizations that affect backtracking verbs

    PCRE contains some optimizations that are used to speed up matching by running some checks at the start of each match attempt. For example, it may know the minimum length of matching subject, or that a particular character must be present. When one of these optimizations bypasses the running of a match, any included backtracking verbs will not, of course, be processed. You can suppress the start-of-match optimizations by setting the PCRE_NO_START_OPTIMIZE option when calling pcre_compile() or pcre_exec(), or by starting the pattern with (*NO_START_OPT). There is more discussion of this option in the section entitled "Option bits for pcre_exec()" in the pcreapi documentation.

    Experiments with Perl suggest that it too has similar optimizations, sometimes leading to anomalous results.


    Verbs that act immediately

    The following verbs act as soon as they are encountered. They may not be followed by a name.

       (*ACCEPT)
    
    This verb causes the match to end successfully, skipping the remainder of the pattern. However, when it is inside a subpattern that is called as a subroutine, only that subpattern is ended successfully. Matching then continues at the outer level. If (*ACCEPT) in triggered in a positive assertion, the assertion succeeds; in a negative assertion, the assertion fails.

    If (*ACCEPT) is inside capturing parentheses, the data so far is captured. For example:

      A((?:A|B(*ACCEPT)|C)D)
    
    This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is captured by the outer parentheses.
      (*FAIL) or (*F)
    
    This verb causes a matching failure, forcing backtracking to occur. It is equivalent to (?!) but easier to read. The Perl documentation notes that it is probably useful only when combined with (?{}) or (??{}). Those are, of course, Perl features that are not present in PCRE. The nearest equivalent is the callout feature, as for example in this pattern:
      a+(?C)(*FAIL)
    
    A match with the string "aaaa" always fails, but the callout is taken before each backtrack happens (in this example, 10 times).


    Recording which path was taken

    There is one verb whose main purpose is to track how a match was arrived at, though it also has a secondary use in conjunction with advancing the match starting point (see (*SKIP) below).

      (*MARK:NAME) or (*:NAME)
    
    A name is always required with this verb. There may be as many instances of (*MARK) as you like in a pattern, and their names do not have to be unique.

    When a match succeeds, the name of the last-encountered (*MARK:NAME), (*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to the caller as described in the section entitled "Extra data for pcre_exec()" in the pcreapi documentation. Here is an example of pcretest output, where the /K modifier requests the retrieval and outputting of (*MARK) data:

        re> /X(*MARK:A)Y|X(*MARK:B)Z/K
      data> XY
       0: XY
      MK: A
      XZ
       0: XZ
      MK: B
    
    The (*MARK) name is tagged with "MK:" in this output, and in this example it indicates which of the two alternatives matched. This is a more efficient way of obtaining this information than putting each alternative in its own capturing parentheses.

    If a verb with a name is encountered in a positive assertion that is true, the name is recorded and passed back if it is the last-encountered. This does not happen for negative assertions or failing positive assertions.

    After a partial match or a failed match, the last encountered name in the entire match process is returned. For example:

        re> /X(*MARK:A)Y|X(*MARK:B)Z/K
      data> XP
      No match, mark = B
    
    Note that in this unanchored example the mark is retained from the match attempt that started at the letter "X" in the subject. Subsequent match attempts starting at "P" and then with an empty string do not get as far as the (*MARK) item, but nevertheless do not reset it.

    If you are interested in (*MARK) values after failed matches, you should probably set the PCRE_NO_START_OPTIMIZE option (see above) to ensure that the match is always attempted.


    Verbs that act after backtracking

    The following verbs do nothing when they are encountered. Matching continues with what follows, but if there is no subsequent match, causing a backtrack to the verb, a failure is forced. That is, backtracking cannot pass to the left of the verb. However, when one of these verbs appears inside an atomic group or an assertion that is true, its effect is confined to that group, because once the group has been matched, there is never any backtracking into it. In this situation, backtracking can "jump back" to the left of the entire atomic group or assertion. (Remember also, as stated above, that this localization also applies in subroutine calls.)

    These verbs differ in exactly what kind of failure occurs when backtracking reaches them. The behaviour described below is what happens when the verb is not in a subroutine or an assertion. Subsequent sections cover these special cases.

      (*COMMIT)
    
    This verb, which may not be followed by a name, causes the whole match to fail outright if there is a later matching failure that causes backtracking to reach it. Even if the pattern is unanchored, no further attempts to find a match by advancing the starting point take place. If (*COMMIT) is the only backtracking verb that is encountered, once it has been passed pcre_exec() is committed to finding a match at the current starting point, or not at all. For example:
      a+(*COMMIT)b
    
    This matches "xxaab" but not "aacaab". It can be thought of as a kind of dynamic anchor, or "I've started, so I must finish." The name of the most recently passed (*MARK) in the path is passed back when (*COMMIT) forces a match failure.

    If there is more than one backtracking verb in a pattern, a different one that follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a match does not always guarantee that a match must be at this starting point.

    Note that (*COMMIT) at the start of a pattern is not the same as an anchor, unless PCRE's start-of-match optimizations are turned off, as shown in this output from pcretest:

        re> /(*COMMIT)abc/
      data> xyzabc
       0: abc
      data> xyzabc\Y
      No match
    
    For this pattern, PCRE knows that any match must start with "a", so the optimization skips along the subject to "a" before applying the pattern to the first set of data. The match attempt then succeeds. In the second set of data, the escape sequence \Y is interpreted by the pcretest program. It causes the PCRE_NO_START_OPTIMIZE option to be set when pcre_exec() is called. This disables the optimization that skips along to the first character. The pattern is now applied starting at "x", and so the (*COMMIT) causes the match to fail without trying any other starting points.
      (*PRUNE) or (*PRUNE:NAME)
    
    This verb causes the match to fail at the current starting position in the subject if there is a later matching failure that causes backtracking to reach it. If the pattern is unanchored, the normal "bumpalong" advance to the next starting character then happens. Backtracking can occur as usual to the left of (*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but if there is no match to the right, backtracking cannot cross (*PRUNE). In simple cases, the use of (*PRUNE) is just an alternative to an atomic group or possessive quantifier, but there are some uses of (*PRUNE) that cannot be expressed in any other way. In an anchored pattern (*PRUNE) has the same effect as (*COMMIT).

    The behaviour of (*PRUNE:NAME) is the not the same as (*MARK:NAME)(*PRUNE). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK).

      (*SKIP)
    
    This verb, when given without a name, is like (*PRUNE), except that if the pattern is unanchored, the "bumpalong" advance is not to the next character, but to the position in the subject where (*SKIP) was encountered. (*SKIP) signifies that whatever text was matched leading up to it cannot be part of a successful match. Consider:
      a+(*SKIP)b
    
    If the subject is "aaaac...", after the first match attempt fails (starting at the first character in the string), the starting point skips on to start the next attempt at "c". Note that a possessive quantifer does not have the same effect as this example; although it would suppress backtracking during the first match attempt, the second attempt would start at the second character instead of skipping on to "c".
      (*SKIP:NAME)
    
    When (*SKIP) has an associated name, its behaviour is modified. When it is triggered, the previous path through the pattern is searched for the most recent (*MARK) that has the same name. If one is found, the "bumpalong" advance is to the subject position that corresponds to that (*MARK) instead of to where (*SKIP) was encountered. If no (*MARK) with a matching name is found, the (*SKIP) is ignored.

    Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores names that are set by (*PRUNE:NAME) or (*THEN:NAME).

      (*THEN) or (*THEN:NAME)
    
    This verb causes a skip to the next innermost alternative when backtracking reaches it. That is, it cancels any further backtracking within the current alternative. Its name comes from the observation that it can be used for a pattern-based if-then-else block:
      ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...
    
    If the COND1 pattern matches, FOO is tried (and possibly further items after the end of the group if FOO succeeds); on failure, the matcher skips to the second alternative and tries COND2, without backtracking into COND1. If that succeeds and BAR fails, COND3 is tried. If subsequently BAZ fails, there are no more alternatives, so there is a backtrack to whatever came before the entire group. If (*THEN) is not inside an alternation, it acts like (*PRUNE).

    The behaviour of (*THEN:NAME) is the not the same as (*MARK:NAME)(*THEN). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK).

    A subpattern that does not contain a | character is just a part of the enclosing alternative; it is not a nested alternation with only one alternative. The effect of (*THEN) extends beyond such a subpattern to the enclosing alternative. Consider this pattern, where A, B, etc. are complex pattern fragments that do not contain any | characters at this level:

      A (B(*THEN)C) | D
    
    If A and B are matched, but there is a failure in C, matching does not backtrack into A; instead it moves to the next alternative, that is, D. However, if the subpattern containing (*THEN) is given an alternative, it behaves differently:
      A (B(*THEN)C | (*FAIL)) | D
    
    The effect of (*THEN) is now confined to the inner subpattern. After a failure in C, matching moves to (*FAIL), which causes the whole subpattern to fail because there are no more alternatives to try. In this case, matching does now backtrack into A.

    Note that a conditional subpattern is not considered as having two alternatives, because only one is ever used. In other words, the | character in a conditional subpattern has a different meaning. Ignoring white space, consider:

      ^.*? (?(?=a) a | b(*THEN)c )
    
    If the subject is "ba", this pattern does not match. Because .*? is ungreedy, it initially matches zero characters. The condition (?=a) then fails, the character "b" is matched, but "c" is not. At this point, matching does not backtrack to .*? as might perhaps be expected from the presence of the | character. The conditional subpattern is part of the single alternative that comprises the whole pattern, and so the match fails. (If there was a backtrack into .*?, allowing it to match "b", the match would succeed.)

    The verbs just described provide four different "strengths" of control when subsequent matching fails. (*THEN) is the weakest, carrying on the match at the next alternative. (*PRUNE) comes next, failing the match at the current starting position, but allowing an advance to the next character (for an unanchored pattern). (*SKIP) is similar, except that the advance may be more than one character. (*COMMIT) is the strongest, causing the entire match to fail.


    More than one backtracking verb

    If more than one backtracking verb is present in a pattern, the one that is backtracked onto first acts. For example, consider this pattern, where A, B, etc. are complex pattern fragments:

      (A(*COMMIT)B(*THEN)C|ABD)
    
    If A matches but B fails, the backtrack to (*COMMIT) causes the entire match to fail. However, if A and B match, but C fails, the backtrack to (*THEN) causes the next alternative (ABD) to be tried. This behaviour is consistent, but is not always the same as Perl's. It means that if two or more backtracking verbs appear in succession, all the the last of them has no effect. Consider this example:
      ...(*COMMIT)(*PRUNE)...
    
    If there is a matching failure to the right, backtracking onto (*PRUNE) causes it to be triggered, and its action is taken. There can never be a backtrack onto (*COMMIT).


    Backtracking verbs in repeated groups

    PCRE differs from Perl in its handling of backtracking verbs in repeated groups. For example, consider:

      /(a(*COMMIT)b)+ac/
    
    If the subject is "abac", Perl matches, but PCRE fails because the (*COMMIT) in the second repeat of the group acts.


    Backtracking verbs in assertions

    (*FAIL) in an assertion has its normal effect: it forces an immediate backtrack.

    (*ACCEPT) in a positive assertion causes the assertion to succeed without any further processing. In a negative assertion, (*ACCEPT) causes the assertion to fail without any further processing.

    The other backtracking verbs are not treated specially if they appear in a positive assertion. In particular, (*THEN) skips to the next alternative in the innermost enclosing group that has alternations, whether or not this is within the assertion.

    Negative assertions are, however, different, in order to ensure that changing a positive assertion into a negative assertion changes its result. Backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes a negative assertion to be true, without considering any further alternative branches in the assertion. Backtracking into (*THEN) causes it to skip to the next enclosing alternative within the assertion (the normal behaviour), but if the assertion does not have such an alternative, (*THEN) behaves like (*PRUNE).


    Backtracking verbs in subroutines

    These behaviours occur whether or not the subpattern is called recursively. Perl's treatment of subroutines is different in some cases.

    (*FAIL) in a subpattern called as a subroutine has its normal effect: it forces an immediate backtrack.

    (*ACCEPT) in a subpattern called as a subroutine causes the subroutine match to succeed without any further processing. Matching then continues after the subroutine call.

    (*COMMIT), (*SKIP), and (*PRUNE) in a subpattern called as a subroutine cause the subroutine match to fail.

    (*THEN) skips to the next alternative in the innermost enclosing group within the subpattern that has alternatives. If there is no such group within the subpattern, (*THEN) causes the subroutine match to fail.


    SEE ALSO

    pcreapi(3), pcrecallout(3), pcrematching(3), pcresyntax(3), pcre(3), pcre16(3), pcre32(3).


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 23 October 2016
    Copyright © 1997-2016 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcreperform.html ================================================ pcreperform specification

    pcreperform man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    PCRE PERFORMANCE

    Two aspects of performance are discussed below: memory usage and processing time. The way you express your pattern as a regular expression can affect both of them.


    COMPILED PATTERN MEMORY USAGE

    Patterns are compiled by PCRE into a reasonably efficient interpretive code, so that most simple patterns do not use much memory. However, there is one case where the memory usage of a compiled pattern can be unexpectedly large. If a parenthesized subpattern has a quantifier with a minimum greater than 1 and/or a limited maximum, the whole subpattern is repeated in the compiled code. For example, the pattern

      (abc|def){2,4}
    
    is compiled as if it were
      (abc|def)(abc|def)((abc|def)(abc|def)?)?
    
    (Technical aside: It is done this way so that backtrack points within each of the repetitions can be independently maintained.)

    For regular expressions whose quantifiers use only small numbers, this is not usually a problem. However, if the numbers are large, and particularly if such repetitions are nested, the memory usage can become an embarrassment. For example, the very simple pattern

      ((ab){1,1000}c){1,3}
    
    uses 51K bytes when compiled using the 8-bit library. When PCRE is compiled with its default internal pointer size of two bytes, the size limit on a compiled pattern is 64K data units, and this is reached with the above pattern if the outer repetition is increased from 3 to 4. PCRE can be compiled to use larger internal pointers and thus handle larger compiled patterns, but it is better to try to rewrite your pattern to use less memory if you can.

    One way of reducing the memory usage for such patterns is to make use of PCRE's "subroutine" facility. Re-writing the above pattern as

      ((ab)(?2){0,999}c)(?1){0,2}
    
    reduces the memory requirements to 18K, and indeed it remains under 20K even with the outer repetition increased to 100. However, this pattern is not exactly equivalent, because the "subroutine" calls are treated as atomic groups into which there can be no backtracking if there is a subsequent matching failure. Therefore, PCRE cannot do this kind of rewriting automatically. Furthermore, there is a noticeable loss of speed when executing the modified pattern. Nevertheless, if the atomic grouping is not a problem and the loss of speed is acceptable, this kind of rewriting will allow you to process patterns that PCRE cannot otherwise handle.


    STACK USAGE AT RUN TIME

    When pcre_exec() or pcre[16|32]_exec() is used for matching, certain kinds of pattern can cause it to use large amounts of the process stack. In some environments the default process stack is quite small, and if it runs out the result is often SIGSEGV. This issue is probably the most frequently raised problem with PCRE. Rewriting your pattern can often help. The pcrestack documentation discusses this issue in detail.


    PROCESSING TIME

    Certain items in regular expression patterns are processed more efficiently than others. It is more efficient to use a character class like [aeiou] than a set of single-character alternatives such as (a|e|i|o|u). In general, the simplest construction that provides the required behaviour is usually the most efficient. Jeffrey Friedl's book contains a lot of useful general discussion about optimizing regular expressions for efficient performance. This document contains a few observations about PCRE.

    Using Unicode character properties (the \p, \P, and \X escapes) is slow, because PCRE has to use a multi-stage table lookup whenever it needs a character's property. If you can find an alternative pattern that does not use character properties, it will probably be faster.

    By default, the escape sequences \b, \d, \s, and \w, and the POSIX character classes such as [:alpha:] do not use Unicode properties, partly for backwards compatibility, and partly for performance reasons. However, you can set PCRE_UCP if you want Unicode character properties to be used. This can double the matching time for items such as \d, when matched with a traditional matching function; the performance loss is less with a DFA matching function, and in both cases there is not much difference for \b.

    When a pattern begins with .* not in parentheses, or in parentheses that are not the subject of a backreference, and the PCRE_DOTALL option is set, the pattern is implicitly anchored by PCRE, since it can match only at the start of a subject string. However, if PCRE_DOTALL is not set, PCRE cannot make this optimization, because the . metacharacter does not then match a newline, and if the subject string contains newlines, the pattern may match from the character immediately following one of them instead of from the very start. For example, the pattern

      .*second
    
    matches the subject "first\nand second" (where \n stands for a newline character), with the match starting at the seventh character. In order to do this, PCRE has to retry the match starting after every newline in the subject.

    If you are using such a pattern with subject strings that do not contain newlines, the best performance is obtained by setting PCRE_DOTALL, or starting the pattern with ^.* or ^.*? to indicate explicit anchoring. That saves PCRE from having to scan along the subject looking for a newline to restart at.

    Beware of patterns that contain nested indefinite repeats. These can take a long time to run when applied to a string that does not match. Consider the pattern fragment

      ^(a+)*
    
    This can match "aaaa" in 16 different ways, and this number increases very rapidly as the string gets longer. (The * repeat can match 0, 1, 2, 3, or 4 times, and for each of those cases other than 0 or 4, the + repeats can match different numbers of times.) When the remainder of the pattern is such that the entire match is going to fail, PCRE has in principle to try every possible variation, and this can take an extremely long time, even for relatively short strings.

    An optimization catches some of the more simple cases such as

      (a+)*b
    
    where a literal character follows. Before embarking on the standard matching procedure, PCRE checks that there is a "b" later in the subject string, and if there is not, it fails the match immediately. However, when there is no following literal this optimization cannot be used. You can see the difference by comparing the behaviour of
      (a+)*\d
    
    with the pattern above. The former gives a failure almost instantly when applied to a whole line of "a" characters, whereas the latter takes an appreciable time with strings longer than about 20 characters.

    In many cases, the solution to this kind of performance issue is to use an atomic group or a possessive quantifier.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 25 August 2012
    Copyright © 1997-2012 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcreposix.html ================================================ pcreposix specification

    pcreposix man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SYNOPSIS

    #include <pcreposix.h>

    int regcomp(regex_t *preg, const char *pattern, int cflags);

    int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);

    void regfree(regex_t *preg);


    DESCRIPTION

    This set of functions provides a POSIX-style API for the PCRE regular expression 8-bit library. See the pcreapi documentation for a description of PCRE's native API, which contains much additional functionality. There is no POSIX-style wrapper for PCRE's 16-bit and 32-bit library.

    The functions described here are just wrapper functions that ultimately call the PCRE native API. Their prototypes are defined in the pcreposix.h header file, and on Unix systems the library itself is called pcreposix.a, so can be accessed by adding -lpcreposix to the command for linking an application that uses them. Because the POSIX functions call the native ones, it is also necessary to add -lpcre.

    I have implemented only those POSIX option bits that can be reasonably mapped to PCRE native options. In addition, the option REG_EXTENDED is defined with the value zero. This has no effect, but since programs that are written to the POSIX interface often use it, this makes it easier to slot in PCRE as a replacement library. Other POSIX options are not even defined.

    There are also some other options that are not defined by POSIX. These have been added at the request of users who want to make use of certain PCRE-specific features via the POSIX calling interface.

    When PCRE is called via these functions, it is only the API that is POSIX-like in style. The syntax and semantics of the regular expressions themselves are still those of Perl, subject to the setting of various PCRE options, as described below. "POSIX-like in style" means that the API approximates to the POSIX definition; it is not fully POSIX-compatible, and in multi-byte encoding domains it is probably even less compatible.

    The header for these functions is supplied as pcreposix.h to avoid any potential clash with other POSIX libraries. It can, of course, be renamed or aliased as regex.h, which is the "correct" name. It provides two structure types, regex_t for compiled internal forms, and regmatch_t for returning captured substrings. It also defines some constants whose names start with "REG_"; these are used for setting options and identifying error codes.


    COMPILING A PATTERN

    The function regcomp() is called to compile a pattern into an internal form. The pattern is a C string terminated by a binary zero, and is passed in the argument pattern. The preg argument is a pointer to a regex_t structure that is used as a base for storing information about the compiled regular expression.

    The argument cflags is either zero, or contains one or more of the bits defined by the following macros:

      REG_DOTALL
    
    The PCRE_DOTALL option is set when the regular expression is passed for compilation to the native function. Note that REG_DOTALL is not part of the POSIX standard.
      REG_ICASE
    
    The PCRE_CASELESS option is set when the regular expression is passed for compilation to the native function.
      REG_NEWLINE
    
    The PCRE_MULTILINE option is set when the regular expression is passed for compilation to the native function. Note that this does not mimic the defined POSIX behaviour for REG_NEWLINE (see the following section).
      REG_NOSUB
    
    The PCRE_NO_AUTO_CAPTURE option is set when the regular expression is passed for compilation to the native function. In addition, when a pattern that is compiled with this flag is passed to regexec() for matching, the nmatch and pmatch arguments are ignored, and no captured strings are returned.
      REG_UCP
    
    The PCRE_UCP option is set when the regular expression is passed for compilation to the native function. This causes PCRE to use Unicode properties when matchine \d, \w, etc., instead of just recognizing ASCII values. Note that REG_UTF8 is not part of the POSIX standard.
      REG_UNGREEDY
    
    The PCRE_UNGREEDY option is set when the regular expression is passed for compilation to the native function. Note that REG_UNGREEDY is not part of the POSIX standard.
      REG_UTF8
    
    The PCRE_UTF8 option is set when the regular expression is passed for compilation to the native function. This causes the pattern itself and all data strings used for matching it to be treated as UTF-8 strings. Note that REG_UTF8 is not part of the POSIX standard.

    In the absence of these flags, no options are passed to the native function. This means the the regex is compiled with PCRE default semantics. In particular, the way it handles newline characters in the subject string is the Perl way, not the POSIX way. Note that setting PCRE_MULTILINE has only some of the effects specified for REG_NEWLINE. It does not affect the way newlines are matched by . (they are not) or by a negative class such as [^a] (they are).

    The yield of regcomp() is zero on success, and non-zero otherwise. The preg structure is filled in on success, and one member of the structure is public: re_nsub contains the number of capturing subpatterns in the regular expression. Various error codes are defined in the header file.

    NOTE: If the yield of regcomp() is non-zero, you must not attempt to use the contents of the preg structure. If, for example, you pass it to regexec(), the result is undefined and your program is likely to crash.


    MATCHING NEWLINE CHARACTERS

    This area is not simple, because POSIX and Perl take different views of things. It is not possible to get PCRE to obey POSIX semantics, but then PCRE was never intended to be a POSIX engine. The following table lists the different possibilities for matching newline characters in PCRE:

                              Default   Change with
    
      . matches newline          no     PCRE_DOTALL
      newline matches [^a]       yes    not changeable
      $ matches \n at end        yes    PCRE_DOLLARENDONLY
      $ matches \n in middle     no     PCRE_MULTILINE
      ^ matches \n in middle     no     PCRE_MULTILINE
    
    This is the equivalent table for POSIX:
                              Default   Change with
    
      . matches newline          yes    REG_NEWLINE
      newline matches [^a]       yes    REG_NEWLINE
      $ matches \n at end        no     REG_NEWLINE
      $ matches \n in middle     no     REG_NEWLINE
      ^ matches \n in middle     no     REG_NEWLINE
    
    PCRE's behaviour is the same as Perl's, except that there is no equivalent for PCRE_DOLLAR_ENDONLY in Perl. In both PCRE and Perl, there is no way to stop newline from matching [^a].

    The default POSIX newline handling can be obtained by setting PCRE_DOTALL and PCRE_DOLLAR_ENDONLY, but there is no way to make PCRE behave exactly as for the REG_NEWLINE action.


    MATCHING A PATTERN

    The function regexec() is called to match a compiled pattern preg against a given string, which is by default terminated by a zero byte (but see REG_STARTEND below), subject to the options in eflags. These can be:

      REG_NOTBOL
    
    The PCRE_NOTBOL option is set when calling the underlying PCRE matching function.
      REG_NOTEMPTY
    
    The PCRE_NOTEMPTY option is set when calling the underlying PCRE matching function. Note that REG_NOTEMPTY is not part of the POSIX standard. However, setting this option can give more POSIX-like behaviour in some situations.
      REG_NOTEOL
    
    The PCRE_NOTEOL option is set when calling the underlying PCRE matching function.
      REG_STARTEND
    
    The string is considered to start at string + pmatch[0].rm_so and to have a terminating NUL located at string + pmatch[0].rm_eo (there need not actually be a NUL at that location), regardless of the value of nmatch. This is a BSD extension, compatible with but not specified by IEEE Standard 1003.2 (POSIX.2), and should be used with caution in software intended to be portable to other systems. Note that a non-zero rm_so does not imply REG_NOTBOL; REG_STARTEND affects only the location of the string, not how it is matched.

    If the pattern was compiled with the REG_NOSUB flag, no data about any matched strings is returned. The nmatch and pmatch arguments of regexec() are ignored.

    If the value of nmatch is zero, or if the value pmatch is NULL, no data about any matched strings is returned.

    Otherwise,the portion of the string that was matched, and also any captured substrings, are returned via the pmatch argument, which points to an array of nmatch structures of type regmatch_t, containing the members rm_so and rm_eo. These contain the offset to the first character of each substring and the offset to the first character after the end of each substring, respectively. The 0th element of the vector relates to the entire portion of string that was matched; subsequent elements relate to the capturing subpatterns of the regular expression. Unused entries in the array have both structure members set to -1.

    A successful match yields a zero return; various error codes are defined in the header file, of which REG_NOMATCH is the "expected" failure code.


    ERROR MESSAGES

    The regerror() function maps a non-zero errorcode from either regcomp() or regexec() to a printable message. If preg is not NULL, the error should have arisen from the use of that structure. A message terminated by a binary zero is placed in errbuf. The length of the message, including the zero, is limited to errbuf_size. The yield of the function is the size of buffer needed to hold the whole message.


    MEMORY USAGE

    Compiling a regular expression causes memory to be allocated and associated with the preg structure. The function regfree() frees all such memory, after which preg may no longer be used as a compiled expression.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 09 January 2012
    Copyright © 1997-2012 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcreprecompile.html ================================================ pcreprecompile specification

    pcreprecompile man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SAVING AND RE-USING PRECOMPILED PCRE PATTERNS

    If you are running an application that uses a large number of regular expression patterns, it may be useful to store them in a precompiled form instead of having to compile them every time the application is run. If you are not using any private character tables (see the pcre_maketables() documentation), this is relatively straightforward. If you are using private tables, it is a little bit more complicated. However, if you are using the just-in-time optimization feature, it is not possible to save and reload the JIT data.

    If you save compiled patterns to a file, you can copy them to a different host and run them there. If the two hosts have different endianness (byte order), you should run the pcre[16|32]_pattern_to_host_byte_order() function on the new host before trying to match the pattern. The matching functions return PCRE_ERROR_BADENDIANNESS if they detect a pattern with the wrong endianness.

    Compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes, and saving and restoring a compiled pattern loses any JIT optimization data.


    SAVING A COMPILED PATTERN

    The value returned by pcre[16|32]_compile() points to a single block of memory that holds the compiled pattern and associated data. You can find the length of this block in bytes by calling pcre[16|32]_fullinfo() with an argument of PCRE_INFO_SIZE. You can then save the data in any appropriate manner. Here is sample code for the 8-bit library that compiles a pattern and writes it to a file. It assumes that the variable fd refers to a file that is open for output:

      int erroroffset, rc, size;
      char *error;
      pcre *re;
    
      re = pcre_compile("my pattern", 0, &error, &erroroffset, NULL);
      if (re == NULL) { ... handle errors ... }
      rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
      if (rc < 0) { ... handle errors ... }
      rc = fwrite(re, 1, size, fd);
      if (rc != size) { ... handle errors ... }
    
    In this example, the bytes that comprise the compiled pattern are copied exactly. Note that this is binary data that may contain any of the 256 possible byte values. On systems that make a distinction between binary and non-binary data, be sure that the file is opened for binary output.

    If you want to write more than one pattern to a file, you will have to devise a way of separating them. For binary data, preceding each pattern with its length is probably the most straightforward approach. Another possibility is to write out the data in hexadecimal instead of binary, one pattern to a line.

    Saving compiled patterns in a file is only one possible way of storing them for later use. They could equally well be saved in a database, or in the memory of some daemon process that passes them via sockets to the processes that want them.

    If the pattern has been studied, it is also possible to save the normal study data in a similar way to the compiled pattern itself. However, if the PCRE_STUDY_JIT_COMPILE was used, the just-in-time data that is created cannot be saved because it is too dependent on the current environment. When studying generates additional information, pcre[16|32]_study() returns a pointer to a pcre[16|32]_extra data block. Its format is defined in the section on matching a pattern in the pcreapi documentation. The study_data field points to the binary study data, and this is what you must save (not the pcre[16|32]_extra block itself). The length of the study data can be obtained by calling pcre[16|32]_fullinfo() with an argument of PCRE_INFO_STUDYSIZE. Remember to check that pcre[16|32]_study() did return a non-NULL value before trying to save the study data.


    RE-USING A PRECOMPILED PATTERN

    Re-using a precompiled pattern is straightforward. Having reloaded it into main memory, called pcre[16|32]_pattern_to_host_byte_order() if necessary, you pass its pointer to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() in the usual way.

    However, if you passed a pointer to custom character tables when the pattern was compiled (the tableptr argument of pcre[16|32]_compile()), you must now pass a similar pointer to pcre[16|32]_exec() or pcre[16|32]_dfa_exec(), because the value saved with the compiled pattern will obviously be nonsense. A field in a pcre[16|32]_extra() block is used to pass this data, as described in the section on matching a pattern in the pcreapi documentation.

    Warning: The tables that pcre_exec() and pcre_dfa_exec() use must be the same as those that were used when the pattern was compiled. If this is not the case, the behaviour is undefined.

    If you did not provide custom character tables when the pattern was compiled, the pointer in the compiled pattern is NULL, which causes the matching functions to use PCRE's internal tables. Thus, you do not need to take any special action at run time in this case.

    If you saved study data with the compiled pattern, you need to create your own pcre[16|32]_extra data block and set the study_data field to point to the reloaded study data. You must also set the PCRE_EXTRA_STUDY_DATA bit in the flags field to indicate that study data is present. Then pass the pcre[16|32]_extra block to the matching function in the usual way. If the pattern was studied for just-in-time optimization, that data cannot be saved, and so is lost by a save/restore cycle.


    COMPATIBILITY WITH DIFFERENT PCRE RELEASES

    In general, it is safest to recompile all saved patterns when you update to a new PCRE release, though not all updates actually require this.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 12 November 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcresample.html ================================================ pcresample specification

    pcresample man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    PCRE SAMPLE PROGRAM

    A simple, complete demonstration program, to get you started with using PCRE, is supplied in the file pcredemo.c in the PCRE distribution. A listing of this program is given in the pcredemo documentation. If you do not have a copy of the PCRE distribution, you can save this listing to re-create pcredemo.c.

    The demonstration program, which uses the original PCRE 8-bit library, compiles the regular expression that is its first argument, and matches it against the subject string in its second argument. No PCRE options are set, and default character tables are used. If matching succeeds, the program outputs the portion of the subject that matched, together with the contents of any captured substrings.

    If the -g option is given on the command line, the program then goes on to check for further matches of the same regular expression in the same subject string. The logic is a little bit tricky because of the possibility of matching an empty string. Comments in the code explain what is going on.

    If PCRE is installed in the standard include and library directories for your operating system, you should be able to compile the demonstration program using this command:

      gcc -o pcredemo pcredemo.c -lpcre
    
    If PCRE is installed elsewhere, you may need to add additional options to the command line. For example, on a Unix-like system that has PCRE installed in /usr/local, you can compile the demonstration program using a command like this:
      gcc -o pcredemo -I/usr/local/include pcredemo.c -L/usr/local/lib -lpcre
    
    In a Windows environment, if you want to statically link the program against a non-dll pcre.a file, you must uncomment the line that defines PCRE_STATIC before including pcre.h, because otherwise the pcre_malloc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results.

    Once you have compiled and linked the demonstration program, you can run simple tests like this:

      ./pcredemo 'cat|dog' 'the cat sat on the mat'
      ./pcredemo -g 'cat|dog' 'the dog sat on the cat'
    
    Note that there is a much more comprehensive test program, called pcretest, which supports many more facilities for testing regular expressions and both PCRE libraries. The pcredemo program is provided as a simple coding example.

    If you try to run pcredemo when PCRE is not installed in the standard library directory, you may get an error like this on some operating systems (e.g. Solaris):

      ld.so.1: a.out: fatal: libpcre.so.0: open failed: No such file or directory
    
    This is caused by the way shared library support works on those systems. You need to add
      -R/usr/local/lib
    
    (for example) to the compile command to get round this problem.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 10 January 2012
    Copyright © 1997-2012 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcrestack.html ================================================ pcrestack specification

    pcrestack man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    PCRE DISCUSSION OF STACK USAGE

    When you call pcre[16|32]_exec(), it makes use of an internal function called match(). This calls itself recursively at branch points in the pattern, in order to remember the state of the match so that it can back up and try a different alternative if the first one fails. As matching proceeds deeper and deeper into the tree of possibilities, the recursion depth increases. The match() function is also called in other circumstances, for example, whenever a parenthesized sub-pattern is entered, and in certain cases of repetition.

    Not all calls of match() increase the recursion depth; for an item such as a* it may be called several times at the same level, after matching different numbers of a's. Furthermore, in a number of cases where the result of the recursive call would immediately be passed back as the result of the current call (a "tail recursion"), the function is just restarted instead.

    The above comments apply when pcre[16|32]_exec() is run in its normal interpretive manner. If the pattern was studied with the PCRE_STUDY_JIT_COMPILE option, and just-in-time compiling was successful, and the options passed to pcre[16|32]_exec() were not incompatible, the matching process uses the JIT-compiled code instead of the match() function. In this case, the memory requirements are handled entirely differently. See the pcrejit documentation for details.

    The pcre[16|32]_dfa_exec() function operates in an entirely different way, and uses recursion only when there is a regular expression recursion or subroutine call in the pattern. This includes the processing of assertion and "once-only" subpatterns, which are handled like subroutine calls. Normally, these are never very deep, and the limit on the complexity of pcre[16|32]_dfa_exec() is controlled by the amount of workspace it is given. However, it is possible to write patterns with runaway infinite recursions; such patterns will cause pcre[16|32]_dfa_exec() to run out of stack. At present, there is no protection against this.

    The comments that follow do NOT apply to pcre[16|32]_dfa_exec(); they are relevant only for pcre[16|32]_exec() without the JIT optimization.


    Reducing pcre[16|32]_exec()'s stack usage

    Each time that match() is actually called recursively, it uses memory from the process stack. For certain kinds of pattern and data, very large amounts of stack may be needed, despite the recognition of "tail recursion". You can often reduce the amount of recursion, and therefore the amount of stack used, by modifying the pattern that is being matched. Consider, for example, this pattern:

      ([^<]|<(?!inet))+
    
    It matches from wherever it starts until it encounters "<inet" or the end of the data, and is the kind of pattern that might be used when processing an XML file. Each iteration of the outer parentheses matches either one character that is not "<" or a "<" that is not followed by "inet". However, each time a parenthesis is processed, a recursion occurs, so this formulation uses a stack frame for each matched character. For a long string, a lot of stack is required. Consider now this rewritten pattern, which matches exactly the same strings:
      ([^<]++|<(?!inet))+
    
    This uses very much less stack, because runs of characters that do not contain "<" are "swallowed" in one item inside the parentheses. Recursion happens only when a "<" character that is not followed by "inet" is encountered (and we assume this is relatively rare). A possessive quantifier is used to stop any backtracking into the runs of non-"<" characters, but that is not related to stack usage.

    This example shows that one way of avoiding stack problems when matching long subject strings is to write repeated parenthesized subpatterns to match more than one character whenever possible.


    Compiling PCRE to use heap instead of stack for pcre[16|32]_exec()

    In environments where stack memory is constrained, you might want to compile PCRE to use heap memory instead of stack for remembering back-up points when pcre[16|32]_exec() is running. This makes it run a lot more slowly, however. Details of how to do this are given in the pcrebuild documentation. When built in this way, instead of using the stack, PCRE obtains and frees memory by calling the functions that are pointed to by the pcre[16|32]_stack_malloc and pcre[16|32]_stack_free variables. By default, these point to malloc() and free(), but you can replace the pointers to cause PCRE to use your own functions. Since the block sizes are always the same, and are always freed in reverse order, it may be possible to implement customized memory handlers that are more efficient than the standard functions.


    Limiting pcre[16|32]_exec()'s stack usage

    You can set limits on the number of times that match() is called, both in total and recursively. If a limit is exceeded, pcre[16|32]_exec() returns an error code. Setting suitable limits should prevent it from running out of stack. The default values of the limits are very large, and unlikely ever to operate. They can be changed when PCRE is built, and they can also be set when pcre[16|32]_exec() is called. For details of these interfaces, see the pcrebuild documentation and the section on extra data for pcre[16|32]_exec() in the pcreapi documentation.

    As a very rough rule of thumb, you should reckon on about 500 bytes per recursion. Thus, if you want to limit your stack usage to 8Mb, you should set the limit at 16000 recursions. A 64Mb stack, on the other hand, can support around 128000 recursions.

    In Unix-like environments, the pcretest test program has a command line option (-S) that can be used to increase the size of its stack. As long as the stack is large enough, another option (-M) can be used to find the smallest limits that allow a particular pattern to match a given subject string. This is done by calling pcre[16|32]_exec() repeatedly with different limits.


    Obtaining an estimate of stack usage

    The actual amount of stack used per recursion can vary quite a lot, depending on the compiler that was used to build PCRE and the optimization or debugging options that were set for it. The rule of thumb value of 500 bytes mentioned above may be larger or smaller than what is actually needed. A better approximation can be obtained by running this command:

      pcretest -m -C
    
    The -C option causes pcretest to output information about the options with which PCRE was compiled. When -m is also given (before -C), information about stack use is given in a line like this:
      Match recursion uses stack: approximate frame size = 640 bytes
    
    The value is approximate because some recursions need a bit more (up to perhaps 16 more bytes).

    If the above command is given when PCRE is compiled to use the heap instead of the stack for recursion, the value that is output is the size of each block that is obtained from the heap.


    Changing stack size in Unix-like systems

    In Unix-like environments, there is not often a problem with the stack unless very long strings are involved, though the default limit on stack size varies from system to system. Values from 8Mb to 64Mb are common. You can find your default limit by running the command:

      ulimit -s
    
    Unfortunately, the effect of running out of stack is often SIGSEGV, though sometimes a more explicit error message is given. You can normally increase the limit on stack size by code such as this:
      struct rlimit rlim;
      getrlimit(RLIMIT_STACK, &rlim);
      rlim.rlim_cur = 100*1024*1024;
      setrlimit(RLIMIT_STACK, &rlim);
    
    This reads the current limits (soft and hard) using getrlimit(), then attempts to increase the soft limit to 100Mb using setrlimit(). You must do this before calling pcre[16|32]_exec().


    Changing stack size in Mac OS X

    Using setrlimit(), as described above, should also work on Mac OS X. It is also possible to set a stack size when linking a program. There is a discussion about stack sizes in Mac OS X at this web site: http://developer.apple.com/qa/qa2005/qa1419.html.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 24 June 2012
    Copyright © 1997-2012 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcresyntax.html ================================================ pcresyntax specification

    pcresyntax man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    PCRE REGULAR EXPRESSION SYNTAX SUMMARY

    The full syntax and semantics of the regular expressions that are supported by PCRE are described in the pcrepattern documentation. This document contains a quick-reference summary of the syntax.


    QUOTING

      \x         where x is non-alphanumeric is a literal x
      \Q...\E    treat enclosed characters as literal
    


    CHARACTERS

      \a         alarm, that is, the BEL character (hex 07)
      \cx        "control-x", where x is any ASCII character
      \e         escape (hex 1B)
      \f         form feed (hex 0C)
      \n         newline (hex 0A)
      \r         carriage return (hex 0D)
      \t         tab (hex 09)
      \0dd       character with octal code 0dd
      \ddd       character with octal code ddd, or backreference
      \o{ddd..}  character with octal code ddd..
      \xhh       character with hex code hh
      \x{hhh..}  character with hex code hhh..
    
    Note that \0dd is always an octal code, and that \8 and \9 are the literal characters "8" and "9".


    CHARACTER TYPES

      .          any character except newline;
                   in dotall mode, any character whatsoever
      \C         one data unit, even in UTF mode (best avoided)
      \d         a decimal digit
      \D         a character that is not a decimal digit
      \h         a horizontal white space character
      \H         a character that is not a horizontal white space character
      \N         a character that is not a newline
      \p{xx}     a character with the xx property
      \P{xx}     a character without the xx property
      \R         a newline sequence
      \s         a white space character
      \S         a character that is not a white space character
      \v         a vertical white space character
      \V         a character that is not a vertical white space character
      \w         a "word" character
      \W         a "non-word" character
      \X         a Unicode extended grapheme cluster
    
    By default, \d, \s, and \w match only ASCII characters, even in UTF-8 mode or in the 16- bit and 32-bit libraries. However, if locale-specific matching is happening, \s and \w may also match characters with code points in the range 128-255. If the PCRE_UCP option is set, the behaviour of these escape sequences is changed to use Unicode properties and they match many more characters.


    GENERAL CATEGORY PROPERTIES FOR \p and \P

      C          Other
      Cc         Control
      Cf         Format
      Cn         Unassigned
      Co         Private use
      Cs         Surrogate
    
      L          Letter
      Ll         Lower case letter
      Lm         Modifier letter
      Lo         Other letter
      Lt         Title case letter
      Lu         Upper case letter
      L&         Ll, Lu, or Lt
    
      M          Mark
      Mc         Spacing mark
      Me         Enclosing mark
      Mn         Non-spacing mark
    
      N          Number
      Nd         Decimal number
      Nl         Letter number
      No         Other number
    
      P          Punctuation
      Pc         Connector punctuation
      Pd         Dash punctuation
      Pe         Close punctuation
      Pf         Final punctuation
      Pi         Initial punctuation
      Po         Other punctuation
      Ps         Open punctuation
    
      S          Symbol
      Sc         Currency symbol
      Sk         Modifier symbol
      Sm         Mathematical symbol
      So         Other symbol
    
      Z          Separator
      Zl         Line separator
      Zp         Paragraph separator
      Zs         Space separator
    


    PCRE SPECIAL CATEGORY PROPERTIES FOR \p and \P

      Xan        Alphanumeric: union of properties L and N
      Xps        POSIX space: property Z or tab, NL, VT, FF, CR
      Xsp        Perl space: property Z or tab, NL, VT, FF, CR
      Xuc        Univerally-named character: one that can be
                   represented by a Universal Character Name
      Xwd        Perl word: property Xan or underscore
    
    Perl and POSIX space are now the same. Perl added VT to its space character set at release 5.18 and PCRE changed at release 8.34.


    SCRIPT NAMES FOR \p AND \P

    Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hieroglyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Shavian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi.


    CHARACTER CLASSES

      [...]       positive character class
      [^...]      negative character class
      [x-y]       range (can be used for hex characters)
      [[:xxx:]]   positive POSIX named set
      [[:^xxx:]]  negative POSIX named set
    
      alnum       alphanumeric
      alpha       alphabetic
      ascii       0-127
      blank       space or tab
      cntrl       control character
      digit       decimal digit
      graph       printing, excluding space
      lower       lower case letter
      print       printing, including space
      punct       printing, excluding alphanumeric
      space       white space
      upper       upper case letter
      word        same as \w
      xdigit      hexadecimal digit
    
    In PCRE, POSIX character set names recognize only ASCII characters by default, but some of them use Unicode properties if PCRE_UCP is set. You can use \Q...\E inside a character class.


    QUANTIFIERS

      ?           0 or 1, greedy
      ?+          0 or 1, possessive
      ??          0 or 1, lazy
      *           0 or more, greedy
      *+          0 or more, possessive
      *?          0 or more, lazy
      +           1 or more, greedy
      ++          1 or more, possessive
      +?          1 or more, lazy
      {n}         exactly n
      {n,m}       at least n, no more than m, greedy
      {n,m}+      at least n, no more than m, possessive
      {n,m}?      at least n, no more than m, lazy
      {n,}        n or more, greedy
      {n,}+       n or more, possessive
      {n,}?       n or more, lazy
    


    ANCHORS AND SIMPLE ASSERTIONS

      \b          word boundary
      \B          not a word boundary
      ^           start of subject
                   also after internal newline in multiline mode
      \A          start of subject
      $           end of subject
                   also before newline at end of subject
                   also before internal newline in multiline mode
      \Z          end of subject
                   also before newline at end of subject
      \z          end of subject
      \G          first matching position in subject
    


    MATCH POINT RESET

      \K          reset start of match
    
    \K is honoured in positive assertions, but ignored in negative ones.


    ALTERNATION

      expr|expr|expr...
    


    CAPTURING

      (...)           capturing group
      (?<name>...)    named capturing group (Perl)
      (?'name'...)    named capturing group (Perl)
      (?P<name>...)   named capturing group (Python)
      (?:...)         non-capturing group
      (?|...)         non-capturing group; reset group numbers for
                       capturing groups in each alternative
    


    ATOMIC GROUPS

      (?>...)         atomic, non-capturing group
    


    COMMENT

      (?#....)        comment (not nestable)
    


    OPTION SETTING

      (?i)            caseless
      (?J)            allow duplicate names
      (?m)            multiline
      (?s)            single line (dotall)
      (?U)            default ungreedy (lazy)
      (?x)            extended (ignore white space)
      (?-...)         unset option(s)
    
    The following are recognized only at the very start of a pattern or after one of the newline or \R options with similar syntax. More than one of them may appear.
      (*LIMIT_MATCH=d) set the match limit to d (decimal number)
      (*LIMIT_RECURSION=d) set the recursion limit to d (decimal number)
      (*NO_AUTO_POSSESS) no auto-possessification (PCRE_NO_AUTO_POSSESS)
      (*NO_START_OPT) no start-match optimization (PCRE_NO_START_OPTIMIZE)
      (*UTF8)         set UTF-8 mode: 8-bit library (PCRE_UTF8)
      (*UTF16)        set UTF-16 mode: 16-bit library (PCRE_UTF16)
      (*UTF32)        set UTF-32 mode: 32-bit library (PCRE_UTF32)
      (*UTF)          set appropriate UTF mode for the library in use
      (*UCP)          set PCRE_UCP (use Unicode properties for \d etc)
    
    Note that LIMIT_MATCH and LIMIT_RECURSION can only reduce the value of the limits set by the caller of pcre_exec(), not increase them.


    NEWLINE CONVENTION

    These are recognized only at the very start of the pattern or after option settings with a similar syntax.

      (*CR)           carriage return only
      (*LF)           linefeed only
      (*CRLF)         carriage return followed by linefeed
      (*ANYCRLF)      all three of the above
      (*ANY)          any Unicode newline sequence
    


    WHAT \R MATCHES

    These are recognized only at the very start of the pattern or after option setting with a similar syntax.

      (*BSR_ANYCRLF)  CR, LF, or CRLF
      (*BSR_UNICODE)  any Unicode newline sequence
    


    LOOKAHEAD AND LOOKBEHIND ASSERTIONS

      (?=...)         positive look ahead
      (?!...)         negative look ahead
      (?<=...)        positive look behind
      (?<!...)        negative look behind
    
    Each top-level branch of a look behind must be of a fixed length.


    BACKREFERENCES

      \n              reference by number (can be ambiguous)
      \gn             reference by number
      \g{n}           reference by number
      \g{-n}          relative reference by number
      \k<name>        reference by name (Perl)
      \k'name'        reference by name (Perl)
      \g{name}        reference by name (Perl)
      \k{name}        reference by name (.NET)
      (?P=name)       reference by name (Python)
    


    SUBROUTINE REFERENCES (POSSIBLY RECURSIVE)

      (?R)            recurse whole pattern
      (?n)            call subpattern by absolute number
      (?+n)           call subpattern by relative number
      (?-n)           call subpattern by relative number
      (?&name)        call subpattern by name (Perl)
      (?P>name)       call subpattern by name (Python)
      \g<name>        call subpattern by name (Oniguruma)
      \g'name'        call subpattern by name (Oniguruma)
      \g<n>           call subpattern by absolute number (Oniguruma)
      \g'n'           call subpattern by absolute number (Oniguruma)
      \g<+n>          call subpattern by relative number (PCRE extension)
      \g'+n'          call subpattern by relative number (PCRE extension)
      \g<-n>          call subpattern by relative number (PCRE extension)
      \g'-n'          call subpattern by relative number (PCRE extension)
    


    CONDITIONAL PATTERNS

      (?(condition)yes-pattern)
      (?(condition)yes-pattern|no-pattern)
    
      (?(n)...        absolute reference condition
      (?(+n)...       relative reference condition
      (?(-n)...       relative reference condition
      (?(<name>)...   named reference condition (Perl)
      (?('name')...   named reference condition (Perl)
      (?(name)...     named reference condition (PCRE)
      (?(R)...        overall recursion condition
      (?(Rn)...       specific group recursion condition
      (?(R&name)...   specific recursion condition
      (?(DEFINE)...   define subpattern for reference
      (?(assert)...   assertion condition
    


    BACKTRACKING CONTROL

    The following act immediately they are reached:

      (*ACCEPT)       force successful match
      (*FAIL)         force backtrack; synonym (*F)
      (*MARK:NAME)    set name to be passed back; synonym (*:NAME)
    
    The following act only when a subsequent match failure causes a backtrack to reach them. They all force a match failure, but they differ in what happens afterwards. Those that advance the start-of-match point do so only if the pattern is not anchored.
      (*COMMIT)       overall failure, no advance of starting point
      (*PRUNE)        advance to next starting character
      (*PRUNE:NAME)   equivalent to (*MARK:NAME)(*PRUNE)
      (*SKIP)         advance to current matching position
      (*SKIP:NAME)    advance to position corresponding to an earlier
                      (*MARK:NAME); if not found, the (*SKIP) is ignored
      (*THEN)         local failure, backtrack to next alternation
      (*THEN:NAME)    equivalent to (*MARK:NAME)(*THEN)
    


    CALLOUTS

      (?C)      callout
      (?Cn)     callout with data n
    


    SEE ALSO

    pcrepattern(3), pcreapi(3), pcrecallout(3), pcrematching(3), pcre(3).


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 08 January 2014
    Copyright © 1997-2014 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcretest.html ================================================ pcretest specification

    pcretest man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.


    SYNOPSIS

    pcretest [options] [input file [output file]]

    pcretest was written as a test program for the PCRE regular expression library itself, but it can also be used for experimenting with regular expressions. This document describes the features of the test program; for details of the regular expressions themselves, see the pcrepattern documentation. For details of the PCRE library function calls and their options, see the pcreapi , pcre16 and pcre32 documentation.

    The input for pcretest is a sequence of regular expression patterns and strings to be matched, as described below. The output shows the result of each match. Options on the command line and the patterns control PCRE options and exactly what is output.

    As PCRE has evolved, it has acquired many different features, and as a result, pcretest now has rather a lot of obscure options for testing every possible feature. Some of these options are specifically designed for use in conjunction with the test script and data files that are distributed as part of PCRE, and are unlikely to be of use otherwise. They are all documented here, but without much justification.


    INPUT DATA FORMAT

    Input to pcretest is processed line by line, either by calling the C library's fgets() function, or via the libreadline library (see below). In Unix-like environments, fgets() treats any bytes other than newline as data characters. However, in some Windows environments character 26 (hex 1A) causes an immediate end of file, and no further data is read. For maximum portability, therefore, it is safest to use only ASCII characters in pcretest input files.

    The input is processed using using C's string functions, so must not contain binary zeroes, even though in Unix-like environments, fgets() treats any bytes other than newline as data characters.


    PCRE's 8-BIT, 16-BIT AND 32-BIT LIBRARIES

    From release 8.30, two separate PCRE libraries can be built. The original one supports 8-bit character strings, whereas the newer 16-bit library supports character strings encoded in 16-bit units. From release 8.32, a third library can be built, supporting character strings encoded in 32-bit units. The pcretest program can be used to test all three libraries. However, it is itself still an 8-bit program, reading 8-bit input and writing 8-bit output. When testing the 16-bit or 32-bit library, the patterns and data strings are converted to 16- or 32-bit format before being passed to the PCRE library functions. Results are converted to 8-bit for output.

    References to functions and structures of the form pcre[16|32]_xx below mean "pcre_xx when using the 8-bit library, pcre16_xx when using the 16-bit library, or pcre32_xx when using the 32-bit library".


    COMMAND LINE OPTIONS

    -8 If both the 8-bit library has been built, this option causes the 8-bit library to be used (which is the default); if the 8-bit library has not been built, this option causes an error.

    -16 If both the 8-bit or the 32-bit, and the 16-bit libraries have been built, this option causes the 16-bit library to be used. If only the 16-bit library has been built, this is the default (so has no effect). If only the 8-bit or the 32-bit library has been built, this option causes an error.

    -32 If both the 8-bit or the 16-bit, and the 32-bit libraries have been built, this option causes the 32-bit library to be used. If only the 32-bit library has been built, this is the default (so has no effect). If only the 8-bit or the 16-bit library has been built, this option causes an error.

    -b Behave as if each pattern has the /B (show byte code) modifier; the internal form is output after compilation.

    -C Output the version number of the PCRE library, and all available information about the optional features that are included, and then exit with zero exit code. All other options are ignored.

    -C option Output information about a specific build-time option, then exit. This functionality is intended for use in scripts such as RunTest. The following options output the value and set the exit code as indicated:

      ebcdic-nl  the code for LF (= NL) in an EBCDIC environment:
                   0x15 or 0x25
                   0 if used in an ASCII environment
                   exit code is always 0
      linksize   the configured internal link size (2, 3, or 4)
                   exit code is set to the link size
      newline    the default newline setting:
                   CR, LF, CRLF, ANYCRLF, or ANY
                   exit code is always 0
      bsr        the default setting for what \R matches:
                   ANYCRLF or ANY
                   exit code is always 0
    
    The following options output 1 for true or 0 for false, and set the exit code to the same value:
      ebcdic     compiled for an EBCDIC environment
      jit        just-in-time support is available
      pcre16     the 16-bit library was built
      pcre32     the 32-bit library was built
      pcre8      the 8-bit library was built
      ucp        Unicode property support is available
      utf        UTF-8 and/or UTF-16 and/or UTF-32 support
                   is available
    
    If an unknown option is given, an error message is output; the exit code is 0.

    -d Behave as if each pattern has the /D (debug) modifier; the internal form and information about the compiled pattern is output after compilation; -d is equivalent to -b -i.

    -dfa Behave as if each data line contains the \D escape sequence; this causes the alternative matching function, pcre[16|32]_dfa_exec(), to be used instead of the standard pcre[16|32]_exec() function (more detail is given below).

    -help Output a brief summary these options and then exit.

    -i Behave as if each pattern has the /I modifier; information about the compiled pattern is given after compilation.

    -M Behave as if each data line contains the \M escape sequence; this causes PCRE to discover the minimum MATCH_LIMIT and MATCH_LIMIT_RECURSION settings by calling pcre[16|32]_exec() repeatedly with different limits.

    -m Output the size of each compiled pattern after it has been compiled. This is equivalent to adding /M to each regular expression. The size is given in bytes for both libraries.

    -O Behave as if each pattern has the /O modifier, that is disable auto-possessification for all patterns.

    -o osize Set the number of elements in the output vector that is used when calling pcre[16|32]_exec() or pcre[16|32]_dfa_exec() to be osize. The default value is 45, which is enough for 14 capturing subexpressions for pcre[16|32]_exec() or 22 different matches for pcre[16|32]_dfa_exec(). The vector size can be changed for individual matching calls by including \O in the data line (see below).

    -p Behave as if each pattern has the /P modifier; the POSIX wrapper API is used to call PCRE. None of the other options has any effect when -p is set. This option can be used only with the 8-bit library.

    -q Do not output the version number of pcretest at the start of execution.

    -S size On Unix-like systems, set the size of the run-time stack to size megabytes.

    -s or -s+ Behave as if each pattern has the /S modifier; in other words, force each pattern to be studied. If -s+ is used, all the JIT compile options are passed to pcre[16|32]_study(), causing just-in-time optimization to be set up if it is available, for both full and partial matching. Specific JIT compile options can be selected by following -s+ with a digit in the range 1 to 7, which selects the JIT compile modes as follows:

      1  normal match only
      2  soft partial match only
      3  normal match and soft partial match
      4  hard partial match only
      6  soft and hard partial match
      7  all three modes (default)
    
    If -s++ is used instead of -s+ (with or without a following digit), the text "(JIT)" is added to the first output line after a match or no match when JIT-compiled code was actually used.

    Note that there are pattern options that can override -s, either specifying no studying at all, or suppressing JIT compilation.

    If the /I or /D option is present on a pattern (requesting output about the compiled pattern), information about the result of studying is not included when studying is caused only by -s and neither -i nor -d is present on the command line. This behaviour means that the output from tests that are run with and without -s should be identical, except when options that output information about the actual running of a match are set.

    The -M, -t, and -tm options, which give information about resources used, are likely to produce different output with and without -s. Output may also differ if the /C option is present on an individual pattern. This uses callouts to trace the the matching process, and this may be different between studied and non-studied patterns. If the pattern contains (*MARK) items there may also be differences, for the same reason. The -s command line option can be overridden for specific patterns that should never be studied (see the /S pattern modifier below).

    -t Run each compile, study, and match many times with a timer, and output the resulting times per compile, study, or match (in milliseconds). Do not set -m with -t, because you will then get the size output a zillion times, and the timing will be distorted. You can control the number of iterations that are used for timing by following -t with a number (as a separate item on the command line). For example, "-t 1000" iterates 1000 times. The default is to iterate 500000 times.

    -tm This is like -t except that it times only the matching phase, not the compile or study phases.

    -T -TM These behave like -t and -tm, but in addition, at the end of a run, the total times for all compiles, studies, and matches are output.


    DESCRIPTION

    If pcretest is given two filename arguments, it reads from the first and writes to the second. If it is given only one filename argument, it reads from that file and writes to stdout. Otherwise, it reads from stdin and writes to stdout, and prompts for each line of input, using "re>" to prompt for regular expressions, and "data>" to prompt for data lines.

    When pcretest is built, a configuration option can specify that it should be linked with the libreadline library. When this is done, if the input is from a terminal, it is read using the readline() function. This provides line-editing and history facilities. The output from the -help option states whether or not readline() will be used.

    The program handles any number of sets of input on a single input file. Each set starts with a regular expression, and continues with any number of data lines to be matched against that pattern.

    Each data line is matched separately and independently. If you want to do multi-line matches, you have to use the \n escape sequence (or \r or \r\n, etc., depending on the newline setting) in a single line of input to encode the newline sequences. There is no limit on the length of data lines; the input buffer is automatically extended if it is too small.

    An empty line signals the end of the data lines, at which point a new regular expression is read. The regular expressions are given enclosed in any non-alphanumeric delimiters other than backslash, for example:

      /(a|bc)x+yz/
    
    White space before the initial delimiter is ignored. A regular expression may be continued over several input lines, in which case the newline characters are included within it. It is possible to include the delimiter within the pattern by escaping it, for example
      /abc\/def/
    
    If you do so, the escape and the delimiter form part of the pattern, but since delimiters are always non-alphanumeric, this does not affect its interpretation. If the terminating delimiter is immediately followed by a backslash, for example,
      /abc/\
    
    then a backslash is added to the end of the pattern. This is done to provide a way of testing the error condition that arises if a pattern finishes with a backslash, because
      /abc\/
    
    is interpreted as the first line of a pattern that starts with "abc/", causing pcretest to read the next line as a continuation of the regular expression.


    PATTERN MODIFIERS

    A pattern may be followed by any number of modifiers, which are mostly single characters, though some of these can be qualified by further characters. Following Perl usage, these are referred to below as, for example, "the /i modifier", even though the delimiter of the pattern need not always be a slash, and no slash is used when writing modifiers. White space may appear between the final pattern delimiter and the first modifier, and between the modifiers themselves. For reference, here is a complete list of modifiers. They fall into several groups that are described in detail in the following sections.

      /8              set UTF mode
      /9              set PCRE_NEVER_UTF (locks out UTF mode)
      /?              disable UTF validity check
      /+              show remainder of subject after match
      /=              show all captures (not just those that are set)
    
      /A              set PCRE_ANCHORED
      /B              show compiled code
      /C              set PCRE_AUTO_CALLOUT
      /D              same as /B plus /I
      /E              set PCRE_DOLLAR_ENDONLY
      /F              flip byte order in compiled pattern
      /f              set PCRE_FIRSTLINE
      /G              find all matches (shorten string)
      /g              find all matches (use startoffset)
      /I              show information about pattern
      /i              set PCRE_CASELESS
      /J              set PCRE_DUPNAMES
      /K              show backtracking control names
      /L              set locale
      /M              show compiled memory size
      /m              set PCRE_MULTILINE
      /N              set PCRE_NO_AUTO_CAPTURE
      /O              set PCRE_NO_AUTO_POSSESS
      /P              use the POSIX wrapper
      /Q              test external stack check function
      /S              study the pattern after compilation
      /s              set PCRE_DOTALL
      /T              select character tables
      /U              set PCRE_UNGREEDY
      /W              set PCRE_UCP
      /X              set PCRE_EXTRA
      /x              set PCRE_EXTENDED
      /Y              set PCRE_NO_START_OPTIMIZE
      /Z              don't show lengths in /B output
    
      /<any>          set PCRE_NEWLINE_ANY
      /<anycrlf>      set PCRE_NEWLINE_ANYCRLF
      /<cr>           set PCRE_NEWLINE_CR
      /<crlf>         set PCRE_NEWLINE_CRLF
      /<lf>           set PCRE_NEWLINE_LF
      /<bsr_anycrlf>  set PCRE_BSR_ANYCRLF
      /<bsr_unicode>  set PCRE_BSR_UNICODE
      /<JS>           set PCRE_JAVASCRIPT_COMPAT
    
    


    Perl-compatible modifiers

    The /i, /m, /s, and /x modifiers set the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, or PCRE_EXTENDED options, respectively, when pcre[16|32]_compile() is called. These four modifier letters have the same effect as they do in Perl. For example:

      /caseless/i
    
    


    Modifiers for other PCRE options

    The following table shows additional modifiers for setting PCRE compile-time options that do not correspond to anything in Perl:

      /8              PCRE_UTF8           ) when using the 8-bit
      /?              PCRE_NO_UTF8_CHECK  )   library
    
      /8              PCRE_UTF16          ) when using the 16-bit
      /?              PCRE_NO_UTF16_CHECK )   library
    
      /8              PCRE_UTF32          ) when using the 32-bit
      /?              PCRE_NO_UTF32_CHECK )   library
    
      /9              PCRE_NEVER_UTF
      /A              PCRE_ANCHORED
      /C              PCRE_AUTO_CALLOUT
      /E              PCRE_DOLLAR_ENDONLY
      /f              PCRE_FIRSTLINE
      /J              PCRE_DUPNAMES
      /N              PCRE_NO_AUTO_CAPTURE
      /O              PCRE_NO_AUTO_POSSESS
      /U              PCRE_UNGREEDY
      /W              PCRE_UCP
      /X              PCRE_EXTRA
      /Y              PCRE_NO_START_OPTIMIZE
      /<any>          PCRE_NEWLINE_ANY
      /<anycrlf>      PCRE_NEWLINE_ANYCRLF
      /<cr>           PCRE_NEWLINE_CR
      /<crlf>         PCRE_NEWLINE_CRLF
      /<lf>           PCRE_NEWLINE_LF
      /<bsr_anycrlf>  PCRE_BSR_ANYCRLF
      /<bsr_unicode>  PCRE_BSR_UNICODE
      /<JS>           PCRE_JAVASCRIPT_COMPAT
    
    The modifiers that are enclosed in angle brackets are literal strings as shown, including the angle brackets, but the letters within can be in either case. This example sets multiline matching with CRLF as the line ending sequence:
      /^abc/m<CRLF>
    
    As well as turning on the PCRE_UTF8/16/32 option, the /8 modifier causes all non-printing characters in output strings to be printed using the \x{hh...} notation. Otherwise, those less than 0x100 are output in hex without the curly brackets.

    Full details of the PCRE options are given in the pcreapi documentation.


    Finding all matches in a string

    Searching for all possible matches within each subject string can be requested by the /g or /G modifier. After finding a match, PCRE is called again to search the remainder of the subject string. The difference between /g and /G is that the former uses the startoffset argument to pcre[16|32]_exec() to start searching at a new point within the entire string (which is in effect what Perl does), whereas the latter passes over a shortened substring. This makes a difference to the matching process if the pattern begins with a lookbehind assertion (including \b or \B).

    If any call to pcre[16|32]_exec() in a /g or /G sequence matches an empty string, the next call is done with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set in order to search for another, non-empty, match at the same point. If this second match fails, the start offset is advanced, and the normal match is retried. This imitates the way Perl handles such cases when using the /g modifier or the split() function. Normally, the start offset is advanced by one character, but if the newline convention recognizes CRLF as a newline, and the current character is CR followed by LF, an advance of two is used.


    Other modifiers

    There are yet more modifiers for controlling the way pcretest operates.

    The /+ modifier requests that as well as outputting the substring that matched the entire pattern, pcretest should in addition output the remainder of the subject string. This is useful for tests where the subject contains multiple copies of the same substring. If the + modifier appears twice, the same action is taken for captured substrings. In each case the remainder is output on the following line with a plus character following the capture number. Note that this modifier must not immediately follow the /S modifier because /S+ and /S++ have other meanings.

    The /= modifier requests that the values of all potential captured parentheses be output after a match. By default, only those up to the highest one actually used in the match are output (corresponding to the return code from pcre[16|32]_exec()). Values in the offsets vector corresponding to higher numbers should be set to -1, and these are output as "<unset>". This modifier gives a way of checking that this is happening.

    The /B modifier is a debugging feature. It requests that pcretest output a representation of the compiled code after compilation. Normally this information contains length and offset values; however, if /Z is also present, this data is replaced by spaces. This is a special feature for use in the automatic test scripts; it ensures that the same output is generated for different internal link sizes.

    The /D modifier is a PCRE debugging feature, and is equivalent to /BI, that is, both the /B and the /I modifiers.

    The /F modifier causes pcretest to flip the byte order of the 2-byte and 4-byte fields in the compiled pattern. This facility is for testing the feature in PCRE that allows it to execute patterns that were compiled on a host with a different endianness. This feature is not available when the POSIX interface to PCRE is being used, that is, when the /P pattern modifier is specified. See also the section about saving and reloading compiled patterns below.

    The /I modifier requests that pcretest output information about the compiled pattern (whether it is anchored, has a fixed first character, and so on). It does this by calling pcre[16|32]_fullinfo() after compiling a pattern. If the pattern is studied, the results of that are also output. In this output, the word "char" means a non-UTF character, that is, the value of a single data item (8-bit, 16-bit, or 32-bit, depending on the library that is being tested).

    The /K modifier requests pcretest to show names from backtracking control verbs that are returned from calls to pcre[16|32]_exec(). It causes pcretest to create a pcre[16|32]_extra block if one has not already been created by a call to pcre[16|32]_study(), and to set the PCRE_EXTRA_MARK flag and the mark field within it, every time that pcre[16|32]_exec() is called. If the variable that the mark field points to is non-NULL for a match, non-match, or partial match, pcretest prints the string to which it points. For a match, this is shown on a line by itself, tagged with "MK:". For a non-match it is added to the message.

    The /L modifier must be followed directly by the name of a locale, for example,

      /pattern/Lfr_FR
    
    For this reason, it must be the last modifier. The given locale is set, pcre[16|32]_maketables() is called to build a set of character tables for the locale, and this is then passed to pcre[16|32]_compile() when compiling the regular expression. Without an /L (or /T) modifier, NULL is passed as the tables pointer; that is, /L applies only to the expression on which it appears.

    The /M modifier causes the size in bytes of the memory block used to hold the compiled pattern to be output. This does not include the size of the pcre[16|32] block; it is just the actual compiled data. If the pattern is successfully studied with the PCRE_STUDY_JIT_COMPILE option, the size of the JIT compiled code is also output.

    The /Q modifier is used to test the use of pcre_stack_guard. It must be followed by '0' or '1', specifying the return code to be given from an external function that is passed to PCRE and used for stack checking during compilation (see the pcreapi documentation for details).

    The /S modifier causes pcre[16|32]_study() to be called after the expression has been compiled, and the results used when the expression is matched. There are a number of qualifying characters that may follow /S. They may appear in any order.

    If /S is followed by an exclamation mark, pcre[16|32]_study() is called with the PCRE_STUDY_EXTRA_NEEDED option, causing it always to return a pcre_extra block, even when studying discovers no useful information.

    If /S is followed by a second S character, it suppresses studying, even if it was requested externally by the -s command line option. This makes it possible to specify that certain patterns are always studied, and others are never studied, independently of -s. This feature is used in the test files in a few cases where the output is different when the pattern is studied.

    If the /S modifier is followed by a + character, the call to pcre[16|32]_study() is made with all the JIT study options, requesting just-in-time optimization support if it is available, for both normal and partial matching. If you want to restrict the JIT compiling modes, you can follow /S+ with a digit in the range 1 to 7:

      1  normal match only
      2  soft partial match only
      3  normal match and soft partial match
      4  hard partial match only
      6  soft and hard partial match
      7  all three modes (default)
    
    If /S++ is used instead of /S+ (with or without a following digit), the text "(JIT)" is added to the first output line after a match or no match when JIT-compiled code was actually used.

    Note that there is also an independent /+ modifier; it must not be given immediately after /S or /S+ because this will be misinterpreted.

    If JIT studying is successful, the compiled JIT code will automatically be used when pcre[16|32]_exec() is run, except when incompatible run-time options are specified. For more details, see the pcrejit documentation. See also the \J escape sequence below for a way of setting the size of the JIT stack.

    Finally, if /S is followed by a minus character, JIT compilation is suppressed, even if it was requested externally by the -s command line option. This makes it possible to specify that JIT is never to be used for certain patterns.

    The /T modifier must be followed by a single digit. It causes a specific set of built-in character tables to be passed to pcre[16|32]_compile(). It is used in the standard PCRE tests to check behaviour with different character tables. The digit specifies the tables as follows:

      0   the default ASCII tables, as distributed in
            pcre_chartables.c.dist
      1   a set of tables defining ISO 8859 characters
    
    In table 1, some characters whose codes are greater than 128 are identified as letters, digits, spaces, etc.


    Using the POSIX wrapper API

    The /P modifier causes pcretest to call PCRE via the POSIX wrapper API rather than its native API. This supports only the 8-bit library. When /P is set, the following modifiers set options for the regcomp() function:

      /i    REG_ICASE
      /m    REG_NEWLINE
      /N    REG_NOSUB
      /s    REG_DOTALL     )
      /U    REG_UNGREEDY   ) These options are not part of
      /W    REG_UCP        )   the POSIX standard
      /8    REG_UTF8       )
    
    The /+ modifier works as described above. All other modifiers are ignored.


    Locking out certain modifiers

    PCRE can be compiled with or without support for certain features such as UTF-8/16/32 or Unicode properties. Accordingly, the standard tests are split up into a number of different files that are selected for running depending on which features are available. When updating the tests, it is all too easy to put a new test into the wrong file by mistake; for example, to put a test that requires UTF support into a file that is used when it is not available. To help detect such mistakes as early as possible, there is a facility for locking out specific modifiers. If an input line for pcretest starts with the string "< forbid " the following sequence of characters is taken as a list of forbidden modifiers. For example, in the test files that must not use UTF or Unicode property support, this line appears:

      < forbid 8W
    
    This locks out the /8 and /W modifiers. An immediate error is given if they are subsequently encountered. If the character string contains < but not >, all the multi-character modifiers that begin with < are locked out. Otherwise, such modifiers must be explicitly listed, for example:
      < forbid <JS><cr>
    
    There must be a single space between < and "forbid" for this feature to be recognised. If there is not, the line is interpreted either as a request to re-load a pre-compiled pattern (see "SAVING AND RELOADING COMPILED PATTERNS" below) or, if there is a another < character, as a pattern that uses < as its delimiter.


    DATA LINES

    Before each data line is passed to pcre[16|32]_exec(), leading and trailing white space is removed, and it is then scanned for \ escapes. Some of these are pretty esoteric features, intended for checking out some of the more complicated features of PCRE. If you are just testing "ordinary" regular expressions, you probably don't need any of these. The following escapes are recognized:

      \a         alarm (BEL, \x07)
      \b         backspace (\x08)
      \e         escape (\x27)
      \f         form feed (\x0c)
      \n         newline (\x0a)
      \qdd       set the PCRE_MATCH_LIMIT limit to dd (any number of digits)
      \r         carriage return (\x0d)
      \t         tab (\x09)
      \v         vertical tab (\x0b)
      \nnn       octal character (up to 3 octal digits); always
                   a byte unless > 255 in UTF-8 or 16-bit or 32-bit mode
      \o{dd...}  octal character (any number of octal digits}
      \xhh       hexadecimal byte (up to 2 hex digits)
      \x{hh...}  hexadecimal character (any number of hex digits)
      \A         pass the PCRE_ANCHORED option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \B         pass the PCRE_NOTBOL option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \Cdd       call pcre[16|32]_copy_substring() for substring dd after a successful match (number less than 32)
      \Cname     call pcre[16|32]_copy_named_substring() for substring "name" after a successful match (name termin-
                   ated by next non alphanumeric character)
      \C+        show the current captured substrings at callout time
      \C-        do not supply a callout function
      \C!n       return 1 instead of 0 when callout number n is reached
      \C!n!m     return 1 instead of 0 when callout number n is reached for the nth time
      \C*n       pass the number n (may be negative) as callout data; this is used as the callout return value
      \D         use the pcre[16|32]_dfa_exec() match function
      \F         only shortest match for pcre[16|32]_dfa_exec()
      \Gdd       call pcre[16|32]_get_substring() for substring dd after a successful match (number less than 32)
      \Gname     call pcre[16|32]_get_named_substring() for substring "name" after a successful match (name termin-
                   ated by next non-alphanumeric character)
      \Jdd       set up a JIT stack of dd kilobytes maximum (any number of digits)
      \L         call pcre[16|32]_get_substringlist() after a successful match
      \M         discover the minimum MATCH_LIMIT and MATCH_LIMIT_RECURSION settings
      \N         pass the PCRE_NOTEMPTY option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec(); if used twice, pass the
                   PCRE_NOTEMPTY_ATSTART option
      \Odd       set the size of the output vector passed to pcre[16|32]_exec() to dd (any number of digits)
      \P         pass the PCRE_PARTIAL_SOFT option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec(); if used twice, pass the
                   PCRE_PARTIAL_HARD option
      \Qdd       set the PCRE_MATCH_LIMIT_RECURSION limit to dd (any number of digits)
      \R         pass the PCRE_DFA_RESTART option to pcre[16|32]_dfa_exec()
      \S         output details of memory get/free calls during matching
      \Y         pass the PCRE_NO_START_OPTIMIZE option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \Z         pass the PCRE_NOTEOL option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \?         pass the PCRE_NO_UTF[8|16|32]_CHECK option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \>dd       start the match at offset dd (optional "-"; then any number of digits); this sets the startoffset
                   argument for pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \<cr>      pass the PCRE_NEWLINE_CR option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \<lf>      pass the PCRE_NEWLINE_LF option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \<crlf>    pass the PCRE_NEWLINE_CRLF option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \<anycrlf> pass the PCRE_NEWLINE_ANYCRLF option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
      \<any>     pass the PCRE_NEWLINE_ANY option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec()
    
    The use of \x{hh...} is not dependent on the use of the /8 modifier on the pattern. It is recognized always. There may be any number of hexadecimal digits inside the braces; invalid values provoke error messages.

    Note that \xhh specifies one byte rather than one character in UTF-8 mode; this makes it possible to construct invalid UTF-8 sequences for testing purposes. On the other hand, \x{hh} is interpreted as a UTF-8 character in UTF-8 mode, generating more than one byte if the value is greater than 127. When testing the 8-bit library not in UTF-8 mode, \x{hh} generates one byte for values less than 256, and causes an error for greater values.

    In UTF-16 mode, all 4-digit \x{hhhh} values are accepted. This makes it possible to construct invalid UTF-16 sequences for testing purposes.

    In UTF-32 mode, all 4- to 8-digit \x{...} values are accepted. This makes it possible to construct invalid UTF-32 sequences for testing purposes.

    The escapes that specify line ending sequences are literal strings, exactly as shown. No more than one newline setting should be present in any data line.

    A backslash followed by anything else just escapes the anything else. If the very last character is a backslash, it is ignored. This gives a way of passing an empty line as data, since a real empty line terminates the data input.

    The \J escape provides a way of setting the maximum stack size that is used by the just-in-time optimization code. It is ignored if JIT optimization is not being used. Providing a stack that is larger than the default 32K is necessary only for very complicated patterns.

    If \M is present, pcretest calls pcre[16|32]_exec() several times, with different values in the match_limit and match_limit_recursion fields of the pcre[16|32]_extra data structure, until it finds the minimum numbers for each parameter that allow pcre[16|32]_exec() to complete without error. Because this is testing a specific feature of the normal interpretive pcre[16|32]_exec() execution, the use of any JIT optimization that might have been set up by the /S+ qualifier of -s+ option is disabled.

    The match_limit number is a measure of the amount of backtracking that takes place, and checking it out can be instructive. For most simple matches, the number is quite small, but for patterns with very large numbers of matching possibilities, it can become large very quickly with increasing length of subject string. The match_limit_recursion number is a measure of how much stack (or, if PCRE is compiled with NO_RECURSE, how much heap) memory is needed to complete the match attempt.

    When \O is used, the value specified may be higher or lower than the size set by the -O command line option (or defaulted to 45); \O applies only to the call of pcre[16|32]_exec() for the line in which it appears.

    If the /P modifier was present on the pattern, causing the POSIX wrapper API to be used, the only option-setting sequences that have any effect are \B, \N, and \Z, causing REG_NOTBOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to regexec().


    THE ALTERNATIVE MATCHING FUNCTION

    By default, pcretest uses the standard PCRE matching function, pcre[16|32]_exec() to match each data line. PCRE also supports an alternative matching function, pcre[16|32]_dfa_test(), which operates in a different way, and has some restrictions. The differences between the two functions are described in the pcrematching documentation.

    If a data line contains the \D escape sequence, or if the command line contains the -dfa option, the alternative matching function is used. This function finds all possible matches at a given point. If, however, the \F escape sequence is present in the data line, it stops after the first match is found. This is always the shortest possible match.


    DEFAULT OUTPUT FROM PCRETEST

    This section describes the output when the normal matching function, pcre[16|32]_exec(), is being used.

    When a match succeeds, pcretest outputs the list of captured substrings that pcre[16|32]_exec() returns, starting with number 0 for the string that matched the whole pattern. Otherwise, it outputs "No match" when the return is PCRE_ERROR_NOMATCH, and "Partial match:" followed by the partially matching substring when pcre[16|32]_exec() returns PCRE_ERROR_PARTIAL. (Note that this is the entire substring that was inspected during the partial match; it may include characters before the actual match start if a lookbehind assertion, \K, \b, or \B was involved.) For any other return, pcretest outputs the PCRE negative error number and a short descriptive phrase. If the error is a failed UTF string check, the offset of the start of the failing character and the reason code are also output, provided that the size of the output vector is at least two. Here is an example of an interactive pcretest run.

      $ pcretest
      PCRE version 8.13 2011-04-30
    
        re> /^abc(\d+)/
      data> abc123
       0: abc123
       1: 123
      data> xyz
      No match
    
    Unset capturing substrings that are not followed by one that is set are not returned by pcre[16|32]_exec(), and are not shown by pcretest. In the following example, there are two capturing substrings, but when the first data line is matched, the second, unset substring is not shown. An "internal" unset substring is shown as "<unset>", as for the second data line.
        re> /(a)|(b)/
      data> a
       0: a
       1: a
      data> b
       0: b
       1: <unset>
       2: b
    
    If the strings contain any non-printing characters, they are output as \xhh escapes if the value is less than 256 and UTF mode is not set. Otherwise they are output as \x{hh...} escapes. See below for the definition of non-printing characters. If the pattern has the /+ modifier, the output for substring 0 is followed by the the rest of the subject string, identified by "0+" like this:
        re> /cat/+
      data> cataract
       0: cat
       0+ aract
    
    If the pattern has the /g or /G modifier, the results of successive matching attempts are output in sequence, like this:
        re> /\Bi(\w\w)/g
      data> Mississippi
       0: iss
       1: ss
       0: iss
       1: ss
       0: ipp
       1: pp
    
    "No match" is output only if the first match attempt fails. Here is an example of a failure message (the offset 4 that is specified by \>4 is past the end of the subject string):
        re> /xyz/
      data> xyz\>4
      Error -24 (bad offset value)
    

    If any of the sequences \C, \G, or \L are present in a data line that is successfully matched, the substrings extracted by the convenience functions are output with C, G, or L after the string number instead of a colon. This is in addition to the normal full list. The string length (that is, the return from the extraction function) is given in parentheses after each string for \C and \G.

    Note that whereas patterns can be continued over several lines (a plain ">" prompt is used for continuations), data lines may not. However newlines can be included in data by means of the \n escape (or \r, \r\n, etc., depending on the newline sequence setting).


    OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION

    When the alternative matching function, pcre[16|32]_dfa_exec(), is used (by means of the \D escape sequence or the -dfa command line option), the output consists of a list of all the matches that start at the first point in the subject where there is at least one match. For example:

        re> /(tang|tangerine|tan)/
      data> yellow tangerine\D
       0: tangerine
       1: tang
       2: tan
    
    (Using the normal matching function on this data finds only "tang".) The longest matching string is always given first (and numbered zero). After a PCRE_ERROR_PARTIAL return, the output is "Partial match:", followed by the partially matching substring. (Note that this is the entire substring that was inspected during the partial match; it may include characters before the actual match start if a lookbehind assertion, \K, \b, or \B was involved.)

    If /g is present on the pattern, the search for further matches resumes at the end of the longest match. For example:

        re> /(tang|tangerine|tan)/g
      data> yellow tangerine and tangy sultana\D
       0: tangerine
       1: tang
       2: tan
       0: tang
       1: tan
       0: tan
    
    Since the matching function does not support substring capture, the escape sequences that are concerned with captured substrings are not relevant.


    RESTARTING AFTER A PARTIAL MATCH

    When the alternative matching function has given the PCRE_ERROR_PARTIAL return, indicating that the subject partially matched the pattern, you can restart the match with additional subject data by means of the \R escape sequence. For example:

        re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
      data> 23ja\P\D
      Partial match: 23ja
      data> n05\R\D
       0: n05
    
    For further information about partial matching, see the pcrepartial documentation.


    CALLOUTS

    If the pattern contains any callout requests, pcretest's callout function is called during matching. This works with both matching functions. By default, the called function displays the callout number, the start and current positions in the text at the callout time, and the next pattern item to be tested. For example:

      --->pqrabcdef
        0    ^  ^     \d
    
    This output indicates that callout number 0 occurred for a match attempt starting at the fourth character of the subject string, when the pointer was at the seventh character of the data, and when the next pattern item was \d. Just one circumflex is output if the start and current positions are the same.

    Callouts numbered 255 are assumed to be automatic callouts, inserted as a result of the /C pattern modifier. In this case, instead of showing the callout number, the offset in the pattern, preceded by a plus, is output. For example:

        re> /\d?[A-E]\*/C
      data> E*
      --->E*
       +0 ^      \d?
       +3 ^      [A-E]
       +8 ^^     \*
      +10 ^ ^
       0: E*
    
    If a pattern contains (*MARK) items, an additional line is output whenever a change of latest mark is passed to the callout function. For example:
        re> /a(*MARK:X)bc/C
      data> abc
      --->abc
       +0 ^       a
       +1 ^^      (*MARK:X)
      +10 ^^      b
      Latest Mark: X
      +11 ^ ^     c
      +12 ^  ^
       0: abc
    
    The mark changes between matching "a" and "b", but stays the same for the rest of the match, so nothing more is output. If, as a result of backtracking, the mark reverts to being unset, the text "<unset>" is output.

    The callout function in pcretest returns zero (carry on matching) by default, but you can use a \C item in a data line (as described above) to change this and other parameters of the callout.

    Inserting callouts can be helpful when using pcretest to check complicated regular expressions. For further information about callouts, see the pcrecallout documentation.


    NON-PRINTING CHARACTERS

    When pcretest is outputting text in the compiled version of a pattern, bytes other than 32-126 are always treated as non-printing characters are are therefore shown as hex escapes.

    When pcretest is outputting text that is a matched part of a subject string, it behaves in the same way, unless a different locale has been set for the pattern (using the /L modifier). In this case, the isprint() function to distinguish printing and non-printing characters.


    SAVING AND RELOADING COMPILED PATTERNS

    The facilities described in this section are not available when the POSIX interface to PCRE is being used, that is, when the /P pattern modifier is specified.

    When the POSIX interface is not in use, you can cause pcretest to write a compiled pattern to a file, by following the modifiers with > and a file name. For example:

      /pattern/im >/some/file
    
    See the pcreprecompile documentation for a discussion about saving and re-using compiled patterns. Note that if the pattern was successfully studied with JIT optimization, the JIT data cannot be saved.

    The data that is written is binary. The first eight bytes are the length of the compiled pattern data followed by the length of the optional study data, each written as four bytes in big-endian order (most significant byte first). If there is no study data (either the pattern was not studied, or studying did not return any data), the second length is zero. The lengths are followed by an exact copy of the compiled pattern. If there is additional study data, this (excluding any JIT data) follows immediately after the compiled pattern. After writing the file, pcretest expects to read a new pattern.

    A saved pattern can be reloaded into pcretest by specifying < and a file name instead of a pattern. There must be no space between < and the file name, which must not contain a < character, as otherwise pcretest will interpret the line as a pattern delimited by < characters. For example:

       re> </some/file
      Compiled pattern loaded from /some/file
      No study data
    
    If the pattern was previously studied with the JIT optimization, the JIT information cannot be saved and restored, and so is lost. When the pattern has been loaded, pcretest proceeds to read data lines in the usual way.

    You can copy a file written by pcretest to a different host and reload it there, even if the new host has opposite endianness to the one on which the pattern was compiled. For example, you can compile on an i86 machine and run on a SPARC machine. When a pattern is reloaded on a host with different endianness, the confirmation message is changed to:

      Compiled pattern (byte-inverted) loaded from /some/file
    
    The test suite contains some saved pre-compiled patterns with different endianness. These are reloaded using "<!" instead of just "<". This suppresses the "(byte-inverted)" text so that the output is the same on all hosts. It also forces debugging output once the pattern has been reloaded.

    File names for saving and reloading can be absolute or relative, but note that the shell facility of expanding a file name that starts with a tilde (~) is not available.

    The ability to save and reload files in pcretest is intended for testing and experimentation. It is not intended for production use because only a single pattern can be written to a file. Furthermore, there is no facility for supplying custom character tables for use with a reloaded pattern. If the original pattern was compiled with custom tables, an attempt to match a subject string using a reloaded pattern is likely to cause pcretest to crash. Finally, if you attempt to load a file that is not in the correct format, the result is undefined.


    SEE ALSO

    pcre(3), pcre16(3), pcre32(3), pcreapi(3), pcrecallout(3), pcrejit, pcrematching(3), pcrepartial(d), pcrepattern(3), pcreprecompile(3).


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 23 February 2017
    Copyright © 1997-2017 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/html/pcreunicode.html ================================================ pcreunicode specification

    pcreunicode man page

    Return to the PCRE index page.

    This page is part of the PCRE HTML documentation. It was generated automatically from the original man page. If there is any nonsense in it, please consult the man page, in case the conversion went wrong.

    UTF-8, UTF-16, UTF-32, AND UNICODE PROPERTY SUPPORT

    As well as UTF-8 support, PCRE also supports UTF-16 (from release 8.30) and UTF-32 (from release 8.32), by means of two additional libraries. They can be built as well as, or instead of, the 8-bit library.


    UTF-8 SUPPORT

    In order process UTF-8 strings, you must build PCRE's 8-bit library with UTF support, and, in addition, you must call pcre_compile() with the PCRE_UTF8 option flag, or the pattern must start with the sequence (*UTF8) or (*UTF). When either of these is the case, both the pattern and any subject strings that are matched against it are treated as UTF-8 strings instead of strings of individual 1-byte characters.


    UTF-16 AND UTF-32 SUPPORT

    In order process UTF-16 or UTF-32 strings, you must build PCRE's 16-bit or 32-bit library with UTF support, and, in addition, you must call pcre16_compile() or pcre32_compile() with the PCRE_UTF16 or PCRE_UTF32 option flag, as appropriate. Alternatively, the pattern must start with the sequence (*UTF16), (*UTF32), as appropriate, or (*UTF), which can be used with either library. When UTF mode is set, both the pattern and any subject strings that are matched against it are treated as UTF-16 or UTF-32 strings instead of strings of individual 16-bit or 32-bit characters.


    UTF SUPPORT OVERHEAD

    If you compile PCRE with UTF support, but do not use it at run time, the library will be a bit bigger, but the additional run time overhead is limited to testing the PCRE_UTF[8|16|32] flag occasionally, so should not be very big.


    UNICODE PROPERTY SUPPORT

    If PCRE is built with Unicode character property support (which implies UTF support), the escape sequences \p{..}, \P{..}, and \X can be used. The available properties that can be tested are limited to the general category properties such as Lu for an upper case letter or Nd for a decimal number, the Unicode script names such as Arabic or Han, and the derived properties Any and L&. Full lists is given in the pcrepattern and pcresyntax documentation. Only the short names for properties are supported. For example, \p{L} matches a letter. Its Perl synonym, \p{Letter}, is not supported. Furthermore, in Perl, many properties may optionally be prefixed by "Is", for compatibility with Perl 5.6. PCRE does not support this.


    Validity of UTF-8 strings

    When you set the PCRE_UTF8 flag, the byte strings passed as patterns and subjects are (by default) checked for validity on entry to the relevant functions. The entire string is checked before any other processing takes place. From release 7.3 of PCRE, the check is according the rules of RFC 3629, which are themselves derived from the Unicode specification. Earlier releases of PCRE followed the rules of RFC 2279, which allows the full range of 31-bit values (0 to 0x7FFFFFFF). The current check allows only values in the range U+0 to U+10FFFF, excluding the surrogate area. (From release 8.33 the so-called "non-character" code points are no longer excluded because Unicode corrigendum #9 makes it clear that they should not be.)

    Characters in the "Surrogate Area" of Unicode are reserved for use by UTF-16, where they are used in pairs to encode codepoints with values greater than 0xFFFF. The code points that are encoded by UTF-16 pairs are available independently in the UTF-8 and UTF-32 encodings. (In other words, the whole surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and UTF-32.)

    If an invalid UTF-8 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first byte of the failing character. The run-time functions pcre_exec() and pcre_dfa_exec() also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this.

    In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve performance, for example in the case of a long subject string that is being scanned repeatedly. If you set the PCRE_NO_UTF8_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-8 codes. In this case, it does not diagnose an invalid UTF-8 string.

    Note that passing PCRE_NO_UTF8_CHECK to pcre_compile() just disables the check for the pattern; it does not also apply to subject strings. If you want to disable the check for a subject string you must pass this option to pcre_exec() or pcre_dfa_exec().

    If you pass an invalid UTF-8 string when PCRE_NO_UTF8_CHECK is set, the result is undefined and your program may crash.


    Validity of UTF-16 strings

    When you set the PCRE_UTF16 flag, the strings of 16-bit data units that are passed as patterns and subjects are (by default) checked for validity on entry to the relevant functions. Values other than those in the surrogate range U+D800 to U+DFFF are independent code points. Values in the surrogate range must be used in pairs in the correct manner.

    If an invalid UTF-16 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first data unit of the failing character. The run-time functions pcre16_exec() and pcre16_dfa_exec() also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this.

    In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve performance. If you set the PCRE_NO_UTF16_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-16 sequences. In this case, it does not diagnose an invalid UTF-16 string. However, if an invalid string is passed, the result is undefined.


    Validity of UTF-32 strings

    When you set the PCRE_UTF32 flag, the strings of 32-bit data units that are passed as patterns and subjects are (by default) checked for validity on entry to the relevant functions. This check allows only values in the range U+0 to U+10FFFF, excluding the surrogate area U+D800 to U+DFFF.

    If an invalid UTF-32 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first data unit of the failing character. The run-time functions pcre32_exec() and pcre32_dfa_exec() also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this.

    In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve performance. If you set the PCRE_NO_UTF32_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-32 sequences. In this case, it does not diagnose an invalid UTF-32 string. However, if an invalid string is passed, the result is undefined.


    General comments about UTF modes

    1. Codepoints less than 256 can be specified in patterns by either braced or unbraced hexadecimal escape sequences (for example, \x{b3} or \xb3). Larger values have to use braced sequences.

    2. Octal numbers up to \777 are recognized, and in UTF-8 mode they match two-byte characters for values greater than \177.

    3. Repeat quantifiers apply to complete UTF characters, not to individual data units, for example: \x{100}{3}.

    4. The dot metacharacter matches one UTF character instead of a single data unit.

    5. The escape sequence \C can be used to match a single byte in UTF-8 mode, or a single 16-bit data unit in UTF-16 mode, or a single 32-bit data unit in UTF-32 mode, but its use can lead to some strange effects because it breaks up multi-unit characters (see the description of \C in the pcrepattern documentation). The use of \C is not supported in the alternative matching function pcre[16|32]_dfa_exec(), nor is it supported in UTF mode by the JIT optimization of pcre[16|32]_exec(). If JIT optimization is requested for a UTF pattern that contains \C, it will not succeed, and so the matching will be carried out by the normal interpretive function.

    6. The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test characters of any code value, but, by default, the characters that PCRE recognizes as digits, spaces, or word characters remain the same set as in non-UTF mode, all with values less than 256. This remains true even when PCRE is built to include Unicode property support, because to do otherwise would slow down PCRE in many common cases. Note in particular that this applies to \b and \B, because they are defined in terms of \w and \W. If you really want to test for a wider sense of, say, "digit", you can use explicit Unicode property tests such as \p{Nd}. Alternatively, if you set the PCRE_UCP option, the way that the character escapes work is changed so that Unicode properties are used to determine which characters match. There are more details in the section on generic character types in the pcrepattern documentation.

    7. Similarly, characters that match the POSIX named character classes are all low-valued characters, unless the PCRE_UCP option is set.

    8. However, the horizontal and vertical white space matching escapes (\h, \H, \v, and \V) do match all the appropriate Unicode characters, whether or not PCRE_UCP is set.

    9. Case-insensitive matching applies only to characters whose values are less than 128, unless PCRE is built with Unicode property support. A few Unicode characters such as Greek sigma have more than two codepoints that are case-equivalent. Up to and including PCRE release 8.31, only one-to-one case mappings were supported, but later releases (with Unicode property support) do treat as case-equivalent all versions of characters such as Greek sigma.


    AUTHOR

    Philip Hazel
    University Computing Service
    Cambridge CB2 3QH, England.


    REVISION

    Last updated: 27 February 2013
    Copyright © 1997-2013 University of Cambridge.

    Return to the PCRE index page.

    ================================================ FILE: src/pcre/doc/index.html.src ================================================ PCRE specification

    Perl-compatible Regular Expressions (PCRE)

    The HTML documentation for PCRE consists of a number of pages that are listed below in alphabetical order. If you are new to PCRE, please read the first one first.

    pcre   Introductory page
    pcre-config   Information about the installation configuration
    pcre16   Discussion of the 16-bit PCRE library
    pcre32   Discussion of the 32-bit PCRE library
    pcreapi   PCRE's native API
    pcrebuild   Building PCRE
    pcrecallout   The callout facility
    pcrecompat   Compability with Perl
    pcrecpp   The C++ wrapper for the PCRE library
    pcredemo   A demonstration C program that uses the PCRE library
    pcregrep   The pcregrep command
    pcrejit   Discussion of the just-in-time optimization support
    pcrelimits   Details of size and other limits
    pcrematching   Discussion of the two matching algorithms
    pcrepartial   Using PCRE for partial matching
    pcrepattern   Specification of the regular expressions supported by PCRE
    pcreperform   Some comments on performance
    pcreposix   The POSIX API to the PCRE 8-bit library
    pcreprecompile   How to save and re-use compiled patterns
    pcresample   Discussion of the pcredemo program
    pcrestack   Discussion of PCRE's stack usage
    pcresyntax   Syntax quick-reference summary
    pcretest   The pcretest command for testing PCRE
    pcreunicode   Discussion of Unicode and UTF-8/UTF-16/UTF-32 support

    There are also individual pages that summarize the interface for each function in the library. There is a single page for each triple of 8-bit/16-bit/32-bit functions.

    pcre_assign_jit_stack   Assign stack for JIT matching
    pcre_compile   Compile a regular expression
    pcre_compile2   Compile a regular expression (alternate interface)
    pcre_config   Show build-time configuration options
    pcre_copy_named_substring   Extract named substring into given buffer
    pcre_copy_substring   Extract numbered substring into given buffer
    pcre_dfa_exec   Match a compiled pattern to a subject string (DFA algorithm; not Perl compatible)
    pcre_exec   Match a compiled pattern to a subject string (Perl compatible)
    pcre_free_study   Free study data
    pcre_free_substring   Free extracted substring
    pcre_free_substring_list   Free list of extracted substrings
    pcre_fullinfo   Extract information about a pattern
    pcre_get_named_substring   Extract named substring into new memory
    pcre_get_stringnumber   Convert captured string name to number
    pcre_get_stringtable_entries   Find table entries for given string name
    pcre_get_substring   Extract numbered substring into new memory
    pcre_get_substring_list   Extract all substrings into new memory
    pcre_jit_exec   Fast path interface to JIT matching
    pcre_jit_stack_alloc   Create a stack for JIT matching
    pcre_jit_stack_free   Free a JIT matching stack
    pcre_maketables   Build character tables in current locale
    pcre_pattern_to_host_byte_order   Convert compiled pattern to host byte order if necessary
    pcre_refcount   Maintain reference count in compiled pattern
    pcre_study   Study a compiled pattern
    pcre_utf16_to_host_byte_order   Convert UTF-16 string to host byte order if necessary
    pcre_utf32_to_host_byte_order   Convert UTF-32 string to host byte order if necessary
    pcre_version   Return PCRE version and release date
    ================================================ FILE: src/pcre/doc/pcre-config.1 ================================================ .TH PCRE-CONFIG 1 "01 January 2012" "PCRE 8.30" .SH NAME pcre-config - program to return PCRE configuration .SH SYNOPSIS .rs .sp .nf .B pcre-config [--prefix] [--exec-prefix] [--version] [--libs] .B " [--libs16] [--libs32] [--libs-cpp] [--libs-posix]" .B " [--cflags] [--cflags-posix]" .fi . . .SH DESCRIPTION .rs .sp \fBpcre-config\fP returns the configuration of the installed PCRE libraries and the options required to compile a program to use them. Some of the options apply only to the 8-bit, or 16-bit, or 32-bit libraries, respectively, and are not available if only one of those libraries has been built. If an unavailable option is encountered, the "usage" information is output. . . .SH OPTIONS .rs .TP 10 \fB--prefix\fP Writes the directory prefix used in the PCRE installation for architecture independent files (\fI/usr\fP on many systems, \fI/usr/local\fP on some systems) to the standard output. .TP 10 \fB--exec-prefix\fP Writes the directory prefix used in the PCRE installation for architecture dependent files (normally the same as \fB--prefix\fP) to the standard output. .TP 10 \fB--version\fP Writes the version number of the installed PCRE libraries to the standard output. .TP 10 \fB--libs\fP Writes to the standard output the command line options required to link with the 8-bit PCRE library (\fB-lpcre\fP on many systems). .TP 10 \fB--libs16\fP Writes to the standard output the command line options required to link with the 16-bit PCRE library (\fB-lpcre16\fP on many systems). .TP 10 \fB--libs32\fP Writes to the standard output the command line options required to link with the 32-bit PCRE library (\fB-lpcre32\fP on many systems). .TP 10 \fB--libs-cpp\fP Writes to the standard output the command line options required to link with PCRE's C++ wrapper library (\fB-lpcrecpp\fP \fB-lpcre\fP on many systems). .TP 10 \fB--libs-posix\fP Writes to the standard output the command line options required to link with PCRE's POSIX API wrapper library (\fB-lpcreposix\fP \fB-lpcre\fP on many systems). .TP 10 \fB--cflags\fP Writes to the standard output the command line options required to compile files that use PCRE (this may include some \fB-I\fP options, but is blank on many systems). .TP 10 \fB--cflags-posix\fP Writes to the standard output the command line options required to compile files that use PCRE's POSIX API wrapper library (this may include some \fB-I\fP options, but is blank on many systems). . . .SH "SEE ALSO" .rs .sp \fBpcre(3)\fP . . .SH AUTHOR .rs .sp This manual page was originally written by Mark Baker for the Debian GNU/Linux system. It has been subsequently revised as a generic PCRE man page. . . .SH REVISION .rs .sp .nf Last updated: 24 June 2012 .fi ================================================ FILE: src/pcre/doc/pcre-config.txt ================================================ PCRE-CONFIG(1) General Commands Manual PCRE-CONFIG(1) NAME pcre-config - program to return PCRE configuration SYNOPSIS pcre-config [--prefix] [--exec-prefix] [--version] [--libs] [--libs16] [--libs32] [--libs-cpp] [--libs-posix] [--cflags] [--cflags-posix] DESCRIPTION pcre-config returns the configuration of the installed PCRE libraries and the options required to compile a program to use them. Some of the options apply only to the 8-bit, or 16-bit, or 32-bit libraries, respectively, and are not available if only one of those libraries has been built. If an unavailable option is encountered, the "usage" infor- mation is output. OPTIONS --prefix Writes the directory prefix used in the PCRE installation for architecture independent files (/usr on many systems, /usr/local on some systems) to the standard output. --exec-prefix Writes the directory prefix used in the PCRE installation for architecture dependent files (normally the same as --prefix) to the standard output. --version Writes the version number of the installed PCRE libraries to the standard output. --libs Writes to the standard output the command line options required to link with the 8-bit PCRE library (-lpcre on many systems). --libs16 Writes to the standard output the command line options required to link with the 16-bit PCRE library (-lpcre16 on many systems). --libs32 Writes to the standard output the command line options required to link with the 32-bit PCRE library (-lpcre32 on many systems). --libs-cpp Writes to the standard output the command line options required to link with PCRE's C++ wrapper library (-lpcrecpp -lpcre on many systems). --libs-posix Writes to the standard output the command line options required to link with PCRE's POSIX API wrapper library (-lpcreposix -lpcre on many systems). --cflags Writes to the standard output the command line options required to compile files that use PCRE (this may include some -I options, but is blank on many systems). --cflags-posix Writes to the standard output the command line options required to compile files that use PCRE's POSIX API wrapper library (this may include some -I options, but is blank on many systems). SEE ALSO pcre(3) AUTHOR This manual page was originally written by Mark Baker for the Debian GNU/Linux system. It has been subsequently revised as a generic PCRE man page. REVISION Last updated: 24 June 2012 ================================================ FILE: src/pcre/doc/pcre.3 ================================================ .TH PCRE 3 "10 February 2015" "PCRE 8.37" .SH NAME PCRE - Perl-compatible regular expressions (original API) .SH "PLEASE TAKE NOTE" .rs .sp This document relates to PCRE releases that use the original API, with library names libpcre, libpcre16, and libpcre32. January 2015 saw the first release of a new API, known as PCRE2, with release numbers starting at 10.00 and library names libpcre2-8, libpcre2-16, and libpcre2-32. The old libraries (now called PCRE1) are still being maintained for bug fixes, but there will be no new development. New projects are advised to use the new PCRE2 libraries. . . .SH INTRODUCTION .rs .sp The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl, with just a few differences. Some features that appeared in Python and PCRE before they appeared in Perl are also available using the Python syntax, there is some support for one or two .NET and Oniguruma syntax items, and there is an option for requesting some minor changes that give better JavaScript compatibility. .P Starting with release 8.30, it is possible to compile two separate PCRE libraries: the original, which supports 8-bit character strings (including UTF-8 strings), and a second library that supports 16-bit character strings (including UTF-16 strings). The build process allows either one or both to be built. The majority of the work to make this possible was done by Zoltan Herczeg. .P Starting with release 8.32 it is possible to compile a third separate PCRE library that supports 32-bit character strings (including UTF-32 strings). The build process allows any combination of the 8-, 16- and 32-bit libraries. The work to make this possible was done by Christian Persch. .P The three libraries contain identical sets of functions, except that the names in the 16-bit library start with \fBpcre16_\fP instead of \fBpcre_\fP, and the names in the 32-bit library start with \fBpcre32_\fP instead of \fBpcre_\fP. To avoid over-complication and reduce the documentation maintenance load, most of the documentation describes the 8-bit library, with the differences for the 16-bit and 32-bit libraries described separately in the .\" HREF \fBpcre16\fP and .\" HREF \fBpcre32\fP .\" pages. References to functions or structures of the form \fIpcre[16|32]_xxx\fP should be read as meaning "\fIpcre_xxx\fP when using the 8-bit library, \fIpcre16_xxx\fP when using the 16-bit library, or \fIpcre32_xxx\fP when using the 32-bit library". .P The current implementation of PCRE corresponds approximately with Perl 5.12, including support for UTF-8/16/32 encoded strings and Unicode general category properties. However, UTF-8/16/32 and Unicode support has to be explicitly enabled; it is not the default. The Unicode tables correspond to Unicode release 6.3.0. .P In addition to the Perl-compatible matching function, PCRE contains an alternative function that matches the same compiled patterns in a different way. In certain circumstances, the alternative function has some advantages. For a discussion of the two matching algorithms, see the .\" HREF \fBpcrematching\fP .\" page. .P PCRE is written in C and released as a C library. A number of people have written wrappers and interfaces of various kinds. In particular, Google Inc. have provided a comprehensive C++ wrapper for the 8-bit library. This is now included as part of the PCRE distribution. The .\" HREF \fBpcrecpp\fP .\" page has details of this interface. Other people's contributions can be found in the \fIContrib\fP directory at the primary FTP site, which is: .sp .\" HTML .\" ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre .\" .P Details of exactly which Perl regular expression features are and are not supported by PCRE are given in separate documents. See the .\" HREF \fBpcrepattern\fP .\" and .\" HREF \fBpcrecompat\fP .\" pages. There is a syntax summary in the .\" HREF \fBpcresyntax\fP .\" page. .P Some features of PCRE can be included, excluded, or changed when the library is built. The .\" HREF \fBpcre_config()\fP .\" function makes it possible for a client to discover which features are available. The features themselves are described in the .\" HREF \fBpcrebuild\fP .\" page. Documentation about building PCRE for various operating systems can be found in the .\" HTML .\" \fBREADME\fP .\" and .\" HTML .\" \fBNON-AUTOTOOLS_BUILD\fP .\" files in the source distribution. .P The libraries contains a number of undocumented internal functions and data tables that are used by more than one of the exported external functions, but which are not intended for use by external callers. Their names all begin with "_pcre_" or "_pcre16_" or "_pcre32_", which hopefully will not provoke any name clashes. In some environments, it is possible to control which external symbols are exported when a shared library is built, and in these cases the undocumented symbols are not exported. . . .SH "SECURITY CONSIDERATIONS" .rs .sp If you are using PCRE in a non-UTF application that permits users to supply arbitrary patterns for compilation, you should be aware of a feature that allows users to turn on UTF support from within a pattern, provided that PCRE was built with UTF support. For example, an 8-bit pattern that begins with "(*UTF8)" or "(*UTF)" turns on UTF-8 mode, which interprets patterns and subjects as strings of UTF-8 characters instead of individual 8-bit characters. This causes both the pattern and any data against which it is matched to be checked for UTF-8 validity. If the data string is very long, such a check might use sufficiently many resources as to cause your application to lose performance. .P One way of guarding against this possibility is to use the \fBpcre_fullinfo()\fP function to check the compiled pattern's options for UTF. Alternatively, from release 8.33, you can set the PCRE_NEVER_UTF option at compile time. This causes an compile time error if a pattern contains a UTF-setting sequence. .P If your application is one that supports UTF, be aware that validity checking can take time. If the same data string is to be matched many times, you can use the PCRE_NO_UTF[8|16|32]_CHECK option for the second and subsequent matches to save redundant checks. .P Another way that performance can be hit is by running a pattern that has a very large search tree against a string that will never match. Nested unlimited repeats in a pattern are a common example. PCRE provides some protection against this: see the PCRE_EXTRA_MATCH_LIMIT feature in the .\" HREF \fBpcreapi\fP .\" page. . . .SH "USER DOCUMENTATION" .rs .sp The user documentation for PCRE comprises a number of different sections. In the "man" format, each of these is a separate "man page". In the HTML format, each is a separate page, linked from the index page. In the plain text format, the descriptions of the \fBpcregrep\fP and \fBpcretest\fP programs are in files called \fBpcregrep.txt\fP and \fBpcretest.txt\fP, respectively. The remaining sections, except for the \fBpcredemo\fP section (which is a program listing), are concatenated in \fBpcre.txt\fP, for ease of searching. The sections are as follows: .sp pcre this document pcre-config show PCRE installation configuration information pcre16 details of the 16-bit library pcre32 details of the 32-bit library pcreapi details of PCRE's native C API pcrebuild building PCRE pcrecallout details of the callout feature pcrecompat discussion of Perl compatibility pcrecpp details of the C++ wrapper for the 8-bit library pcredemo a demonstration C program that uses PCRE pcregrep description of the \fBpcregrep\fP command (8-bit only) pcrejit discussion of the just-in-time optimization support pcrelimits details of size and other limits pcrematching discussion of the two matching algorithms pcrepartial details of the partial matching facility .\" JOIN pcrepattern syntax and semantics of supported regular expressions pcreperform discussion of performance issues pcreposix the POSIX-compatible C API for the 8-bit library pcreprecompile details of saving and re-using precompiled patterns pcresample discussion of the pcredemo program pcrestack discussion of stack usage pcresyntax quick syntax reference pcretest description of the \fBpcretest\fP testing command pcreunicode discussion of Unicode and UTF-8/16/32 support .sp In the "man" and HTML formats, there is also a short page for each C library function, listing its arguments and results. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi .P Putting an actual email address here seems to have been a spam magnet, so I've taken it away. If you want to email me, use my two initials, followed by the two digits 10, at the domain cam.ac.uk. . . .SH REVISION .rs .sp .nf Last updated: 10 February 2015 Copyright (c) 1997-2015 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcre.txt ================================================ ----------------------------------------------------------------------------- This file contains a concatenation of the PCRE man pages, converted to plain text format for ease of searching with a text editor, or for use on systems that do not have a man page processor. The small individual files that give synopses of each function in the library have not been included. Neither has the pcredemo program. There are separate text files for the pcregrep and pcretest commands. ----------------------------------------------------------------------------- PCRE(3) Library Functions Manual PCRE(3) NAME PCRE - Perl-compatible regular expressions (original API) PLEASE TAKE NOTE This document relates to PCRE releases that use the original API, with library names libpcre, libpcre16, and libpcre32. January 2015 saw the first release of a new API, known as PCRE2, with release numbers start- ing at 10.00 and library names libpcre2-8, libpcre2-16, and libpcre2-32. The old libraries (now called PCRE1) are still being main- tained for bug fixes, but there will be no new development. New projects are advised to use the new PCRE2 libraries. INTRODUCTION The PCRE library is a set of functions that implement regular expres- sion pattern matching using the same syntax and semantics as Perl, with just a few differences. Some features that appeared in Python and PCRE before they appeared in Perl are also available using the Python syn- tax, there is some support for one or two .NET and Oniguruma syntax items, and there is an option for requesting some minor changes that give better JavaScript compatibility. Starting with release 8.30, it is possible to compile two separate PCRE libraries: the original, which supports 8-bit character strings (including UTF-8 strings), and a second library that supports 16-bit character strings (including UTF-16 strings). The build process allows either one or both to be built. The majority of the work to make this possible was done by Zoltan Herczeg. Starting with release 8.32 it is possible to compile a third separate PCRE library that supports 32-bit character strings (including UTF-32 strings). The build process allows any combination of the 8-, 16- and 32-bit libraries. The work to make this possible was done by Christian Persch. The three libraries contain identical sets of functions, except that the names in the 16-bit library start with pcre16_ instead of pcre_, and the names in the 32-bit library start with pcre32_ instead of pcre_. To avoid over-complication and reduce the documentation mainte- nance load, most of the documentation describes the 8-bit library, with the differences for the 16-bit and 32-bit libraries described sepa- rately in the pcre16 and pcre32 pages. References to functions or structures of the form pcre[16|32]_xxx should be read as meaning "pcre_xxx when using the 8-bit library, pcre16_xxx when using the 16-bit library, or pcre32_xxx when using the 32-bit library". The current implementation of PCRE corresponds approximately with Perl 5.12, including support for UTF-8/16/32 encoded strings and Unicode general category properties. However, UTF-8/16/32 and Unicode support has to be explicitly enabled; it is not the default. The Unicode tables correspond to Unicode release 6.3.0. In addition to the Perl-compatible matching function, PCRE contains an alternative function that matches the same compiled patterns in a dif- ferent way. In certain circumstances, the alternative function has some advantages. For a discussion of the two matching algorithms, see the pcrematching page. PCRE is written in C and released as a C library. A number of people have written wrappers and interfaces of various kinds. In particular, Google Inc. have provided a comprehensive C++ wrapper for the 8-bit library. This is now included as part of the PCRE distribution. The pcrecpp page has details of this interface. Other people's contribu- tions can be found in the Contrib directory at the primary FTP site, which is: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre Details of exactly which Perl regular expression features are and are not supported by PCRE are given in separate documents. See the pcrepat- tern and pcrecompat pages. There is a syntax summary in the pcresyntax page. Some features of PCRE can be included, excluded, or changed when the library is built. The pcre_config() function makes it possible for a client to discover which features are available. The features them- selves are described in the pcrebuild page. Documentation about build- ing PCRE for various operating systems can be found in the README and NON-AUTOTOOLS_BUILD files in the source distribution. The libraries contains a number of undocumented internal functions and data tables that are used by more than one of the exported external functions, but which are not intended for use by external callers. Their names all begin with "_pcre_" or "_pcre16_" or "_pcre32_", which hopefully will not provoke any name clashes. In some environments, it is possible to control which external symbols are exported when a shared library is built, and in these cases the undocumented symbols are not exported. SECURITY CONSIDERATIONS If you are using PCRE in a non-UTF application that permits users to supply arbitrary patterns for compilation, you should be aware of a feature that allows users to turn on UTF support from within a pattern, provided that PCRE was built with UTF support. For example, an 8-bit pattern that begins with "(*UTF8)" or "(*UTF)" turns on UTF-8 mode, which interprets patterns and subjects as strings of UTF-8 characters instead of individual 8-bit characters. This causes both the pattern and any data against which it is matched to be checked for UTF-8 valid- ity. If the data string is very long, such a check might use suffi- ciently many resources as to cause your application to lose perfor- mance. One way of guarding against this possibility is to use the pcre_fullinfo() function to check the compiled pattern's options for UTF. Alternatively, from release 8.33, you can set the PCRE_NEVER_UTF option at compile time. This causes an compile time error if a pattern contains a UTF-setting sequence. If your application is one that supports UTF, be aware that validity checking can take time. If the same data string is to be matched many times, you can use the PCRE_NO_UTF[8|16|32]_CHECK option for the second and subsequent matches to save redundant checks. Another way that performance can be hit is by running a pattern that has a very large search tree against a string that will never match. Nested unlimited repeats in a pattern are a common example. PCRE pro- vides some protection against this: see the PCRE_EXTRA_MATCH_LIMIT fea- ture in the pcreapi page. USER DOCUMENTATION The user documentation for PCRE comprises a number of different sec- tions. In the "man" format, each of these is a separate "man page". In the HTML format, each is a separate page, linked from the index page. In the plain text format, the descriptions of the pcregrep and pcretest programs are in files called pcregrep.txt and pcretest.txt, respec- tively. The remaining sections, except for the pcredemo section (which is a program listing), are concatenated in pcre.txt, for ease of searching. The sections are as follows: pcre this document pcre-config show PCRE installation configuration information pcre16 details of the 16-bit library pcre32 details of the 32-bit library pcreapi details of PCRE's native C API pcrebuild building PCRE pcrecallout details of the callout feature pcrecompat discussion of Perl compatibility pcrecpp details of the C++ wrapper for the 8-bit library pcredemo a demonstration C program that uses PCRE pcregrep description of the pcregrep command (8-bit only) pcrejit discussion of the just-in-time optimization support pcrelimits details of size and other limits pcrematching discussion of the two matching algorithms pcrepartial details of the partial matching facility pcrepattern syntax and semantics of supported regular expressions pcreperform discussion of performance issues pcreposix the POSIX-compatible C API for the 8-bit library pcreprecompile details of saving and re-using precompiled patterns pcresample discussion of the pcredemo program pcrestack discussion of stack usage pcresyntax quick syntax reference pcretest description of the pcretest testing command pcreunicode discussion of Unicode and UTF-8/16/32 support In the "man" and HTML formats, there is also a short page for each C library function, listing its arguments and results. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. Putting an actual email address here seems to have been a spam magnet, so I've taken it away. If you want to email me, use my two initials, followed by the two digits 10, at the domain cam.ac.uk. REVISION Last updated: 10 February 2015 Copyright (c) 1997-2015 University of Cambridge. ------------------------------------------------------------------------------ PCRE(3) Library Functions Manual PCRE(3) NAME PCRE - Perl-compatible regular expressions #include PCRE 16-BIT API BASIC FUNCTIONS pcre16 *pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre16 *pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre16_extra *pcre16_study(const pcre16 *code, int options, const char **errptr); void pcre16_free_study(pcre16_extra *extra); int pcre16_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize); int pcre16_dfa_exec(const pcre16 *code, const pcre16_extra *extra, PCRE_SPTR16 subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount); PCRE 16-BIT API STRING EXTRACTION FUNCTIONS int pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_UCHAR16 *buffer, int buffersize); int pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR16 *buffer, int buffersize); int pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_SPTR16 *stringptr); int pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 name); int pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 name, PCRE_UCHAR16 **first, PCRE_UCHAR16 **last); int pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR16 *stringptr); int pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 **listptr); void pcre16_free_substring(PCRE_SPTR16 stringptr); void pcre16_free_substring_list(PCRE_SPTR16 *stringptr); PCRE 16-BIT API AUXILIARY FUNCTIONS pcre16_jit_stack *pcre16_jit_stack_alloc(int startsize, int maxsize); void pcre16_jit_stack_free(pcre16_jit_stack *stack); void pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *data); const unsigned char *pcre16_maketables(void); int pcre16_fullinfo(const pcre16 *code, const pcre16_extra *extra, int what, void *where); int pcre16_refcount(pcre16 *code, int adjust); int pcre16_config(int what, void *where); const char *pcre16_version(void); int pcre16_pattern_to_host_byte_order(pcre16 *code, pcre16_extra *extra, const unsigned char *tables); PCRE 16-BIT API INDIRECTED FUNCTIONS void *(*pcre16_malloc)(size_t); void (*pcre16_free)(void *); void *(*pcre16_stack_malloc)(size_t); void (*pcre16_stack_free)(void *); int (*pcre16_callout)(pcre16_callout_block *); PCRE 16-BIT API 16-BIT-ONLY FUNCTION int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input, int length, int *byte_order, int keep_boms); THE PCRE 16-BIT LIBRARY Starting with release 8.30, it is possible to compile a PCRE library that supports 16-bit character strings, including UTF-16 strings, as well as or instead of the original 8-bit library. The majority of the work to make this possible was done by Zoltan Herczeg. The two libraries contain identical sets of functions, used in exactly the same way. Only the names of the functions and the data types of their argu- ments and results are different. To avoid over-complication and reduce the documentation maintenance load, most of the PCRE documentation describes the 8-bit library, with only occasional references to the 16-bit library. This page describes what is different when you use the 16-bit library. WARNING: A single application can be linked with both libraries, but you must take care when processing any particular pattern to use func- tions from just one library. For example, if you want to study a pat- tern that was compiled with pcre16_compile(), you must do so with pcre16_study(), not pcre_study(), and you must free the study data with pcre16_free_study(). THE HEADER FILE There is only one header file, pcre.h. It contains prototypes for all the functions in all libraries, as well as definitions of flags, struc- tures, error codes, etc. THE LIBRARY NAME In Unix-like systems, the 16-bit library is called libpcre16, and can normally be accesss by adding -lpcre16 to the command for linking an application that uses PCRE. STRING TYPES In the 8-bit library, strings are passed to PCRE library functions as vectors of bytes with the C type "char *". In the 16-bit library, strings are passed as vectors of unsigned 16-bit quantities. The macro PCRE_UCHAR16 specifies an appropriate data type, and PCRE_SPTR16 is defined as "const PCRE_UCHAR16 *". In very many environments, "short int" is a 16-bit data type. When PCRE is built, it defines PCRE_UCHAR16 as "unsigned short int", but checks that it really is a 16-bit data type. If it is not, the build fails with an error message telling the maintainer to modify the definition appropriately. STRUCTURE TYPES The types of the opaque structures that are used for compiled 16-bit patterns and JIT stacks are pcre16 and pcre16_jit_stack respectively. The type of the user-accessible structure that is returned by pcre16_study() is pcre16_extra, and the type of the structure that is used for passing data to a callout function is pcre16_callout_block. These structures contain the same fields, with the same names, as their 8-bit counterparts. The only difference is that pointers to character strings are 16-bit instead of 8-bit types. 16-BIT FUNCTIONS For every function in the 8-bit library there is a corresponding func- tion in the 16-bit library with a name that starts with pcre16_ instead of pcre_. The prototypes are listed above. In addition, there is one extra function, pcre16_utf16_to_host_byte_order(). This is a utility function that converts a UTF-16 character string to host byte order if necessary. The other 16-bit functions expect the strings they are passed to be in host byte order. The input and output arguments of pcre16_utf16_to_host_byte_order() may point to the same address, that is, conversion in place is supported. The output buffer must be at least as long as the input. The length argument specifies the number of 16-bit data units in the input string; a negative value specifies a zero-terminated string. If byte_order is NULL, it is assumed that the string starts off in host byte order. This may be changed by byte-order marks (BOMs) anywhere in the string (commonly as the first character). If byte_order is not NULL, a non-zero value of the integer to which it points means that the input starts off in host byte order, otherwise the opposite order is assumed. Again, BOMs in the string can change this. The final byte order is passed back at the end of processing. If keep_boms is not zero, byte-order mark characters (0xfeff) are copied into the output string. Otherwise they are discarded. The result of the function is the number of 16-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated. SUBJECT STRING OFFSETS The lengths and starting offsets of subject strings must be specified in 16-bit data units, and the offsets within subject strings that are returned by the matching functions are in also 16-bit units rather than bytes. NAMED SUBPATTERNS The name-to-number translation table that is maintained for named sub- patterns uses 16-bit characters. The pcre16_get_stringtable_entries() function returns the length of each entry in the table as the number of 16-bit data units. OPTION NAMES There are two new general option names, PCRE_UTF16 and PCRE_NO_UTF16_CHECK, which correspond to PCRE_UTF8 and PCRE_NO_UTF8_CHECK in the 8-bit library. In fact, these new options define the same bits in the options word. There is a discussion about the validity of UTF-16 strings in the pcreunicode page. For the pcre16_config() function there is an option PCRE_CONFIG_UTF16 that returns 1 if UTF-16 support is configured, otherwise 0. If this option is given to pcre_config() or pcre32_config(), or if the PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF32 option is given to pcre16_con- fig(), the result is the PCRE_ERROR_BADOPTION error. CHARACTER CODES In 16-bit mode, when PCRE_UTF16 is not set, character values are treated in the same way as in 8-bit, non UTF-8 mode, except, of course, that they can range from 0 to 0xffff instead of 0 to 0xff. Character types for characters less than 0xff can therefore be influenced by the locale in the same way as before. Characters greater than 0xff have only one case, and no "type" (such as letter or digit). In UTF-16 mode, the character code is Unicode, in the range 0 to 0x10ffff, with the exception of values in the range 0xd800 to 0xdfff because those are "surrogate" values that are used in pairs to encode values greater than 0xffff. A UTF-16 string can indicate its endianness by special code knows as a byte-order mark (BOM). The PCRE functions do not handle this, expecting strings to be in host byte order. A utility function called pcre16_utf16_to_host_byte_order() is provided to help with this (see above). ERROR NAMES The errors PCRE_ERROR_BADUTF16_OFFSET and PCRE_ERROR_SHORTUTF16 corre- spond to their 8-bit counterparts. The error PCRE_ERROR_BADMODE is given when a compiled pattern is passed to a function that processes patterns in the other mode, for example, if a pattern compiled with pcre_compile() is passed to pcre16_exec(). There are new error codes whose names begin with PCRE_UTF16_ERR for invalid UTF-16 strings, corresponding to the PCRE_UTF8_ERR codes for UTF-8 strings that are described in the section entitled "Reason codes for invalid UTF-8 strings" in the main pcreapi page. The UTF-16 errors are: PCRE_UTF16_ERR1 Missing low surrogate at end of string PCRE_UTF16_ERR2 Invalid low surrogate follows high surrogate PCRE_UTF16_ERR3 Isolated low surrogate PCRE_UTF16_ERR4 Non-character ERROR TEXTS If there is an error while compiling a pattern, the error text that is passed back by pcre16_compile() or pcre16_compile2() is still an 8-bit character string, zero-terminated. CALLOUTS The subject and mark fields in the callout block that is passed to a callout function point to 16-bit vectors. TESTING The pcretest program continues to operate with 8-bit input and output files, but it can be used for testing the 16-bit library. If it is run with the command line option -16, patterns and subject strings are con- verted from 8-bit to 16-bit before being passed to PCRE, and the 16-bit library functions are used instead of the 8-bit ones. Returned 16-bit strings are converted to 8-bit for output. If both the 8-bit and the 32-bit libraries were not compiled, pcretest defaults to 16-bit and the -16 option is ignored. When PCRE is being built, the RunTest script that is called by "make check" uses the pcretest -C option to discover which of the 8-bit, 16-bit and 32-bit libraries has been built, and runs the tests appro- priately. NOT SUPPORTED IN 16-BIT MODE Not all the features of the 8-bit library are available with the 16-bit library. The C++ and POSIX wrapper functions support only the 8-bit library, and the pcregrep program is at present 8-bit only. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 12 May 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCRE(3) Library Functions Manual PCRE(3) NAME PCRE - Perl-compatible regular expressions #include PCRE 32-BIT API BASIC FUNCTIONS pcre32 *pcre32_compile(PCRE_SPTR32 pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre32 *pcre32_compile2(PCRE_SPTR32 pattern, int options, int *errorcodeptr, const unsigned char *tableptr); pcre32_extra *pcre32_study(const pcre32 *code, int options, const char **errptr); void pcre32_free_study(pcre32_extra *extra); int pcre32_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize); int pcre32_dfa_exec(const pcre32 *code, const pcre32_extra *extra, PCRE_SPTR32 subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount); PCRE 32-BIT API STRING EXTRACTION FUNCTIONS int pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_UCHAR32 *buffer, int buffersize); int pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR32 *buffer, int buffersize); int pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_SPTR32 *stringptr); int pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 name); int pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 name, PCRE_UCHAR32 **first, PCRE_UCHAR32 **last); int pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR32 *stringptr); int pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 **listptr); void pcre32_free_substring(PCRE_SPTR32 stringptr); void pcre32_free_substring_list(PCRE_SPTR32 *stringptr); PCRE 32-BIT API AUXILIARY FUNCTIONS pcre32_jit_stack *pcre32_jit_stack_alloc(int startsize, int maxsize); void pcre32_jit_stack_free(pcre32_jit_stack *stack); void pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *data); const unsigned char *pcre32_maketables(void); int pcre32_fullinfo(const pcre32 *code, const pcre32_extra *extra, int what, void *where); int pcre32_refcount(pcre32 *code, int adjust); int pcre32_config(int what, void *where); const char *pcre32_version(void); int pcre32_pattern_to_host_byte_order(pcre32 *code, pcre32_extra *extra, const unsigned char *tables); PCRE 32-BIT API INDIRECTED FUNCTIONS void *(*pcre32_malloc)(size_t); void (*pcre32_free)(void *); void *(*pcre32_stack_malloc)(size_t); void (*pcre32_stack_free)(void *); int (*pcre32_callout)(pcre32_callout_block *); PCRE 32-BIT API 32-BIT-ONLY FUNCTION int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *output, PCRE_SPTR32 input, int length, int *byte_order, int keep_boms); THE PCRE 32-BIT LIBRARY Starting with release 8.32, it is possible to compile a PCRE library that supports 32-bit character strings, including UTF-32 strings, as well as or instead of the original 8-bit library. This work was done by Christian Persch, based on the work done by Zoltan Herczeg for the 16-bit library. All three libraries contain identical sets of func- tions, used in exactly the same way. Only the names of the functions and the data types of their arguments and results are different. To avoid over-complication and reduce the documentation maintenance load, most of the PCRE documentation describes the 8-bit library, with only occasional references to the 16-bit and 32-bit libraries. This page describes what is different when you use the 32-bit library. WARNING: A single application can be linked with all or any of the three libraries, but you must take care when processing any particular pattern to use functions from just one library. For example, if you want to study a pattern that was compiled with pcre32_compile(), you must do so with pcre32_study(), not pcre_study(), and you must free the study data with pcre32_free_study(). THE HEADER FILE There is only one header file, pcre.h. It contains prototypes for all the functions in all libraries, as well as definitions of flags, struc- tures, error codes, etc. THE LIBRARY NAME In Unix-like systems, the 32-bit library is called libpcre32, and can normally be accesss by adding -lpcre32 to the command for linking an application that uses PCRE. STRING TYPES In the 8-bit library, strings are passed to PCRE library functions as vectors of bytes with the C type "char *". In the 32-bit library, strings are passed as vectors of unsigned 32-bit quantities. The macro PCRE_UCHAR32 specifies an appropriate data type, and PCRE_SPTR32 is defined as "const PCRE_UCHAR32 *". In very many environments, "unsigned int" is a 32-bit data type. When PCRE is built, it defines PCRE_UCHAR32 as "unsigned int", but checks that it really is a 32-bit data type. If it is not, the build fails with an error message telling the maintainer to modify the definition appropriately. STRUCTURE TYPES The types of the opaque structures that are used for compiled 32-bit patterns and JIT stacks are pcre32 and pcre32_jit_stack respectively. The type of the user-accessible structure that is returned by pcre32_study() is pcre32_extra, and the type of the structure that is used for passing data to a callout function is pcre32_callout_block. These structures contain the same fields, with the same names, as their 8-bit counterparts. The only difference is that pointers to character strings are 32-bit instead of 8-bit types. 32-BIT FUNCTIONS For every function in the 8-bit library there is a corresponding func- tion in the 32-bit library with a name that starts with pcre32_ instead of pcre_. The prototypes are listed above. In addition, there is one extra function, pcre32_utf32_to_host_byte_order(). This is a utility function that converts a UTF-32 character string to host byte order if necessary. The other 32-bit functions expect the strings they are passed to be in host byte order. The input and output arguments of pcre32_utf32_to_host_byte_order() may point to the same address, that is, conversion in place is supported. The output buffer must be at least as long as the input. The length argument specifies the number of 32-bit data units in the input string; a negative value specifies a zero-terminated string. If byte_order is NULL, it is assumed that the string starts off in host byte order. This may be changed by byte-order marks (BOMs) anywhere in the string (commonly as the first character). If byte_order is not NULL, a non-zero value of the integer to which it points means that the input starts off in host byte order, otherwise the opposite order is assumed. Again, BOMs in the string can change this. The final byte order is passed back at the end of processing. If keep_boms is not zero, byte-order mark characters (0xfeff) are copied into the output string. Otherwise they are discarded. The result of the function is the number of 32-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated. SUBJECT STRING OFFSETS The lengths and starting offsets of subject strings must be specified in 32-bit data units, and the offsets within subject strings that are returned by the matching functions are in also 32-bit units rather than bytes. NAMED SUBPATTERNS The name-to-number translation table that is maintained for named sub- patterns uses 32-bit characters. The pcre32_get_stringtable_entries() function returns the length of each entry in the table as the number of 32-bit data units. OPTION NAMES There are two new general option names, PCRE_UTF32 and PCRE_NO_UTF32_CHECK, which correspond to PCRE_UTF8 and PCRE_NO_UTF8_CHECK in the 8-bit library. In fact, these new options define the same bits in the options word. There is a discussion about the validity of UTF-32 strings in the pcreunicode page. For the pcre32_config() function there is an option PCRE_CONFIG_UTF32 that returns 1 if UTF-32 support is configured, otherwise 0. If this option is given to pcre_config() or pcre16_config(), or if the PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF16 option is given to pcre32_con- fig(), the result is the PCRE_ERROR_BADOPTION error. CHARACTER CODES In 32-bit mode, when PCRE_UTF32 is not set, character values are treated in the same way as in 8-bit, non UTF-8 mode, except, of course, that they can range from 0 to 0x7fffffff instead of 0 to 0xff. Charac- ter types for characters less than 0xff can therefore be influenced by the locale in the same way as before. Characters greater than 0xff have only one case, and no "type" (such as letter or digit). In UTF-32 mode, the character code is Unicode, in the range 0 to 0x10ffff, with the exception of values in the range 0xd800 to 0xdfff because those are "surrogate" values that are ill-formed in UTF-32. A UTF-32 string can indicate its endianness by special code knows as a byte-order mark (BOM). The PCRE functions do not handle this, expecting strings to be in host byte order. A utility function called pcre32_utf32_to_host_byte_order() is provided to help with this (see above). ERROR NAMES The error PCRE_ERROR_BADUTF32 corresponds to its 8-bit counterpart. The error PCRE_ERROR_BADMODE is given when a compiled pattern is passed to a function that processes patterns in the other mode, for example, if a pattern compiled with pcre_compile() is passed to pcre32_exec(). There are new error codes whose names begin with PCRE_UTF32_ERR for invalid UTF-32 strings, corresponding to the PCRE_UTF8_ERR codes for UTF-8 strings that are described in the section entitled "Reason codes for invalid UTF-8 strings" in the main pcreapi page. The UTF-32 errors are: PCRE_UTF32_ERR1 Surrogate character (range from 0xd800 to 0xdfff) PCRE_UTF32_ERR2 Non-character PCRE_UTF32_ERR3 Character > 0x10ffff ERROR TEXTS If there is an error while compiling a pattern, the error text that is passed back by pcre32_compile() or pcre32_compile2() is still an 8-bit character string, zero-terminated. CALLOUTS The subject and mark fields in the callout block that is passed to a callout function point to 32-bit vectors. TESTING The pcretest program continues to operate with 8-bit input and output files, but it can be used for testing the 32-bit library. If it is run with the command line option -32, patterns and subject strings are con- verted from 8-bit to 32-bit before being passed to PCRE, and the 32-bit library functions are used instead of the 8-bit ones. Returned 32-bit strings are converted to 8-bit for output. If both the 8-bit and the 16-bit libraries were not compiled, pcretest defaults to 32-bit and the -32 option is ignored. When PCRE is being built, the RunTest script that is called by "make check" uses the pcretest -C option to discover which of the 8-bit, 16-bit and 32-bit libraries has been built, and runs the tests appro- priately. NOT SUPPORTED IN 32-BIT MODE Not all the features of the 8-bit library are available with the 32-bit library. The C++ and POSIX wrapper functions support only the 8-bit library, and the pcregrep program is at present 8-bit only. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 12 May 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCREBUILD(3) Library Functions Manual PCREBUILD(3) NAME PCRE - Perl-compatible regular expressions BUILDING PCRE PCRE is distributed with a configure script that can be used to build the library in Unix-like environments using the applications known as Autotools. Also in the distribution are files to support building using CMake instead of configure. The text file README contains general information about building with Autotools (some of which is repeated below), and also has some comments about building on various operating systems. There is a lot more information about building PCRE without using Autotools (including information about using CMake and building "by hand") in the text file called NON-AUTOTOOLS-BUILD. You should consult this file as well as the README file if you are building in a non-Unix-like environment. PCRE BUILD-TIME OPTIONS The rest of this document describes the optional features of PCRE that can be selected when the library is compiled. It assumes use of the configure script, where the optional features are selected or dese- lected by providing options to configure before running the make com- mand. However, the same options can be selected in both Unix-like and non-Unix-like environments using the GUI facility of cmake-gui if you are using CMake instead of configure to build PCRE. If you are not using Autotools or CMake, option selection can be done by editing the config.h file, or by passing parameter settings to the compiler, as described in NON-AUTOTOOLS-BUILD. The complete list of options for configure (which includes the standard ones such as the selection of the installation directory) can be obtained by running ./configure --help The following sections include descriptions of options whose names begin with --enable or --disable. These settings specify changes to the defaults for the configure command. Because of the way that configure works, --enable and --disable always come in pairs, so the complemen- tary option always exists as well, but as it specifies the default, it is not described. BUILDING 8-BIT, 16-BIT AND 32-BIT LIBRARIES By default, a library called libpcre is built, containing functions that take string arguments contained in vectors of bytes, either as single-byte characters, or interpreted as UTF-8 strings. You can also build a separate library, called libpcre16, in which strings are con- tained in vectors of 16-bit data units and interpreted either as sin- gle-unit characters or UTF-16 strings, by adding --enable-pcre16 to the configure command. You can also build yet another separate library, called libpcre32, in which strings are contained in vectors of 32-bit data units and interpreted either as single-unit characters or UTF-32 strings, by adding --enable-pcre32 to the configure command. If you do not want the 8-bit library, add --disable-pcre8 as well. At least one of the three libraries must be built. Note that the C++ and POSIX wrappers are for the 8-bit library only, and that pcregrep is an 8-bit program. None of these are built if you select only the 16-bit or 32-bit libraries. BUILDING SHARED AND STATIC LIBRARIES The Autotools PCRE building process uses libtool to build both shared and static libraries by default. You can suppress one of these by adding one of --disable-shared --disable-static to the configure command, as required. C++ SUPPORT By default, if the 8-bit library is being built, the configure script will search for a C++ compiler and C++ header files. If it finds them, it automatically builds the C++ wrapper library (which supports only 8-bit strings). You can disable this by adding --disable-cpp to the configure command. UTF-8, UTF-16 AND UTF-32 SUPPORT To build PCRE with support for UTF Unicode character strings, add --enable-utf to the configure command. This setting applies to all three libraries, adding support for UTF-8 to the 8-bit library, support for UTF-16 to the 16-bit library, and support for UTF-32 to the to the 32-bit library. There are no separate options for enabling UTF-8, UTF-16 and UTF-32 independently because that would allow ridiculous settings such as requesting UTF-16 support while building only the 8-bit library. It is not possible to build one library with UTF support and another with- out in the same configuration. (For backwards compatibility, --enable- utf8 is a synonym of --enable-utf.) Of itself, this setting does not make PCRE treat strings as UTF-8, UTF-16 or UTF-32. As well as compiling PCRE with this option, you also have have to set the PCRE_UTF8, PCRE_UTF16 or PCRE_UTF32 option (as appropriate) when you call one of the pattern compiling functions. If you set --enable-utf when compiling in an EBCDIC environment, PCRE expects its input to be either ASCII or UTF-8 (depending on the run- time option). It is not possible to support both EBCDIC and UTF-8 codes in the same version of the library. Consequently, --enable-utf and --enable-ebcdic are mutually exclusive. UNICODE CHARACTER PROPERTY SUPPORT UTF support allows the libraries to process character codepoints up to 0x10ffff in the strings that they handle. On its own, however, it does not provide any facilities for accessing the properties of such charac- ters. If you want to be able to use the pattern escapes \P, \p, and \X, which refer to Unicode character properties, you must add --enable-unicode-properties to the configure command. This implies UTF support, even if you have not explicitly requested it. Including Unicode property support adds around 30K of tables to the PCRE library. Only the general category properties such as Lu and Nd are supported. Details are given in the pcrepattern documentation. JUST-IN-TIME COMPILER SUPPORT Just-in-time compiler support is included in the build by specifying --enable-jit This support is available only for certain hardware architectures. If this option is set for an unsupported architecture, a compile time error occurs. See the pcrejit documentation for a discussion of JIT usage. When JIT support is enabled, pcregrep automatically makes use of it, unless you add --disable-pcregrep-jit to the "configure" command. CODE VALUE OF NEWLINE By default, PCRE interprets the linefeed (LF) character as indicating the end of a line. This is the normal newline character on Unix-like systems. You can compile PCRE to use carriage return (CR) instead, by adding --enable-newline-is-cr to the configure command. There is also a --enable-newline-is-lf option, which explicitly specifies linefeed as the newline character. Alternatively, you can specify that line endings are to be indicated by the two character sequence CRLF. If you want this, add --enable-newline-is-crlf to the configure command. There is a fourth option, specified by --enable-newline-is-anycrlf which causes PCRE to recognize any of the three sequences CR, LF, or CRLF as indicating a line ending. Finally, a fifth option, specified by --enable-newline-is-any causes PCRE to recognize any Unicode newline sequence. Whatever line ending convention is selected when PCRE is built can be overridden when the library functions are called. At build time it is conventional to use the standard for your operating system. WHAT \R MATCHES By default, the sequence \R in a pattern matches any Unicode newline sequence, whatever has been selected as the line ending sequence. If you specify --enable-bsr-anycrlf the default is changed so that \R matches only CR, LF, or CRLF. What- ever is selected when PCRE is built can be overridden when the library functions are called. POSIX MALLOC USAGE When the 8-bit library is called through the POSIX interface (see the pcreposix documentation), additional working storage is required for holding the pointers to capturing substrings, because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper func- tion uses space on the stack, because this is faster than using mal- loc() for each call. The default threshold above which the stack is no longer used is 10; it can be changed by adding a setting such as --with-posix-malloc-threshold=20 to the configure command. HANDLING VERY LARGE PATTERNS Within a compiled pattern, offset values are used to point from one part to another (for example, from an opening parenthesis to an alter- nation metacharacter). By default, in the 8-bit and 16-bit libraries, two-byte values are used for these offsets, leading to a maximum size for a compiled pattern of around 64K. This is sufficient to handle all but the most gigantic patterns. Nevertheless, some people do want to process truly enormous patterns, so it is possible to compile PCRE to use three-byte or four-byte offsets by adding a setting such as --with-link-size=3 to the configure command. The value given must be 2, 3, or 4. For the 16-bit library, a value of 3 is rounded up to 4. In these libraries, using longer offsets slows down the operation of PCRE because it has to load additional data when handling them. For the 32-bit library the value is always 4 and cannot be overridden; the value of --with-link- size is ignored. AVOIDING EXCESSIVE STACK USAGE When matching with the pcre_exec() function, PCRE implements backtrack- ing by making recursive calls to an internal function called match(). In environments where the size of the stack is limited, this can se- verely limit PCRE's operation. (The Unix environment does not usually suffer from this problem, but it may sometimes be necessary to increase the maximum stack size. There is a discussion in the pcrestack docu- mentation.) An alternative approach to recursion that uses memory from the heap to remember data, instead of using recursive function calls, has been implemented to work round the problem of limited stack size. If you want to build a version of PCRE that works this way, add --disable-stack-for-recursion to the configure command. With this configuration, PCRE will use the pcre_stack_malloc and pcre_stack_free variables to call memory manage- ment functions. By default these point to malloc() and free(), but you can replace the pointers so that your own functions are used instead. Separate functions are provided rather than using pcre_malloc and pcre_free because the usage is very predictable: the block sizes requested are always the same, and the blocks are always freed in reverse order. A calling program might be able to implement optimized functions that perform better than malloc() and free(). PCRE runs noticeably more slowly when built in this way. This option affects only the pcre_exec() function; it is not relevant for pcre_dfa_exec(). LIMITING PCRE RESOURCE USAGE Internally, PCRE has a function called match(), which it calls repeat- edly (sometimes recursively) when matching a pattern with the pcre_exec() function. By controlling the maximum number of times this function may be called during a single matching operation, a limit can be placed on the resources used by a single call to pcre_exec(). The limit can be changed at run time, as described in the pcreapi documen- tation. The default is 10 million, but this can be changed by adding a setting such as --with-match-limit=500000 to the configure command. This setting has no effect on the pcre_dfa_exec() matching function. In some environments it is desirable to limit the depth of recursive calls of match() more strictly than the total number of calls, in order to restrict the maximum amount of stack (or heap, if --disable-stack- for-recursion is specified) that is used. A second limit controls this; it defaults to the value that is set for --with-match-limit, which imposes no additional constraints. However, you can set a lower limit by adding, for example, --with-match-limit-recursion=10000 to the configure command. This value can also be overridden at run time. CREATING CHARACTER TABLES AT BUILD TIME PCRE uses fixed tables for processing characters whose code values are less than 256. By default, PCRE is built with a set of tables that are distributed in the file pcre_chartables.c.dist. These tables are for ASCII codes only. If you add --enable-rebuild-chartables to the configure command, the distributed tables are no longer used. Instead, a program called dftables is compiled and run. This outputs the source for new set of tables, created in the default locale of your C run-time system. (This method of replacing the tables does not work if you are cross compiling, because dftables is run on the local host. If you need to create alternative tables when cross compiling, you will have to do so "by hand".) USING EBCDIC CODE PCRE assumes by default that it will run in an environment where the character code is ASCII (or Unicode, which is a superset of ASCII). This is the case for most computer operating systems. PCRE can, how- ever, be compiled to run in an EBCDIC environment by adding --enable-ebcdic to the configure command. This setting implies --enable-rebuild-charta- bles. You should only use it if you know that you are in an EBCDIC environment (for example, an IBM mainframe operating system). The --enable-ebcdic option is incompatible with --enable-utf. The EBCDIC character that corresponds to an ASCII LF is assumed to have the value 0x15 by default. However, in some EBCDIC environments, 0x25 is used. In such an environment you should use --enable-ebcdic-nl25 as well as, or instead of, --enable-ebcdic. The EBCDIC character for CR has the same value as in ASCII, namely, 0x0d. Whichever of 0x15 and 0x25 is not chosen as LF is made to correspond to the Unicode NEL char- acter (which, in Unicode, is 0x85). The options that select newline behaviour, such as --enable-newline-is- cr, and equivalent run-time options, refer to these character values in an EBCDIC environment. PCREGREP OPTIONS FOR COMPRESSED FILE SUPPORT By default, pcregrep reads all files as plain text. You can build it so that it recognizes files whose names end in .gz or .bz2, and reads them with libz or libbz2, respectively, by adding one or both of --enable-pcregrep-libz --enable-pcregrep-libbz2 to the configure command. These options naturally require that the rel- evant libraries are installed on your system. Configuration will fail if they are not. PCREGREP BUFFER SIZE pcregrep uses an internal buffer to hold a "window" on the file it is scanning, in order to be able to output "before" and "after" lines when it finds a match. The size of the buffer is controlled by a parameter whose default value is 20K. The buffer itself is three times this size, but because of the way it is used for holding "before" lines, the long- est line that is guaranteed to be processable is the parameter size. You can change the default parameter value by adding, for example, --with-pcregrep-bufsize=50K to the configure command. The caller of pcregrep can, however, override this value by specifying a run-time option. PCRETEST OPTION FOR LIBREADLINE SUPPORT If you add --enable-pcretest-libreadline to the configure command, pcretest is linked with the libreadline library, and when its input is from a terminal, it reads it using the readline() function. This provides line-editing and history facilities. Note that libreadline is GPL-licensed, so if you distribute a binary of pcretest linked in this way, there may be licensing issues. Setting this option causes the -lreadline option to be added to the pcretest build. In many operating environments with a sytem-installed libreadline this is sufficient. However, in some environments (e.g. if an unmodified distribution version of readline is in use), some extra configuration may be necessary. The INSTALL file for libreadline says this: "Readline uses the termcap functions, but does not link with the termcap or curses library itself, allowing applications which link with readline the to choose an appropriate library." If your environment has not been set up so that an appropriate library is automatically included, you may need to add something like LIBS="-ncurses" immediately before the configure command. DEBUGGING WITH VALGRIND SUPPORT By adding the --enable-valgrind option to to the configure command, PCRE will use valgrind annotations to mark certain memory regions as unaddressable. This allows it to detect invalid memory accesses, and is mostly useful for debugging PCRE itself. CODE COVERAGE REPORTING If your C compiler is gcc, you can build a version of PCRE that can generate a code coverage report for its test suite. To enable this, you must install lcov version 1.6 or above. Then specify --enable-coverage to the configure command and build PCRE in the usual way. Note that using ccache (a caching C compiler) is incompatible with code coverage reporting. If you have configured ccache to run automatically on your system, you must set the environment variable CCACHE_DISABLE=1 before running make to build PCRE, so that ccache is not used. When --enable-coverage is used, the following addition targets are added to the Makefile: make coverage This creates a fresh coverage report for the PCRE test suite. It is equivalent to running "make coverage-reset", "make coverage-baseline", "make check", and then "make coverage-report". make coverage-reset This zeroes the coverage counters, but does nothing else. make coverage-baseline This captures baseline coverage information. make coverage-report This creates the coverage report. make coverage-clean-report This removes the generated coverage report without cleaning the cover- age data itself. make coverage-clean-data This removes the captured coverage data without removing the coverage files created at compile time (*.gcno). make coverage-clean This cleans all coverage data including the generated coverage report. For more information about code coverage, see the gcov and lcov docu- mentation. SEE ALSO pcreapi(3), pcre16, pcre32, pcre_config(3). AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 12 May 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCREMATCHING(3) Library Functions Manual PCREMATCHING(3) NAME PCRE - Perl-compatible regular expressions PCRE MATCHING ALGORITHMS This document describes the two different algorithms that are available in PCRE for matching a compiled regular expression against a given sub- ject string. The "standard" algorithm is the one provided by the pcre_exec(), pcre16_exec() and pcre32_exec() functions. These work in the same as as Perl's matching function, and provide a Perl-compatible matching operation. The just-in-time (JIT) optimization that is described in the pcrejit documentation is compatible with these func- tions. An alternative algorithm is provided by the pcre_dfa_exec(), pcre16_dfa_exec() and pcre32_dfa_exec() functions; they operate in a different way, and are not Perl-compatible. This alternative has advan- tages and disadvantages compared with the standard algorithm, and these are described below. When there is only one possible way in which a given subject string can match a pattern, the two algorithms give the same answer. A difference arises, however, when there are multiple possibilities. For example, if the pattern ^<.*> is matched against the string there are three possible answers. The standard algorithm finds only one of them, whereas the alternative algorithm finds all three. REGULAR EXPRESSIONS AS TREES The set of strings that are matched by a regular expression can be rep- resented as a tree structure. An unlimited repetition in the pattern makes the tree of infinite size, but it is still a tree. Matching the pattern to a given subject string (from a given starting point) can be thought of as a search of the tree. There are two ways to search a tree: depth-first and breadth-first, and these correspond to the two matching algorithms provided by PCRE. THE STANDARD MATCHING ALGORITHM In the terminology of Jeffrey Friedl's book "Mastering Regular Expres- sions", the standard algorithm is an "NFA algorithm". It conducts a depth-first search of the pattern tree. That is, it proceeds along a single path through the tree, checking that the subject matches what is required. When there is a mismatch, the algorithm tries any alterna- tives at the current point, and if they all fail, it backs up to the previous branch point in the tree, and tries the next alternative branch at that level. This often involves backing up (moving to the left) in the subject string as well. The order in which repetition branches are tried is controlled by the greedy or ungreedy nature of the quantifier. If a leaf node is reached, a matching string has been found, and at that point the algorithm stops. Thus, if there is more than one possi- ble match, this algorithm returns the first one that it finds. Whether this is the shortest, the longest, or some intermediate length depends on the way the greedy and ungreedy repetition quantifiers are specified in the pattern. Because it ends up with a single path through the tree, it is rela- tively straightforward for this algorithm to keep track of the sub- strings that are matched by portions of the pattern in parentheses. This provides support for capturing parentheses and back references. THE ALTERNATIVE MATCHING ALGORITHM This algorithm conducts a breadth-first search of the tree. Starting from the first matching point in the subject, it scans the subject string from left to right, once, character by character, and as it does this, it remembers all the paths through the tree that represent valid matches. In Friedl's terminology, this is a kind of "DFA algorithm", though it is not implemented as a traditional finite state machine (it keeps multiple states active simultaneously). Although the general principle of this matching algorithm is that it scans the subject string only once, without backtracking, there is one exception: when a lookaround assertion is encountered, the characters following or preceding the current point have to be independently inspected. The scan continues until either the end of the subject is reached, or there are no more unterminated paths. At this point, terminated paths represent the different matching possibilities (if there are none, the match has failed). Thus, if there is more than one possible match, this algorithm finds all of them, and in particular, it finds the long- est. The matches are returned in decreasing order of length. There is an option to stop the algorithm after the first match (which is neces- sarily the shortest) is found. Note that all the matches that are found start at the same point in the subject. If the pattern cat(er(pillar)?)? is matched against the string "the caterpillar catchment", the result will be the three strings "caterpillar", "cater", and "cat" that start at the fifth character of the subject. The algorithm does not automati- cally move on to find matches that start at later positions. PCRE's "auto-possessification" optimization usually applies to charac- ter repeats at the end of a pattern (as well as internally). For exam- ple, the pattern "a\d+" is compiled as if it were "a\d++" because there is no point even considering the possibility of backtracking into the repeated digits. For DFA matching, this means that only one possible match is found. If you really do want multiple matches in such cases, either use an ungreedy repeat ("a\d+?") or set the PCRE_NO_AUTO_POSSESS option when compiling. There are a number of features of PCRE regular expressions that are not supported by the alternative matching algorithm. They are as follows: 1. Because the algorithm finds all possible matches, the greedy or ungreedy nature of repetition quantifiers is not relevant. Greedy and ungreedy quantifiers are treated in exactly the same way. However, pos- sessive quantifiers can make a difference when what follows could also match what is quantified, for example in a pattern like this: ^a++\w! This pattern matches "aaab!" but not "aaa!", which would be matched by a non-possessive quantifier. Similarly, if an atomic group is present, it is matched as if it were a standalone pattern at the current point, and the longest match is then "locked in" for the rest of the overall pattern. 2. When dealing with multiple paths through the tree simultaneously, it is not straightforward to keep track of captured substrings for the different matching possibilities, and PCRE's implementation of this algorithm does not attempt to do this. This means that no captured sub- strings are available. 3. Because no substrings are captured, back references within the pat- tern are not supported, and cause errors if encountered. 4. For the same reason, conditional expressions that use a backrefer- ence as the condition or test for a specific group recursion are not supported. 5. Because many paths through the tree may be active, the \K escape sequence, which resets the start of the match when encountered (but may be on some paths and not on others), is not supported. It causes an error if encountered. 6. Callouts are supported, but the value of the capture_top field is always 1, and the value of the capture_last field is always -1. 7. The \C escape sequence, which (in the standard algorithm) always matches a single data unit, even in UTF-8, UTF-16 or UTF-32 modes, is not supported in these modes, because the alternative algorithm moves through the subject string one character (not data unit) at a time, for all active paths through the tree. 8. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not supported. (*FAIL) is supported, and behaves like a failing negative assertion. ADVANTAGES OF THE ALTERNATIVE ALGORITHM Using the alternative matching algorithm provides the following advan- tages: 1. All possible matches (at a single point in the subject) are automat- ically found, and in particular, the longest match is found. To find more than one match using the standard algorithm, you have to do kludgy things with callouts. 2. Because the alternative algorithm scans the subject string just once, and never needs to backtrack (except for lookbehinds), it is pos- sible to pass very long subject strings to the matching function in several pieces, checking for partial matching each time. Although it is possible to do multi-segment matching using the standard algorithm by retaining partially matched substrings, it is more complicated. The pcrepartial documentation gives details of partial matching and dis- cusses multi-segment matching. DISADVANTAGES OF THE ALTERNATIVE ALGORITHM The alternative algorithm suffers from a number of disadvantages: 1. It is substantially slower than the standard algorithm. This is partly because it has to search for all possible matches, but is also because it is less susceptible to optimization. 2. Capturing parentheses and back references are not supported. 3. Although atomic groups are supported, their use does not provide the performance advantage that it does for the standard algorithm. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 12 November 2013 Copyright (c) 1997-2012 University of Cambridge. ------------------------------------------------------------------------------ PCREAPI(3) Library Functions Manual PCREAPI(3) NAME PCRE - Perl-compatible regular expressions #include PCRE NATIVE API BASIC FUNCTIONS pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre *pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre_extra *pcre_study(const pcre *code, int options, const char **errptr); void pcre_free_study(pcre_extra *extra); int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize); int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount); PCRE NATIVE API STRING EXTRACTION FUNCTIONS int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize); int pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize); int pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr); int pcre_get_stringnumber(const pcre *code, const char *name); int pcre_get_stringtable_entries(const pcre *code, const char *name, char **first, char **last); int pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr); int pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr); void pcre_free_substring(const char *stringptr); void pcre_free_substring_list(const char **stringptr); PCRE NATIVE API AUXILIARY FUNCTIONS int pcre_jit_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, pcre_jit_stack *jstack); pcre_jit_stack *pcre_jit_stack_alloc(int startsize, int maxsize); void pcre_jit_stack_free(pcre_jit_stack *stack); void pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *data); const unsigned char *pcre_maketables(void); int pcre_fullinfo(const pcre *code, const pcre_extra *extra, int what, void *where); int pcre_refcount(pcre *code, int adjust); int pcre_config(int what, void *where); const char *pcre_version(void); int pcre_pattern_to_host_byte_order(pcre *code, pcre_extra *extra, const unsigned char *tables); PCRE NATIVE API INDIRECTED FUNCTIONS void *(*pcre_malloc)(size_t); void (*pcre_free)(void *); void *(*pcre_stack_malloc)(size_t); void (*pcre_stack_free)(void *); int (*pcre_callout)(pcre_callout_block *); int (*pcre_stack_guard)(void); PCRE 8-BIT, 16-BIT, AND 32-BIT LIBRARIES As well as support for 8-bit character strings, PCRE also supports 16-bit strings (from release 8.30) and 32-bit strings (from release 8.32), by means of two additional libraries. They can be built as well as, or instead of, the 8-bit library. To avoid too much complication, this document describes the 8-bit versions of the functions, with only occasional references to the 16-bit and 32-bit libraries. The 16-bit and 32-bit functions operate in the same way as their 8-bit counterparts; they just use different data types for their arguments and results, and their names start with pcre16_ or pcre32_ instead of pcre_. For every option that has UTF8 in its name (for example, PCRE_UTF8), there are corresponding 16-bit and 32-bit names with UTF8 replaced by UTF16 or UTF32, respectively. This facility is in fact just cosmetic; the 16-bit and 32-bit option names define the same bit val- ues. References to bytes and UTF-8 in this document should be read as refer- ences to 16-bit data units and UTF-16 when using the 16-bit library, or 32-bit data units and UTF-32 when using the 32-bit library, unless specified otherwise. More details of the specific differences for the 16-bit and 32-bit libraries are given in the pcre16 and pcre32 pages. PCRE API OVERVIEW PCRE has its own native API, which is described in this document. There are also some wrapper functions (for the 8-bit library only) that cor- respond to the POSIX regular expression API, but they do not give access to all the functionality. They are described in the pcreposix documentation. Both of these APIs define a set of C function calls. A C++ wrapper (again for the 8-bit library only) is also distributed with PCRE. It is documented in the pcrecpp page. The native API C function prototypes are defined in the header file pcre.h, and on Unix-like systems the (8-bit) library itself is called libpcre. It can normally be accessed by adding -lpcre to the command for linking an application that uses PCRE. The header file defines the macros PCRE_MAJOR and PCRE_MINOR to contain the major and minor release numbers for the library. Applications can use these to include support for different releases of PCRE. In a Windows environment, if you want to statically link an application program against a non-dll pcre.a file, you must define PCRE_STATIC before including pcre.h or pcrecpp.h, because otherwise the pcre_mal- loc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results. The functions pcre_compile(), pcre_compile2(), pcre_study(), and pcre_exec() are used for compiling and matching regular expressions in a Perl-compatible manner. A sample program that demonstrates the sim- plest way of using them is provided in the file called pcredemo.c in the PCRE source distribution. A listing of this program is given in the pcredemo documentation, and the pcresample documentation describes how to compile and run it. Just-in-time compiler support is an optional feature of PCRE that can be built in appropriate hardware environments. It greatly speeds up the matching performance of many patterns. Simple programs can easily request that it be used if available, by setting an option that is ignored when it is not relevant. More complicated programs might need to make use of the functions pcre_jit_stack_alloc(), pcre_jit_stack_free(), and pcre_assign_jit_stack() in order to control the JIT code's memory usage. From release 8.32 there is also a direct interface for JIT execution, which gives improved performance. The JIT-specific functions are dis- cussed in the pcrejit documentation. A second matching function, pcre_dfa_exec(), which is not Perl-compati- ble, is also provided. This uses a different algorithm for the match- ing. The alternative algorithm finds all possible matches (at a given point in the subject), and scans the subject just once (unless there are lookbehind assertions). However, this algorithm does not return captured substrings. A description of the two matching algorithms and their advantages and disadvantages is given in the pcrematching docu- mentation. In addition to the main compiling and matching functions, there are convenience functions for extracting captured substrings from a subject string that is matched by pcre_exec(). They are: pcre_copy_substring() pcre_copy_named_substring() pcre_get_substring() pcre_get_named_substring() pcre_get_substring_list() pcre_get_stringnumber() pcre_get_stringtable_entries() pcre_free_substring() and pcre_free_substring_list() are also provided, to free the memory used for extracted strings. The function pcre_maketables() is used to build a set of character tables in the current locale for passing to pcre_compile(), pcre_exec(), or pcre_dfa_exec(). This is an optional facility that is provided for specialist use. Most commonly, no special tables are passed, in which case internal tables that are generated when PCRE is built are used. The function pcre_fullinfo() is used to find out information about a compiled pattern. The function pcre_version() returns a pointer to a string containing the version of PCRE and its date of release. The function pcre_refcount() maintains a reference count in a data block containing a compiled pattern. This is provided for the benefit of object-oriented applications. The global variables pcre_malloc and pcre_free initially contain the entry points of the standard malloc() and free() functions, respec- tively. PCRE calls the memory management functions via these variables, so a calling program can replace them if it wishes to intercept the calls. This should be done before calling any PCRE functions. The global variables pcre_stack_malloc and pcre_stack_free are also indirections to memory management functions. These special functions are used only when PCRE is compiled to use the heap for remembering data, instead of recursive function calls, when running the pcre_exec() function. See the pcrebuild documentation for details of how to do this. It is a non-standard way of building PCRE, for use in environ- ments that have limited stacks. Because of the greater use of memory management, it runs more slowly. Separate functions are provided so that special-purpose external code can be used for this case. When used, these functions always allocate memory blocks of the same size. There is a discussion about PCRE's stack usage in the pcrestack docu- mentation. The global variable pcre_callout initially contains NULL. It can be set by the caller to a "callout" function, which PCRE will then call at specified points during a matching operation. Details are given in the pcrecallout documentation. The global variable pcre_stack_guard initially contains NULL. It can be set by the caller to a function that is called by PCRE whenever it starts to compile a parenthesized part of a pattern. When parentheses are nested, PCRE uses recursive function calls, which use up the system stack. This function is provided so that applications with restricted stacks can force a compilation error if the stack runs out. The func- tion should return zero if all is well, or non-zero to force an error. NEWLINES PCRE supports five different conventions for indicating line breaks in strings: a single CR (carriage return) character, a single LF (line- feed) character, the two-character sequence CRLF, any of the three pre- ceding, or any Unicode newline sequence. The Unicode newline sequences are the three just mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029). Each of the first three conventions is used by at least one operating system as its standard newline sequence. When PCRE is built, a default can be specified. The default default is LF, which is the Unix stan- dard. When PCRE is run, the default can be overridden, either when a pattern is compiled, or when it is matched. At compile time, the newline convention can be specified by the options argument of pcre_compile(), or it can be specified by special text at the start of the pattern itself; this overrides any other settings. See the pcrepattern page for details of the special character sequences. In the PCRE documentation the word "newline" is used to mean "the char- acter or pair of characters that indicate a line break". The choice of newline convention affects the handling of the dot, circumflex, and dollar metacharacters, the handling of #-comments in /x mode, and, when CRLF is a recognized line ending sequence, the match position advance- ment for a non-anchored pattern. There is more detail about this in the section on pcre_exec() options below. The choice of newline convention does not affect the interpretation of the \n or \r escape sequences, nor does it affect what \R matches, which is controlled in a similar way, but by separate options. MULTITHREADING The PCRE functions can be used in multi-threading applications, with the proviso that the memory management functions pointed to by pcre_malloc, pcre_free, pcre_stack_malloc, and pcre_stack_free, and the callout and stack-checking functions pointed to by pcre_callout and pcre_stack_guard, are shared by all threads. The compiled form of a regular expression is not altered during match- ing, so the same compiled pattern can safely be used by several threads at once. If the just-in-time optimization feature is being used, it needs sepa- rate memory stack areas for each thread. See the pcrejit documentation for more details. SAVING PRECOMPILED PATTERNS FOR LATER USE The compiled form of a regular expression can be saved and re-used at a later time, possibly by a different program, and even on a host other than the one on which it was compiled. Details are given in the pcreprecompile documentation, which includes a description of the pcre_pattern_to_host_byte_order() function. However, compiling a regu- lar expression with one version of PCRE for use with a different ver- sion is not guaranteed to work and may cause crashes. CHECKING BUILD-TIME OPTIONS int pcre_config(int what, void *where); The function pcre_config() makes it possible for a PCRE client to dis- cover which optional features have been compiled into the PCRE library. The pcrebuild documentation has more details about these optional fea- tures. The first argument for pcre_config() is an integer, specifying which information is required; the second argument is a pointer to a variable into which the information is placed. The returned value is zero on success, or the negative error code PCRE_ERROR_BADOPTION if the value in the first argument is not recognized. The following information is available: PCRE_CONFIG_UTF8 The output is an integer that is set to one if UTF-8 support is avail- able; otherwise it is set to zero. This value should normally be given to the 8-bit version of this function, pcre_config(). If it is given to the 16-bit or 32-bit version of this function, the result is PCRE_ERROR_BADOPTION. PCRE_CONFIG_UTF16 The output is an integer that is set to one if UTF-16 support is avail- able; otherwise it is set to zero. This value should normally be given to the 16-bit version of this function, pcre16_config(). If it is given to the 8-bit or 32-bit version of this function, the result is PCRE_ERROR_BADOPTION. PCRE_CONFIG_UTF32 The output is an integer that is set to one if UTF-32 support is avail- able; otherwise it is set to zero. This value should normally be given to the 32-bit version of this function, pcre32_config(). If it is given to the 8-bit or 16-bit version of this function, the result is PCRE_ERROR_BADOPTION. PCRE_CONFIG_UNICODE_PROPERTIES The output is an integer that is set to one if support for Unicode character properties is available; otherwise it is set to zero. PCRE_CONFIG_JIT The output is an integer that is set to one if support for just-in-time compiling is available; otherwise it is set to zero. PCRE_CONFIG_JITTARGET The output is a pointer to a zero-terminated "const char *" string. If JIT support is available, the string contains the name of the architec- ture for which the JIT compiler is configured, for example "x86 32bit (little endian + unaligned)". If JIT support is not available, the result is NULL. PCRE_CONFIG_NEWLINE The output is an integer whose value specifies the default character sequence that is recognized as meaning "newline". The values that are supported in ASCII/Unicode environments are: 10 for LF, 13 for CR, 3338 for CRLF, -2 for ANYCRLF, and -1 for ANY. In EBCDIC environments, CR, ANYCRLF, and ANY yield the same values. However, the value for LF is normally 21, though some EBCDIC environments use 37. The corresponding values for CRLF are 3349 and 3365. The default should normally corre- spond to the standard sequence for your operating system. PCRE_CONFIG_BSR The output is an integer whose value indicates what character sequences the \R escape sequence matches by default. A value of 0 means that \R matches any Unicode line ending sequence; a value of 1 means that \R matches only CR, LF, or CRLF. The default can be overridden when a pat- tern is compiled or matched. PCRE_CONFIG_LINK_SIZE The output is an integer that contains the number of bytes used for internal linkage in compiled regular expressions. For the 8-bit library, the value can be 2, 3, or 4. For the 16-bit library, the value is either 2 or 4 and is still a number of bytes. For the 32-bit library, the value is either 2 or 4 and is still a number of bytes. The default value of 2 is sufficient for all but the most massive patterns, since it allows the compiled pattern to be up to 64K in size. Larger values allow larger regular expressions to be compiled, at the expense of slower matching. PCRE_CONFIG_POSIX_MALLOC_THRESHOLD The output is an integer that contains the threshold above which the POSIX interface uses malloc() for output vectors. Further details are given in the pcreposix documentation. PCRE_CONFIG_PARENS_LIMIT The output is a long integer that gives the maximum depth of nesting of parentheses (of any kind) in a pattern. This limit is imposed to cap the amount of system stack used when a pattern is compiled. It is spec- ified when PCRE is built; the default is 250. This limit does not take into account the stack that may already be used by the calling applica- tion. For finer control over compilation stack usage, you can set a pointer to an external checking function in pcre_stack_guard. PCRE_CONFIG_MATCH_LIMIT The output is a long integer that gives the default limit for the num- ber of internal matching function calls in a pcre_exec() execution. Further details are given with pcre_exec() below. PCRE_CONFIG_MATCH_LIMIT_RECURSION The output is a long integer that gives the default limit for the depth of recursion when calling the internal matching function in a pcre_exec() execution. Further details are given with pcre_exec() below. PCRE_CONFIG_STACKRECURSE The output is an integer that is set to one if internal recursion when running pcre_exec() is implemented by recursive function calls that use the stack to remember their state. This is the usual way that PCRE is compiled. The output is zero if PCRE was compiled to use blocks of data on the heap instead of recursive function calls. In this case, pcre_stack_malloc and pcre_stack_free are called to manage memory blocks on the heap, thus avoiding the use of the stack. COMPILING A PATTERN pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre *pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errptr, int *erroffset, const unsigned char *tableptr); Either of the functions pcre_compile() or pcre_compile2() can be called to compile a pattern into an internal form. The only difference between the two interfaces is that pcre_compile2() has an additional argument, errorcodeptr, via which a numerical error code can be returned. To avoid too much repetition, we refer just to pcre_compile() below, but the information applies equally to pcre_compile2(). The pattern is a C string terminated by a binary zero, and is passed in the pattern argument. A pointer to a single block of memory that is obtained via pcre_malloc is returned. This contains the compiled code and related data. The pcre type is defined for the returned block; this is a typedef for a structure whose contents are not externally defined. It is up to the caller to free the memory (via pcre_free) when it is no longer required. Although the compiled code of a PCRE regex is relocatable, that is, it does not depend on memory location, the complete pcre data block is not fully relocatable, because it may contain a copy of the tableptr argu- ment, which is an address (see below). The options argument contains various bit settings that affect the com- pilation. It should be zero if no options are required. The available options are described below. Some of them (in particular, those that are compatible with Perl, but some others as well) can also be set and unset from within the pattern (see the detailed description in the pcrepattern documentation). For those options that can be different in different parts of the pattern, the contents of the options argument specifies their settings at the start of compilation and execution. The PCRE_ANCHORED, PCRE_BSR_xxx, PCRE_NEWLINE_xxx, PCRE_NO_UTF8_CHECK, and PCRE_NO_START_OPTIMIZE options can be set at the time of matching as well as at compile time. If errptr is NULL, pcre_compile() returns NULL immediately. Otherwise, if compilation of a pattern fails, pcre_compile() returns NULL, and sets the variable pointed to by errptr to point to a textual error mes- sage. This is a static string that is part of the library. You must not try to free it. Normally, the offset from the start of the pattern to the data unit that was being processed when the error was discovered is placed in the variable pointed to by erroffset, which must not be NULL (if it is, an immediate error is given). However, for an invalid UTF-8 or UTF-16 string, the offset is that of the first data unit of the failing character. Some errors are not detected until the whole pattern has been scanned; in these cases, the offset passed back is the length of the pattern. Note that the offset is in data units, not characters, even in a UTF mode. It may sometimes point into the middle of a UTF-8 or UTF-16 char- acter. If pcre_compile2() is used instead of pcre_compile(), and the error- codeptr argument is not NULL, a non-zero error code number is returned via this argument in the event of an error. This is in addition to the textual error message. Error codes and messages are listed below. If the final argument, tableptr, is NULL, PCRE uses a default set of character tables that are built when PCRE is compiled, using the default C locale. Otherwise, tableptr must be an address that is the result of a call to pcre_maketables(). This value is stored with the compiled pattern, and used again by pcre_exec() and pcre_dfa_exec() when the pattern is matched. For more discussion, see the section on locale support below. This code fragment shows a typical straightforward call to pcre_com- pile(): pcre *re; const char *error; int erroffset; re = pcre_compile( "^A.*Z", /* the pattern */ 0, /* default options */ &error, /* for error message */ &erroffset, /* for error offset */ NULL); /* use default character tables */ The following names for option bits are defined in the pcre.h header file: PCRE_ANCHORED If this bit is set, the pattern is forced to be "anchored", that is, it is constrained to match only at the first matching point in the string that is being searched (the "subject string"). This effect can also be achieved by appropriate constructs in the pattern itself, which is the only way to do it in Perl. PCRE_AUTO_CALLOUT If this bit is set, pcre_compile() automatically inserts callout items, all with number 255, before each pattern item. For discussion of the callout facility, see the pcrecallout documentation. PCRE_BSR_ANYCRLF PCRE_BSR_UNICODE These options (which are mutually exclusive) control what the \R escape sequence matches. The choice is either to match only CR, LF, or CRLF, or to match any Unicode newline sequence. The default is specified when PCRE is built. It can be overridden from within the pattern, or by set- ting an option when a compiled pattern is matched. PCRE_CASELESS If this bit is set, letters in the pattern match both upper and lower case letters. It is equivalent to Perl's /i option, and it can be changed within a pattern by a (?i) option setting. In UTF-8 mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is com- piled with Unicode property support, but not otherwise. If you want to use caseless matching for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF-8 support. PCRE_DOLLAR_ENDONLY If this bit is set, a dollar metacharacter in the pattern matches only at the end of the subject string. Without this option, a dollar also matches immediately before a newline at the end of the string (but not before any other newlines). The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. There is no equivalent to this option in Perl, and no way to set it within a pattern. PCRE_DOTALL If this bit is set, a dot metacharacter in the pattern matches a char- acter of any value, including one that indicates a newline. However, it only ever matches one character, even if newlines are coded as CRLF. Without this option, a dot does not match when the current position is at a newline. This option is equivalent to Perl's /s option, and it can be changed within a pattern by a (?s) option setting. A negative class such as [^a] always matches newline characters, independent of the set- ting of this option. PCRE_DUPNAMES If this bit is set, names used to identify capturing subpatterns need not be unique. This can be helpful for certain types of pattern when it is known that only one instance of the named subpattern can ever be matched. There are more details of named subpatterns below; see also the pcrepattern documentation. PCRE_EXTENDED If this bit is set, most white space characters in the pattern are totally ignored except when escaped or inside a character class. How- ever, white space is not allowed within sequences such as (?> that introduce various parenthesized subpatterns, nor within a numerical quantifier such as {1,3}. However, ignorable white space is permitted between an item and a following quantifier and between a quantifier and a following + that indicates possessiveness. White space did not used to include the VT character (code 11), because Perl did not treat this character as white space. However, Perl changed at release 5.18, so PCRE followed at release 8.34, and VT is now treated as white space. PCRE_EXTENDED also causes characters between an unescaped # outside a character class and the next newline, inclusive, to be ignored. PCRE_EXTENDED is equivalent to Perl's /x option, and it can be changed within a pattern by a (?x) option setting. Which characters are interpreted as newlines is controlled by the options passed to pcre_compile() or by a special sequence at the start of the pattern, as described in the section entitled "Newline conven- tions" in the pcrepattern documentation. Note that the end of this type of comment is a literal newline sequence in the pattern; escape sequences that happen to represent a newline do not count. This option makes it possible to include comments inside complicated patterns. Note, however, that this applies only to data characters. White space characters may never appear within special character sequences in a pattern, for example within the sequence (?( that intro- duces a conditional subpattern. PCRE_EXTRA This option was invented in order to turn on additional functionality of PCRE that is incompatible with Perl, but it is currently of very little use. When set, any backslash in a pattern that is followed by a letter that has no special meaning causes an error, thus reserving these combinations for future expansion. By default, as in Perl, a backslash followed by a letter with no special meaning is treated as a literal. (Perl can, however, be persuaded to give an error for this, by running it with the -w option.) There are at present no other features controlled by this option. It can also be set by a (?X) option setting within a pattern. PCRE_FIRSTLINE If this option is set, an unanchored pattern is required to match before or at the first newline in the subject string, though the matched text may continue over the newline. PCRE_JAVASCRIPT_COMPAT If this option is set, PCRE's behaviour is changed in some ways so that it is compatible with JavaScript rather than Perl. The changes are as follows: (1) A lone closing square bracket in a pattern causes a compile-time error, because this is illegal in JavaScript (by default it is treated as a data character). Thus, the pattern AB]CD becomes illegal when this option is set. (2) At run time, a back reference to an unset subpattern group matches an empty string (by default this causes the current matching alterna- tive to fail). A pattern such as (\1)(a) succeeds when this option is set (assuming it can find an "a" in the subject), whereas it fails by default, for Perl compatibility. (3) \U matches an upper case "U" character; by default \U causes a com- pile time error (Perl uses \U to upper case subsequent characters). (4) \u matches a lower case "u" character unless it is followed by four hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, \u causes a compile time error (Perl uses it to upper case the following character). (5) \x matches a lower case "x" character unless it is followed by two hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, as in Perl, a hexadecimal number is always expected after \x, but it may have zero, one, or two digits (so, for example, \xz matches a binary zero character followed by z). PCRE_MULTILINE By default, for the purposes of matching "start of line" and "end of line", PCRE treats the subject string as consisting of a single line of characters, even if it actually contains newlines. The "start of line" metacharacter (^) matches only at the start of the string, and the "end of line" metacharacter ($) matches only at the end of the string, or before a terminating newline (except when PCRE_DOLLAR_ENDONLY is set). Note, however, that unless PCRE_DOTALL is set, the "any character" metacharacter (.) does not match at a newline. This behaviour (for ^, $, and dot) is the same as Perl. When PCRE_MULTILINE it is set, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no new- lines in a subject string, or no occurrences of ^ or $ in a pattern, setting PCRE_MULTILINE has no effect. PCRE_NEVER_UTF This option locks out interpretation of the pattern as UTF-8 (or UTF-16 or UTF-32 in the 16-bit and 32-bit libraries). In particular, it pre- vents the creator of the pattern from switching to UTF interpretation by starting the pattern with (*UTF). This may be useful in applications that process patterns from external sources. The combination of PCRE_UTF8 and PCRE_NEVER_UTF also causes an error. PCRE_NEWLINE_CR PCRE_NEWLINE_LF PCRE_NEWLINE_CRLF PCRE_NEWLINE_ANYCRLF PCRE_NEWLINE_ANY These options override the default newline definition that was chosen when PCRE was built. Setting the first or the second specifies that a newline is indicated by a single character (CR or LF, respectively). Setting PCRE_NEWLINE_CRLF specifies that a newline is indicated by the two-character CRLF sequence. Setting PCRE_NEWLINE_ANYCRLF specifies that any of the three preceding sequences should be recognized. Setting PCRE_NEWLINE_ANY specifies that any Unicode newline sequence should be recognized. In an ASCII/Unicode environment, the Unicode newline sequences are the three just mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line sep- arator, U+2028), and PS (paragraph separator, U+2029). For the 8-bit library, the last two are recognized only in UTF-8 mode. When PCRE is compiled to run in an EBCDIC (mainframe) environment, the code for CR is 0x0d, the same as ASCII. However, the character code for LF is normally 0x15, though in some EBCDIC environments 0x25 is used. Whichever of these is not LF is made to correspond to Unicode's NEL character. EBCDIC codes are all less than 256. For more details, see the pcrebuild documentation. The newline setting in the options word uses three bits that are treated as a number, giving eight possibilities. Currently only six are used (default plus the five values above). This means that if you set more than one newline option, the combination may or may not be sensi- ble. For example, PCRE_NEWLINE_CR with PCRE_NEWLINE_LF is equivalent to PCRE_NEWLINE_CRLF, but other combinations may yield unused numbers and cause an error. The only time that a line break in a pattern is specially recognized when compiling is when PCRE_EXTENDED is set. CR and LF are white space characters, and so are ignored in this mode. Also, an unescaped # out- side a character class indicates a comment that lasts until after the next line break sequence. In other circumstances, line break sequences in patterns are treated as literal data. The newline option that is set at compile time becomes the default that is used for pcre_exec() and pcre_dfa_exec(), but it can be overridden. PCRE_NO_AUTO_CAPTURE If this option is set, it disables the use of numbered capturing paren- theses in the pattern. Any opening parenthesis that is not followed by ? behaves as if it were followed by ?: but named parentheses can still be used for capturing (and they acquire numbers in the usual way). There is no equivalent of this option in Perl. PCRE_NO_AUTO_POSSESS If this option is set, it disables "auto-possessification". This is an optimization that, for example, turns a+b into a++b in order to avoid backtracks into a+ that can never be successful. However, if callouts are in use, auto-possessification means that some of them are never taken. You can set this option if you want the matching functions to do a full unoptimized search and run all the callouts, but it is mainly provided for testing purposes. PCRE_NO_START_OPTIMIZE This is an option that acts at matching time; that is, it is really an option for pcre_exec() or pcre_dfa_exec(). If it is set at compile time, it is remembered with the compiled pattern and assumed at match- ing time. This is necessary if you want to use JIT execution, because the JIT compiler needs to know whether or not this option is set. For details see the discussion of PCRE_NO_START_OPTIMIZE below. PCRE_UCP This option changes the way PCRE processes \B, \b, \D, \d, \S, \s, \W, \w, and some of the POSIX character classes. By default, only ASCII characters are recognized, but if PCRE_UCP is set, Unicode properties are used instead to classify characters. More details are given in the section on generic character types in the pcrepattern page. If you set PCRE_UCP, matching one of the items it affects takes much longer. The option is available only if PCRE has been compiled with Unicode prop- erty support. PCRE_UNGREEDY This option inverts the "greediness" of the quantifiers so that they are not greedy by default, but become greedy if followed by "?". It is not compatible with Perl. It can also be set by a (?U) option setting within the pattern. PCRE_UTF8 This option causes PCRE to regard both the pattern and the subject as strings of UTF-8 characters instead of single-byte strings. However, it is available only when PCRE is built to include UTF support. If not, the use of this option provokes an error. Details of how this option changes the behaviour of PCRE are given in the pcreunicode page. PCRE_NO_UTF8_CHECK When PCRE_UTF8 is set, the validity of the pattern as a UTF-8 string is automatically checked. There is a discussion about the validity of UTF-8 strings in the pcreunicode page. If an invalid UTF-8 sequence is found, pcre_compile() returns an error. If you already know that your pattern is valid, and you want to skip this check for performance rea- sons, you can set the PCRE_NO_UTF8_CHECK option. When it is set, the effect of passing an invalid UTF-8 string as a pattern is undefined. It may cause your program to crash or loop. Note that this option can also be passed to pcre_exec() and pcre_dfa_exec(), to suppress the validity checking of subject strings only. If the same string is being matched many times, the option can be safely set for the second and subsequent matchings to improve performance. COMPILATION ERROR CODES The following table lists the error codes than may be returned by pcre_compile2(), along with the error messages that may be returned by both compiling functions. Note that error messages are always 8-bit ASCII strings, even in 16-bit or 32-bit mode. As PCRE has developed, some error codes have fallen out of use. To avoid confusion, they have not been re-used. 0 no error 1 \ at end of pattern 2 \c at end of pattern 3 unrecognized character follows \ 4 numbers out of order in {} quantifier 5 number too big in {} quantifier 6 missing terminating ] for character class 7 invalid escape sequence in character class 8 range out of order in character class 9 nothing to repeat 10 [this code is not in use] 11 internal error: unexpected repeat 12 unrecognized character after (? or (?- 13 POSIX named classes are supported only within a class 14 missing ) 15 reference to non-existent subpattern 16 erroffset passed as NULL 17 unknown option bit(s) set 18 missing ) after comment 19 [this code is not in use] 20 regular expression is too large 21 failed to get memory 22 unmatched parentheses 23 internal error: code overflow 24 unrecognized character after (?< 25 lookbehind assertion is not fixed length 26 malformed number or name after (?( 27 conditional group contains more than two branches 28 assertion expected after (?( 29 (?R or (?[+-]digits must be followed by ) 30 unknown POSIX class name 31 POSIX collating elements are not supported 32 this version of PCRE is compiled without UTF support 33 [this code is not in use] 34 character value in \x{} or \o{} is too large 35 invalid condition (?(0) 36 \C not allowed in lookbehind assertion 37 PCRE does not support \L, \l, \N{name}, \U, or \u 38 number after (?C is > 255 39 closing ) for (?C expected 40 recursive call could loop indefinitely 41 unrecognized character after (?P 42 syntax error in subpattern name (missing terminator) 43 two named subpatterns have the same name 44 invalid UTF-8 string (specifically UTF-8) 45 support for \P, \p, and \X has not been compiled 46 malformed \P or \p sequence 47 unknown property name after \P or \p 48 subpattern name is too long (maximum 32 characters) 49 too many named subpatterns (maximum 10000) 50 [this code is not in use] 51 octal value is greater than \377 in 8-bit non-UTF-8 mode 52 internal error: overran compiling workspace 53 internal error: previously-checked referenced subpattern not found 54 DEFINE group contains more than one branch 55 repeating a DEFINE group is not allowed 56 inconsistent NEWLINE options 57 \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number 58 a numbered reference must not be zero 59 an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) 60 (*VERB) not recognized or malformed 61 number is too big 62 subpattern name expected 63 digit expected after (?+ 64 ] is an invalid data character in JavaScript compatibility mode 65 different names for subpatterns of the same number are not allowed 66 (*MARK) must have an argument 67 this version of PCRE is not compiled with Unicode property support 68 \c must be followed by an ASCII character 69 \k is not followed by a braced, angle-bracketed, or quoted name 70 internal error: unknown opcode in find_fixedlength() 71 \N is not supported in a class 72 too many forward references 73 disallowed Unicode code point (>= 0xd800 && <= 0xdfff) 74 invalid UTF-16 string (specifically UTF-16) 75 name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN) 76 character value in \u.... sequence is too large 77 invalid UTF-32 string (specifically UTF-32) 78 setting UTF is disabled by the application 79 non-hex character in \x{} (closing brace missing?) 80 non-octal character in \o{} (closing brace missing?) 81 missing opening brace after \o 82 parentheses are too deeply nested 83 invalid range in character class 84 group name must start with a non-digit 85 parentheses are too deeply nested (stack check) The numbers 32 and 10000 in errors 48 and 49 are defaults; different values may be used if the limits were changed when PCRE was built. STUDYING A PATTERN pcre_extra *pcre_study(const pcre *code, int options, const char **errptr); If a compiled pattern is going to be used several times, it is worth spending more time analyzing it in order to speed up the time taken for matching. The function pcre_study() takes a pointer to a compiled pat- tern as its first argument. If studying the pattern produces additional information that will help speed up matching, pcre_study() returns a pointer to a pcre_extra block, in which the study_data field points to the results of the study. The returned value from pcre_study() can be passed directly to pcre_exec() or pcre_dfa_exec(). However, a pcre_extra block also con- tains other fields that can be set by the caller before the block is passed; these are described below in the section on matching a pattern. If studying the pattern does not produce any useful information, pcre_study() returns NULL by default. In that circumstance, if the calling program wants to pass any of the other fields to pcre_exec() or pcre_dfa_exec(), it must set up its own pcre_extra block. However, if pcre_study() is called with the PCRE_STUDY_EXTRA_NEEDED option, it returns a pcre_extra block even if studying did not find any additional information. It may still return NULL, however, if an error occurs in pcre_study(). The second argument of pcre_study() contains option bits. There are three further options in addition to PCRE_STUDY_EXTRA_NEEDED: PCRE_STUDY_JIT_COMPILE PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE If any of these are set, and the just-in-time compiler is available, the pattern is further compiled into machine code that executes much faster than the pcre_exec() interpretive matching function. If the just-in-time compiler is not available, these options are ignored. All undefined bits in the options argument must be zero. JIT compilation is a heavyweight optimization. It can take some time for patterns to be analyzed, and for one-off matches and simple pat- terns the benefit of faster execution might be offset by a much slower study time. Not all patterns can be optimized by the JIT compiler. For those that cannot be handled, matching automatically falls back to the pcre_exec() interpreter. For more details, see the pcrejit documenta- tion. The third argument for pcre_study() is a pointer for an error message. If studying succeeds (even if no data is returned), the variable it points to is set to NULL. Otherwise it is set to point to a textual error message. This is a static string that is part of the library. You must not try to free it. You should test the error pointer for NULL after calling pcre_study(), to be sure that it has run successfully. When you are finished with a pattern, you can free the memory used for the study data by calling pcre_free_study(). This function was added to the API for release 8.20. For earlier versions, the memory could be freed with pcre_free(), just like the pattern itself. This will still work in cases where JIT optimization is not used, but it is advisable to change to the new function when convenient. This is a typical way in which pcre_study() is used (except that in a real application there should be tests for errors): int rc; pcre *re; pcre_extra *sd; re = pcre_compile("pattern", 0, &error, &erroroffset, NULL); sd = pcre_study( re, /* result of pcre_compile() */ 0, /* no options */ &error); /* set to NULL or points to a message */ rc = pcre_exec( /* see below for details of pcre_exec() options */ re, sd, "subject", 7, 0, 0, ovector, 30); ... pcre_free_study(sd); pcre_free(re); Studying a pattern does two things: first, a lower bound for the length of subject string that is needed to match the pattern is computed. This does not mean that there are any strings of that length that match, but it does guarantee that no shorter strings match. The value is used to avoid wasting time by trying to match strings that are shorter than the lower bound. You can find out the value in a calling program via the pcre_fullinfo() function. Studying a pattern is also useful for non-anchored patterns that do not have a single fixed starting character. A bitmap of possible starting bytes is created. This speeds up finding a position in the subject at which to start matching. (In 16-bit mode, the bitmap is used for 16-bit values less than 256. In 32-bit mode, the bitmap is used for 32-bit values less than 256.) These two optimizations apply to both pcre_exec() and pcre_dfa_exec(), and the information is also used by the JIT compiler. The optimiza- tions can be disabled by setting the PCRE_NO_START_OPTIMIZE option. You might want to do this if your pattern contains callouts or (*MARK) and you want to make use of these facilities in cases where matching fails. PCRE_NO_START_OPTIMIZE can be specified at either compile time or exe- cution time. However, if PCRE_NO_START_OPTIMIZE is passed to pcre_exec(), (that is, after any JIT compilation has happened) JIT exe- cution is disabled. For JIT execution to work with PCRE_NO_START_OPTI- MIZE, the option must be set at compile time. There is a longer discussion of PCRE_NO_START_OPTIMIZE below. LOCALE SUPPORT PCRE handles caseless matching, and determines whether characters are letters, digits, or whatever, by reference to a set of tables, indexed by character code point. When running in UTF-8 mode, or in the 16- or 32-bit libraries, this applies only to characters with code points less than 256. By default, higher-valued code points never match escapes such as \w or \d. However, if PCRE is built with Unicode property sup- port, all characters can be tested with \p and \P, or, alternatively, the PCRE_UCP option can be set when a pattern is compiled; this causes \w and friends to use Unicode property support instead of the built-in tables. The use of locales with Unicode is discouraged. If you are handling characters with code points greater than 128, you should either use Unicode support, or use locales, but not try to mix the two. PCRE contains an internal set of tables that are used when the final argument of pcre_compile() is NULL. These are sufficient for many applications. Normally, the internal tables recognize only ASCII char- acters. However, when PCRE is built, it is possible to cause the inter- nal tables to be rebuilt in the default "C" locale of the local system, which may cause them to be different. The internal tables can always be overridden by tables supplied by the application that calls PCRE. These may be created in a different locale from the default. As more and more applications change to using Uni- code, the need for this locale support is expected to die away. External tables are built by calling the pcre_maketables() function, which has no arguments, in the relevant locale. The result can then be passed to pcre_compile() as often as necessary. For example, to build and use tables that are appropriate for the French locale (where accented characters with values greater than 128 are treated as let- ters), the following code could be used: setlocale(LC_CTYPE, "fr_FR"); tables = pcre_maketables(); re = pcre_compile(..., tables); The locale name "fr_FR" is used on Linux and other Unix-like systems; if you are using Windows, the name for the French locale is "french". When pcre_maketables() runs, the tables are built in memory that is obtained via pcre_malloc. It is the caller's responsibility to ensure that the memory containing the tables remains available for as long as it is needed. The pointer that is passed to pcre_compile() is saved with the compiled pattern, and the same tables are used via this pointer by pcre_study() and also by pcre_exec() and pcre_dfa_exec(). Thus, for any single pat- tern, compilation, studying and matching all happen in the same locale, but different patterns can be processed in different locales. It is possible to pass a table pointer or NULL (indicating the use of the internal tables) to pcre_exec() or pcre_dfa_exec() (see the discus- sion below in the section on matching a pattern). This facility is pro- vided for use with pre-compiled patterns that have been saved and reloaded. Character tables are not saved with patterns, so if a non- standard table was used at compile time, it must be provided again when the reloaded pattern is matched. Attempting to use this facility to match a pattern in a different locale from the one in which it was com- piled is likely to lead to anomalous (usually incorrect) results. INFORMATION ABOUT A PATTERN int pcre_fullinfo(const pcre *code, const pcre_extra *extra, int what, void *where); The pcre_fullinfo() function returns information about a compiled pat- tern. It replaces the pcre_info() function, which was removed from the library at version 8.30, after more than 10 years of obsolescence. The first argument for pcre_fullinfo() is a pointer to the compiled pattern. The second argument is the result of pcre_study(), or NULL if the pattern was not studied. The third argument specifies which piece of information is required, and the fourth argument is a pointer to a variable to receive the data. The yield of the function is zero for success, or one of the following negative numbers: PCRE_ERROR_NULL the argument code was NULL the argument where was NULL PCRE_ERROR_BADMAGIC the "magic number" was not found PCRE_ERROR_BADENDIANNESS the pattern was compiled with different endianness PCRE_ERROR_BADOPTION the value of what was invalid PCRE_ERROR_UNSET the requested field is not set The "magic number" is placed at the start of each compiled pattern as an simple check against passing an arbitrary memory pointer. The endi- anness error can occur if a compiled pattern is saved and reloaded on a different host. Here is a typical call of pcre_fullinfo(), to obtain the length of the compiled pattern: int rc; size_t length; rc = pcre_fullinfo( re, /* result of pcre_compile() */ sd, /* result of pcre_study(), or NULL */ PCRE_INFO_SIZE, /* what is required */ &length); /* where to put the data */ The possible values for the third argument are defined in pcre.h, and are as follows: PCRE_INFO_BACKREFMAX Return the number of the highest back reference in the pattern. The fourth argument should point to an int variable. Zero is returned if there are no back references. PCRE_INFO_CAPTURECOUNT Return the number of capturing subpatterns in the pattern. The fourth argument should point to an int variable. PCRE_INFO_DEFAULT_TABLES Return a pointer to the internal default character tables within PCRE. The fourth argument should point to an unsigned char * variable. This information call is provided for internal use by the pcre_study() func- tion. External callers can cause PCRE to use its internal tables by passing a NULL table pointer. PCRE_INFO_FIRSTBYTE (deprecated) Return information about the first data unit of any matched string, for a non-anchored pattern. The name of this option refers to the 8-bit library, where data units are bytes. The fourth argument should point to an int variable. Negative values are used for special cases. How- ever, this means that when the 32-bit library is in non-UTF-32 mode, the full 32-bit range of characters cannot be returned. For this rea- son, this value is deprecated; use PCRE_INFO_FIRSTCHARACTERFLAGS and PCRE_INFO_FIRSTCHARACTER instead. If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), its value is returned. In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library the value can be up to 0x10ffff. If there is no fixed first value, and if either (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored), -1 is returned, indicating that the pattern matches only at the start of a subject string or after any newline within the string. Otherwise -2 is returned. For anchored patterns, -2 is returned. PCRE_INFO_FIRSTCHARACTER Return the value of the first data unit (non-UTF character) of any matched string in the situation where PCRE_INFO_FIRSTCHARACTERFLAGS returns 1; otherwise return 0. The fourth argument should point to an uint_t variable. In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff, and up to 0xffffffff when not using UTF-32 mode. PCRE_INFO_FIRSTCHARACTERFLAGS Return information about the first data unit of any matched string, for a non-anchored pattern. The fourth argument should point to an int variable. If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), 1 is returned, and the character value can be retrieved using PCRE_INFO_FIRSTCHARACTER. If there is no fixed first value, and if either (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored), 2 is returned, indicating that the pattern matches only at the start of a subject string or after any newline within the string. Otherwise 0 is returned. For anchored patterns, 0 is returned. PCRE_INFO_FIRSTTABLE If the pattern was studied, and this resulted in the construction of a 256-bit table indicating a fixed set of values for the first data unit in any matching string, a pointer to the table is returned. Otherwise NULL is returned. The fourth argument should point to an unsigned char * variable. PCRE_INFO_HASCRORLF Return 1 if the pattern contains any explicit matches for CR or LF characters, otherwise 0. The fourth argument should point to an int variable. An explicit match is either a literal CR or LF character, or \r or \n. PCRE_INFO_JCHANGED Return 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise 0. The fourth argument should point to an int variable. (?J) and (?-J) set and unset the local PCRE_DUPNAMES option, respectively. PCRE_INFO_JIT Return 1 if the pattern was studied with one of the JIT options, and just-in-time compiling was successful. The fourth argument should point to an int variable. A return value of 0 means that JIT support is not available in this version of PCRE, or that the pattern was not studied with a JIT option, or that the JIT compiler could not handle this par- ticular pattern. See the pcrejit documentation for details of what can and cannot be handled. PCRE_INFO_JITSIZE If the pattern was successfully studied with a JIT option, return the size of the JIT compiled code, otherwise return zero. The fourth argu- ment should point to a size_t variable. PCRE_INFO_LASTLITERAL Return the value of the rightmost literal data unit that must exist in any matched string, other than at its start, if such a value has been recorded. The fourth argument should point to an int variable. If there is no such value, -1 is returned. For anchored patterns, a last literal value is recorded only if it follows something of variable length. For example, for the pattern /^a\d+z\d+/ the returned value is "z", but for /^a\dz\d/ the returned value is -1. Since for the 32-bit library using the non-UTF-32 mode, this function is unable to return the full 32-bit range of characters, this value is deprecated; instead the PCRE_INFO_REQUIREDCHARFLAGS and PCRE_INFO_REQUIREDCHAR values should be used. PCRE_INFO_MATCH_EMPTY Return 1 if the pattern can match an empty string, otherwise 0. The fourth argument should point to an int variable. PCRE_INFO_MATCHLIMIT If the pattern set a match limit by including an item of the form (*LIMIT_MATCH=nnnn) at the start, the value is returned. The fourth argument should point to an unsigned 32-bit integer. If no such value has been set, the call to pcre_fullinfo() returns the error PCRE_ERROR_UNSET. PCRE_INFO_MAXLOOKBEHIND Return the number of characters (NB not data units) in the longest lookbehind assertion in the pattern. This information is useful when doing multi-segment matching using the partial matching facilities. Note that the simple assertions \b and \B require a one-character look- behind. \A also registers a one-character lookbehind, though it does not actually inspect the previous character. This is to ensure that at least one character from the old segment is retained when a new segment is processed. Otherwise, if there are no lookbehinds in the pattern, \A might match incorrectly at the start of a new segment. PCRE_INFO_MINLENGTH If the pattern was studied and a minimum length for matching subject strings was computed, its value is returned. Otherwise the returned value is -1. The value is a number of characters, which in UTF mode may be different from the number of data units. The fourth argument should point to an int variable. A non-negative value is a lower bound to the length of any matching string. There may not be any strings of that length that do actually match, but every string that does match is at least that long. PCRE_INFO_NAMECOUNT PCRE_INFO_NAMEENTRYSIZE PCRE_INFO_NAMETABLE PCRE supports the use of named as well as numbered capturing parenthe- ses. The names are just an additional way of identifying the parenthe- ses, which still acquire numbers. Several convenience functions such as pcre_get_named_substring() are provided for extracting captured sub- strings by name. It is also possible to extract the data directly, by first converting the name to a number in order to access the correct pointers in the output vector (described with pcre_exec() below). To do the conversion, you need to use the name-to-number map, which is described by these three values. The map consists of a number of fixed-size entries. PCRE_INFO_NAMECOUNT gives the number of entries, and PCRE_INFO_NAMEENTRYSIZE gives the size of each entry; both of these return an int value. The entry size depends on the length of the longest name. PCRE_INFO_NAMETABLE returns a pointer to the first entry of the table. This is a pointer to char in the 8-bit library, where the first two bytes of each entry are the num- ber of the capturing parenthesis, most significant byte first. In the 16-bit library, the pointer points to 16-bit data units, the first of which contains the parenthesis number. In the 32-bit library, the pointer points to 32-bit data units, the first of which contains the parenthesis number. The rest of the entry is the corresponding name, zero terminated. The names are in alphabetical order. If (?| is used to create multiple groups with the same number, as described in the section on duplicate subpattern numbers in the pcrepattern page, the groups may be given the same name, but there is only one entry in the table. Different names for groups of the same number are not permitted. Duplicate names for subpatterns with different numbers are permitted, but only if PCRE_DUP- NAMES is set. They appear in the table in the order in which they were found in the pattern. In the absence of (?| this is the order of increasing number; when (?| is used this is not necessarily the case because later subpatterns may have lower numbers. As a simple example of the name/number table, consider the following pattern after compilation by the 8-bit library (assume PCRE_EXTENDED is set, so white space - including newlines - is ignored): (? (?(\d\d)?\d\d) - (?\d\d) - (?\d\d) ) There are four named subpatterns, so the table has four entries, and each entry in the table is eight bytes long. The table is as follows, with non-printing bytes shows in hexadecimal, and undefined bytes shown as ??: 00 01 d a t e 00 ?? 00 05 d a y 00 ?? ?? 00 04 m o n t h 00 00 02 y e a r 00 ?? When writing code to extract data from named subpatterns using the name-to-number map, remember that the length of the entries is likely to be different for each compiled pattern. PCRE_INFO_OKPARTIAL Return 1 if the pattern can be used for partial matching with pcre_exec(), otherwise 0. The fourth argument should point to an int variable. From release 8.00, this always returns 1, because the restrictions that previously applied to partial matching have been lifted. The pcrepartial documentation gives details of partial match- ing. PCRE_INFO_OPTIONS Return a copy of the options with which the pattern was compiled. The fourth argument should point to an unsigned long int variable. These option bits are those specified in the call to pcre_compile(), modified by any top-level option settings at the start of the pattern itself. In other words, they are the options that will be in force when matching starts. For example, if the pattern /(?im)abc(?-i)d/ is compiled with the PCRE_EXTENDED option, the result is PCRE_CASELESS, PCRE_MULTILINE, and PCRE_EXTENDED. A pattern is automatically anchored by PCRE if all of its top-level alternatives begin with one of the following: ^ unless PCRE_MULTILINE is set \A always \G always .* if PCRE_DOTALL is set and there are no back references to the subpattern in which .* appears For such patterns, the PCRE_ANCHORED bit is set in the options returned by pcre_fullinfo(). PCRE_INFO_RECURSIONLIMIT If the pattern set a recursion limit by including an item of the form (*LIMIT_RECURSION=nnnn) at the start, the value is returned. The fourth argument should point to an unsigned 32-bit integer. If no such value has been set, the call to pcre_fullinfo() returns the error PCRE_ERROR_UNSET. PCRE_INFO_SIZE Return the size of the compiled pattern in bytes (for all three libraries). The fourth argument should point to a size_t variable. This value does not include the size of the pcre structure that is returned by pcre_compile(). The value that is passed as the argument to pcre_malloc() when pcre_compile() is getting memory in which to place the compiled data is the value returned by this option plus the size of the pcre structure. Studying a compiled pattern, with or without JIT, does not alter the value returned by this option. PCRE_INFO_STUDYSIZE Return the size in bytes (for all three libraries) of the data block pointed to by the study_data field in a pcre_extra block. If pcre_extra is NULL, or there is no study data, zero is returned. The fourth argu- ment should point to a size_t variable. The study_data field is set by pcre_study() to record information that will speed up matching (see the section entitled "Studying a pattern" above). The format of the study_data block is private, but its length is made available via this option so that it can be saved and restored (see the pcreprecompile documentation for details). PCRE_INFO_REQUIREDCHARFLAGS Returns 1 if there is a rightmost literal data unit that must exist in any matched string, other than at its start. The fourth argument should point to an int variable. If there is no such value, 0 is returned. If returning 1, the character value itself can be retrieved using PCRE_INFO_REQUIREDCHAR. For anchored patterns, a last literal value is recorded only if it fol- lows something of variable length. For example, for the pattern /^a\d+z\d+/ the returned value 1 (with "z" returned from PCRE_INFO_REQUIREDCHAR), but for /^a\dz\d/ the returned value is 0. PCRE_INFO_REQUIREDCHAR Return the value of the rightmost literal data unit that must exist in any matched string, other than at its start, if such a value has been recorded. The fourth argument should point to an uint32_t variable. If there is no such value, 0 is returned. REFERENCE COUNTS int pcre_refcount(pcre *code, int adjust); The pcre_refcount() function is used to maintain a reference count in the data block that contains a compiled pattern. It is provided for the benefit of applications that operate in an object-oriented manner, where different parts of the application may be using the same compiled pattern, but you want to free the block when they are all done. When a pattern is compiled, the reference count field is initialized to zero. It is changed only by calling this function, whose action is to add the adjust value (which may be positive or negative) to it. The yield of the function is the new value. However, the value of the count is constrained to lie between 0 and 65535, inclusive. If the new value is outside these limits, it is forced to the appropriate limit value. Except when it is zero, the reference count is not correctly preserved if a pattern is compiled on one host and then transferred to a host whose byte-order is different. (This seems a highly unlikely scenario.) MATCHING A PATTERN: THE TRADITIONAL FUNCTION int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize); The function pcre_exec() is called to match a subject string against a compiled pattern, which is passed in the code argument. If the pattern was studied, the result of the study should be passed in the extra argument. You can call pcre_exec() with the same code and extra argu- ments as many times as you like, in order to match different subject strings with the same pattern. This function is the main matching facility of the library, and it operates in a Perl-like manner. For specialist use there is also an alternative matching function, which is described below in the section about the pcre_dfa_exec() function. In most applications, the pattern will have been compiled (and option- ally studied) in the same process that calls pcre_exec(). However, it is possible to save compiled patterns and study data, and then use them later in different processes, possibly even on different hosts. For a discussion about this, see the pcreprecompile documentation. Here is an example of a simple call to pcre_exec(): int rc; int ovector[30]; rc = pcre_exec( re, /* result of pcre_compile() */ NULL, /* we didn't study the pattern */ "some string", /* the subject string */ 11, /* the length of the subject string */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* vector of integers for substring information */ 30); /* number of elements (NOT size in bytes) */ Extra data for pcre_exec() If the extra argument is not NULL, it must point to a pcre_extra data block. The pcre_study() function returns such a block (when it doesn't return NULL), but you can also create one for yourself, and pass addi- tional information in it. The pcre_extra block contains the following fields (not necessarily in this order): unsigned long int flags; void *study_data; void *executable_jit; unsigned long int match_limit; unsigned long int match_limit_recursion; void *callout_data; const unsigned char *tables; unsigned char **mark; In the 16-bit version of this structure, the mark field has type "PCRE_UCHAR16 **". In the 32-bit version of this structure, the mark field has type "PCRE_UCHAR32 **". The flags field is used to specify which of the other fields are set. The flag bits are: PCRE_EXTRA_CALLOUT_DATA PCRE_EXTRA_EXECUTABLE_JIT PCRE_EXTRA_MARK PCRE_EXTRA_MATCH_LIMIT PCRE_EXTRA_MATCH_LIMIT_RECURSION PCRE_EXTRA_STUDY_DATA PCRE_EXTRA_TABLES Other flag bits should be set to zero. The study_data field and some- times the executable_jit field are set in the pcre_extra block that is returned by pcre_study(), together with the appropriate flag bits. You should not set these yourself, but you may add to the block by setting other fields and their corresponding flag bits. The match_limit field provides a means of preventing PCRE from using up a vast amount of resources when running patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is a pattern that uses nested unlim- ited repeats. Internally, pcre_exec() uses a function called match(), which it calls repeatedly (sometimes recursively). The limit set by match_limit is imposed on the number of times this function is called during a match, which has the effect of limiting the amount of backtracking that can take place. For patterns that are not anchored, the count restarts from zero for each position in the subject string. When pcre_exec() is called with a pattern that was successfully studied with a JIT option, the way that the matching is executed is entirely different. However, there is still the possibility of runaway matching that goes on for a very long time, and so the match_limit value is also used in this case (but in a different way) to limit how long the match- ing can continue. The default value for the limit can be set when PCRE is built; the default default is 10 million, which handles all but the most extreme cases. You can override the default by suppling pcre_exec() with a pcre_extra block in which match_limit is set, and PCRE_EXTRA_MATCH_LIMIT is set in the flags field. If the limit is exceeded, pcre_exec() returns PCRE_ERROR_MATCHLIMIT. A value for the match limit may also be supplied by an item at the start of a pattern of the form (*LIMIT_MATCH=d) where d is a decimal number. However, such a setting is ignored unless d is less than the limit set by the caller of pcre_exec() or, if no such limit is set, less than the default. The match_limit_recursion field is similar to match_limit, but instead of limiting the total number of times that match() is called, it limits the depth of recursion. The recursion depth is a smaller number than the total number of calls, because not all calls to match() are recur- sive. This limit is of use only if it is set smaller than match_limit. Limiting the recursion depth limits the amount of machine stack that can be used, or, when PCRE has been compiled to use memory on the heap instead of the stack, the amount of heap memory that can be used. This limit is not relevant, and is ignored, when matching is done using JIT compiled code. The default value for match_limit_recursion can be set when PCRE is built; the default default is the same value as the default for match_limit. You can override the default by suppling pcre_exec() with a pcre_extra block in which match_limit_recursion is set, and PCRE_EXTRA_MATCH_LIMIT_RECURSION is set in the flags field. If the limit is exceeded, pcre_exec() returns PCRE_ERROR_RECURSIONLIMIT. A value for the recursion limit may also be supplied by an item at the start of a pattern of the form (*LIMIT_RECURSION=d) where d is a decimal number. However, such a setting is ignored unless d is less than the limit set by the caller of pcre_exec() or, if no such limit is set, less than the default. The callout_data field is used in conjunction with the "callout" fea- ture, and is described in the pcrecallout documentation. The tables field is provided for use with patterns that have been pre- compiled using custom character tables, saved to disc or elsewhere, and then reloaded, because the tables that were used to compile a pattern are not saved with it. See the pcreprecompile documentation for a dis- cussion of saving compiled patterns for later use. If NULL is passed using this mechanism, it forces PCRE's internal tables to be used. Warning: The tables that pcre_exec() uses must be the same as those that were used when the pattern was compiled. If this is not the case, the behaviour of pcre_exec() is undefined. Therefore, when a pattern is compiled and matched in the same process, this field should never be set. In this (the most common) case, the correct table pointer is auto- matically passed with the compiled pattern from pcre_compile() to pcre_exec(). If PCRE_EXTRA_MARK is set in the flags field, the mark field must be set to point to a suitable variable. If the pattern contains any back- tracking control verbs such as (*MARK:NAME), and the execution ends up with a name to pass back, a pointer to the name string (zero termi- nated) is placed in the variable pointed to by the mark field. The names are within the compiled pattern; if you wish to retain such a name you must copy it before freeing the memory of a compiled pattern. If there is no name to pass back, the variable pointed to by the mark field is set to NULL. For details of the backtracking control verbs, see the section entitled "Backtracking control" in the pcrepattern doc- umentation. Option bits for pcre_exec() The unused bits of the options argument for pcre_exec() must be zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NEWLINE_xxx, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_NO_START_OPTIMIZE, PCRE_NO_UTF8_CHECK, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. If the pattern was successfully studied with one of the just-in-time (JIT) compile options, the only supported options for JIT execution are PCRE_NO_UTF8_CHECK, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. If an unsupported option is used, JIT execution is disabled and the normal interpretive code in pcre_exec() is run. PCRE_ANCHORED The PCRE_ANCHORED option limits pcre_exec() to matching at the first matching position. If a pattern was compiled with PCRE_ANCHORED, or turned out to be anchored by virtue of its contents, it cannot be made unachored at matching time. PCRE_BSR_ANYCRLF PCRE_BSR_UNICODE These options (which are mutually exclusive) control what the \R escape sequence matches. The choice is either to match only CR, LF, or CRLF, or to match any Unicode newline sequence. These options override the choice that was made or defaulted when the pattern was compiled. PCRE_NEWLINE_CR PCRE_NEWLINE_LF PCRE_NEWLINE_CRLF PCRE_NEWLINE_ANYCRLF PCRE_NEWLINE_ANY These options override the newline definition that was chosen or defaulted when the pattern was compiled. For details, see the descrip- tion of pcre_compile() above. During matching, the newline choice affects the behaviour of the dot, circumflex, and dollar metacharac- ters. It may also alter the way the match position is advanced after a match failure for an unanchored pattern. When PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANYCRLF, or PCRE_NEWLINE_ANY is set, and a match attempt for an unanchored pattern fails when the cur- rent position is at a CRLF sequence, and the pattern contains no explicit matches for CR or LF characters, the match position is advanced by two characters instead of one, in other words, to after the CRLF. The above rule is a compromise that makes the most common cases work as expected. For example, if the pattern is .+A (and the PCRE_DOTALL option is not set), it does not match the string "\r\nA" because, after failing at the start, it skips both the CR and the LF before retrying. However, the pattern [\r\n]A does match that string, because it con- tains an explicit CR or LF reference, and so advances only by one char- acter after the first failure. An explicit match for CR of LF is either a literal appearance of one of those characters, or one of the \r or \n escape sequences. Implicit matches such as [^X] do not count, nor does \s (which includes CR and LF in the characters that it matches). Notwithstanding the above, anomalous effects may still occur when CRLF is a valid newline sequence and explicit \r or \n escapes appear in the pattern. PCRE_NOTBOL This option specifies that first character of the subject string is not the beginning of a line, so the circumflex metacharacter should not match before it. Setting this without PCRE_MULTILINE (at compile time) causes circumflex never to match. This option affects only the behav- iour of the circumflex metacharacter. It does not affect \A. PCRE_NOTEOL This option specifies that the end of the subject string is not the end of a line, so the dollar metacharacter should not match it nor (except in multiline mode) a newline immediately before it. Setting this with- out PCRE_MULTILINE (at compile time) causes dollar never to match. This option affects only the behaviour of the dollar metacharacter. It does not affect \Z or \z. PCRE_NOTEMPTY An empty string is not considered to be a valid match if this option is set. If there are alternatives in the pattern, they are tried. If all the alternatives match the empty string, the entire match fails. For example, if the pattern a?b? is applied to a string not beginning with "a" or "b", it matches an empty string at the start of the subject. With PCRE_NOTEMPTY set, this match is not valid, so PCRE searches further into the string for occur- rences of "a" or "b". PCRE_NOTEMPTY_ATSTART This is like PCRE_NOTEMPTY, except that an empty string match that is not at the start of the subject is permitted. If the pattern is anchored, such a match can occur only if the pattern contains \K. Perl has no direct equivalent of PCRE_NOTEMPTY or PCRE_NOTEMPTY_ATSTART, but it does make a special case of a pattern match of the empty string within its split() function, and when using the /g modifier. It is possible to emulate Perl's behaviour after matching a null string by first trying the match again at the same off- set with PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED, and then if that fails, by advancing the starting offset (see below) and trying an ordi- nary match again. There is some code that demonstrates how to do this in the pcredemo sample program. In the most general case, you have to check to see if the newline convention recognizes CRLF as a newline, and if so, and the current character is CR followed by LF, advance the starting offset by two characters instead of one. PCRE_NO_START_OPTIMIZE There are a number of optimizations that pcre_exec() uses at the start of a match, in order to speed up the process. For example, if it is known that an unanchored match must start with a specific character, it searches the subject for that character, and fails immediately if it cannot find it, without actually running the main matching function. This means that a special item such as (*COMMIT) at the start of a pat- tern is not considered until after a suitable starting point for the match has been found. Also, when callouts or (*MARK) items are in use, these "start-up" optimizations can cause them to be skipped if the pat- tern is never actually used. The start-up optimizations are in effect a pre-scan of the subject that takes place before the pattern is run. The PCRE_NO_START_OPTIMIZE option disables the start-up optimizations, possibly causing performance to suffer, but ensuring that in cases where the result is "no match", the callouts do occur, and that items such as (*COMMIT) and (*MARK) are considered at every possible starting position in the subject string. If PCRE_NO_START_OPTIMIZE is set at compile time, it cannot be unset at matching time. The use of PCRE_NO_START_OPTIMIZE at matching time (that is, passing it to pcre_exec()) disables JIT execution; in this situation, matching is always done using interpretively. Setting PCRE_NO_START_OPTIMIZE can change the outcome of a matching operation. Consider the pattern (*COMMIT)ABC When this is compiled, PCRE records the fact that a match must start with the character "A". Suppose the subject string is "DEFABC". The start-up optimization scans along the subject, finds "A" and runs the first match attempt from there. The (*COMMIT) item means that the pat- tern must match the current starting position, which in this case, it does. However, if the same match is run with PCRE_NO_START_OPTIMIZE set, the initial scan along the subject string does not happen. The first match attempt is run starting from "D" and when this fails, (*COMMIT) prevents any further matches being tried, so the overall result is "no match". If the pattern is studied, more start-up opti- mizations may be used. For example, a minimum length for the subject may be recorded. Consider the pattern (*MARK:A)(X|Y) The minimum length for a match is one character. If the subject is "ABC", there will be attempts to match "ABC", "BC", "C", and then finally an empty string. If the pattern is studied, the final attempt does not take place, because PCRE knows that the subject is too short, and so the (*MARK) is never encountered. In this case, studying the pattern does not affect the overall match result, which is still "no match", but it does affect the auxiliary information that is returned. PCRE_NO_UTF8_CHECK When PCRE_UTF8 is set at compile time, the validity of the subject as a UTF-8 string is automatically checked when pcre_exec() is subsequently called. The entire string is checked before any other processing takes place. The value of startoffset is also checked to ensure that it points to the start of a UTF-8 character. There is a discussion about the validity of UTF-8 strings in the pcreunicode page. If an invalid sequence of bytes is found, pcre_exec() returns the error PCRE_ERROR_BADUTF8 or, if PCRE_PARTIAL_HARD is set and the problem is a truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8. In both cases, information about the precise nature of the error may also be returned (see the descriptions of these errors in the section enti- tled Error return values from pcre_exec() below). If startoffset con- tains a value that does not point to the start of a UTF-8 character (or to the end of the subject), PCRE_ERROR_BADUTF8_OFFSET is returned. If you already know that your subject is valid, and you want to skip these checks for performance reasons, you can set the PCRE_NO_UTF8_CHECK option when calling pcre_exec(). You might want to do this for the second and subsequent calls to pcre_exec() if you are making repeated calls to find all the matches in a single subject string. However, you should be sure that the value of startoffset points to the start of a character (or the end of the subject). When PCRE_NO_UTF8_CHECK is set, the effect of passing an invalid string as a subject or an invalid value of startoffset is undefined. Your program may crash or loop. PCRE_PARTIAL_HARD PCRE_PARTIAL_SOFT These options turn on the partial matching feature. For backwards com- patibility, PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. A partial match occurs if the end of the subject string is reached successfully, but there are not enough subject characters to complete the match. If this happens when PCRE_PARTIAL_SOFT (but not PCRE_PARTIAL_HARD) is set, matching continues by testing any remaining alternatives. Only if no complete match can be found is PCRE_ERROR_PARTIAL returned instead of PCRE_ERROR_NOMATCH. In other words, PCRE_PARTIAL_SOFT says that the caller is prepared to handle a partial match, but only if no complete match can be found. If PCRE_PARTIAL_HARD is set, it overrides PCRE_PARTIAL_SOFT. In this case, if a partial match is found, pcre_exec() immediately returns PCRE_ERROR_PARTIAL, without considering any other alternatives. In other words, when PCRE_PARTIAL_HARD is set, a partial match is consid- ered to be more important that an alternative complete match. In both cases, the portion of the string that was inspected when the partial match was found is set as the first matching string. There is a more detailed discussion of partial and multi-segment matching, with examples, in the pcrepartial documentation. The string to be matched by pcre_exec() The subject string is passed to pcre_exec() as a pointer in subject, a length in length, and a starting offset in startoffset. The units for length and startoffset are bytes for the 8-bit library, 16-bit data items for the 16-bit library, and 32-bit data items for the 32-bit library. If startoffset is negative or greater than the length of the subject, pcre_exec() returns PCRE_ERROR_BADOFFSET. When the starting offset is zero, the search for a match starts at the beginning of the subject, and this is by far the most common case. In UTF-8 or UTF-16 mode, the offset must point to the start of a character, or the end of the sub- ject (in UTF-32 mode, one data unit equals one character, so all off- sets are valid). Unlike the pattern string, the subject may contain binary zeroes. A non-zero starting offset is useful when searching for another match in the same subject by calling pcre_exec() again after a previous suc- cess. Setting startoffset differs from just passing over a shortened string and setting PCRE_NOTBOL in the case of a pattern that begins with any kind of lookbehind. For example, consider the pattern \Biss\B which finds occurrences of "iss" in the middle of words. (\B matches only if the current position in the subject is not a word boundary.) When applied to the string "Mississipi" the first call to pcre_exec() finds the first occurrence. If pcre_exec() is called again with just the remainder of the subject, namely "issipi", it does not match, because \B is always false at the start of the subject, which is deemed to be a word boundary. However, if pcre_exec() is passed the entire string again, but with startoffset set to 4, it finds the second occur- rence of "iss" because it is able to look behind the starting point to discover that it is preceded by a letter. Finding all the matches in a subject is tricky when the pattern can match an empty string. It is possible to emulate Perl's /g behaviour by first trying the match again at the same offset, with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED options, and then if that fails, advancing the starting offset and trying an ordinary match again. There is some code that demonstrates how to do this in the pcre- demo sample program. In the most general case, you have to check to see if the newline convention recognizes CRLF as a newline, and if so, and the current character is CR followed by LF, advance the starting offset by two characters instead of one. If a non-zero starting offset is passed when the pattern is anchored, one attempt to match at the given offset is made. This can only succeed if the pattern does not require the match to be at the start of the subject. How pcre_exec() returns captured substrings In general, a pattern matches a certain portion of the subject, and in addition, further substrings from the subject may be picked out by parts of the pattern. Following the usage in Jeffrey Friedl's book, this is called "capturing" in what follows, and the phrase "capturing subpattern" is used for a fragment of a pattern that picks out a sub- string. PCRE supports several other kinds of parenthesized subpattern that do not cause substrings to be captured. Captured substrings are returned to the caller via a vector of integers whose address is passed in ovector. The number of elements in the vec- tor is passed in ovecsize, which must be a non-negative number. Note: this argument is NOT the size of ovector in bytes. The first two-thirds of the vector is used to pass back captured sub- strings, each substring using a pair of integers. The remaining third of the vector is used as workspace by pcre_exec() while matching cap- turing subpatterns, and is not available for passing back information. The number passed in ovecsize should always be a multiple of three. If it is not, it is rounded down. When a match is successful, information about captured substrings is returned in pairs of integers, starting at the beginning of ovector, and continuing up to two-thirds of its length at the most. The first element of each pair is set to the offset of the first character in a substring, and the second is set to the offset of the first character after the end of a substring. These values are always data unit off- sets, even in UTF mode. They are byte offsets in the 8-bit library, 16-bit data item offsets in the 16-bit library, and 32-bit data item offsets in the 32-bit library. Note: they are not character counts. The first pair of integers, ovector[0] and ovector[1], identify the portion of the subject string matched by the entire pattern. The next pair is used for the first capturing subpattern, and so on. The value returned by pcre_exec() is one more than the highest numbered pair that has been set. For example, if two substrings have been captured, the returned value is 3. If there are no capturing subpatterns, the return value from a successful match is 1, indicating that just the first pair of offsets has been set. If a capturing subpattern is matched repeatedly, it is the last portion of the string that it matched that is returned. If the vector is too small to hold all the captured substring offsets, it is used as far as possible (up to two-thirds of its length), and the function returns a value of zero. If neither the actual string matched nor any captured substrings are of interest, pcre_exec() may be called with ovector passed as NULL and ovecsize as zero. However, if the pat- tern contains back references and the ovector is not big enough to remember the related substrings, PCRE has to get additional memory for use during matching. Thus it is usually advisable to supply an ovector of reasonable size. There are some cases where zero is returned (indicating vector over- flow) when in fact the vector is exactly the right size for the final match. For example, consider the pattern (a)(?:(b)c|bd) If a vector of 6 elements (allowing for only 1 captured substring) is given with subject string "abd", pcre_exec() will try to set the second captured string, thereby recording a vector overflow, before failing to match "c" and backing up to try the second alternative. The zero return, however, does correctly indicate that the maximum number of slots (namely 2) have been filled. In similar cases where there is tem- porary overflow, but the final number of used slots is actually less than the maximum, a non-zero value is returned. The pcre_fullinfo() function can be used to find out how many capturing subpatterns there are in a compiled pattern. The smallest size for ovector that will allow for n captured substrings, in addition to the offsets of the substring matched by the whole pattern, is (n+1)*3. It is possible for capturing subpattern number n+1 to match some part of the subject when subpattern n has not been used at all. For example, if the string "abc" is matched against the pattern (a|(z))(bc) the return from the function is 4, and subpatterns 1 and 3 are matched, but 2 is not. When this happens, both values in the offset pairs corre- sponding to unused subpatterns are set to -1. Offset values that correspond to unused subpatterns at the end of the expression are also set to -1. For example, if the string "abc" is matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are not matched. The return from the function is 2, because the highest used capturing subpattern number is 1, and the offsets for for the second and third capturing subpatterns (assuming the vector is large enough, of course) are set to -1. Note: Elements in the first two-thirds of ovector that do not corre- spond to capturing parentheses in the pattern are never changed. That is, if a pattern contains n capturing parentheses, no more than ovec- tor[0] to ovector[2n+1] are set by pcre_exec(). The other elements (in the first two-thirds) retain whatever values they previously had. Some convenience functions are provided for extracting the captured substrings as separate strings. These are described below. Error return values from pcre_exec() If pcre_exec() fails, it returns a negative number. The following are defined in the header file: PCRE_ERROR_NOMATCH (-1) The subject string did not match the pattern. PCRE_ERROR_NULL (-2) Either code or subject was passed as NULL, or ovector was NULL and ovecsize was not zero. PCRE_ERROR_BADOPTION (-3) An unrecognized bit was set in the options argument. PCRE_ERROR_BADMAGIC (-4) PCRE stores a 4-byte "magic number" at the start of the compiled code, to catch the case when it is passed a junk pointer and to detect when a pattern that was compiled in an environment of one endianness is run in an environment with the other endianness. This is the error that PCRE gives when the magic number is not present. PCRE_ERROR_UNKNOWN_OPCODE (-5) While running the pattern match, an unknown item was encountered in the compiled pattern. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern. PCRE_ERROR_NOMEMORY (-6) If a pattern contains back references, but the ovector that is passed to pcre_exec() is not big enough to remember the referenced substrings, PCRE gets a block of memory at the start of matching to use for this purpose. If the call via pcre_malloc() fails, this error is given. The memory is automatically freed at the end of matching. This error is also given if pcre_stack_malloc() fails in pcre_exec(). This can happen only when PCRE has been compiled with --disable-stack- for-recursion. PCRE_ERROR_NOSUBSTRING (-7) This error is used by the pcre_copy_substring(), pcre_get_substring(), and pcre_get_substring_list() functions (see below). It is never returned by pcre_exec(). PCRE_ERROR_MATCHLIMIT (-8) The backtracking limit, as specified by the match_limit field in a pcre_extra structure (or defaulted) was reached. See the description above. PCRE_ERROR_CALLOUT (-9) This error is never generated by pcre_exec() itself. It is provided for use by callout functions that want to yield a distinctive error code. See the pcrecallout documentation for details. PCRE_ERROR_BADUTF8 (-10) A string that contains an invalid UTF-8 byte sequence was passed as a subject, and the PCRE_NO_UTF8_CHECK option was not set. If the size of the output vector (ovecsize) is at least 2, the byte offset to the start of the the invalid UTF-8 character is placed in the first ele- ment, and a reason code is placed in the second element. The reason codes are listed in the following section. For backward compatibility, if PCRE_PARTIAL_HARD is set and the problem is a truncated UTF-8 char- acter at the end of the subject (reason codes 1 to 5), PCRE_ERROR_SHORTUTF8 is returned instead of PCRE_ERROR_BADUTF8. PCRE_ERROR_BADUTF8_OFFSET (-11) The UTF-8 byte sequence that was passed as a subject was checked and found to be valid (the PCRE_NO_UTF8_CHECK option was not set), but the value of startoffset did not point to the beginning of a UTF-8 charac- ter or the end of the subject. PCRE_ERROR_PARTIAL (-12) The subject string did not match, but it did match partially. See the pcrepartial documentation for details of partial matching. PCRE_ERROR_BADPARTIAL (-13) This code is no longer in use. It was formerly returned when the PCRE_PARTIAL option was used with a compiled pattern containing items that were not supported for partial matching. From release 8.00 onwards, there are no restrictions on partial matching. PCRE_ERROR_INTERNAL (-14) An unexpected internal error has occurred. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern. PCRE_ERROR_BADCOUNT (-15) This error is given if the value of the ovecsize argument is negative. PCRE_ERROR_RECURSIONLIMIT (-21) The internal recursion limit, as specified by the match_limit_recursion field in a pcre_extra structure (or defaulted) was reached. See the description above. PCRE_ERROR_BADNEWLINE (-23) An invalid combination of PCRE_NEWLINE_xxx options was given. PCRE_ERROR_BADOFFSET (-24) The value of startoffset was negative or greater than the length of the subject, that is, the value in length. PCRE_ERROR_SHORTUTF8 (-25) This error is returned instead of PCRE_ERROR_BADUTF8 when the subject string ends with a truncated UTF-8 character and the PCRE_PARTIAL_HARD option is set. Information about the failure is returned as for PCRE_ERROR_BADUTF8. It is in fact sufficient to detect this case, but this special error code for PCRE_PARTIAL_HARD precedes the implementa- tion of returned information; it is retained for backwards compatibil- ity. PCRE_ERROR_RECURSELOOP (-26) This error is returned when pcre_exec() detects a recursion loop within the pattern. Specifically, it means that either the whole pattern or a subpattern has been called recursively for the second time at the same position in the subject string. Some simple patterns that might do this are detected and faulted at compile time, but more complicated cases, in particular mutual recursions between two different subpatterns, can- not be detected until run time. PCRE_ERROR_JIT_STACKLIMIT (-27) This error is returned when a pattern that was successfully studied using a JIT compile option is being matched, but the memory available for the just-in-time processing stack is not large enough. See the pcrejit documentation for more details. PCRE_ERROR_BADMODE (-28) This error is given if a pattern that was compiled by the 8-bit library is passed to a 16-bit or 32-bit library function, or vice versa. PCRE_ERROR_BADENDIANNESS (-29) This error is given if a pattern that was compiled and saved is reloaded on a host with different endianness. The utility function pcre_pattern_to_host_byte_order() can be used to convert such a pattern so that it runs on the new host. PCRE_ERROR_JIT_BADOPTION This error is returned when a pattern that was successfully studied using a JIT compile option is being matched, but the matching mode (partial or complete match) does not correspond to any JIT compilation mode. When the JIT fast path function is used, this error may be also given for invalid options. See the pcrejit documentation for more details. PCRE_ERROR_BADLENGTH (-32) This error is given if pcre_exec() is called with a negative value for the length argument. Error numbers -16 to -20, -22, and 30 are not used by pcre_exec(). Reason codes for invalid UTF-8 strings This section applies only to the 8-bit library. The corresponding information for the 16-bit and 32-bit libraries is given in the pcre16 and pcre32 pages. When pcre_exec() returns either PCRE_ERROR_BADUTF8 or PCRE_ERROR_SHORT- UTF8, and the size of the output vector (ovecsize) is at least 2, the offset of the start of the invalid UTF-8 character is placed in the first output vector element (ovector[0]) and a reason code is placed in the second element (ovector[1]). The reason codes are given names in the pcre.h header file: PCRE_UTF8_ERR1 PCRE_UTF8_ERR2 PCRE_UTF8_ERR3 PCRE_UTF8_ERR4 PCRE_UTF8_ERR5 The string ends with a truncated UTF-8 character; the code specifies how many bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8 characters to be no longer than 4 bytes, the encoding scheme (origi- nally defined by RFC 2279) allows for up to 6 bytes, and this is checked first; hence the possibility of 4 or 5 missing bytes. PCRE_UTF8_ERR6 PCRE_UTF8_ERR7 PCRE_UTF8_ERR8 PCRE_UTF8_ERR9 PCRE_UTF8_ERR10 The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of the character do not have the binary value 0b10 (that is, either the most significant bit is 0, or the next bit is 1). PCRE_UTF8_ERR11 PCRE_UTF8_ERR12 A character that is valid by the RFC 2279 rules is either 5 or 6 bytes long; these code points are excluded by RFC 3629. PCRE_UTF8_ERR13 A 4-byte character has a value greater than 0x10fff; these code points are excluded by RFC 3629. PCRE_UTF8_ERR14 A 3-byte character has a value in the range 0xd800 to 0xdfff; this range of code points are reserved by RFC 3629 for use with UTF-16, and so are excluded from UTF-8. PCRE_UTF8_ERR15 PCRE_UTF8_ERR16 PCRE_UTF8_ERR17 PCRE_UTF8_ERR18 PCRE_UTF8_ERR19 A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes for a value that can be represented by fewer bytes, which is invalid. For example, the two bytes 0xc0, 0xae give the value 0x2e, whose cor- rect coding uses just one byte. PCRE_UTF8_ERR20 The two most significant bits of the first byte of a character have the binary value 0b10 (that is, the most significant bit is 1 and the sec- ond is 0). Such a byte can only validly occur as the second or subse- quent byte of a multi-byte character. PCRE_UTF8_ERR21 The first byte of a character has the value 0xfe or 0xff. These values can never occur in a valid UTF-8 string. PCRE_UTF8_ERR22 This error code was formerly used when the presence of a so-called "non-character" caused an error. Unicode corrigendum #9 makes it clear that such characters should not cause a string to be rejected, and so this code is no longer in use and is never returned. EXTRACTING CAPTURED SUBSTRINGS BY NUMBER int pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize); int pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr); int pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr); Captured substrings can be accessed directly by using the offsets returned by pcre_exec() in ovector. For convenience, the functions pcre_copy_substring(), pcre_get_substring(), and pcre_get_sub- string_list() are provided for extracting captured substrings as new, separate, zero-terminated strings. These functions identify substrings by number. The next section describes functions for extracting named substrings. A substring that contains a binary zero is correctly extracted and has a further zero added on the end, but the result is not, of course, a C string. However, you can process such a string by referring to the length that is returned by pcre_copy_substring() and pcre_get_sub- string(). Unfortunately, the interface to pcre_get_substring_list() is not adequate for handling strings containing binary zeros, because the end of the final string is not independently indicated. The first three arguments are the same for all three of these func- tions: subject is the subject string that has just been successfully matched, ovector is a pointer to the vector of integer offsets that was passed to pcre_exec(), and stringcount is the number of substrings that were captured by the match, including the substring that matched the entire regular expression. This is the value returned by pcre_exec() if it is greater than zero. If pcre_exec() returned zero, indicating that it ran out of space in ovector, the value passed as stringcount should be the number of elements in the vector divided by three. The functions pcre_copy_substring() and pcre_get_substring() extract a single substring, whose number is given as stringnumber. A value of zero extracts the substring that matched the entire pattern, whereas higher values extract the captured substrings. For pcre_copy_sub- string(), the string is placed in buffer, whose length is given by buffersize, while for pcre_get_substring() a new block of memory is obtained via pcre_malloc, and its address is returned via stringptr. The yield of the function is the length of the string, not including the terminating zero, or one of these error codes: PCRE_ERROR_NOMEMORY (-6) The buffer was too small for pcre_copy_substring(), or the attempt to get memory failed for pcre_get_substring(). PCRE_ERROR_NOSUBSTRING (-7) There is no substring whose number is stringnumber. The pcre_get_substring_list() function extracts all available sub- strings and builds a list of pointers to them. All this is done in a single block of memory that is obtained via pcre_malloc. The address of the memory block is returned via listptr, which is also the start of the list of string pointers. The end of the list is marked by a NULL pointer. The yield of the function is zero if all went well, or the error code PCRE_ERROR_NOMEMORY (-6) if the attempt to get the memory block failed. When any of these functions encounter a substring that is unset, which can happen when capturing subpattern number n+1 matches some part of the subject, but subpattern n has not been used at all, they return an empty string. This can be distinguished from a genuine zero-length sub- string by inspecting the appropriate offset in ovector, which is nega- tive for unset substrings. The two convenience functions pcre_free_substring() and pcre_free_sub- string_list() can be used to free the memory returned by a previous call of pcre_get_substring() or pcre_get_substring_list(), respec- tively. They do nothing more than call the function pointed to by pcre_free, which of course could be called directly from a C program. However, PCRE is used in some situations where it is linked via a spe- cial interface to another programming language that cannot use pcre_free directly; it is for these cases that the functions are pro- vided. EXTRACTING CAPTURED SUBSTRINGS BY NAME int pcre_get_stringnumber(const pcre *code, const char *name); int pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize); int pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr); To extract a substring by name, you first have to find associated num- ber. For example, for this pattern (a+)b(?\d+)... the number of the subpattern called "xxx" is 2. If the name is known to be unique (PCRE_DUPNAMES was not set), you can find the number from the name by calling pcre_get_stringnumber(). The first argument is the com- piled pattern, and the second is the name. The yield of the function is the subpattern number, or PCRE_ERROR_NOSUBSTRING (-7) if there is no subpattern of that name. Given the number, you can extract the substring directly, or use one of the functions described in the previous section. For convenience, there are also two functions that do the whole job. Most of the arguments of pcre_copy_named_substring() and pcre_get_named_substring() are the same as those for the similarly named functions that extract by number. As these are described in the previous section, they are not re-described here. There are just two differences: First, instead of a substring number, a substring name is given. Sec- ond, there is an extra argument, given at the start, which is a pointer to the compiled pattern. This is needed in order to gain access to the name-to-number translation table. These functions call pcre_get_stringnumber(), and if it succeeds, they then call pcre_copy_substring() or pcre_get_substring(), as appropri- ate. NOTE: If PCRE_DUPNAMES is set and there are duplicate names, the behaviour may not be what you want (see the next section). Warning: If the pattern uses the (?| feature to set up multiple subpat- terns with the same number, as described in the section on duplicate subpattern numbers in the pcrepattern page, you cannot use names to distinguish the different subpatterns, because names are not included in the compiled code. The matching process uses only numbers. For this reason, the use of different names for subpatterns of the same number causes an error at compile time. DUPLICATE SUBPATTERN NAMES int pcre_get_stringtable_entries(const pcre *code, const char *name, char **first, char **last); When a pattern is compiled with the PCRE_DUPNAMES option, names for subpatterns are not required to be unique. (Duplicate names are always allowed for subpatterns with the same number, created by using the (?| feature. Indeed, if such subpatterns are named, they are required to use the same names.) Normally, patterns with duplicate names are such that in any one match, only one of the named subpatterns participates. An example is shown in the pcrepattern documentation. When duplicates are present, pcre_copy_named_substring() and pcre_get_named_substring() return the first substring corresponding to the given name that is set. If none are set, PCRE_ERROR_NOSUBSTRING (-7) is returned; no data is returned. The pcre_get_stringnumber() function returns one of the numbers that are associated with the name, but it is not defined which it is. If you want to get full details of all captured substrings for a given name, you must use the pcre_get_stringtable_entries() function. The first argument is the compiled pattern, and the second is the name. The third and fourth are pointers to variables which are updated by the function. After it has run, they point to the first and last entries in the name-to-number table for the given name. The function itself returns the length of each entry, or PCRE_ERROR_NOSUBSTRING (-7) if there are none. The format of the table is described above in the sec- tion entitled Information about a pattern above. Given all the rele- vant entries for the name, you can extract each of their numbers, and hence the captured data, if any. FINDING ALL POSSIBLE MATCHES The traditional matching function uses a similar algorithm to Perl, which stops when it finds the first match, starting at a given point in the subject. If you want to find all possible matches, or the longest possible match, consider using the alternative matching function (see below) instead. If you cannot use the alternative function, but still need to find all possible matches, you can kludge it up by making use of the callout facility, which is described in the pcrecallout documen- tation. What you have to do is to insert a callout right at the end of the pat- tern. When your callout function is called, extract and save the cur- rent matched substring. Then return 1, which forces pcre_exec() to backtrack and try other alternatives. Ultimately, when it runs out of matches, pcre_exec() will yield PCRE_ERROR_NOMATCH. OBTAINING AN ESTIMATE OF STACK USAGE Matching certain patterns using pcre_exec() can use a lot of process stack, which in certain environments can be rather limited in size. Some users find it helpful to have an estimate of the amount of stack that is used by pcre_exec(), to help them set recursion limits, as described in the pcrestack documentation. The estimate that is output by pcretest when called with the -m and -C options is obtained by call- ing pcre_exec with the values NULL, NULL, NULL, -999, and -999 for its first five arguments. Normally, if its first argument is NULL, pcre_exec() immediately returns the negative error code PCRE_ERROR_NULL, but with this special combination of arguments, it returns instead a negative number whose absolute value is the approximate stack frame size in bytes. (A nega- tive number is used so that it is clear that no match has happened.) The value is approximate because in some cases, recursive calls to pcre_exec() occur when there are one or two additional variables on the stack. If PCRE has been compiled to use the heap instead of the stack for recursion, the value returned is the size of each block that is obtained from the heap. MATCHING A PATTERN: THE ALTERNATIVE FUNCTION int pcre_dfa_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize, int *workspace, int wscount); The function pcre_dfa_exec() is called to match a subject string against a compiled pattern, using a matching algorithm that scans the subject string just once, and does not backtrack. This has different characteristics to the normal algorithm, and is not compatible with Perl. Some of the features of PCRE patterns are not supported. Never- theless, there are times when this kind of matching can be useful. For a discussion of the two matching algorithms, and a list of features that pcre_dfa_exec() does not support, see the pcrematching documenta- tion. The arguments for the pcre_dfa_exec() function are the same as for pcre_exec(), plus two extras. The ovector argument is used in a differ- ent way, and this is described below. The other common arguments are used in the same way as for pcre_exec(), so their description is not repeated here. The two additional arguments provide workspace for the function. The workspace vector should contain at least 20 elements. It is used for keeping track of multiple paths through the pattern tree. More workspace will be needed for patterns and subjects where there are a lot of potential matches. Here is an example of a simple call to pcre_dfa_exec(): int rc; int ovector[10]; int wspace[20]; rc = pcre_dfa_exec( re, /* result of pcre_compile() */ NULL, /* we didn't study the pattern */ "some string", /* the subject string */ 11, /* the length of the subject string */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* vector of integers for substring information */ 10, /* number of elements (NOT size in bytes) */ wspace, /* working space vector */ 20); /* number of elements (NOT size in bytes) */ Option bits for pcre_dfa_exec() The unused bits of the options argument for pcre_dfa_exec() must be zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NEW- LINE_xxx, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_NO_UTF8_CHECK, PCRE_BSR_ANYCRLF, PCRE_BSR_UNICODE, PCRE_NO_START_OPTIMIZE, PCRE_PARTIAL_HARD, PCRE_PAR- TIAL_SOFT, PCRE_DFA_SHORTEST, and PCRE_DFA_RESTART. All but the last four of these are exactly the same as for pcre_exec(), so their description is not repeated here. PCRE_PARTIAL_HARD PCRE_PARTIAL_SOFT These have the same general effect as they do for pcre_exec(), but the details are slightly different. When PCRE_PARTIAL_HARD is set for pcre_dfa_exec(), it returns PCRE_ERROR_PARTIAL if the end of the sub- ject is reached and there is still at least one matching possibility that requires additional characters. This happens even if some complete matches have also been found. When PCRE_PARTIAL_SOFT is set, the return code PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if the end of the subject is reached, there have been no complete matches, but there is still at least one matching possibility. The portion of the string that was inspected when the longest partial match was found is set as the first matching string in both cases. There is a more detailed discussion of partial and multi-segment matching, with exam- ples, in the pcrepartial documentation. PCRE_DFA_SHORTEST Setting the PCRE_DFA_SHORTEST option causes the matching algorithm to stop as soon as it has found one match. Because of the way the alterna- tive algorithm works, this is necessarily the shortest possible match at the first possible matching point in the subject string. PCRE_DFA_RESTART When pcre_dfa_exec() returns a partial match, it is possible to call it again, with additional subject characters, and have it continue with the same match. The PCRE_DFA_RESTART option requests this action; when it is set, the workspace and wscount options must reference the same vector as before because data about the match so far is left in them after a partial match. There is more discussion of this facility in the pcrepartial documentation. Successful returns from pcre_dfa_exec() When pcre_dfa_exec() succeeds, it may have matched more than one sub- string in the subject. Note, however, that all the matches from one run of the function start at the same point in the subject. The shorter matches are all initial substrings of the longer matches. For example, if the pattern <.*> is matched against the string This is no more the three matched strings are On success, the yield of the function is a number greater than zero, which is the number of matched substrings. The substrings themselves are returned in ovector. Each string uses two elements; the first is the offset to the start, and the second is the offset to the end. In fact, all the strings have the same start offset. (Space could have been saved by giving this only once, but it was decided to retain some compatibility with the way pcre_exec() returns data, even though the meaning of the strings is different.) The strings are returned in reverse order of length; that is, the long- est matching string is given first. If there were too many matches to fit into ovector, the yield of the function is zero, and the vector is filled with the longest matches. Unlike pcre_exec(), pcre_dfa_exec() can use the entire ovector for returning matched strings. NOTE: PCRE's "auto-possessification" optimization usually applies to character repeats at the end of a pattern (as well as internally). For example, the pattern "a\d+" is compiled as if it were "a\d++" because there is no point even considering the possibility of backtracking into the repeated digits. For DFA matching, this means that only one possi- ble match is found. If you really do want multiple matches in such cases, either use an ungreedy repeat ("a\d+?") or set the PCRE_NO_AUTO_POSSESS option when compiling. Error returns from pcre_dfa_exec() The pcre_dfa_exec() function returns a negative number when it fails. Many of the errors are the same as for pcre_exec(), and these are described above. There are in addition the following errors that are specific to pcre_dfa_exec(): PCRE_ERROR_DFA_UITEM (-16) This return is given if pcre_dfa_exec() encounters an item in the pat- tern that it does not support, for instance, the use of \C or a back reference. PCRE_ERROR_DFA_UCOND (-17) This return is given if pcre_dfa_exec() encounters a condition item that uses a back reference for the condition, or a test for recursion in a specific group. These are not supported. PCRE_ERROR_DFA_UMLIMIT (-18) This return is given if pcre_dfa_exec() is called with an extra block that contains a setting of the match_limit or match_limit_recursion fields. This is not supported (these fields are meaningless for DFA matching). PCRE_ERROR_DFA_WSSIZE (-19) This return is given if pcre_dfa_exec() runs out of space in the workspace vector. PCRE_ERROR_DFA_RECURSE (-20) When a recursive subpattern is processed, the matching function calls itself recursively, using private vectors for ovector and workspace. This error is given if the output vector is not large enough. This should be extremely rare, as a vector of size 1000 is used. PCRE_ERROR_DFA_BADRESTART (-30) When pcre_dfa_exec() is called with the PCRE_DFA_RESTART option, some plausibility checks are made on the contents of the workspace, which should contain data about the previous partial match. If any of these checks fail, this error is given. SEE ALSO pcre16(3), pcre32(3), pcrebuild(3), pcrecallout(3), pcrecpp(3)(3), pcrematching(3), pcrepartial(3), pcreposix(3), pcreprecompile(3), pcre- sample(3), pcrestack(3). AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 18 December 2015 Copyright (c) 1997-2015 University of Cambridge. ------------------------------------------------------------------------------ PCRECALLOUT(3) Library Functions Manual PCRECALLOUT(3) NAME PCRE - Perl-compatible regular expressions SYNOPSIS #include int (*pcre_callout)(pcre_callout_block *); int (*pcre16_callout)(pcre16_callout_block *); int (*pcre32_callout)(pcre32_callout_block *); DESCRIPTION PCRE provides a feature called "callout", which is a means of temporar- ily passing control to the caller of PCRE in the middle of pattern matching. The caller of PCRE provides an external function by putting its entry point in the global variable pcre_callout (pcre16_callout for the 16-bit library, pcre32_callout for the 32-bit library). By default, this variable contains NULL, which disables all calling out. Within a regular expression, (?C) indicates the points at which the external function is to be called. Different callout points can be identified by putting a number less than 256 after the letter C. The default value is zero. For example, this pattern has two callout points: (?C1)abc(?C2)def If the PCRE_AUTO_CALLOUT option bit is set when a pattern is compiled, PCRE automatically inserts callouts, all with number 255, before each item in the pattern. For example, if PCRE_AUTO_CALLOUT is used with the pattern A(\d{2}|--) it is processed as if it were (?C255)A(?C255)((?C255)\d{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255) Notice that there is a callout before and after each parenthesis and alternation bar. If the pattern contains a conditional group whose con- dition is an assertion, an automatic callout is inserted immediately before the condition. Such a callout may also be inserted explicitly, for example: (?(?C9)(?=a)ab|de) This applies only to assertion conditions (because they are themselves independent groups). Automatic callouts can be used for tracking the progress of pattern matching. The pcretest program has a pattern qualifier (/C) that sets automatic callouts; when it is used, the output indicates how the pat- tern is being matched. This is useful information when you are trying to optimize the performance of a particular pattern. MISSING CALLOUTS You should be aware that, because of optimizations in the way PCRE com- piles and matches patterns, callouts sometimes do not happen exactly as you might expect. At compile time, PCRE "auto-possessifies" repeated items when it knows that what follows cannot be part of the repeat. For example, a+[bc] is compiled as if it were a++[bc]. The pcretest output when this pattern is anchored and then applied with automatic callouts to the string "aaaa" is: --->aaaa +0 ^ ^ +1 ^ a+ +3 ^ ^ [bc] No match This indicates that when matching [bc] fails, there is no backtracking into a+ and therefore the callouts that would be taken for the back- tracks do not occur. You can disable the auto-possessify feature by passing PCRE_NO_AUTO_POSSESS to pcre_compile(), or starting the pattern with (*NO_AUTO_POSSESS). If this is done in pcretest (using the /O qualifier), the output changes to this: --->aaaa +0 ^ ^ +1 ^ a+ +3 ^ ^ [bc] +3 ^ ^ [bc] +3 ^ ^ [bc] +3 ^^ [bc] No match This time, when matching [bc] fails, the matcher backtracks into a+ and tries again, repeatedly, until a+ itself fails. Other optimizations that provide fast "no match" results also affect callouts. For example, if the pattern is ab(?C4)cd PCRE knows that any matching string must contain the letter "d". If the subject string is "abyz", the lack of "d" means that matching doesn't ever start, and the callout is never reached. However, with "abyd", though the result is still no match, the callout is obeyed. If the pattern is studied, PCRE knows the minimum length of a matching string, and will immediately give a "no match" return without actually running a match if the subject is not long enough, or, for unanchored patterns, if it has been scanned far enough. You can disable these optimizations by passing the PCRE_NO_START_OPTI- MIZE option to the matching function, or by starting the pattern with (*NO_START_OPT). This slows down the matching process, but does ensure that callouts such as the example above are obeyed. THE CALLOUT INTERFACE During matching, when PCRE reaches a callout point, the external func- tion defined by pcre_callout or pcre[16|32]_callout is called (if it is set). This applies to both normal and DFA matching. The only argument to the callout function is a pointer to a pcre_callout or pcre[16|32]_callout block. These structures contains the following fields: int version; int callout_number; int *offset_vector; const char *subject; (8-bit version) PCRE_SPTR16 subject; (16-bit version) PCRE_SPTR32 subject; (32-bit version) int subject_length; int start_match; int current_position; int capture_top; int capture_last; void *callout_data; int pattern_position; int next_item_length; const unsigned char *mark; (8-bit version) const PCRE_UCHAR16 *mark; (16-bit version) const PCRE_UCHAR32 *mark; (32-bit version) The version field is an integer containing the version number of the block format. The initial version was 0; the current version is 2. The version number will change again in future if additional fields are added, but the intention is never to remove any of the existing fields. The callout_number field contains the number of the callout, as com- piled into the pattern (that is, the number after ?C for manual call- outs, and 255 for automatically generated callouts). The offset_vector field is a pointer to the vector of offsets that was passed by the caller to the matching function. When pcre_exec() or pcre[16|32]_exec() is used, the contents can be inspected, in order to extract substrings that have been matched so far, in the same way as for extracting substrings after a match has completed. For the DFA matching functions, this field is not useful. The subject and subject_length fields contain copies of the values that were passed to the matching function. The start_match field normally contains the offset within the subject at which the current match attempt started. However, if the escape sequence \K has been encountered, this value is changed to reflect the modified starting point. If the pattern is not anchored, the callout function may be called several times from the same point in the pattern for different starting points in the subject. The current_position field contains the offset within the subject of the current match pointer. When the pcre_exec() or pcre[16|32]_exec() is used, the capture_top field contains one more than the number of the highest numbered cap- tured substring so far. If no substrings have been captured, the value of capture_top is one. This is always the case when the DFA functions are used, because they do not support captured substrings. The capture_last field contains the number of the most recently cap- tured substring. However, when a recursion exits, the value reverts to what it was outside the recursion, as do the values of all captured substrings. If no substrings have been captured, the value of cap- ture_last is -1. This is always the case for the DFA matching func- tions. The callout_data field contains a value that is passed to a matching function specifically so that it can be passed back in callouts. It is passed in the callout_data field of a pcre_extra or pcre[16|32]_extra data structure. If no such data was passed, the value of callout_data in a callout block is NULL. There is a description of the pcre_extra structure in the pcreapi documentation. The pattern_position field is present from version 1 of the callout structure. It contains the offset to the next item to be matched in the pattern string. The next_item_length field is present from version 1 of the callout structure. It contains the length of the next item to be matched in the pattern string. When the callout immediately precedes an alternation bar, a closing parenthesis, or the end of the pattern, the length is zero. When the callout precedes an opening parenthesis, the length is that of the entire subpattern. The pattern_position and next_item_length fields are intended to help in distinguishing between different automatic callouts, which all have the same callout number. However, they are set for all callouts. The mark field is present from version 2 of the callout structure. In callouts from pcre_exec() or pcre[16|32]_exec() it contains a pointer to the zero-terminated name of the most recently passed (*MARK), (*PRUNE), or (*THEN) item in the match, or NULL if no such items have been passed. Instances of (*PRUNE) or (*THEN) without a name do not obliterate a previous (*MARK). In callouts from the DFA matching func- tions this field always contains NULL. RETURN VALUES The external callout function returns an integer to PCRE. If the value is zero, matching proceeds as normal. If the value is greater than zero, matching fails at the current point, but the testing of other matching possibilities goes ahead, just as if a lookahead assertion had failed. If the value is less than zero, the match is abandoned, the matching function returns the negative value. Negative values should normally be chosen from the set of PCRE_ERROR_xxx values. In particular, PCRE_ERROR_NOMATCH forces a stan- dard "no match" failure. The error number PCRE_ERROR_CALLOUT is reserved for use by callout functions; it will never be used by PCRE itself. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 12 November 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCRECOMPAT(3) Library Functions Manual PCRECOMPAT(3) NAME PCRE - Perl-compatible regular expressions DIFFERENCES BETWEEN PCRE AND PERL This document describes the differences in the ways that PCRE and Perl handle regular expressions. The differences described here are with respect to Perl versions 5.10 and above. 1. PCRE has only a subset of Perl's Unicode support. Details of what it does have are given in the pcreunicode page. 2. PCRE allows repeat quantifiers only on parenthesized assertions, but they do not mean what you might think. For example, (?!a){3} does not assert that the next three characters are not "a". It just asserts that the next character is not "a" three times (in principle: PCRE optimizes this to run the assertion just once). Perl allows repeat quantifiers on other assertions such as \b, but these do not seem to have any use. 3. Capturing subpatterns that occur inside negative lookahead asser- tions are counted, but their entries in the offsets vector are never set. Perl sometimes (but not always) sets its numerical variables from inside negative assertions. 4. Though binary zero characters are supported in the subject string, they are not allowed in a pattern string because it is passed as a nor- mal C string, terminated by zero. The escape sequence \0 can be used in the pattern to represent a binary zero. 5. The following Perl escape sequences are not supported: \l, \u, \L, \U, and \N when followed by a character name or Unicode value. (\N on its own, matching a non-newline character, is supported.) In fact these are implemented by Perl's general string-handling and are not part of its pattern matching engine. If any of these are encountered by PCRE, an error is generated by default. However, if the PCRE_JAVASCRIPT_COM- PAT option is set, \U and \u are interpreted as JavaScript interprets them. 6. The Perl escape sequences \p, \P, and \X are supported only if PCRE is built with Unicode character property support. The properties that can be tested with \p and \P are limited to the general category prop- erties such as Lu and Nd, script names such as Greek or Han, and the derived properties Any and L&. PCRE does support the Cs (surrogate) property, which Perl does not; the Perl documentation says "Because Perl hides the need for the user to understand the internal representa- tion of Unicode characters, there is no need to implement the somewhat messy concept of surrogates." 7. PCRE does support the \Q...\E escape for quoting substrings. Charac- ters in between are treated as literals. This is slightly different from Perl in that $ and @ are also handled as literals inside the quotes. In Perl, they cause variable interpolation (but of course PCRE does not have variables). Note the following examples: Pattern PCRE matches Perl matches \Qabc$xyz\E abc$xyz abc followed by the contents of $xyz \Qabc\$xyz\E abc\$xyz abc\$xyz \Qabc\E\$\Qxyz\E abc$xyz abc$xyz The \Q...\E sequence is recognized both inside and outside character classes. 8. Fairly obviously, PCRE does not support the (?{code}) and (??{code}) constructions. However, there is support for recursive patterns. This is not available in Perl 5.8, but it is in Perl 5.10. Also, the PCRE "callout" feature allows an external function to be called during pat- tern matching. See the pcrecallout documentation for details. 9. Subpatterns that are called as subroutines (whether or not recur- sively) are always treated as atomic groups in PCRE. This is like Python, but unlike Perl. Captured values that are set outside a sub- routine call can be reference from inside in PCRE, but not in Perl. There is a discussion that explains these differences in more detail in the section on recursion differences from Perl in the pcrepattern page. 10. If any of the backtracking control verbs are used in a subpattern that is called as a subroutine (whether or not recursively), their effect is confined to that subpattern; it does not extend to the sur- rounding pattern. This is not always the case in Perl. In particular, if (*THEN) is present in a group that is called as a subroutine, its action is limited to that group, even if the group does not contain any | characters. Note that such subpatterns are processed as anchored at the point where they are tested. 11. If a pattern contains more than one backtracking control verb, the first one that is backtracked onto acts. For example, in the pattern A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure in C triggers (*PRUNE). Perl's behaviour is more complex; in many cases it is the same as PCRE, but there are examples where it differs. 12. Most backtracking verbs in assertions have their normal actions. They are not confined to the assertion. 13. There are some differences that are concerned with the settings of captured strings when part of a pattern is repeated. For example, matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE it is set to "b". 14. PCRE's handling of duplicate subpattern numbers and duplicate sub- pattern names is not as general as Perl's. This is a consequence of the fact the PCRE works internally just with numbers, using an external ta- ble to translate between numbers and names. In particular, a pattern such as (?|(?A)|(?B), where the two capturing parentheses have the same number but different names, is not supported, and causes an error at compile time. If it were allowed, it would not be possible to distinguish which parentheses matched, because both names map to cap- turing subpattern number 1. To avoid this confusing situation, an error is given at compile time. 15. Perl recognizes comments in some places that PCRE does not, for example, between the ( and ? at the start of a subpattern. If the /x modifier is set, Perl allows white space between ( and ? (though cur- rent Perls warn that this is deprecated) but PCRE never does, even if the PCRE_EXTENDED option is set. 16. Perl, when in warning mode, gives warnings for character classes such as [A-\d] or [a-[:digit:]]. It then treats the hyphens as liter- als. PCRE has no warning features, so it gives an error in these cases because they are almost certainly user mistakes. 17. In PCRE, the upper/lower case character properties Lu and Ll are not affected when case-independent matching is specified. For example, \p{Lu} always matches an upper case letter. I think Perl has changed in this respect; in the release at the time of writing (5.16), \p{Lu} and \p{Ll} match all letters, regardless of case, when case independence is specified. 18. PCRE provides some extensions to the Perl regular expression facil- ities. Perl 5.10 includes new features that are not in earlier ver- sions of Perl, some of which (such as named parentheses) have been in PCRE for some time. This list is with respect to Perl 5.10: (a) Although lookbehind assertions in PCRE must match fixed length strings, each alternative branch of a lookbehind assertion can match a different length of string. Perl requires them all to have the same length. (b) If PCRE_DOLLAR_ENDONLY is set and PCRE_MULTILINE is not set, the $ meta-character matches only at the very end of the string. (c) If PCRE_EXTRA is set, a backslash followed by a letter with no spe- cial meaning is faulted. Otherwise, like Perl, the backslash is quietly ignored. (Perl can be made to issue a warning.) (d) If PCRE_UNGREEDY is set, the greediness of the repetition quanti- fiers is inverted, that is, by default they are not greedy, but if fol- lowed by a question mark they are. (e) PCRE_ANCHORED can be used at matching time to force a pattern to be tried only at the first matching position in the subject string. (f) The PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, and PCRE_NO_AUTO_CAPTURE options for pcre_exec() have no Perl equiva- lents. (g) The \R escape sequence can be restricted to match only CR, LF, or CRLF by the PCRE_BSR_ANYCRLF option. (h) The callout facility is PCRE-specific. (i) The partial matching facility is PCRE-specific. (j) Patterns compiled by PCRE can be saved and re-used at a later time, even on different hosts that have the other endianness. However, this does not apply to optimized data created by the just-in-time compiler. (k) The alternative matching functions (pcre_dfa_exec(), pcre16_dfa_exec() and pcre32_dfa_exec(),) match in a different way and are not Perl-compatible. (l) PCRE recognizes some special sequences such as (*CR) at the start of a pattern that set overall options that cannot be changed within the pattern. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 10 November 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCREPATTERN(3) Library Functions Manual PCREPATTERN(3) NAME PCRE - Perl-compatible regular expressions PCRE REGULAR EXPRESSION DETAILS The syntax and semantics of the regular expressions that are supported by PCRE are described in detail below. There is a quick-reference syn- tax summary in the pcresyntax page. PCRE tries to match Perl syntax and semantics as closely as it can. PCRE also supports some alternative regular expression syntax (which does not conflict with the Perl syn- tax) in order to provide some compatibility with regular expressions in Python, .NET, and Oniguruma. Perl's regular expressions are described in its own documentation, and regular expressions in general are covered in a number of books, some of which have copious examples. Jeffrey Friedl's "Mastering Regular Expressions", published by O'Reilly, covers regular expressions in great detail. This description of PCRE's regular expressions is intended as reference material. This document discusses the patterns that are supported by PCRE when one its main matching functions, pcre_exec() (8-bit) or pcre[16|32]_exec() (16- or 32-bit), is used. PCRE also has alternative matching functions, pcre_dfa_exec() and pcre[16|32_dfa_exec(), which match using a different algorithm that is not Perl-compatible. Some of the features discussed below are not available when DFA matching is used. The advantages and disadvantages of the alternative functions, and how they differ from the normal functions, are discussed in the pcrematching page. SPECIAL START-OF-PATTERN ITEMS A number of options that can be passed to pcre_compile() can also be set by special items at the start of a pattern. These are not Perl-com- patible, but are provided to make these options accessible to pattern writers who are not able to change the program that processes the pat- tern. Any number of these items may appear, but they must all be together right at the start of the pattern string, and the letters must be in upper case. UTF support The original operation of PCRE was on strings of one-byte characters. However, there is now also support for UTF-8 strings in the original library, an extra library that supports 16-bit and UTF-16 character strings, and a third library that supports 32-bit and UTF-32 character strings. To use these features, PCRE must be built to include appropri- ate support. When using UTF strings you must either call the compiling function with the PCRE_UTF8, PCRE_UTF16, or PCRE_UTF32 option, or the pattern must start with one of these special sequences: (*UTF8) (*UTF16) (*UTF32) (*UTF) (*UTF) is a generic sequence that can be used with any of the libraries. Starting a pattern with such a sequence is equivalent to setting the relevant option. How setting a UTF mode affects pattern matching is mentioned in several places below. There is also a summary of features in the pcreunicode page. Some applications that allow their users to supply patterns may wish to restrict them to non-UTF data for security reasons. If the PCRE_NEVER_UTF option is set at compile time, (*UTF) etc. are not allowed, and their appearance causes an error. Unicode property support Another special sequence that may appear at the start of a pattern is (*UCP). This has the same effect as setting the PCRE_UCP option: it causes sequences such as \d and \w to use Unicode properties to deter- mine character types, instead of recognizing only characters with codes less than 128 via a lookup table. Disabling auto-possessification If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as setting the PCRE_NO_AUTO_POSSESS option at compile time. This stops PCRE from making quantifiers possessive when what follows cannot match the repeated item. For example, by default a+b is treated as a++b. For more details, see the pcreapi documentation. Disabling start-up optimizations If a pattern starts with (*NO_START_OPT), it has the same effect as setting the PCRE_NO_START_OPTIMIZE option either at compile or matching time. This disables several optimizations for quickly reaching "no match" results. For more details, see the pcreapi documentation. Newline conventions PCRE supports five different conventions for indicating line breaks in strings: a single CR (carriage return) character, a single LF (line- feed) character, the two-character sequence CRLF, any of the three pre- ceding, or any Unicode newline sequence. The pcreapi page has further discussion about newlines, and shows how to set the newline convention in the options arguments for the compiling and matching functions. It is also possible to specify a newline convention by starting a pat- tern string with one of the following five sequences: (*CR) carriage return (*LF) linefeed (*CRLF) carriage return, followed by linefeed (*ANYCRLF) any of the three above (*ANY) all Unicode newline sequences These override the default and the options given to the compiling func- tion. For example, on a Unix system where LF is the default newline sequence, the pattern (*CR)a.b changes the convention to CR. That pattern matches "a\nb" because LF is no longer a newline. If more than one of these settings is present, the last one is used. The newline convention affects where the circumflex and dollar asser- tions are true. It also affects the interpretation of the dot metachar- acter when PCRE_DOTALL is not set, and the behaviour of \N. However, it does not affect what the \R escape sequence matches. By default, this is any Unicode newline sequence, for Perl compatibility. However, this can be changed; see the description of \R in the section entitled "New- line sequences" below. A change of \R setting can be combined with a change of newline convention. Setting match and recursion limits The caller of pcre_exec() can set a limit on the number of times the internal match() function is called and on the maximum depth of recur- sive calls. These facilities are provided to catch runaway matches that are provoked by patterns with huge matching trees (a typical example is a pattern with nested unlimited repeats) and to avoid running out of system stack by too much recursion. When one of these limits is reached, pcre_exec() gives an error return. The limits can also be set by items at the start of the pattern of the form (*LIMIT_MATCH=d) (*LIMIT_RECURSION=d) where d is any number of decimal digits. However, the value of the set- ting must be less than the value set (or defaulted) by the caller of pcre_exec() for it to have any effect. In other words, the pattern writer can lower the limits set by the programmer, but not raise them. If there is more than one setting of one of these limits, the lower value is used. EBCDIC CHARACTER CODES PCRE can be compiled to run in an environment that uses EBCDIC as its character code rather than ASCII or Unicode (typically a mainframe sys- tem). In the sections below, character code values are ASCII or Uni- code; in an EBCDIC environment these characters may have different code values, and there are no code points greater than 255. CHARACTERS AND METACHARACTERS A regular expression is a pattern that is matched against a subject string from left to right. Most characters stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern The quick brown fox matches a portion of a subject string that is identical to itself. When caseless matching is specified (the PCRE_CASELESS option), letters are matched independently of case. In a UTF mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher val- ues, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF support. The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of metacharacters, which do not stand for themselves but instead are interpreted in some special way. There are two different sets of metacharacters: those that are recog- nized anywhere in the pattern except within square brackets, and those that are recognized within square brackets. Outside square brackets, the metacharacters are as follows: \ general escape character with several uses ^ assert start of string (or line, in multiline mode) $ assert end of string (or line, in multiline mode) . match any character except newline (by default) [ start character class definition | start of alternative branch ( start subpattern ) end subpattern ? extends the meaning of ( also 0 or 1 quantifier also quantifier minimizer * 0 or more quantifier + 1 or more quantifier also "possessive quantifier" { start min/max quantifier Part of a pattern that is in square brackets is called a "character class". In a character class the only metacharacters are: \ general escape character ^ negate the class, but only if the first character - indicates character range [ POSIX character class (only if followed by POSIX syntax) ] terminates the character class The following sections describe the use of each of the metacharacters. BACKSLASH The backslash character has several uses. Firstly, if it is followed by a character that is not a number or a letter, it takes away any special meaning that character may have. This use of backslash as an escape character applies both inside and outside character classes. For example, if you want to match a * character, you write \* in the pattern. This escaping action applies whether or not the following character would otherwise be interpreted as a metacharacter, so it is always safe to precede a non-alphanumeric with backslash to specify that it stands for itself. In particular, if you want to match a back- slash, you write \\. In a UTF mode, only ASCII numbers and letters have any special meaning after a backslash. All other characters (in particular, those whose codepoints are greater than 127) are treated as literals. If a pattern is compiled with the PCRE_EXTENDED option, most white space in the pattern (other than in a character class), and characters between a # outside a character class and the next newline, inclusive, are ignored. An escaping backslash can be used to include a white space or # character as part of the pattern. If you want to remove the special meaning from a sequence of charac- ters, you can do so by putting them between \Q and \E. This is differ- ent from Perl in that $ and @ are handled as literals in \Q...\E sequences in PCRE, whereas in Perl, $ and @ cause variable interpola- tion. Note the following examples: Pattern PCRE matches Perl matches \Qabc$xyz\E abc$xyz abc followed by the contents of $xyz \Qabc\$xyz\E abc\$xyz abc\$xyz \Qabc\E\$\Qxyz\E abc$xyz abc$xyz The \Q...\E sequence is recognized both inside and outside character classes. An isolated \E that is not preceded by \Q is ignored. If \Q is not followed by \E later in the pattern, the literal interpretation continues to the end of the pattern (that is, \E is assumed at the end). If the isolated \Q is inside a character class, this causes an error, because the character class is not terminated. Non-printing characters A second use of backslash provides a way of encoding non-printing char- acters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters, apart from the binary zero that terminates a pattern, but when a pattern is being prepared by text editing, it is often easier to use one of the following escape sequences than the binary character it represents. In an ASCII or Uni- code environment, these escapes are as follows: \a alarm, that is, the BEL character (hex 07) \cx "control-x", where x is any ASCII character \e escape (hex 1B) \f form feed (hex 0C) \n linefeed (hex 0A) \r carriage return (hex 0D) \t tab (hex 09) \0dd character with octal code 0dd \ddd character with octal code ddd, or back reference \o{ddd..} character with octal code ddd.. \xhh character with hex code hh \x{hhh..} character with hex code hhh.. (non-JavaScript mode) \uhhhh character with hex code hhhh (JavaScript mode only) The precise effect of \cx on ASCII characters is as follows: if x is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus \cA to \cZ become hex 01 to hex 1A (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes hex 7B (; is 3B). If the data item (byte or 16-bit value) following \c has a value greater than 127, a compile-time error occurs. This locks out non-ASCII characters in all modes. When PCRE is compiled in EBCDIC mode, \a, \e, \f, \n, \r, and \t gener- ate the appropriate EBCDIC code values. The \c escape is processed as specified for Perl in the perlebcdic document. The only characters that are allowed after \c are A-Z, a-z, or one of @, [, \, ], ^, _, or ?. Any other character provokes a compile-time error. The sequence \c@ encodes character code 0; after \c the letters (in either case) encode characters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters 27-31 (hex 1B to hex 1F), and \c? becomes either 255 (hex FF) or 95 (hex 5F). Thus, apart from \c?, these escapes generate the same character code values as they do in an ASCII environment, though the meanings of the values mostly differ. For example, \cG always generates code value 7, which is BEL in ASCII but DEL in EBCDIC. The sequence \c? generates DEL (127, hex 7F) in an ASCII environment, but because 127 is not a control character in EBCDIC, Perl makes it generate the APC character. Unfortunately, there are several variants of EBCDIC. In most of them the APC character has the value 255 (hex FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If certain other characters have POSIX-BC values, PCRE makes \c? generate 95; otherwise it generates 255. After \0 up to two further octal digits are read. If there are fewer than two digits, just those that are present are used. Thus the sequence \0\x\015 specifies two binary zeros followed by a CR character (code value 13). Make sure you supply two digits after the initial zero if the pattern character that follows is itself an octal digit. The escape \o must be followed by a sequence of octal digits, enclosed in braces. An error occurs if this is not the case. This escape is a recent addition to Perl; it provides way of specifying character code points as octal numbers greater than 0777, and it also allows octal numbers and back references to be unambiguously specified. For greater clarity and unambiguity, it is best to avoid following \ by a digit greater than zero. Instead, use \o{} or \x{} to specify charac- ter numbers, and \g{} to specify back references. The following para- graphs describe the old, ambiguous syntax. The handling of a backslash followed by a digit other than 0 is compli- cated, and Perl has changed in recent releases, causing PCRE also to change. Outside a character class, PCRE reads the digit and any follow- ing digits as a decimal number. If the number is less than 8, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a back reference. A description of how this works is given later, following the discussion of parenthesized subpatterns. Inside a character class, or if the decimal number following \ is greater than 7 and there have not been that many capturing subpatterns, PCRE handles \8 and \9 as the literal characters "8" and "9", and oth- erwise re-reads up to three octal digits following the backslash, using them to generate a data character. Any subsequent digits stand for themselves. For example: \040 is another way of writing an ASCII space \40 is the same, provided there are fewer than 40 previous capturing subpatterns \7 is always a back reference \11 might be a back reference, or another way of writing a tab \011 is always a tab \0113 is a tab followed by the character "3" \113 might be a back reference, otherwise the character with octal code 113 \377 might be a back reference, otherwise the value 255 (decimal) \81 is either a back reference, or the two characters "8" and "1" Note that octal values of 100 or greater that are specified using this syntax must not be introduced by a leading zero, because no more than three octal digits are ever read. By default, after \x that is not followed by {, from zero to two hexa- decimal digits are read (letters can be in upper or lower case). Any number of hexadecimal digits may appear between \x{ and }. If a charac- ter other than a hexadecimal digit appears between \x{ and }, or if there is no terminating }, an error occurs. If the PCRE_JAVASCRIPT_COMPAT option is set, the interpretation of \x is as just described only when it is followed by two hexadecimal dig- its. Otherwise, it matches a literal "x" character. In JavaScript mode, support for code points greater than 256 is provided by \u, which must be followed by four hexadecimal digits; otherwise it matches a literal "u" character. Characters whose value is less than 256 can be defined by either of the two syntaxes for \x (or by \u in JavaScript mode). There is no differ- ence in the way they are handled. For example, \xdc is exactly the same as \x{dc} (or \u00dc in JavaScript mode). Constraints on character values Characters that are specified using octal or hexadecimal numbers are limited to certain values, as follows: 8-bit non-UTF mode less than 0x100 8-bit UTF-8 mode less than 0x10ffff and a valid codepoint 16-bit non-UTF mode less than 0x10000 16-bit UTF-16 mode less than 0x10ffff and a valid codepoint 32-bit non-UTF mode less than 0x100000000 32-bit UTF-32 mode less than 0x10ffff and a valid codepoint Invalid Unicode codepoints are the range 0xd800 to 0xdfff (the so- called "surrogate" codepoints), and 0xffef. Escape sequences in character classes All the sequences that define a single character value can be used both inside and outside character classes. In addition, inside a character class, \b is interpreted as the backspace character (hex 08). \N is not allowed in a character class. \B, \R, and \X are not special inside a character class. Like other unrecognized escape sequences, they are treated as the literal characters "B", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set. Outside a character class, these sequences have different meanings. Unsupported escape sequences In Perl, the sequences \l, \L, \u, and \U are recognized by its string handler and used to modify the case of following characters. By default, PCRE does not support these escape sequences. However, if the PCRE_JAVASCRIPT_COMPAT option is set, \U matches a "U" character, and \u can be used to define a character by code point, as described in the previous section. Absolute and relative back references The sequence \g followed by an unsigned or a negative number, option- ally enclosed in braces, is an absolute or relative back reference. A named back reference can be coded as \g{name}. Back references are dis- cussed later, following the discussion of parenthesized subpatterns. Absolute and relative subroutine calls For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative syntax for referencing a subpattern as a "subroutine". Details are discussed later. Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not synonymous. The former is a back reference; the latter is a subroutine call. Generic character types Another use of backslash is for specifying generic character types: \d any decimal digit \D any character that is not a decimal digit \h any horizontal white space character \H any character that is not a horizontal white space character \s any white space character \S any character that is not a white space character \v any vertical white space character \V any character that is not a vertical white space character \w any "word" character \W any "non-word" character There is also the single sequence \N, which matches a non-newline char- acter. This is the same as the "." metacharacter when PCRE_DOTALL is not set. Perl also uses \N to match characters by name; PCRE does not support this. Each pair of lower and upper case escape sequences partitions the com- plete set of characters into two disjoint sets. Any given character matches one, and only one, of each pair. The sequences can appear both inside and outside character classes. They each match one character of the appropriate type. If the current matching point is at the end of the subject string, all of them fail, because there is no character to match. For compatibility with Perl, \s did not used to match the VT character (code 11), which made it different from the the POSIX "space" class. However, Perl added VT at release 5.18, and PCRE followed suit at release 8.34. The default \s characters are now HT (9), LF (10), VT (11), FF (12), CR (13), and space (32), which are defined as white space in the "C" locale. This list may vary if locale-specific matching is taking place. For example, in some locales the "non-breaking space" character (\xA0) is recognized as white space, and in others the VT character is not. A "word" character is an underscore or any character that is a letter or digit. By default, the definition of letters and digits is con- trolled by PCRE's low-valued character tables, and may vary if locale- specific matching is taking place (see "Locale support" in the pcreapi page). For example, in a French locale such as "fr_FR" in Unix-like systems, or "french" in Windows, some character codes greater than 127 are used for accented letters, and these are then matched by \w. The use of locales with Unicode is discouraged. By default, characters whose code points are greater than 127 never match \d, \s, or \w, and always match \D, \S, and \W, although this may vary for characters in the range 128-255 when locale-specific matching is happening. These escape sequences retain their original meanings from before Unicode support was available, mainly for efficiency rea- sons. If PCRE is compiled with Unicode property support, and the PCRE_UCP option is set, the behaviour is changed so that Unicode prop- erties are used to determine character types, as follows: \d any character that matches \p{Nd} (decimal digit) \s any character that matches \p{Z} or \h or \v \w any character that matches \p{L} or \p{N}, plus underscore The upper case escapes match the inverse sets of characters. Note that \d matches only decimal digits, whereas \w matches any Unicode digit, as well as any Unicode letter, and underscore. Note also that PCRE_UCP affects \b, and \B because they are defined in terms of \w and \W. Matching these sequences is noticeably slower when PCRE_UCP is set. The sequences \h, \H, \v, and \V are features that were added to Perl at release 5.10. In contrast to the other sequences, which match only ASCII characters by default, these always match certain high-valued code points, whether or not PCRE_UCP is set. The horizontal space char- acters are: U+0009 Horizontal tab (HT) U+0020 Space U+00A0 Non-break space U+1680 Ogham space mark U+180E Mongolian vowel separator U+2000 En quad U+2001 Em quad U+2002 En space U+2003 Em space U+2004 Three-per-em space U+2005 Four-per-em space U+2006 Six-per-em space U+2007 Figure space U+2008 Punctuation space U+2009 Thin space U+200A Hair space U+202F Narrow no-break space U+205F Medium mathematical space U+3000 Ideographic space The vertical space characters are: U+000A Linefeed (LF) U+000B Vertical tab (VT) U+000C Form feed (FF) U+000D Carriage return (CR) U+0085 Next line (NEL) U+2028 Line separator U+2029 Paragraph separator In 8-bit, non-UTF-8 mode, only the characters with codepoints less than 256 are relevant. Newline sequences Outside a character class, by default, the escape sequence \R matches any Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent to the following: (?>\r\n|\n|\x0b|\f|\r|\x85) This is an example of an "atomic group", details of which are given below. This particular group matches either the two-character sequence CR followed by LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (car- riage return, U+000D), or NEL (next line, U+0085). The two-character sequence is treated as a single unit that cannot be split. In other modes, two additional characters whose codepoints are greater than 255 are added: LS (line separator, U+2028) and PS (paragraph sepa- rator, U+2029). Unicode character property support is not needed for these characters to be recognized. It is possible to restrict \R to match only CR, LF, or CRLF (instead of the complete set of Unicode line endings) by setting the option PCRE_BSR_ANYCRLF either at compile time or when the pattern is matched. (BSR is an abbrevation for "backslash R".) This can be made the default when PCRE is built; if this is the case, the other behaviour can be requested via the PCRE_BSR_UNICODE option. It is also possible to specify these settings by starting a pattern string with one of the following sequences: (*BSR_ANYCRLF) CR, LF, or CRLF only (*BSR_UNICODE) any Unicode newline sequence These override the default and the options given to the compiling func- tion, but they can themselves be overridden by options given to a matching function. Note that these special settings, which are not Perl-compatible, are recognized only at the very start of a pattern, and that they must be in upper case. If more than one of them is present, the last one is used. They can be combined with a change of newline convention; for example, a pattern can start with: (*ANY)(*BSR_ANYCRLF) They can also be combined with the (*UTF8), (*UTF16), (*UTF32), (*UTF) or (*UCP) special sequences. Inside a character class, \R is treated as an unrecognized escape sequence, and so matches the letter "R" by default, but causes an error if PCRE_EXTRA is set. Unicode character properties When PCRE is built with Unicode character property support, three addi- tional escape sequences that match characters with specific properties are available. When in 8-bit non-UTF-8 mode, these sequences are of course limited to testing characters whose codepoints are less than 256, but they do work in this mode. The extra escape sequences are: \p{xx} a character with the xx property \P{xx} a character without the xx property \X a Unicode extended grapheme cluster The property names represented by xx above are limited to the Unicode script names, the general category properties, "Any", which matches any character (including newline), and some special PCRE properties (described in the next section). Other Perl properties such as "InMu- sicalSymbols" are not currently supported by PCRE. Note that \P{Any} does not match any characters, so always causes a match failure. Sets of Unicode characters are defined as belonging to certain scripts. A character from one of these sets can be matched using a script name. For example: \p{Greek} \P{Han} Those that are not part of an identified script are lumped together as "Common". The current list of scripts is: Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Car- ian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cunei- form, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hiero- glyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip- tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin- ear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha- vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi. Each character has exactly one Unicode general category property, spec- ified by a two-letter abbreviation. For compatibility with Perl, nega- tion can be specified by including a circumflex between the opening brace and the property name. For example, \p{^Lu} is the same as \P{Lu}. If only one letter is specified with \p or \P, it includes all the gen- eral category properties that start with that letter. In this case, in the absence of negation, the curly brackets in the escape sequence are optional; these two examples have the same effect: \p{L} \pL The following general category property codes are supported: C Other Cc Control Cf Format Cn Unassigned Co Private use Cs Surrogate L Letter Ll Lower case letter Lm Modifier letter Lo Other letter Lt Title case letter Lu Upper case letter M Mark Mc Spacing mark Me Enclosing mark Mn Non-spacing mark N Number Nd Decimal number Nl Letter number No Other number P Punctuation Pc Connector punctuation Pd Dash punctuation Pe Close punctuation Pf Final punctuation Pi Initial punctuation Po Other punctuation Ps Open punctuation S Symbol Sc Currency symbol Sk Modifier symbol Sm Mathematical symbol So Other symbol Z Separator Zl Line separator Zp Paragraph separator Zs Space separator The special property L& is also supported: it matches a character that has the Lu, Ll, or Lt property, in other words, a letter that is not classified as a modifier or "other". The Cs (Surrogate) property applies only to characters in the range U+D800 to U+DFFF. Such characters are not valid in Unicode strings and so cannot be tested by PCRE, unless UTF validity checking has been turned off (see the discussion of PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK and PCRE_NO_UTF32_CHECK in the pcreapi page). Perl does not support the Cs property. The long synonyms for property names that Perl supports (such as \p{Letter}) are not supported by PCRE, nor is it permitted to prefix any of these properties with "Is". No character that is in the Unicode table has the Cn (unassigned) prop- erty. Instead, this property is assumed for any code point that is not in the Unicode table. Specifying caseless matching does not affect these escape sequences. For example, \p{Lu} always matches only upper case letters. This is different from the behaviour of current versions of Perl. Matching characters by Unicode property is not fast, because PCRE has to do a multistage table lookup in order to find a character's prop- erty. That is why the traditional escape sequences such as \d and \w do not use Unicode properties in PCRE by default, though you can make them do so by setting the PCRE_UCP option or by starting the pattern with (*UCP). Extended grapheme clusters The \X escape matches any number of Unicode characters that form an "extended grapheme cluster", and treats the sequence as an atomic group (see below). Up to and including release 8.31, PCRE matched an ear- lier, simpler definition that was equivalent to (?>\PM\pM*) That is, it matched a character without the "mark" property, followed by zero or more characters with the "mark" property. Characters with the "mark" property are typically non-spacing accents that affect the preceding character. This simple definition was extended in Unicode to include more compli- cated kinds of composite character by giving each character a grapheme breaking property, and creating rules that use these properties to define the boundaries of extended grapheme clusters. In releases of PCRE later than 8.31, \X matches one of these clusters. \X always matches at least one character. Then it decides whether to add additional characters according to the following rules for ending a cluster: 1. End at the end of the subject string. 2. Do not end between CR and LF; otherwise end after any control char- acter. 3. Do not break Hangul (a Korean script) syllable sequences. Hangul characters are of five types: L, V, T, LV, and LVT. An L character may be followed by an L, V, LV, or LVT character; an LV or V character may be followed by a V or T character; an LVT or T character may be follwed only by a T character. 4. Do not end before extending characters or spacing marks. Characters with the "mark" property always have the "extend" grapheme breaking property. 5. Do not end after prepend characters. 6. Otherwise, end the cluster. PCRE's additional properties As well as the standard Unicode properties described above, PCRE sup- ports four more that make it possible to convert traditional escape sequences such as \w and \s to use Unicode properties. PCRE uses these non-standard, non-Perl properties internally when PCRE_UCP is set. How- ever, they may also be used explicitly. These properties are: Xan Any alphanumeric character Xps Any POSIX space character Xsp Any Perl space character Xwd Any Perl "word" character Xan matches characters that have either the L (letter) or the N (num- ber) property. Xps matches the characters tab, linefeed, vertical tab, form feed, or carriage return, and any other character that has the Z (separator) property. Xsp is the same as Xps; it used to exclude ver- tical tab, for Perl compatibility, but Perl changed, and so PCRE fol- lowed at release 8.34. Xwd matches the same characters as Xan, plus underscore. There is another non-standard property, Xuc, which matches any charac- ter that can be represented by a Universal Character Name in C++ and other programming languages. These are the characters $, @, ` (grave accent), and all characters with Unicode code points greater than or equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that most base (ASCII) characters are excluded. (Universal Character Names are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit. Note that the Xuc property does not match these sequences but the char- acters that they represent.) Resetting the match start The escape sequence \K causes any previously matched characters not to be included in the final matched sequence. For example, the pattern: foo\Kbar matches "foobar", but reports that it has matched "bar". This feature is similar to a lookbehind assertion (described below). However, in this case, the part of the subject before the real match does not have to be of fixed length, as lookbehind assertions do. The use of \K does not interfere with the setting of captured substrings. For example, when the pattern (foo)\Kbar matches "foobar", the first substring is still set to "foo". Perl documents that the use of \K within assertions is "not well defined". In PCRE, \K is acted upon when it occurs inside positive assertions, but is ignored in negative assertions. Note that when a pattern such as (?=ab\K) matches, the reported start of the match can be greater than the end of the match. Simple assertions The final use of backslash is for certain simple assertions. An asser- tion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described below. The backslashed assertions are: \b matches at a word boundary \B matches when not at a word boundary \A matches at the start of the subject \Z matches at the end of the subject also matches before a newline at the end of the subject \z matches only at the end of the subject \G matches at the first matching position in the subject Inside a character class, \b has a different meaning; it matches the backspace character. If any other of these assertions appears in a character class, by default it matches the corresponding literal char- acter (for example, \B matches the letter B). However, if the PCRE_EXTRA option is set, an "invalid escape sequence" error is gener- ated instead. A word boundary is a position in the subject string where the current character and the previous character do not both match \w or \W (i.e. one matches \w and the other matches \W), or the start or end of the string if the first or last character matches \w, respectively. In a UTF mode, the meanings of \w and \W can be changed by setting the PCRE_UCP option. When this is done, it also affects \b and \B. Neither PCRE nor Perl has a separate "start of word" or "end of word" metase- quence. However, whatever follows \b normally determines which it is. For example, the fragment \ba matches "a" at the start of a word. The \A, \Z, and \z assertions differ from the traditional circumflex and dollar (described in the next section) in that they only ever match at the very start and end of the subject string, whatever options are set. Thus, they are independent of multiline mode. These three asser- tions are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options, which affect only the behaviour of the circumflex and dollar metacharacters. However, if the startoffset argument of pcre_exec() is non-zero, indi- cating that matching is to start at a point other than the beginning of the subject, \A can never match. The difference between \Z and \z is that \Z matches before a newline at the end of the string as well as at the very end, whereas \z matches only at the end. The \G assertion is true only when the current matching position is at the start point of the match, as specified by the startoffset argument of pcre_exec(). It differs from \A when the value of startoffset is non-zero. By calling pcre_exec() multiple times with appropriate argu- ments, you can mimic Perl's /g option, and it is in this kind of imple- mentation where \G can be useful. Note, however, that PCRE's interpretation of \G, as the start of the current match, is subtly different from Perl's, which defines it as the end of the previous match. In Perl, these can be different when the previously matched string was empty. Because PCRE does just one match at a time, it cannot reproduce this behaviour. If all the alternatives of a pattern begin with \G, the expression is anchored to the starting match position, and the "anchored" flag is set in the compiled regular expression. CIRCUMFLEX AND DOLLAR The circumflex and dollar metacharacters are zero-width assertions. That is, they test for a particular condition being true without con- suming any characters from the subject string. Outside a character class, in the default matching mode, the circumflex character is an assertion that is true only if the current matching point is at the start of the subject string. If the startoffset argu- ment of pcre_exec() is non-zero, circumflex can never match if the PCRE_MULTILINE option is unset. Inside a character class, circumflex has an entirely different meaning (see below). Circumflex need not be the first character of the pattern if a number of alternatives are involved, but it should be the first thing in each alternative in which it appears if the pattern is ever to match that branch. If all possible alternatives start with a circumflex, that is, if the pattern is constrained to match only at the start of the sub- ject, it is said to be an "anchored" pattern. (There are also other constructs that can cause a pattern to be anchored.) The dollar character is an assertion that is true only if the current matching point is at the end of the subject string, or immediately before a newline at the end of the string (by default). Note, however, that it does not actually match the newline. Dollar need not be the last character of the pattern if a number of alternatives are involved, but it should be the last item in any branch in which it appears. Dol- lar has no special meaning in a character class. The meaning of dollar can be changed so that it matches only at the very end of the string, by setting the PCRE_DOLLAR_ENDONLY option at compile time. This does not affect the \Z assertion. The meanings of the circumflex and dollar characters are changed if the PCRE_MULTILINE option is set. When this is the case, a circumflex matches immediately after internal newlines as well as at the start of the subject string. It does not match after a newline that ends the string. A dollar matches before any newlines in the string, as well as at the very end, when PCRE_MULTILINE is set. When newline is specified as the two-character sequence CRLF, isolated CR and LF characters do not indicate newlines. For example, the pattern /^abc$/ matches the subject string "def\nabc" (where \n represents a newline) in multiline mode, but not otherwise. Consequently, patterns that are anchored in single line mode because all branches start with ^ are not anchored in multiline mode, and a match for circumflex is possible when the startoffset argument of pcre_exec() is non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. Note that the sequences \A, \Z, and \z can be used to match the start and end of the subject in both modes, and if all branches of a pattern start with \A it is always anchored, whether or not PCRE_MULTILINE is set. FULL STOP (PERIOD, DOT) AND \N Outside a character class, a dot in the pattern matches any one charac- ter in the subject string except (by default) a character that signi- fies the end of a line. When a line ending is defined as a single character, dot never matches that character; when the two-character sequence CRLF is used, dot does not match CR if it is immediately followed by LF, but otherwise it matches all characters (including isolated CRs and LFs). When any Uni- code line endings are being recognized, dot does not match CR or LF or any of the other line ending characters. The behaviour of dot with regard to newlines can be changed. If the PCRE_DOTALL option is set, a dot matches any one character, without exception. If the two-character sequence CRLF is present in the subject string, it takes two dots to match it. The handling of dot is entirely independent of the handling of circum- flex and dollar, the only relationship being that they both involve newlines. Dot has no special meaning in a character class. The escape sequence \N behaves like a dot, except that it is not affected by the PCRE_DOTALL option. In other words, it matches any character except one that signifies the end of a line. Perl also uses \N to match characters by name; PCRE does not support this. MATCHING A SINGLE DATA UNIT Outside a character class, the escape sequence \C matches any one data unit, whether or not a UTF mode is set. In the 8-bit library, one data unit is one byte; in the 16-bit library it is a 16-bit unit; in the 32-bit library it is a 32-bit unit. Unlike a dot, \C always matches line-ending characters. The feature is provided in Perl in order to match individual bytes in UTF-8 mode, but it is unclear how it can use- fully be used. Because \C breaks up characters into individual data units, matching one unit with \C in a UTF mode means that the rest of the string may start with a malformed UTF character. This has undefined results, because PCRE assumes that it is dealing with valid UTF strings (and by default it checks this at the start of processing unless the PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK or PCRE_NO_UTF32_CHECK option is used). PCRE does not allow \C to appear in lookbehind assertions (described below) in a UTF mode, because this would make it impossible to calcu- late the length of the lookbehind. In general, the \C escape sequence is best avoided. However, one way of using it that avoids the problem of malformed UTF characters is to use a lookahead to check the length of the next character, as in this pat- tern, which could be used with a UTF-8 string (ignore white space and line breaks): (?| (?=[\x00-\x7f])(\C) | (?=[\x80-\x{7ff}])(\C)(\C) | (?=[\x{800}-\x{ffff}])(\C)(\C)(\C) | (?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C)) A group that starts with (?| resets the capturing parentheses numbers in each alternative (see "Duplicate Subpattern Numbers" below). The assertions at the start of each branch check the next UTF-8 character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The character's individual bytes are then captured by the appropriate num- ber of groups. SQUARE BRACKETS AND CHARACTER CLASSES An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not spe- cial by default. However, if the PCRE_JAVASCRIPT_COMPAT option is set, a lone closing square bracket causes a compile-time error. If a closing square bracket is required as a member of the class, it should be the first data character in the class (after an initial circumflex, if present) or escaped with a backslash. A character class matches a single character in the subject. In a UTF mode, the character may be more than one data unit long. A matched character must be in the set of characters defined by the class, unless the first character in the class definition is a circumflex, in which case the subject character must not be in the set defined by the class. If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash. For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient notation for specifying the characters that are in the class by enumerating those that are not. A class that starts with a circumflex is not an assertion; it still con- sumes a character from the subject string, and therefore it fails if the current pointer is at the end of the string. In UTF-8 (UTF-16, UTF-32) mode, characters with values greater than 255 (0xffff) can be included in a class as a literal string of data units, or by using the \x{ escaping mechanism. When caseless matching is set, any letters in a class represent both their upper case and lower case versions, so for example, a caseless [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not match "A", whereas a caseful version would. In a UTF mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching in a UTF mode for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF support. Characters that might indicate line breaks are never treated in any special way when matching character classes, whatever line-ending sequence is in use, and whatever setting of the PCRE_DOTALL and PCRE_MULTILINE options is used. A class such as [^a] always matches one of these characters. The minus (hyphen) character can be used to specify a range of charac- ters in a character class. For example, [d-m] matches any letter between d and m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last character in the class, or immediately after a range. For example, [b-d-z] matches letters in the range b to d, a hyphen charac- ter, or z. It is not possible to have the literal character "]" as the end charac- ter of a range. A pattern such as [W-]46] is interpreted as a class of two characters ("W" and "-") followed by a literal string "46]", so it would match "W46]" or "-46]". However, if the "]" is escaped with a backslash it is interpreted as the end of range, so [W-\]46] is inter- preted as a class containing a range followed by two other characters. The octal or hexadecimal representation of "]" can also be used to end a range. An error is generated if a POSIX character class (see below) or an escape sequence other than one that defines a single character appears at a point where a range ending character is expected. For example, [z-\xff] is valid, but [A-\d] and [A-[:digit:]] are not. Ranges operate in the collating sequence of character values. They can also be used for characters specified numerically, for example [\000-\037]. Ranges can include any characters that are valid for the current mode. If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, [W-c] is equivalent to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if character tables for a French locale are in use, [\xc8-\xcb] matches accented E characters in both cases. In UTF modes, PCRE supports the concept of case for characters with values greater than 128 only when it is compiled with Unicode property support. The character escape sequences \d, \D, \h, \H, \p, \P, \s, \S, \v, \V, \w, and \W may appear in a character class, and add the characters that they match to the class. For example, [\dABCDEF] matches any hexadeci- mal digit. In UTF modes, the PCRE_UCP option affects the meanings of \d, \s, \w and their upper case partners, just as it does when they appear outside a character class, as described in the section entitled "Generic character types" above. The escape sequence \b has a different meaning inside a character class; it matches the backspace character. The sequences \B, \N, \R, and \X are not special inside a character class. Like any other unrecognized escape sequences, they are treated as the literal characters "B", "N", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set. A circumflex can conveniently be used with the upper case character types to specify a more restricted set of characters than the matching lower case type. For example, the class [^\W_] matches any letter or digit, but not underscore, whereas [\w] includes underscore. A positive character class should be read as "something OR something OR ..." and a negative class as "NOT something AND NOT something AND NOT ...". The only metacharacters that are recognized in character classes are backslash, hyphen (only where it can be interpreted as specifying a range), circumflex (only at the start), opening square bracket (only when it can be interpreted as introducing a POSIX class name, or for a special compatibility feature - see the next two sections), and the terminating closing square bracket. However, escaping other non- alphanumeric characters does no harm. POSIX CHARACTER CLASSES Perl supports the POSIX notation for character classes. This uses names enclosed by [: and :] within the enclosing square brackets. PCRE also supports this notation. For example, [01[:alpha:]%] matches "0", "1", any alphabetic character, or "%". The supported class names are: alnum letters and digits alpha letters ascii character codes 0 - 127 blank space or tab only cntrl control characters digit decimal digits (same as \d) graph printing characters, excluding space lower lower case letters print printing characters, including space punct printing characters, excluding letters and digits and space space white space (the same as \s from PCRE 8.34) upper upper case letters word "word" characters (same as \w) xdigit hexadecimal digits The default "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13), and space (32). If locale-specific matching is taking place, the list of space characters may be different; there may be fewer or more of them. "Space" used to be different to \s, which did not include VT, for Perl compatibility. However, Perl changed at release 5.18, and PCRE followed at release 8.34. "Space" and \s now match the same set of characters. The name "word" is a Perl extension, and "blank" is a GNU extension from Perl 5.8. Another Perl extension is negation, which is indicated by a ^ character after the colon. For example, [12[:^digit:]] matches "1", "2", or any non-digit. PCRE (and Perl) also recognize the POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not supported, and an error is given if they are encountered. By default, characters with values greater than 128 do not match any of the POSIX character classes. However, if the PCRE_UCP option is passed to pcre_compile(), some of the classes are changed so that Unicode character properties are used. This is achieved by replacing certain POSIX classes by other sequences, as follows: [:alnum:] becomes \p{Xan} [:alpha:] becomes \p{L} [:blank:] becomes \h [:digit:] becomes \p{Nd} [:lower:] becomes \p{Ll} [:space:] becomes \p{Xps} [:upper:] becomes \p{Lu} [:word:] becomes \p{Xwd} Negated versions, such as [:^alpha:] use \P instead of \p. Three other POSIX classes are handled specially in UCP mode: [:graph:] This matches characters that have glyphs that mark the page when printed. In Unicode property terms, it matches all char- acters with the L, M, N, P, S, or Cf properties, except for: U+061C Arabic Letter Mark U+180E Mongolian Vowel Separator U+2066 - U+2069 Various "isolate"s [:print:] This matches the same characters as [:graph:] plus space characters that are not controls, that is, characters with the Zs property. [:punct:] This matches all characters that have the Unicode P (punctua- tion) property, plus those characters whose code points are less than 128 that have the S (Symbol) property. The other POSIX classes are unchanged, and match only characters with code points less than 128. COMPATIBILITY FEATURE FOR WORD BOUNDARIES In the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word" and "end of word". PCRE treats these items as follows: [[:<:]] is converted to \b(?=\w) [[:>:]] is converted to \b(?<=\w) Only these exact character sequences are recognized. A sequence such as [a[:<:]b] provokes error for an unrecognized POSIX class name. This support is not compatible with Perl. It is provided to help migrations from other environments, and is best not used in any new patterns. Note that \b matches at the start and the end of a word (see "Simple asser- tions" above), and in a Perl-style pattern the preceding or following character normally shows which is wanted, without the need for the assertions that are used above in order to give exactly the POSIX be- haviour. VERTICAL BAR Vertical bar characters are used to separate alternative patterns. For example, the pattern gilbert|sullivan matches either "gilbert" or "sullivan". Any number of alternatives may appear, and an empty alternative is permitted (matching the empty string). The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. If the alternatives are within a subpattern (defined below), "succeeds" means matching the rest of the main pattern as well as the alternative in the subpattern. INTERNAL OPTION SETTING The settings of the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and PCRE_EXTENDED options (which are Perl-compatible) can be changed from within the pattern by a sequence of Perl option letters enclosed between "(?" and ")". The option letters are i for PCRE_CASELESS m for PCRE_MULTILINE s for PCRE_DOTALL x for PCRE_EXTENDED For example, (?im) sets caseless, multiline matching. It is also possi- ble to unset these options by preceding the letter with a hyphen, and a combined setting and unsetting such as (?im-sx), which sets PCRE_CASE- LESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED, is also permitted. If a letter appears both before and after the hyphen, the option is unset. The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA can be changed in the same way as the Perl-compatible options by using the characters J, U and X respectively. When one of these option changes occurs at top level (that is, not inside subpattern parentheses), the change applies to the remainder of the pattern that follows. An option change within a subpattern (see below for a description of subpatterns) affects only that part of the subpattern that follows it, so (a(?i)b)c matches abc and aBc and no other strings (assuming PCRE_CASELESS is not used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example, (a(?i)b|c) matches "ab", "aB", "c", and "C", even though when matching "C" the first branch is abandoned before the option setting. This is because the effects of option settings happen at compile time. There would be some very weird behaviour otherwise. Note: There are other PCRE-specific options that can be set by the application when the compiling or matching functions are called. In some cases the pattern can contain special leading sequences such as (*CRLF) to override what the application has set or what has been defaulted. Details are given in the section entitled "Newline sequences" above. There are also the (*UTF8), (*UTF16),(*UTF32), and (*UCP) leading sequences that can be used to set UTF and Unicode prop- erty modes; they are equivalent to setting the PCRE_UTF8, PCRE_UTF16, PCRE_UTF32 and the PCRE_UCP options, respectively. The (*UTF) sequence is a generic version that can be used with any of the libraries. How- ever, the application can set the PCRE_NEVER_UTF option, which locks out the use of the (*UTF) sequences. SUBPATTERNS Subpatterns are delimited by parentheses (round brackets), which can be nested. Turning part of a pattern into a subpattern does two things: 1. It localizes a set of alternatives. For example, the pattern cat(aract|erpillar|) matches "cataract", "caterpillar", or "cat". Without the parentheses, it would match "cataract", "erpillar" or an empty string. 2. It sets up the subpattern as a capturing subpattern. This means that, when the whole pattern matches, that portion of the subject string that matched the subpattern is passed back to the caller via the ovector argument of the matching function. (This applies only to the traditional matching functions; the DFA matching functions do not sup- port capturing.) Opening parentheses are counted from left to right (starting from 1) to obtain numbers for the capturing subpatterns. For example, if the string "the red king" is matched against the pattern the ((red|white) (king|queen)) the captured substrings are "red king", "red", and "king", and are num- bered 1, 2, and 3, respectively. The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by a question mark and a colon, the subpattern does not do any captur- ing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string "the white queen" is matched against the pattern the ((?:red|white) (king|queen)) the captured substrings are "white queen" and "queen", and are numbered 1 and 2. The maximum number of capturing subpatterns is 65535. As a convenient shorthand, if any option settings are required at the start of a non-capturing subpattern, the option letters may appear between the "?" and the ":". Thus the two patterns (?i:saturday|sunday) (?:(?i)saturday|sunday) match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match "SUNDAY" as well as "Saturday". DUPLICATE SUBPATTERN NUMBERS Perl 5.10 introduced a feature whereby each alternative in a subpattern uses the same numbers for its capturing parentheses. Such a subpattern starts with (?| and is itself a non-capturing subpattern. For example, consider this pattern: (?|(Sat)ur|(Sun))day Because the two alternatives are inside a (?| group, both sets of cap- turing parentheses are numbered one. Thus, when the pattern matches, you can look at captured substring number one, whichever alternative matched. This construct is useful when you want to capture part, but not all, of one of a number of alternatives. Inside a (?| group, paren- theses are numbered as usual, but the number is reset at the start of each branch. The numbers of any capturing parentheses that follow the subpattern start after the highest number used in any branch. The fol- lowing example is taken from the Perl documentation. The numbers under- neath show in which buffer the captured content will be stored. # before ---------------branch-reset----------- after / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x # 1 2 2 3 2 3 4 A back reference to a numbered subpattern uses the most recent value that is set for that number by any subpattern. The following pattern matches "abcabc" or "defdef": /(?|(abc)|(def))\1/ In contrast, a subroutine call to a numbered subpattern always refers to the first one in the pattern with the given number. The following pattern matches "abcabc" or "defabc": /(?|(abc)|(def))(?1)/ If a condition test for a subpattern's having matched refers to a non- unique number, the test is true if any of the subpatterns of that num- ber have matched. An alternative approach to using this "branch reset" feature is to use duplicate named subpatterns, as described in the next section. NAMED SUBPATTERNS Identifying capturing parentheses by number is simple, but it can be very hard to keep track of the numbers in complicated regular expres- sions. Furthermore, if an expression is modified, the numbers may change. To help with this difficulty, PCRE supports the naming of sub- patterns. This feature was not added to Perl until release 5.10. Python had the feature earlier, and PCRE introduced it at release 4.0, using the Python syntax. PCRE now supports both the Perl and the Python syn- tax. Perl allows identically numbered subpatterns to have different names, but PCRE does not. In PCRE, a subpattern can be named in one of three ways: (?...) or (?'name'...) as in Perl, or (?P...) as in Python. References to capturing parentheses from other parts of the pattern, such as back references, recursion, and conditions, can be made by name as well as by number. Names consist of up to 32 alphanumeric characters and underscores, but must start with a non-digit. Named capturing parentheses are still allocated numbers as well as names, exactly as if the names were not present. The PCRE API provides function calls for extracting the name- to-number translation table from a compiled pattern. There is also a convenience function for extracting a captured substring by name. By default, a name must be unique within a pattern, but it is possible to relax this constraint by setting the PCRE_DUPNAMES option at compile time. (Duplicate names are also always permitted for subpatterns with the same number, set up as described in the previous section.) Dupli- cate names can be useful for patterns where only one instance of the named parentheses can match. Suppose you want to match the name of a weekday, either as a 3-letter abbreviation or as the full name, and in both cases you want to extract the abbreviation. This pattern (ignoring the line breaks) does the job: (?Mon|Fri|Sun)(?:day)?| (?Tue)(?:sday)?| (?Wed)(?:nesday)?| (?Thu)(?:rsday)?| (?Sat)(?:urday)? There are five capturing substrings, but only one is ever set after a match. (An alternative way of solving this problem is to use a "branch reset" subpattern, as described in the previous section.) The convenience function for extracting the data by name returns the substring for the first (and in this example, the only) subpattern of that name that matched. This saves searching to find which numbered subpattern it was. If you make a back reference to a non-unique named subpattern from elsewhere in the pattern, the subpatterns to which the name refers are checked in the order in which they appear in the overall pattern. The first one that is set is used for the reference. For example, this pat- tern matches both "foofoo" and "barbar" but not "foobar" or "barfoo": (?:(?foo)|(?bar))\k If you make a subroutine call to a non-unique named subpattern, the one that corresponds to the first occurrence of the name is used. In the absence of duplicate numbers (see the previous section) this is the one with the lowest number. If you use a named reference in a condition test (see the section about conditions below), either to check whether a subpattern has matched, or to check for recursion, all subpatterns with the same name are tested. If the condition is true for any one of them, the overall condition is true. This is the same behaviour as testing by number. For further details of the interfaces for handling named subpatterns, see the pcreapi documentation. Warning: You cannot use different names to distinguish between two sub- patterns with the same number because PCRE uses only the numbers when matching. For this reason, an error is given at compile time if differ- ent names are given to subpatterns with the same number. However, you can always give the same name to subpatterns with the same number, even when PCRE_DUPNAMES is not set. REPETITION Repetition is specified by quantifiers, which can follow any of the following items: a literal data character the dot metacharacter the \C escape sequence the \X escape sequence the \R escape sequence an escape such as \d or \pL that matches a single character a character class a back reference (see next section) a parenthesized subpattern (including assertions) a subroutine call to a subpattern (recursive or otherwise) The general repetition quantifier specifies a minimum and maximum num- ber of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: z{2,4} matches "zz", "zzz", or "zzzz". A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus [aeiou]{3,} matches at least 3 successive vowels, but may match many more, while \d{8} matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For exam- ple, {,6} is not a quantifier, but a literal string of four characters. In UTF modes, quantifiers apply to characters rather than to individual data units. Thus, for example, \x{100}{2} matches two characters, each of which is represented by a two-byte sequence in a UTF-8 string. Simi- larly, \X{3} matches three Unicode extended grapheme clusters, each of which may be several data units long (and they may be of different lengths). The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. This may be use- ful for subpatterns that are referenced as subroutines from elsewhere in the pattern (but see also the section entitled "Defining subpatterns for use by reference only" below). Items other than subpatterns that have a {0} quantifier are omitted from the compiled pattern. For convenience, the three most common quantifiers have single-charac- ter abbreviations: * is equivalent to {0,} + is equivalent to {1,} ? is equivalent to {0,1} It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: (a?)* Earlier versions of Perl and PCRE used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly bro- ken. By default, the quantifiers are "greedy", that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between /* and */ and within the comment, individual * and / characters may appear. An attempt to match C comments by applying the pattern /\*.*\*/ to the string /* first comment */ not comment /* second comment */ fails, because it matches the entire string owing to the greediness of the .* item. However, if a quantifier is followed by a question mark, it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern /\*.*?\*/ does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in \d??\d which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches. If the PCRE_UNGREEDY option is set (an option that is not available in Perl), the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour. When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more memory is required for the compiled pattern, in proportion to the size of the minimum or maximum. If a pattern starts with .* or .{0,} and the PCRE_DOTALL option (equiv- alent to Perl's /s) is set, thus allowing the dot to match newlines, the pattern is implicitly anchored, because whatever follows will be tried against every character position in the subject string, so there is no point in retrying the overall match at any position after the first. PCRE normally treats such a pattern as though it were preceded by \A. In cases where it is known that the subject string contains no new- lines, it is worth setting PCRE_DOTALL in order to obtain this opti- mization, or alternatively using ^ to indicate anchoring explicitly. However, there are some cases where the optimization cannot be used. When .* is inside capturing parentheses that are the subject of a back reference elsewhere in the pattern, a match at the start may fail where a later one succeeds. Consider, for example: (.*)abc\1 If the subject is "xyz123abc123" the match point is the fourth charac- ter. For this reason, such a pattern is not implicitly anchored. Another case where implicit anchoring is not applied is when the lead- ing .* is inside an atomic group. Once again, a match at the start may fail where a later one succeeds. Consider this pattern: (?>.*?a)b It matches "ab" in the subject "aab". The use of the backtracking con- trol verbs (*PRUNE) and (*SKIP) also disable this optimization. When a capturing subpattern is repeated, the value captured is the sub- string that matched the final iteration. For example, after (tweedle[dume]{3}\s*)+ has matched "tweedledum tweedledee" the value of the captured substring is "tweedledee". However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous itera- tions. For example, after /(a|(b))+/ matches "aba" the value of the second captured substring is "b". ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy") repetition, failure of what follows normally causes the repeated item to be re-evaluated to see if a different number of repeats allows the rest of the pattern to match. Sometimes it is useful to prevent this, either to change the nature of the match, or to cause it fail earlier than it otherwise might, when the author of the pattern knows there is no point in carrying on. Consider, for example, the pattern \d+foo when applied to the subject line 123456bar After matching all 6 digits and then failing to match "foo", the normal action of the matcher is to try again with only 5 digits matching the \d+ item, and then with 4, and so on, before ultimately failing. "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides the means for specifying that once a subpattern has matched, it is not to be re-evaluated in this way. If we use atomic grouping for the previous example, the matcher gives up immediately on failing to match "foo" the first time. The notation is a kind of special parenthesis, starting with (?> as in this example: (?>\d+)foo This kind of parenthesis "locks up" the part of the pattern it con- tains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal. An alternative description is that a subpattern of this type matches the string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string. Atomic grouping subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both \d+ and \d+? are pre- pared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\d+) can only match an entire sequence of digits. Atomic groups in general can of course contain arbitrarily complicated subpatterns, and can be nested. However, when the subpattern for an atomic group is just a single repeated item, as in the example above, a simpler notation, called a "possessive quantifier" can be used. This consists of an additional + character following a quantifier. Using this notation, the previous example can be rewritten as \d++foo Note that a possessive quantifier can be used with an entire group, for example: (abc|xyz){2,3}+ Possessive quantifiers are always greedy; the setting of the PCRE_UNGREEDY option is ignored. They are a convenient notation for the simpler forms of atomic group. However, there is no difference in the meaning of a possessive quantifier and the equivalent atomic group, though there may be a performance difference; possessive quantifiers should be slightly faster. The possessive quantifier syntax is an extension to the Perl 5.8 syn- tax. Jeffrey Friedl originated the idea (and the name) in the first edition of his book. Mike McCloskey liked it, so implemented it when he built Sun's Java package, and PCRE copied it from there. It ultimately found its way into Perl at release 5.10. PCRE has an optimization that automatically "possessifies" certain sim- ple pattern constructs. For example, the sequence A+B is treated as A++B because there is no point in backtracking into a sequence of A's when B must follow. When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of an atomic group is the only way to avoid some failing matches taking a very long time indeed. The pattern (\D+|<\d+>)*[!?] matches an unlimited number of substrings that either consist of non- digits, or digits enclosed in <>, followed by either ! or ?. When it matches, it runs quickly. However, if it is applied to aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa it takes a long time before reporting failure. This is because the string can be divided between the internal \D+ repeat and the external * repeat in a large number of ways, and all have to be tried. (The example uses [!?] rather than a single character at the end, because both PCRE and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single charac- ter that is required for a match, and fail early if it is not present in the string.) If the pattern is changed so that it uses an atomic group, like this: ((?>\D+)|<\d+>)*[!?] sequences of non-digits cannot be broken, and failure happens quickly. BACK REFERENCES Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing sub- pattern earlier (that is, to its left) in the pattern, provided there have been that many previous capturing left parentheses. However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pat- tern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. A "forward back reference" of this type can make sense when a repetition is involved and the subpattern to the right has participated in an earlier itera- tion. It is not possible to have a numerical "forward back reference" to a subpattern whose number is 10 or more using this syntax because a sequence such as \50 is interpreted as a character defined in octal. See the subsection entitled "Non-printing characters" above for further details of the handling of digits following a backslash. There is no such problem when named parentheses are used. A back reference to any subpattern is possible using named parentheses (see below). Another way of avoiding the ambiguity inherent in the use of digits following a backslash is to use the \g escape sequence. This escape must be followed by an unsigned number or a negative number, optionally enclosed in braces. These examples are all identical: (ring), \1 (ring), \g1 (ring), \g{1} An unsigned number specifies an absolute reference without the ambigu- ity that is present in the older syntax. It is also useful when literal digits follow the reference. A negative number is a relative reference. Consider this example: (abc(def)ghi)\g{-1} The sequence \g{-1} is a reference to the most recently started captur- ing subpattern before \g, that is, is it equivalent to \2 in this exam- ple. Similarly, \g{-2} would be equivalent to \1. The use of relative references can be helpful in long patterns, and also in patterns that are created by joining together fragments that contain references within themselves. A back reference matches whatever actually matched the capturing sub- pattern in the current subject string, rather than anything matching the subpattern itself (see "Subpatterns as subroutines" below for a way of doing that). So the pattern (sens|respons)e and \1ibility matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If caseful matching is in force at the time of the back reference, the case of letters is relevant. For exam- ple, ((?i)rah)\s+\1 matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original capturing subpattern is matched caselessly. There are several different ways of writing back references to named subpatterns. The .NET syntax \k{name} and the Perl syntax \k or \k'name' are supported, as is the Python syntax (?P=name). Perl 5.10's unified back reference syntax, in which \g can be used for both numeric and named references, is also supported. We could rewrite the above example in any of the following ways: (?(?i)rah)\s+\k (?'p1'(?i)rah)\s+\k{p1} (?P(?i)rah)\s+(?P=p1) (?(?i)rah)\s+\g{p1} A subpattern that is referenced by name may appear in the pattern before or after the reference. There may be more than one back reference to the same subpattern. If a subpattern has not actually been used in a particular match, any back references to it always fail by default. For example, the pattern (a|(bc))\2 always fails if it starts to match "a" rather than "bc". However, if the PCRE_JAVASCRIPT_COMPAT option is set at compile time, a back refer- ence to an unset value matches an empty string. Because there may be many capturing parentheses in a pattern, all dig- its following a backslash are taken as part of a potential back refer- ence number. If the pattern continues with a digit character, some delimiter must be used to terminate the back reference. If the PCRE_EXTENDED option is set, this can be white space. Otherwise, the \g{ syntax or an empty comment (see "Comments" below) can be used. Recursive back references A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, (a\1) never matches. However, such references can be useful inside repeated sub- patterns. For example, the pattern (a|b\1)+ matches any number of "a"s and also "aba", "ababbaa" etc. At each iter- ation of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero. Back references of this type cause the group that they reference to be treated as an atomic group. Once the whole group has been matched, a subsequent matching failure cannot cause backtracking into the middle of the group. ASSERTIONS An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are described above. More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it. An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed. Assertion subpatterns are not capturing subpatterns. If such an asser- tion contains capturing subpatterns within it, these are counted for the purposes of numbering the capturing subpatterns in the whole pat- tern. However, substring capturing is carried out only for positive assertions. (Perl sometimes, but not always, does do capturing in nega- tive assertions.) WARNING: If a positive assertion containing one or more capturing sub- patterns succeeds, but failure to match later in the pattern causes backtracking over this assertion, the captures within the assertion are reset only if no higher numbered captures are already set. This is, unfortunately, a fundamental limitation of the current implementation, and as PCRE1 is now in maintenance-only status, it is unlikely ever to change. For compatibility with Perl, assertion subpatterns may be repeated; though it makes no sense to assert the same thing several times, the side effect of capturing parentheses may occasionally be useful. In practice, there only three cases: (1) If the quantifier is {0}, the assertion is never obeyed during matching. However, it may contain internal capturing parenthesized groups that are called from elsewhere via the subroutine mechanism. (2) If quantifier is {0,n} where n is greater than zero, it is treated as if it were {0,1}. At run time, the rest of the pattern match is tried with and without the assertion, the order depending on the greed- iness of the quantifier. (3) If the minimum repetition is greater than zero, the quantifier is ignored. The assertion is obeyed just once when encountered during matching. Lookahead assertions Lookahead assertions start with (?= for positive assertions and (?! for negative assertions. For example, \w+(?=;) matches a word followed by a semicolon, but does not include the semi- colon in the match, and foo(?!bar) matches any occurrence of "foo" that is not followed by "bar". Note that the apparently similar pattern (?!foo)bar does not find an occurrence of "bar" that is preceded by something other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always true when the next three characters are "bar". A lookbehind assertion is needed to achieve the other effect. If you want to force a matching failure at some point in a pattern, the most convenient way to do it is with (?!) because an empty string always matches, so an assertion that requires there not to be an empty string must always fail. The backtracking control verb (*FAIL) or (*F) is a synonym for (?!). Lookbehind assertions Lookbehind assertions start with (?<= for positive assertions and (?)...) or (?('name')...) to test for a used subpattern by name. For compatibility with earlier versions of PCRE, which had this facility before Perl, the syntax (?(name)...) is also recognized. Rewriting the above example to use a named subpattern gives this: (? \( )? [^()]+ (?() \) ) If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them has matched. Checking for pattern recursion If the condition is the string (R), and there is no subpattern with the name R, the condition is true if a recursive call to the whole pattern or any subpattern has been made. If digits or a name preceded by amper- sand follow the letter R, for example: (?(R3)...) or (?(R&name)...) the condition is true if the most recent recursion is into a subpattern whose number or name is given. This condition does not check the entire recursion stack. If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them is the most recent recursion. At "top level", all these recursion test conditions are false. The syntax for recursive patterns is described below. Defining subpatterns for use by reference only If the condition is the string (DEFINE), and there is no subpattern with the name DEFINE, the condition is always false. In this case, there may be only one alternative in the subpattern. It is always skipped if control reaches this point in the pattern; the idea of DEFINE is that it can be used to define subroutines that can be refer- enced from elsewhere. (The use of subroutines is described below.) For example, a pattern to match an IPv4 address such as "192.168.23.245" could be written like this (ignore white space and line breaks): (?(DEFINE) (? 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) ) \b (?&byte) (\.(?&byte)){3} \b The first part of the pattern is a DEFINE group inside which a another group named "byte" is defined. This matches an individual component of an IPv4 address (a number less than 256). When matching takes place, this part of the pattern is skipped because DEFINE acts like a false condition. The rest of the pattern uses references to the named group to match the four dot-separated components of an IPv4 address, insist- ing on a word boundary at each end. Assertion conditions If the condition is not in any of the above formats, it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line: (?(?=[^a-z]*[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) The condition is a positive lookahead assertion that matches an optional sequence of non-letters followed by a letter. In other words, it tests for the presence of at least one letter in the subject. If a letter is found, the subject is matched against the first alternative; otherwise it is matched against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits. COMMENTS There are two ways of including comments in patterns that are processed by PCRE. In both cases, the start of the comment must not be in a char- acter class, nor in the middle of any other sequence of related charac- ters such as (?: or a subpattern name or number. The characters that make up a comment play no part in the pattern matching. The sequence (?# marks the start of a comment that continues up to the next closing parenthesis. Nested parentheses are not permitted. If the PCRE_EXTENDED option is set, an unescaped # character also introduces a comment, which in this case continues to immediately after the next newline character or character sequence in the pattern. Which charac- ters are interpreted as newlines is controlled by the options passed to a compiling function or by a special sequence at the start of the pat- tern, as described in the section entitled "Newline conventions" above. Note that the end of this type of comment is a literal newline sequence in the pattern; escape sequences that happen to represent a newline do not count. For example, consider this pattern when PCRE_EXTENDED is set, and the default newline convention is in force: abc #comment \n still comment On encountering the # character, pcre_compile() skips along, looking for a newline in the pattern. The sequence \n is still literal at this stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so. RECURSIVE PATTERNS Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. For some time, Perl has provided a facility that allows regular expres- sions to recurse (amongst other things). It does this by interpolating Perl code in the expression at run time, and the code can refer to the expression itself. A Perl pattern using code interpolation to solve the parentheses problem can be created like this: $re = qr{\( (?: (?>[^()]+) | (?p{$re}) )* \)}x; The (?p{...}) item interpolates Perl code at run time, and in this case refers recursively to the pattern in which it appears. Obviously, PCRE cannot support the interpolation of Perl code. Instead, it supports special syntax for recursion of the entire pattern, and also for individual subpattern recursion. After its introduction in PCRE and Python, this kind of recursion was subsequently introduced into Perl at release 5.10. A special item that consists of (? followed by a number greater than zero and a closing parenthesis is a recursive subroutine call of the subpattern of the given number, provided that it occurs inside that subpattern. (If not, it is a non-recursive subroutine call, which is described in the next section.) The special item (?R) or (?0) is a recursive call of the entire regular expression. This PCRE pattern solves the nested parentheses problem (assume the PCRE_EXTENDED option is set so that white space is ignored): \( ( [^()]++ | (?R) )* \) First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (that is, a correctly parenthe- sized substring). Finally there is a closing parenthesis. Note the use of a possessive quantifier to avoid backtracking into sequences of non- parentheses. If this were part of a larger pattern, you would not want to recurse the entire pattern, so instead you could use this: ( \( ( [^()]++ | (?1) )* \) ) We have put the pattern into parentheses, and caused the recursion to refer to them instead of the whole pattern. In a larger pattern, keeping track of parenthesis numbers can be tricky. This is made easier by the use of relative references. Instead of (?1) in the pattern above you can write (?-2) to refer to the second most recently opened parentheses preceding the recursion. In other words, a negative number counts capturing parentheses leftwards from the point at which it is encountered. It is also possible to refer to subsequently opened parentheses, by writing references such as (?+2). However, these cannot be recursive because the reference is not inside the parentheses that are refer- enced. They are always non-recursive subroutine calls, as described in the next section. An alternative approach is to use named parentheses instead. The Perl syntax for this is (?&name); PCRE's earlier syntax (?P>name) is also supported. We could rewrite the above example as follows: (? \( ( [^()]++ | (?&pn) )* \) ) If there is more than one subpattern with the same name, the earliest one is used. This particular example pattern that we have been looking at contains nested unlimited repeats, and so the use of a possessive quantifier for matching strings of non-parentheses is important when applying the pat- tern to strings that do not match. For example, when this pattern is applied to (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() it yields "no match" quickly. However, if a possessive quantifier is not used, the match runs for a very long time indeed because there are so many different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported. At the end of a match, the values of capturing parentheses are those from the outermost level. If you want to obtain intermediate values, a callout function can be used (see below and the pcrecallout documenta- tion). If the pattern above is matched against (ab(cd)ef) the value for the inner capturing parentheses (numbered 2) is "ef", which is the last value taken on at the top level. If a capturing sub- pattern is not matched at the top level, its final captured value is unset, even if it was (temporarily) set at a deeper level during the matching process. If there are more than 15 capturing parentheses in a pattern, PCRE has to obtain extra memory to store data during a recursion, which it does by using pcre_malloc, freeing it via pcre_free afterwards. If no memory can be obtained, the match fails with the PCRE_ERROR_NOMEMORY error. Do not confuse the (?R) item with the condition (R), which tests for recursion. Consider this pattern, which matches text in angle brack- ets, allowing for arbitrary nesting. Only digits are allowed in nested brackets (that is, when recursing), whereas any characters are permit- ted at the outer level. < (?: (?(R) \d++ | [^<>]*+) | (?R)) * > In this pattern, (?(R) is the start of a conditional subpattern, with two different alternatives for the recursive and non-recursive cases. The (?R) item is the actual recursive call. Differences in recursion processing between PCRE and Perl Recursion processing in PCRE differs from Perl in two important ways. In PCRE (like Python, but unlike Perl), a recursive subpattern call is always treated as an atomic group. That is, once it has matched some of the subject string, it is never re-entered, even if it contains untried alternatives and there is a subsequent matching failure. This can be illustrated by the following pattern, which purports to match a palin- dromic string that contains an odd number of characters (for example, "a", "aba", "abcba", "abcdcba"): ^(.|(.)(?1)\2)$ The idea is that it either matches a single character, or two identical characters surrounding a sub-palindrome. In Perl, this pattern works; in PCRE it does not if the pattern is longer than three characters. Consider the subject string "abcba": At the top level, the first character is matched, but as it is not at the end of the string, the first alternative fails; the second alterna- tive is taken and the recursion kicks in. The recursive call to subpat- tern 1 successfully matches the next character ("b"). (Note that the beginning and end of line tests are not part of the recursion). Back at the top level, the next character ("c") is compared with what subpattern 2 matched, which was "a". This fails. Because the recursion is treated as an atomic group, there are now no backtracking points, and so the entire match fails. (Perl is able, at this point, to re- enter the recursion and try the second alternative.) However, if the pattern is written with the alternatives in the other order, things are different: ^((.)(?1)\2|.)$ This time, the recursing alternative is tried first, and continues to recurse until it runs out of characters, at which point the recursion fails. But this time we do have another alternative to try at the higher level. That is the big difference: in the previous case the remaining alternative is at a deeper recursion level, which PCRE cannot use. To change the pattern so that it matches all palindromic strings, not just those with an odd number of characters, it is tempting to change the pattern to this: ^((.)(?1)\2|.?)$ Again, this works in Perl, but not in PCRE, and for the same reason. When a deeper recursion has matched a single character, it cannot be entered again in order to match an empty string. The solution is to separate the two cases, and write out the odd and even cases as alter- natives at the higher level: ^(?:((.)(?1)\2|)|((.)(?3)\4|.)) If you want to match typical palindromic phrases, the pattern has to ignore all non-word characters, which can be done like this: ^\W*+(?:((.)\W*+(?1)\W*+\2|)|((.)\W*+(?3)\W*+\4|\W*+.\W*+))\W*+$ If run with the PCRE_CASELESS option, this pattern matches phrases such as "A man, a plan, a canal: Panama!" and it works well in both PCRE and Perl. Note the use of the possessive quantifier *+ to avoid backtrack- ing into sequences of non-word characters. Without this, PCRE takes a great deal longer (ten times or more) to match typical phrases, and Perl takes so long that you think it has gone into a loop. WARNING: The palindrome-matching patterns above work only if the sub- ject string does not start with a palindrome that is shorter than the entire string. For example, although "abcba" is correctly matched, if the subject is "ababa", PCRE finds the palindrome "aba" at the start, then fails at top level because the end of the string does not follow. Once again, it cannot jump back into the recursion to try other alter- natives, so the entire match fails. The second way in which PCRE and Perl differ in their recursion pro- cessing is in the handling of captured values. In Perl, when a subpat- tern is called recursively or as a subpattern (see the next section), it has no access to any values that were captured outside the recur- sion, whereas in PCRE these values can be referenced. Consider this pattern: ^(.)(\1|a(?2)) In PCRE, this pattern matches "bab". The first capturing parentheses match "b", then in the second group, when the back reference \1 fails to match "b", the second alternative matches "a" and then recurses. In the recursion, \1 does now match "b" and so the whole match succeeds. In Perl, the pattern fails to match because inside the recursive call \1 cannot access the externally set value. SUBPATTERNS AS SUBROUTINES If the syntax for a recursive subpattern call (either by number or by name) is used outside the parentheses to which it refers, it operates like a subroutine in a programming language. The called subpattern may be defined before or after the reference. A numbered reference can be absolute or relative, as in these examples: (...(absolute)...)...(?2)... (...(relative)...)...(?-1)... (...(?+1)...(relative)... An earlier example pointed out that the pattern (sens|respons)e and \1ibility matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If instead the pattern (sens|respons)e and (?1)ibility is used, it does match "sense and responsibility" as well as the other two strings. Another example is given in the discussion of DEFINE above. All subroutine calls, whether recursive or not, are always treated as atomic groups. That is, once a subroutine has matched some of the sub- ject string, it is never re-entered, even if it contains untried alter- natives and there is a subsequent matching failure. Any capturing parentheses that are set during the subroutine call revert to their previous values afterwards. Processing options such as case-independence are fixed when a subpat- tern is defined, so if it is used as a subroutine, such options cannot be changed for different calls. For example, consider this pattern: (abc)(?i:(?-1)) It matches "abcabc". It does not match "abcABC" because the change of processing option does not affect the called subpattern. ONIGURUMA SUBROUTINE SYNTAX For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative syntax for referencing a subpattern as a subroutine, possibly recursively. Here are two of the examples used above, rewrit- ten using this syntax: (? \( ( (?>[^()]+) | \g )* \) ) (sens|respons)e and \g'1'ibility PCRE supports an extension to Oniguruma: if a number is preceded by a plus or a minus sign it is taken as a relative reference. For example: (abc)(?i:\g<-1>) Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not synonymous. The former is a back reference; the latter is a subroutine call. CALLOUTS Perl has a feature whereby using the sequence (?{...}) causes arbitrary Perl code to be obeyed in the middle of matching a regular expression. This makes it possible, amongst other things, to extract different sub- strings that match the same pair of parentheses when there is a repeti- tion. PCRE provides a similar feature, but of course it cannot obey arbitrary Perl code. The feature is called "callout". The caller of PCRE provides an external function by putting its entry point in the global variable pcre_callout (8-bit library) or pcre[16|32]_callout (16-bit or 32-bit library). By default, this variable contains NULL, which disables all calling out. Within a regular expression, (?C) indicates the points at which the external function is to be called. If you want to identify different callout points, you can put a number less than 256 after the letter C. The default value is zero. For example, this pattern has two callout points: (?C1)abc(?C2)def If the PCRE_AUTO_CALLOUT flag is passed to a compiling function, call- outs are automatically installed before each item in the pattern. They are all numbered 255. If there is a conditional group in the pattern whose condition is an assertion, an additional callout is inserted just before the condition. An explicit callout may also be set at this posi- tion, as in this example: (?(?C9)(?=a)abc|def) Note that this applies only to assertion conditions, not to other types of condition. During matching, when PCRE reaches a callout point, the external func- tion is called. It is provided with the number of the callout, the position in the pattern, and, optionally, one item of data originally supplied by the caller of the matching function. The callout function may cause matching to proceed, to backtrack, or to fail altogether. By default, PCRE implements a number of optimizations at compile time and matching time, and one side-effect is that sometimes callouts are skipped. If you need all possible callouts to happen, you need to set options that disable the relevant optimizations. More details, and a complete description of the interface to the callout function, are given in the pcrecallout documentation. BACKTRACKING CONTROL Perl 5.10 introduced a number of "Special Backtracking Control Verbs", which are still described in the Perl documentation as "experimental and subject to change or removal in a future version of Perl". It goes on to say: "Their usage in production code should be noted to avoid problems during upgrades." The same remarks apply to the PCRE features described in this section. The new verbs make use of what was previously invalid syntax: an open- ing parenthesis followed by an asterisk. They are generally of the form (*VERB) or (*VERB:NAME). Some may take either form, possibly behaving differently depending on whether or not a name is present. A name is any sequence of characters that does not include a closing parenthesis. The maximum length of name is 255 in the 8-bit library and 65535 in the 16-bit and 32-bit libraries. If the name is empty, that is, if the closing parenthesis immediately follows the colon, the effect is as if the colon were not there. Any number of these verbs may occur in a pattern. Since these verbs are specifically related to backtracking, most of them can be used only when the pattern is to be matched using one of the traditional matching functions, because these use a backtracking algorithm. With the exception of (*FAIL), which behaves like a failing negative assertion, the backtracking control verbs cause an error if encountered by a DFA matching function. The behaviour of these verbs in repeated groups, assertions, and in subpatterns called as subroutines (whether or not recursively) is docu- mented below. Optimizations that affect backtracking verbs PCRE contains some optimizations that are used to speed up matching by running some checks at the start of each match attempt. For example, it may know the minimum length of matching subject, or that a particular character must be present. When one of these optimizations bypasses the running of a match, any included backtracking verbs will not, of course, be processed. You can suppress the start-of-match optimizations by setting the PCRE_NO_START_OPTIMIZE option when calling pcre_com- pile() or pcre_exec(), or by starting the pattern with (*NO_START_OPT). There is more discussion of this option in the section entitled "Option bits for pcre_exec()" in the pcreapi documentation. Experiments with Perl suggest that it too has similar optimizations, sometimes leading to anomalous results. Verbs that act immediately The following verbs act as soon as they are encountered. They may not be followed by a name. (*ACCEPT) This verb causes the match to end successfully, skipping the remainder of the pattern. However, when it is inside a subpattern that is called as a subroutine, only that subpattern is ended successfully. Matching then continues at the outer level. If (*ACCEPT) in triggered in a posi- tive assertion, the assertion succeeds; in a negative assertion, the assertion fails. If (*ACCEPT) is inside capturing parentheses, the data so far is cap- tured. For example: A((?:A|B(*ACCEPT)|C)D) This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is cap- tured by the outer parentheses. (*FAIL) or (*F) This verb causes a matching failure, forcing backtracking to occur. It is equivalent to (?!) but easier to read. The Perl documentation notes that it is probably useful only when combined with (?{}) or (??{}). Those are, of course, Perl features that are not present in PCRE. The nearest equivalent is the callout feature, as for example in this pat- tern: a+(?C)(*FAIL) A match with the string "aaaa" always fails, but the callout is taken before each backtrack happens (in this example, 10 times). Recording which path was taken There is one verb whose main purpose is to track how a match was arrived at, though it also has a secondary use in conjunction with advancing the match starting point (see (*SKIP) below). (*MARK:NAME) or (*:NAME) A name is always required with this verb. There may be as many instances of (*MARK) as you like in a pattern, and their names do not have to be unique. When a match succeeds, the name of the last-encountered (*MARK:NAME), (*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to the caller as described in the section entitled "Extra data for pcre_exec()" in the pcreapi documentation. Here is an example of pcretest output, where the /K modifier requests the retrieval and out- putting of (*MARK) data: re> /X(*MARK:A)Y|X(*MARK:B)Z/K data> XY 0: XY MK: A XZ 0: XZ MK: B The (*MARK) name is tagged with "MK:" in this output, and in this exam- ple it indicates which of the two alternatives matched. This is a more efficient way of obtaining this information than putting each alterna- tive in its own capturing parentheses. If a verb with a name is encountered in a positive assertion that is true, the name is recorded and passed back if it is the last-encoun- tered. This does not happen for negative assertions or failing positive assertions. After a partial match or a failed match, the last encountered name in the entire match process is returned. For example: re> /X(*MARK:A)Y|X(*MARK:B)Z/K data> XP No match, mark = B Note that in this unanchored example the mark is retained from the match attempt that started at the letter "X" in the subject. Subsequent match attempts starting at "P" and then with an empty string do not get as far as the (*MARK) item, but nevertheless do not reset it. If you are interested in (*MARK) values after failed matches, you should probably set the PCRE_NO_START_OPTIMIZE option (see above) to ensure that the match is always attempted. Verbs that act after backtracking The following verbs do nothing when they are encountered. Matching con- tinues with what follows, but if there is no subsequent match, causing a backtrack to the verb, a failure is forced. That is, backtracking cannot pass to the left of the verb. However, when one of these verbs appears inside an atomic group or an assertion that is true, its effect is confined to that group, because once the group has been matched, there is never any backtracking into it. In this situation, backtrack- ing can "jump back" to the left of the entire atomic group or asser- tion. (Remember also, as stated above, that this localization also applies in subroutine calls.) These verbs differ in exactly what kind of failure occurs when back- tracking reaches them. The behaviour described below is what happens when the verb is not in a subroutine or an assertion. Subsequent sec- tions cover these special cases. (*COMMIT) This verb, which may not be followed by a name, causes the whole match to fail outright if there is a later matching failure that causes back- tracking to reach it. Even if the pattern is unanchored, no further attempts to find a match by advancing the starting point take place. If (*COMMIT) is the only backtracking verb that is encountered, once it has been passed pcre_exec() is committed to finding a match at the cur- rent starting point, or not at all. For example: a+(*COMMIT)b This matches "xxaab" but not "aacaab". It can be thought of as a kind of dynamic anchor, or "I've started, so I must finish." The name of the most recently passed (*MARK) in the path is passed back when (*COMMIT) forces a match failure. If there is more than one backtracking verb in a pattern, a different one that follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a match does not always guarantee that a match must be at this starting point. Note that (*COMMIT) at the start of a pattern is not the same as an anchor, unless PCRE's start-of-match optimizations are turned off, as shown in this output from pcretest: re> /(*COMMIT)abc/ data> xyzabc 0: abc data> xyzabc\Y No match For this pattern, PCRE knows that any match must start with "a", so the optimization skips along the subject to "a" before applying the pattern to the first set of data. The match attempt then succeeds. In the sec- ond set of data, the escape sequence \Y is interpreted by the pcretest program. It causes the PCRE_NO_START_OPTIMIZE option to be set when pcre_exec() is called. This disables the optimization that skips along to the first character. The pattern is now applied starting at "x", and so the (*COMMIT) causes the match to fail without trying any other starting points. (*PRUNE) or (*PRUNE:NAME) This verb causes the match to fail at the current starting position in the subject if there is a later matching failure that causes backtrack- ing to reach it. If the pattern is unanchored, the normal "bumpalong" advance to the next starting character then happens. Backtracking can occur as usual to the left of (*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but if there is no match to the right, backtracking cannot cross (*PRUNE). In simple cases, the use of (*PRUNE) is just an alternative to an atomic group or possessive quan- tifier, but there are some uses of (*PRUNE) that cannot be expressed in any other way. In an anchored pattern (*PRUNE) has the same effect as (*COMMIT). The behaviour of (*PRUNE:NAME) is the not the same as (*MARK:NAME)(*PRUNE). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK). (*SKIP) This verb, when given without a name, is like (*PRUNE), except that if the pattern is unanchored, the "bumpalong" advance is not to the next character, but to the position in the subject where (*SKIP) was encoun- tered. (*SKIP) signifies that whatever text was matched leading up to it cannot be part of a successful match. Consider: a+(*SKIP)b If the subject is "aaaac...", after the first match attempt fails (starting at the first character in the string), the starting point skips on to start the next attempt at "c". Note that a possessive quan- tifer does not have the same effect as this example; although it would suppress backtracking during the first match attempt, the second attempt would start at the second character instead of skipping on to "c". (*SKIP:NAME) When (*SKIP) has an associated name, its behaviour is modified. When it is triggered, the previous path through the pattern is searched for the most recent (*MARK) that has the same name. If one is found, the "bumpalong" advance is to the subject position that corresponds to that (*MARK) instead of to where (*SKIP) was encountered. If no (*MARK) with a matching name is found, the (*SKIP) is ignored. Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores names that are set by (*PRUNE:NAME) or (*THEN:NAME). (*THEN) or (*THEN:NAME) This verb causes a skip to the next innermost alternative when back- tracking reaches it. That is, it cancels any further backtracking within the current alternative. Its name comes from the observation that it can be used for a pattern-based if-then-else block: ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ... If the COND1 pattern matches, FOO is tried (and possibly further items after the end of the group if FOO succeeds); on failure, the matcher skips to the second alternative and tries COND2, without backtracking into COND1. If that succeeds and BAR fails, COND3 is tried. If subse- quently BAZ fails, there are no more alternatives, so there is a back- track to whatever came before the entire group. If (*THEN) is not inside an alternation, it acts like (*PRUNE). The behaviour of (*THEN:NAME) is the not the same as (*MARK:NAME)(*THEN). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK). A subpattern that does not contain a | character is just a part of the enclosing alternative; it is not a nested alternation with only one alternative. The effect of (*THEN) extends beyond such a subpattern to the enclosing alternative. Consider this pattern, where A, B, etc. are complex pattern fragments that do not contain any | characters at this level: A (B(*THEN)C) | D If A and B are matched, but there is a failure in C, matching does not backtrack into A; instead it moves to the next alternative, that is, D. However, if the subpattern containing (*THEN) is given an alternative, it behaves differently: A (B(*THEN)C | (*FAIL)) | D The effect of (*THEN) is now confined to the inner subpattern. After a failure in C, matching moves to (*FAIL), which causes the whole subpat- tern to fail because there are no more alternatives to try. In this case, matching does now backtrack into A. Note that a conditional subpattern is not considered as having two alternatives, because only one is ever used. In other words, the | character in a conditional subpattern has a different meaning. Ignoring white space, consider: ^.*? (?(?=a) a | b(*THEN)c ) If the subject is "ba", this pattern does not match. Because .*? is ungreedy, it initially matches zero characters. The condition (?=a) then fails, the character "b" is matched, but "c" is not. At this point, matching does not backtrack to .*? as might perhaps be expected from the presence of the | character. The conditional subpattern is part of the single alternative that comprises the whole pattern, and so the match fails. (If there was a backtrack into .*?, allowing it to match "b", the match would succeed.) The verbs just described provide four different "strengths" of control when subsequent matching fails. (*THEN) is the weakest, carrying on the match at the next alternative. (*PRUNE) comes next, failing the match at the current starting position, but allowing an advance to the next character (for an unanchored pattern). (*SKIP) is similar, except that the advance may be more than one character. (*COMMIT) is the strongest, causing the entire match to fail. More than one backtracking verb If more than one backtracking verb is present in a pattern, the one that is backtracked onto first acts. For example, consider this pat- tern, where A, B, etc. are complex pattern fragments: (A(*COMMIT)B(*THEN)C|ABD) If A matches but B fails, the backtrack to (*COMMIT) causes the entire match to fail. However, if A and B match, but C fails, the backtrack to (*THEN) causes the next alternative (ABD) to be tried. This behaviour is consistent, but is not always the same as Perl's. It means that if two or more backtracking verbs appear in succession, all the the last of them has no effect. Consider this example: ...(*COMMIT)(*PRUNE)... If there is a matching failure to the right, backtracking onto (*PRUNE) causes it to be triggered, and its action is taken. There can never be a backtrack onto (*COMMIT). Backtracking verbs in repeated groups PCRE differs from Perl in its handling of backtracking verbs in repeated groups. For example, consider: /(a(*COMMIT)b)+ac/ If the subject is "abac", Perl matches, but PCRE fails because the (*COMMIT) in the second repeat of the group acts. Backtracking verbs in assertions (*FAIL) in an assertion has its normal effect: it forces an immediate backtrack. (*ACCEPT) in a positive assertion causes the assertion to succeed with- out any further processing. In a negative assertion, (*ACCEPT) causes the assertion to fail without any further processing. The other backtracking verbs are not treated specially if they appear in a positive assertion. In particular, (*THEN) skips to the next alternative in the innermost enclosing group that has alternations, whether or not this is within the assertion. Negative assertions are, however, different, in order to ensure that changing a positive assertion into a negative assertion changes its result. Backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes a neg- ative assertion to be true, without considering any further alternative branches in the assertion. Backtracking into (*THEN) causes it to skip to the next enclosing alternative within the assertion (the normal be- haviour), but if the assertion does not have such an alternative, (*THEN) behaves like (*PRUNE). Backtracking verbs in subroutines These behaviours occur whether or not the subpattern is called recur- sively. Perl's treatment of subroutines is different in some cases. (*FAIL) in a subpattern called as a subroutine has its normal effect: it forces an immediate backtrack. (*ACCEPT) in a subpattern called as a subroutine causes the subroutine match to succeed without any further processing. Matching then contin- ues after the subroutine call. (*COMMIT), (*SKIP), and (*PRUNE) in a subpattern called as a subroutine cause the subroutine match to fail. (*THEN) skips to the next alternative in the innermost enclosing group within the subpattern that has alternatives. If there is no such group within the subpattern, (*THEN) causes the subroutine match to fail. SEE ALSO pcreapi(3), pcrecallout(3), pcrematching(3), pcresyntax(3), pcre(3), pcre16(3), pcre32(3). AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 23 October 2016 Copyright (c) 1997-2016 University of Cambridge. ------------------------------------------------------------------------------ PCRESYNTAX(3) Library Functions Manual PCRESYNTAX(3) NAME PCRE - Perl-compatible regular expressions PCRE REGULAR EXPRESSION SYNTAX SUMMARY The full syntax and semantics of the regular expressions that are sup- ported by PCRE are described in the pcrepattern documentation. This document contains a quick-reference summary of the syntax. QUOTING \x where x is non-alphanumeric is a literal x \Q...\E treat enclosed characters as literal CHARACTERS \a alarm, that is, the BEL character (hex 07) \cx "control-x", where x is any ASCII character \e escape (hex 1B) \f form feed (hex 0C) \n newline (hex 0A) \r carriage return (hex 0D) \t tab (hex 09) \0dd character with octal code 0dd \ddd character with octal code ddd, or backreference \o{ddd..} character with octal code ddd.. \xhh character with hex code hh \x{hhh..} character with hex code hhh.. Note that \0dd is always an octal code, and that \8 and \9 are the lit- eral characters "8" and "9". CHARACTER TYPES . any character except newline; in dotall mode, any character whatsoever \C one data unit, even in UTF mode (best avoided) \d a decimal digit \D a character that is not a decimal digit \h a horizontal white space character \H a character that is not a horizontal white space character \N a character that is not a newline \p{xx} a character with the xx property \P{xx} a character without the xx property \R a newline sequence \s a white space character \S a character that is not a white space character \v a vertical white space character \V a character that is not a vertical white space character \w a "word" character \W a "non-word" character \X a Unicode extended grapheme cluster By default, \d, \s, and \w match only ASCII characters, even in UTF-8 mode or in the 16- bit and 32-bit libraries. However, if locale-spe- cific matching is happening, \s and \w may also match characters with code points in the range 128-255. If the PCRE_UCP option is set, the behaviour of these escape sequences is changed to use Unicode proper- ties and they match many more characters. GENERAL CATEGORY PROPERTIES FOR \p and \P C Other Cc Control Cf Format Cn Unassigned Co Private use Cs Surrogate L Letter Ll Lower case letter Lm Modifier letter Lo Other letter Lt Title case letter Lu Upper case letter L& Ll, Lu, or Lt M Mark Mc Spacing mark Me Enclosing mark Mn Non-spacing mark N Number Nd Decimal number Nl Letter number No Other number P Punctuation Pc Connector punctuation Pd Dash punctuation Pe Close punctuation Pf Final punctuation Pi Initial punctuation Po Other punctuation Ps Open punctuation S Symbol Sc Currency symbol Sk Modifier symbol Sm Mathematical symbol So Other symbol Z Separator Zl Line separator Zp Paragraph separator Zs Space separator PCRE SPECIAL CATEGORY PROPERTIES FOR \p and \P Xan Alphanumeric: union of properties L and N Xps POSIX space: property Z or tab, NL, VT, FF, CR Xsp Perl space: property Z or tab, NL, VT, FF, CR Xuc Univerally-named character: one that can be represented by a Universal Character Name Xwd Perl word: property Xan or underscore Perl and POSIX space are now the same. Perl added VT to its space char- acter set at release 5.18 and PCRE changed at release 8.34. SCRIPT NAMES FOR \p AND \P Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Car- ian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cunei- form, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hiero- glyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip- tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin- ear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha- vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi. CHARACTER CLASSES [...] positive character class [^...] negative character class [x-y] range (can be used for hex characters) [[:xxx:]] positive POSIX named set [[:^xxx:]] negative POSIX named set alnum alphanumeric alpha alphabetic ascii 0-127 blank space or tab cntrl control character digit decimal digit graph printing, excluding space lower lower case letter print printing, including space punct printing, excluding alphanumeric space white space upper upper case letter word same as \w xdigit hexadecimal digit In PCRE, POSIX character set names recognize only ASCII characters by default, but some of them use Unicode properties if PCRE_UCP is set. You can use \Q...\E inside a character class. QUANTIFIERS ? 0 or 1, greedy ?+ 0 or 1, possessive ?? 0 or 1, lazy * 0 or more, greedy *+ 0 or more, possessive *? 0 or more, lazy + 1 or more, greedy ++ 1 or more, possessive +? 1 or more, lazy {n} exactly n {n,m} at least n, no more than m, greedy {n,m}+ at least n, no more than m, possessive {n,m}? at least n, no more than m, lazy {n,} n or more, greedy {n,}+ n or more, possessive {n,}? n or more, lazy ANCHORS AND SIMPLE ASSERTIONS \b word boundary \B not a word boundary ^ start of subject also after internal newline in multiline mode \A start of subject $ end of subject also before newline at end of subject also before internal newline in multiline mode \Z end of subject also before newline at end of subject \z end of subject \G first matching position in subject MATCH POINT RESET \K reset start of match \K is honoured in positive assertions, but ignored in negative ones. ALTERNATION expr|expr|expr... CAPTURING (...) capturing group (?...) named capturing group (Perl) (?'name'...) named capturing group (Perl) (?P...) named capturing group (Python) (?:...) non-capturing group (?|...) non-capturing group; reset group numbers for capturing groups in each alternative ATOMIC GROUPS (?>...) atomic, non-capturing group COMMENT (?#....) comment (not nestable) OPTION SETTING (?i) caseless (?J) allow duplicate names (?m) multiline (?s) single line (dotall) (?U) default ungreedy (lazy) (?x) extended (ignore white space) (?-...) unset option(s) The following are recognized only at the very start of a pattern or after one of the newline or \R options with similar syntax. More than one of them may appear. (*LIMIT_MATCH=d) set the match limit to d (decimal number) (*LIMIT_RECURSION=d) set the recursion limit to d (decimal number) (*NO_AUTO_POSSESS) no auto-possessification (PCRE_NO_AUTO_POSSESS) (*NO_START_OPT) no start-match optimization (PCRE_NO_START_OPTIMIZE) (*UTF8) set UTF-8 mode: 8-bit library (PCRE_UTF8) (*UTF16) set UTF-16 mode: 16-bit library (PCRE_UTF16) (*UTF32) set UTF-32 mode: 32-bit library (PCRE_UTF32) (*UTF) set appropriate UTF mode for the library in use (*UCP) set PCRE_UCP (use Unicode properties for \d etc) Note that LIMIT_MATCH and LIMIT_RECURSION can only reduce the value of the limits set by the caller of pcre_exec(), not increase them. NEWLINE CONVENTION These are recognized only at the very start of the pattern or after option settings with a similar syntax. (*CR) carriage return only (*LF) linefeed only (*CRLF) carriage return followed by linefeed (*ANYCRLF) all three of the above (*ANY) any Unicode newline sequence WHAT \R MATCHES These are recognized only at the very start of the pattern or after option setting with a similar syntax. (*BSR_ANYCRLF) CR, LF, or CRLF (*BSR_UNICODE) any Unicode newline sequence LOOKAHEAD AND LOOKBEHIND ASSERTIONS (?=...) positive look ahead (?!...) negative look ahead (?<=...) positive look behind (? reference by name (Perl) \k'name' reference by name (Perl) \g{name} reference by name (Perl) \k{name} reference by name (.NET) (?P=name) reference by name (Python) SUBROUTINE REFERENCES (POSSIBLY RECURSIVE) (?R) recurse whole pattern (?n) call subpattern by absolute number (?+n) call subpattern by relative number (?-n) call subpattern by relative number (?&name) call subpattern by name (Perl) (?P>name) call subpattern by name (Python) \g call subpattern by name (Oniguruma) \g'name' call subpattern by name (Oniguruma) \g call subpattern by absolute number (Oniguruma) \g'n' call subpattern by absolute number (Oniguruma) \g<+n> call subpattern by relative number (PCRE extension) \g'+n' call subpattern by relative number (PCRE extension) \g<-n> call subpattern by relative number (PCRE extension) \g'-n' call subpattern by relative number (PCRE extension) CONDITIONAL PATTERNS (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) (?(n)... absolute reference condition (?(+n)... relative reference condition (?(-n)... relative reference condition (?()... named reference condition (Perl) (?('name')... named reference condition (Perl) (?(name)... named reference condition (PCRE) (?(R)... overall recursion condition (?(Rn)... specific group recursion condition (?(R&name)... specific recursion condition (?(DEFINE)... define subpattern for reference (?(assert)... assertion condition BACKTRACKING CONTROL The following act immediately they are reached: (*ACCEPT) force successful match (*FAIL) force backtrack; synonym (*F) (*MARK:NAME) set name to be passed back; synonym (*:NAME) The following act only when a subsequent match failure causes a back- track to reach them. They all force a match failure, but they differ in what happens afterwards. Those that advance the start-of-match point do so only if the pattern is not anchored. (*COMMIT) overall failure, no advance of starting point (*PRUNE) advance to next starting character (*PRUNE:NAME) equivalent to (*MARK:NAME)(*PRUNE) (*SKIP) advance to current matching position (*SKIP:NAME) advance to position corresponding to an earlier (*MARK:NAME); if not found, the (*SKIP) is ignored (*THEN) local failure, backtrack to next alternation (*THEN:NAME) equivalent to (*MARK:NAME)(*THEN) CALLOUTS (?C) callout (?Cn) callout with data n SEE ALSO pcrepattern(3), pcreapi(3), pcrecallout(3), pcrematching(3), pcre(3). AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 08 January 2014 Copyright (c) 1997-2014 University of Cambridge. ------------------------------------------------------------------------------ PCREUNICODE(3) Library Functions Manual PCREUNICODE(3) NAME PCRE - Perl-compatible regular expressions UTF-8, UTF-16, UTF-32, AND UNICODE PROPERTY SUPPORT As well as UTF-8 support, PCRE also supports UTF-16 (from release 8.30) and UTF-32 (from release 8.32), by means of two additional libraries. They can be built as well as, or instead of, the 8-bit library. UTF-8 SUPPORT In order process UTF-8 strings, you must build PCRE's 8-bit library with UTF support, and, in addition, you must call pcre_compile() with the PCRE_UTF8 option flag, or the pattern must start with the sequence (*UTF8) or (*UTF). When either of these is the case, both the pattern and any subject strings that are matched against it are treated as UTF-8 strings instead of strings of individual 1-byte characters. UTF-16 AND UTF-32 SUPPORT In order process UTF-16 or UTF-32 strings, you must build PCRE's 16-bit or 32-bit library with UTF support, and, in addition, you must call pcre16_compile() or pcre32_compile() with the PCRE_UTF16 or PCRE_UTF32 option flag, as appropriate. Alternatively, the pattern must start with the sequence (*UTF16), (*UTF32), as appropriate, or (*UTF), which can be used with either library. When UTF mode is set, both the pattern and any subject strings that are matched against it are treated as UTF-16 or UTF-32 strings instead of strings of individual 16-bit or 32-bit characters. UTF SUPPORT OVERHEAD If you compile PCRE with UTF support, but do not use it at run time, the library will be a bit bigger, but the additional run time overhead is limited to testing the PCRE_UTF[8|16|32] flag occasionally, so should not be very big. UNICODE PROPERTY SUPPORT If PCRE is built with Unicode character property support (which implies UTF support), the escape sequences \p{..}, \P{..}, and \X can be used. The available properties that can be tested are limited to the general category properties such as Lu for an upper case letter or Nd for a decimal number, the Unicode script names such as Arabic or Han, and the derived properties Any and L&. Full lists is given in the pcrepattern and pcresyntax documentation. Only the short names for properties are supported. For example, \p{L} matches a letter. Its Perl synonym, \p{Letter}, is not supported. Furthermore, in Perl, many properties may optionally be prefixed by "Is", for compatibility with Perl 5.6. PCRE does not support this. Validity of UTF-8 strings When you set the PCRE_UTF8 flag, the byte strings passed as patterns and subjects are (by default) checked for validity on entry to the rel- evant functions. The entire string is checked before any other process- ing takes place. From release 7.3 of PCRE, the check is according the rules of RFC 3629, which are themselves derived from the Unicode speci- fication. Earlier releases of PCRE followed the rules of RFC 2279, which allows the full range of 31-bit values (0 to 0x7FFFFFFF). The current check allows only values in the range U+0 to U+10FFFF, exclud- ing the surrogate area. (From release 8.33 the so-called "non-charac- ter" code points are no longer excluded because Unicode corrigendum #9 makes it clear that they should not be.) Characters in the "Surrogate Area" of Unicode are reserved for use by UTF-16, where they are used in pairs to encode codepoints with values greater than 0xFFFF. The code points that are encoded by UTF-16 pairs are available independently in the UTF-8 and UTF-32 encodings. (In other words, the whole surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and UTF-32.) If an invalid UTF-8 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first byte of the failing character. The run-time functions pcre_exec() and pcre_dfa_exec() also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this. In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve perfor- mance, for example in the case of a long subject string that is being scanned repeatedly. If you set the PCRE_NO_UTF8_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-8 codes. In this case, it does not diagnose an invalid UTF-8 string. Note that passing PCRE_NO_UTF8_CHECK to pcre_compile() just disables the check for the pattern; it does not also apply to subject strings. If you want to disable the check for a subject string you must pass this option to pcre_exec() or pcre_dfa_exec(). If you pass an invalid UTF-8 string when PCRE_NO_UTF8_CHECK is set, the result is undefined and your program may crash. Validity of UTF-16 strings When you set the PCRE_UTF16 flag, the strings of 16-bit data units that are passed as patterns and subjects are (by default) checked for valid- ity on entry to the relevant functions. Values other than those in the surrogate range U+D800 to U+DFFF are independent code points. Values in the surrogate range must be used in pairs in the correct manner. If an invalid UTF-16 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first data unit of the failing character. The run-time functions pcre16_exec() and pcre16_dfa_exec() also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this. In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve perfor- mance. If you set the PCRE_NO_UTF16_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respec- tively) contains only valid UTF-16 sequences. In this case, it does not diagnose an invalid UTF-16 string. However, if an invalid string is passed, the result is undefined. Validity of UTF-32 strings When you set the PCRE_UTF32 flag, the strings of 32-bit data units that are passed as patterns and subjects are (by default) checked for valid- ity on entry to the relevant functions. This check allows only values in the range U+0 to U+10FFFF, excluding the surrogate area U+D800 to U+DFFF. If an invalid UTF-32 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first data unit of the failing character. The run-time functions pcre32_exec() and pcre32_dfa_exec() also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this. In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve perfor- mance. If you set the PCRE_NO_UTF32_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respec- tively) contains only valid UTF-32 sequences. In this case, it does not diagnose an invalid UTF-32 string. However, if an invalid string is passed, the result is undefined. General comments about UTF modes 1. Codepoints less than 256 can be specified in patterns by either braced or unbraced hexadecimal escape sequences (for example, \x{b3} or \xb3). Larger values have to use braced sequences. 2. Octal numbers up to \777 are recognized, and in UTF-8 mode they match two-byte characters for values greater than \177. 3. Repeat quantifiers apply to complete UTF characters, not to individ- ual data units, for example: \x{100}{3}. 4. The dot metacharacter matches one UTF character instead of a single data unit. 5. The escape sequence \C can be used to match a single byte in UTF-8 mode, or a single 16-bit data unit in UTF-16 mode, or a single 32-bit data unit in UTF-32 mode, but its use can lead to some strange effects because it breaks up multi-unit characters (see the description of \C in the pcrepattern documentation). The use of \C is not supported in the alternative matching function pcre[16|32]_dfa_exec(), nor is it supported in UTF mode by the JIT optimization of pcre[16|32]_exec(). If JIT optimization is requested for a UTF pattern that contains \C, it will not succeed, and so the matching will be carried out by the normal interpretive function. 6. The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test characters of any code value, but, by default, the characters that PCRE recognizes as digits, spaces, or word characters remain the same set as in non-UTF mode, all with values less than 256. This remains true even when PCRE is built to include Unicode property support, because to do otherwise would slow down PCRE in many common cases. Note in particular that this applies to \b and \B, because they are defined in terms of \w and \W. If you really want to test for a wider sense of, say, "digit", you can use explicit Unicode property tests such as \p{Nd}. Alternatively, if you set the PCRE_UCP option, the way that the character escapes work is changed so that Unicode properties are used to determine which characters match. There are more details in the sec- tion on generic character types in the pcrepattern documentation. 7. Similarly, characters that match the POSIX named character classes are all low-valued characters, unless the PCRE_UCP option is set. 8. However, the horizontal and vertical white space matching escapes (\h, \H, \v, and \V) do match all the appropriate Unicode characters, whether or not PCRE_UCP is set. 9. Case-insensitive matching applies only to characters whose values are less than 128, unless PCRE is built with Unicode property support. A few Unicode characters such as Greek sigma have more than two code- points that are case-equivalent. Up to and including PCRE release 8.31, only one-to-one case mappings were supported, but later releases (with Unicode property support) do treat as case-equivalent all versions of characters such as Greek sigma. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 27 February 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCREJIT(3) Library Functions Manual PCREJIT(3) NAME PCRE - Perl-compatible regular expressions PCRE JUST-IN-TIME COMPILER SUPPORT Just-in-time compiling is a heavyweight optimization that can greatly speed up pattern matching. However, it comes at the cost of extra pro- cessing before the match is performed. Therefore, it is of most benefit when the same pattern is going to be matched many times. This does not necessarily mean many calls of a matching function; if the pattern is not anchored, matching attempts may take place many times at various positions in the subject, even for a single call. Therefore, if the subject string is very long, it may still pay to use JIT for one-off matches. JIT support applies only to the traditional Perl-compatible matching function. It does not apply when the DFA matching function is being used. The code for this support was written by Zoltan Herczeg. 8-BIT, 16-BIT AND 32-BIT SUPPORT JIT support is available for all of the 8-bit, 16-bit and 32-bit PCRE libraries. To keep this documentation simple, only the 8-bit interface is described in what follows. If you are using the 16-bit library, sub- stitute the 16-bit functions and 16-bit structures (for example, pcre16_jit_stack instead of pcre_jit_stack). If you are using the 32-bit library, substitute the 32-bit functions and 32-bit structures (for example, pcre32_jit_stack instead of pcre_jit_stack). AVAILABILITY OF JIT SUPPORT JIT support is an optional feature of PCRE. The "configure" option --enable-jit (or equivalent CMake option) must be set when PCRE is built if you want to use JIT. The support is limited to the following hardware platforms: ARM v5, v7, and Thumb2 Intel x86 32-bit and 64-bit MIPS 32-bit Power PC 32-bit and 64-bit SPARC 32-bit (experimental) If --enable-jit is set on an unsupported platform, compilation fails. A program that is linked with PCRE 8.20 or later can tell if JIT sup- port is available by calling pcre_config() with the PCRE_CONFIG_JIT option. The result is 1 when JIT is available, and 0 otherwise. How- ever, a simple program does not need to check this in order to use JIT. The normal API is implemented in a way that falls back to the interpre- tive code if JIT is not available. For programs that need the best pos- sible performance, there is also a "fast path" API that is JIT-spe- cific. If your program may sometimes be linked with versions of PCRE that are older than 8.20, but you want to use JIT when it is available, you can test the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such as PCRE_CONFIG_JIT, for compile-time control of your code. Also beware that the pcre_jit_exec() function was not available at all before 8.32, and may not be available at all if PCRE isn't compiled with --enable-jit. See the "JIT FAST PATH API" section below for details. SIMPLE USE OF JIT You have to do two things to make use of the JIT support in the sim- plest way: (1) Call pcre_study() with the PCRE_STUDY_JIT_COMPILE option for each compiled pattern, and pass the resulting pcre_extra block to pcre_exec(). (2) Use pcre_free_study() to free the pcre_extra block when it is no longer needed, instead of just freeing it yourself. This ensures that any JIT data is also freed. For a program that may be linked with pre-8.20 versions of PCRE, you can insert #ifndef PCRE_STUDY_JIT_COMPILE #define PCRE_STUDY_JIT_COMPILE 0 #endif so that no option is passed to pcre_study(), and then use something like this to free the study data: #ifdef PCRE_CONFIG_JIT pcre_free_study(study_ptr); #else pcre_free(study_ptr); #endif PCRE_STUDY_JIT_COMPILE requests the JIT compiler to generate code for complete matches. If you want to run partial matches using the PCRE_PARTIAL_HARD or PCRE_PARTIAL_SOFT options of pcre_exec(), you should set one or both of the following options in addition to, or instead of, PCRE_STUDY_JIT_COMPILE when you call pcre_study(): PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE If using pcre_jit_exec() and supporting a pre-8.32 version of PCRE, you can insert: #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32 pcre_jit_exec(...); #else pcre_exec(...) #endif but as described in the "JIT FAST PATH API" section below this assumes version 8.32 and later are compiled with --enable-jit, which may break. The JIT compiler generates different optimized code for each of the three modes (normal, soft partial, hard partial). When pcre_exec() is called, the appropriate code is run if it is available. Otherwise, the pattern is matched using interpretive code. In some circumstances you may need to call additional functions. These are described in the section entitled "Controlling the JIT stack" below. If JIT support is not available, PCRE_STUDY_JIT_COMPILE etc. are ignored, and no JIT data is created. Otherwise, the compiled pattern is passed to the JIT compiler, which turns it into machine code that exe- cutes much faster than the normal interpretive code. When pcre_exec() is passed a pcre_extra block containing a pointer to JIT code of the appropriate mode (normal or hard/soft partial), it obeys that code instead of running the interpreter. The result is identical, but the compiled JIT code runs much faster. There are some pcre_exec() options that are not supported for JIT exe- cution. There are also some pattern items that JIT cannot handle. Details are given below. In both cases, execution automatically falls back to the interpretive code. If you want to know whether JIT was actually used for a particular match, you should arrange for a JIT callback function to be set up as described in the section entitled "Controlling the JIT stack" below, even if you do not need to supply a non-default JIT stack. Such a callback function is called whenever JIT code is about to be obeyed. If the execution options are not right for JIT execution, the callback function is not obeyed. If the JIT compiler finds an unsupported item, no JIT data is gener- ated. You can find out if JIT execution is available after studying a pattern by calling pcre_fullinfo() with the PCRE_INFO_JIT option. A result of 1 means that JIT compilation was successful. A result of 0 means that JIT support is not available, or the pattern was not studied with PCRE_STUDY_JIT_COMPILE etc., or the JIT compiler was not able to handle the pattern. Once a pattern has been studied, with or without JIT, it can be used as many times as you like for matching different subject strings. UNSUPPORTED OPTIONS AND PATTERN ITEMS The only pcre_exec() options that are supported for JIT execution are PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK, PCRE_NO_UTF32_CHECK, PCRE_NOT- BOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_PAR- TIAL_HARD, and PCRE_PARTIAL_SOFT. The only unsupported pattern items are \C (match a single data unit) when running in a UTF mode, and a callout immediately before an asser- tion condition in a conditional group. RETURN VALUES FROM JIT EXECUTION When a pattern is matched using JIT execution, the return values are the same as those given by the interpretive pcre_exec() code, with the addition of one new error code: PCRE_ERROR_JIT_STACKLIMIT. This means that the memory used for the JIT stack was insufficient. See "Control- ling the JIT stack" below for a discussion of JIT stack usage. For com- patibility with the interpretive pcre_exec() code, no more than two- thirds of the ovector argument is used for passing back captured sub- strings. The error code PCRE_ERROR_MATCHLIMIT is returned by the JIT code if searching a very large pattern tree goes on for too long, as it is in the same circumstance when JIT is not used, but the details of exactly what is counted are not the same. The PCRE_ERROR_RECURSIONLIMIT error code is never returned by JIT execution. SAVING AND RESTORING COMPILED PATTERNS The code that is generated by the JIT compiler is architecture-spe- cific, and is also position dependent. For those reasons it cannot be saved (in a file or database) and restored later like the bytecode and other data of a compiled pattern. Saving and restoring compiled pat- terns is not something many people do. More detail about this facility is given in the pcreprecompile documentation. It should be possible to run pcre_study() on a saved and restored pattern, and thereby recreate the JIT data, but because JIT compilation uses significant resources, it is probably not worth doing this; you might as well recompile the original pattern. CONTROLLING THE JIT STACK When the compiled JIT code runs, it needs a block of memory to use as a stack. By default, it uses 32K on the machine stack. However, some large or complicated patterns need more than this. The error PCRE_ERROR_JIT_STACKLIMIT is given when there is not enough stack. Three functions are provided for managing blocks of memory for use as JIT stacks. There is further discussion about the use of JIT stacks in the section entitled "JIT stack FAQ" below. The pcre_jit_stack_alloc() function creates a JIT stack. Its arguments are a starting size and a maximum size, and it returns a pointer to an opaque structure of type pcre_jit_stack, or NULL if there is an error. The pcre_jit_stack_free() function can be used to free a stack that is no longer needed. (For the technically minded: the address space is allocated by mmap or VirtualAlloc.) JIT uses far less memory for recursion than the interpretive code, and a maximum stack size of 512K to 1M should be more than enough for any pattern. The pcre_assign_jit_stack() function specifies which stack JIT code should use. Its arguments are as follows: pcre_extra *extra pcre_jit_callback callback void *data The extra argument must be the result of studying a pattern with PCRE_STUDY_JIT_COMPILE etc. There are three cases for the values of the other two options: (1) If callback is NULL and data is NULL, an internal 32K block on the machine stack is used. (2) If callback is NULL and data is not NULL, data must be a valid JIT stack, the result of calling pcre_jit_stack_alloc(). (3) If callback is not NULL, it must point to a function that is called with data as an argument at the start of matching, in order to set up a JIT stack. If the return from the callback function is NULL, the internal 32K stack is used; otherwise the return value must be a valid JIT stack, the result of calling pcre_jit_stack_alloc(). A callback function is obeyed whenever JIT code is about to be run; it is not obeyed when pcre_exec() is called with options that are incom- patible for JIT execution. A callback function can therefore be used to determine whether a match operation was executed by JIT or by the interpreter. You may safely use the same JIT stack for more than one pattern (either by assigning directly or by callback), as long as the patterns are all matched sequentially in the same thread. In a multithread application, if you do not specify a JIT stack, or if you assign or pass back NULL from a callback, that is thread-safe, because each thread has its own machine stack. However, if you assign or pass back a non-NULL JIT stack, this must be a different stack for each thread so that the application is thread-safe. Strictly speaking, even more is allowed. You can assign the same non- NULL stack to any number of patterns as long as they are not used for matching by multiple threads at the same time. For example, you can assign the same stack to all compiled patterns, and use a global mutex in the callback to wait until the stack is available for use. However, this is an inefficient solution, and not recommended. This is a suggestion for how a multithreaded program that needs to set up non-default JIT stacks might operate: During thread initalization thread_local_var = pcre_jit_stack_alloc(...) During thread exit pcre_jit_stack_free(thread_local_var) Use a one-line callback function return thread_local_var All the functions described in this section do nothing if JIT is not available, and pcre_assign_jit_stack() does nothing unless the extra argument is non-NULL and points to a pcre_extra block that is the result of a successful study with PCRE_STUDY_JIT_COMPILE etc. JIT STACK FAQ (1) Why do we need JIT stacks? PCRE (and JIT) is a recursive, depth-first engine, so it needs a stack where the local data of the current node is pushed before checking its child nodes. Allocating real machine stack on some platforms is diffi- cult. For example, the stack chain needs to be updated every time if we extend the stack on PowerPC. Although it is possible, its updating time overhead decreases performance. So we do the recursion in memory. (2) Why don't we simply allocate blocks of memory with malloc()? Modern operating systems have a nice feature: they can reserve an address space instead of allocating memory. We can safely allocate mem- ory pages inside this address space, so the stack could grow without moving memory data (this is important because of pointers). Thus we can allocate 1M address space, and use only a single memory page (usually 4K) if that is enough. However, we can still grow up to 1M anytime if needed. (3) Who "owns" a JIT stack? The owner of the stack is the user program, not the JIT studied pattern or anything else. The user program must ensure that if a stack is used by pcre_exec(), (that is, it is assigned to the pattern currently run- ning), that stack must not be used by any other threads (to avoid over- writing the same memory area). The best practice for multithreaded pro- grams is to allocate a stack for each thread, and return this stack through the JIT callback function. (4) When should a JIT stack be freed? You can free a JIT stack at any time, as long as it will not be used by pcre_exec() again. When you assign the stack to a pattern, only a pointer is set. There is no reference counting or any other magic. You can free the patterns and stacks in any order, anytime. Just do not call pcre_exec() with a pattern pointing to an already freed stack, as that will cause SEGFAULT. (Also, do not free a stack currently used by pcre_exec() in another thread). You can also replace the stack for a pattern at any time. You can even free the previous stack before assigning a replacement. (5) Should I allocate/free a stack every time before/after calling pcre_exec()? No, because this is too costly in terms of resources. However, you could implement some clever idea which release the stack if it is not used in let's say two minutes. The JIT callback can help to achieve this without keeping a list of the currently JIT studied patterns. (6) OK, the stack is for long term memory allocation. But what happens if a pattern causes stack overflow with a stack of 1M? Is that 1M kept until the stack is freed? Especially on embedded sytems, it might be a good idea to release mem- ory sometimes without freeing the stack. There is no API for this at the moment. Probably a function call which returns with the currently allocated memory for any stack and another which allows releasing mem- ory (shrinking the stack) would be a good idea if someone needs this. (7) This is too much of a headache. Isn't there any better solution for JIT stack handling? No, thanks to Windows. If POSIX threads were used everywhere, we could throw out this complicated API. EXAMPLE CODE This is a single-threaded example that specifies a JIT stack without using a callback. int rc; int ovector[30]; pcre *re; pcre_extra *extra; pcre_jit_stack *jit_stack; re = pcre_compile(pattern, 0, &error, &erroffset, NULL); /* Check for errors */ extra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, &error); jit_stack = pcre_jit_stack_alloc(32*1024, 512*1024); /* Check for error (NULL) */ pcre_assign_jit_stack(extra, NULL, jit_stack); rc = pcre_exec(re, extra, subject, length, 0, 0, ovector, 30); /* Check results */ pcre_free(re); pcre_free_study(extra); pcre_jit_stack_free(jit_stack); JIT FAST PATH API Because the API described above falls back to interpreted execution when JIT is not available, it is convenient for programs that are writ- ten for general use in many environments. However, calling JIT via pcre_exec() does have a performance impact. Programs that are written for use where JIT is known to be available, and which need the best possible performance, can instead use a "fast path" API to call JIT execution directly instead of calling pcre_exec() (obviously only for patterns that have been successfully studied by JIT). The fast path function is called pcre_jit_exec(), and it takes exactly the same arguments as pcre_exec(), plus one additional argument that must point to a JIT stack. The JIT stack arrangements described above do not apply. The return values are the same as for pcre_exec(). When you call pcre_exec(), as well as testing for invalid options, a number of other sanity checks are performed on the arguments. For exam- ple, if the subject pointer is NULL, or its length is negative, an immediate error is given. Also, unless PCRE_NO_UTF[8|16|32] is set, a UTF subject string is tested for validity. In the interests of speed, these checks do not happen on the JIT fast path, and if invalid data is passed, the result is undefined. Bypassing the sanity checks and the pcre_exec() wrapping can give speedups of more than 10%. Note that the pcre_jit_exec() function is not available in versions of PCRE before 8.32 (released in November 2012). If you need to support versions that old you must either use the slower pcre_exec(), or switch between the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR. Due to an unfortunate implementation oversight, even in versions 8.32 and later there will be no pcre_jit_exec() stub function defined when PCRE is compiled with --disable-jit, which is the default, and there's no way to detect whether PCRE was compiled with --enable-jit via a macro. If you need to support versions older than 8.32, or versions that may not build with --enable-jit, you must either use the slower pcre_exec(), or switch between the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR. Switching between the two by checking the version assumes that all the versions being targeted are built with --enable-jit. To also support builds that may use --disable-jit either pcre_exec() must be used, or a compile-time check for JIT via pcre_config() (which assumes the runtime environment will be the same), or as the Git project decided to do, simply assume that pcre_jit_exec() is present in 8.32 or later unless a compile-time flag is provided, see the "grep: un-break building with PCRE >= 8.32 without --enable-jit" commit in git.git for an example of that. SEE ALSO pcreapi(3) AUTHOR Philip Hazel (FAQ by Zoltan Herczeg) University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 05 July 2017 Copyright (c) 1997-2017 University of Cambridge. ------------------------------------------------------------------------------ PCREPARTIAL(3) Library Functions Manual PCREPARTIAL(3) NAME PCRE - Perl-compatible regular expressions PARTIAL MATCHING IN PCRE In normal use of PCRE, if the subject string that is passed to a match- ing function matches as far as it goes, but is too short to match the entire pattern, PCRE_ERROR_NOMATCH is returned. There are circumstances where it might be helpful to distinguish this case from other cases in which there is no match. Consider, for example, an application where a human is required to type in data for a field with specific formatting requirements. An example might be a date in the form ddmmmyy, defined by this pattern: ^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$ If the application sees the user's keystrokes one by one, and can check that what has been typed so far is potentially valid, it is able to raise an error as soon as a mistake is made, by beeping and not reflecting the character that has been typed, for example. This immedi- ate feedback is likely to be a better user interface than a check that is delayed until the entire string has been entered. Partial matching can also be useful when the subject string is very long and is not all available at once. PCRE supports partial matching by means of the PCRE_PARTIAL_SOFT and PCRE_PARTIAL_HARD options, which can be set when calling any of the matching functions. For backwards compatibility, PCRE_PARTIAL is a syn- onym for PCRE_PARTIAL_SOFT. The essential difference between the two options is whether or not a partial match is preferred to an alterna- tive complete match, though the details differ between the two types of matching function. If both options are set, PCRE_PARTIAL_HARD takes precedence. If you want to use partial matching with just-in-time optimized code, you must call pcre_study(), pcre16_study() or pcre32_study() with one or both of these options: PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE PCRE_STUDY_JIT_COMPILE should also be set if you are going to run non- partial matches on the same pattern. If the appropriate JIT study mode has not been set for a match, the interpretive matching code is used. Setting a partial matching option disables two of PCRE's standard opti- mizations. PCRE remembers the last literal data unit in a pattern, and abandons matching immediately if it is not present in the subject string. This optimization cannot be used for a subject string that might match only partially. If the pattern was studied, PCRE knows the minimum length of a matching string, and does not bother to run the matching function on shorter strings. This optimization is also dis- abled for partial matching. PARTIAL MATCHING USING pcre_exec() OR pcre[16|32]_exec() A partial match occurs during a call to pcre_exec() or pcre[16|32]_exec() when the end of the subject string is reached suc- cessfully, but matching cannot continue because more characters are needed. However, at least one character in the subject must have been inspected. This character need not form part of the final matched string; lookbehind assertions and the \K escape sequence provide ways of inspecting characters before the start of a matched substring. The requirement for inspecting at least one character exists because an empty string can always be matched; without such a restriction there would always be a partial match of an empty string at the end of the subject. If there are at least two slots in the offsets vector when a partial match is returned, the first slot is set to the offset of the earliest character that was inspected. For convenience, the second offset points to the end of the subject so that a substring can easily be identified. If there are at least three slots in the offsets vector, the third slot is set to the offset of the character where matching started. For the majority of patterns, the contents of the first and third slots will be the same. However, for patterns that contain lookbehind asser- tions, or begin with \b or \B, characters before the one where matching started may have been inspected while carrying out the match. For exam- ple, consider this pattern: /(?<=abc)123/ This pattern matches "123", but only if it is preceded by "abc". If the subject string is "xyzabc12", the first two offsets after a partial match are for the substring "abc12", because all these characters were inspected. However, the third offset is set to 6, because that is the offset where matching began. What happens when a partial match is identified depends on which of the two partial matching options are set. PCRE_PARTIAL_SOFT WITH pcre_exec() OR pcre[16|32]_exec() If PCRE_PARTIAL_SOFT is set when pcre_exec() or pcre[16|32]_exec() identifies a partial match, the partial match is remembered, but match- ing continues as normal, and other alternatives in the pattern are tried. If no complete match can be found, PCRE_ERROR_PARTIAL is returned instead of PCRE_ERROR_NOMATCH. This option is "soft" because it prefers a complete match over a par- tial match. All the various matching items in a pattern behave as if the subject string is potentially complete. For example, \z, \Z, and $ match at the end of the subject, as normal, and for \b and \B the end of the subject is treated as a non-alphanumeric. If there is more than one partial match, the first one that was found provides the data that is returned. Consider this pattern: /123\w+X|dogY/ If this is matched against the subject string "abc123dog", both alter- natives fail to match, but the end of the subject is reached during matching, so PCRE_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying "123dog" as the first partial match that was found. (In this example, there are two partial matches, because "dog" on its own partially matches the second alternative.) PCRE_PARTIAL_HARD WITH pcre_exec() OR pcre[16|32]_exec() If PCRE_PARTIAL_HARD is set for pcre_exec() or pcre[16|32]_exec(), PCRE_ERROR_PARTIAL is returned as soon as a partial match is found, without continuing to search for possible complete matches. This option is "hard" because it prefers an earlier partial match over a later com- plete match. For this reason, the assumption is made that the end of the supplied subject string may not be the true end of the available data, and so, if \z, \Z, \b, \B, or $ are encountered at the end of the subject, the result is PCRE_ERROR_PARTIAL, provided that at least one character in the subject has been inspected. Setting PCRE_PARTIAL_HARD also affects the way UTF-8 and UTF-16 subject strings are checked for validity. Normally, an invalid sequence causes the error PCRE_ERROR_BADUTF8 or PCRE_ERROR_BADUTF16. However, in the special case of a truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8 or PCRE_ERROR_SHORTUTF16 is returned when PCRE_PARTIAL_HARD is set. Comparing hard and soft partial matching The difference between the two partial matching options can be illus- trated by a pattern such as: /dog(sbody)?/ This matches either "dog" or "dogsbody", greedily (that is, it prefers the longer string if possible). If it is matched against the string "dog" with PCRE_PARTIAL_SOFT, it yields a complete match for "dog". However, if PCRE_PARTIAL_HARD is set, the result is PCRE_ERROR_PARTIAL. On the other hand, if the pattern is made ungreedy the result is dif- ferent: /dog(sbody)??/ In this case the result is always a complete match because that is found first, and matching never continues after finding a complete match. It might be easier to follow this explanation by thinking of the two patterns like this: /dog(sbody)?/ is the same as /dogsbody|dog/ /dog(sbody)??/ is the same as /dog|dogsbody/ The second pattern will never match "dogsbody", because it will always find the shorter match first. PARTIAL MATCHING USING pcre_dfa_exec() OR pcre[16|32]_dfa_exec() The DFA functions move along the subject string character by character, without backtracking, searching for all possible matches simultane- ously. If the end of the subject is reached before the end of the pat- tern, there is the possibility of a partial match, again provided that at least one character has been inspected. When PCRE_PARTIAL_SOFT is set, PCRE_ERROR_PARTIAL is returned only if there have been no complete matches. Otherwise, the complete matches are returned. However, if PCRE_PARTIAL_HARD is set, a partial match takes precedence over any complete matches. The portion of the string that was inspected when the longest partial match was found is set as the first matching string, provided there are at least two slots in the offsets vector. Because the DFA functions always search for all possible matches, and there is no difference between greedy and ungreedy repetition, their behaviour is different from the standard functions when PCRE_PAR- TIAL_HARD is set. Consider the string "dog" matched against the ungreedy pattern shown above: /dog(sbody)??/ Whereas the standard functions stop as soon as they find the complete match for "dog", the DFA functions also find the partial match for "dogsbody", and so return that when PCRE_PARTIAL_HARD is set. PARTIAL MATCHING AND WORD BOUNDARIES If a pattern ends with one of sequences \b or \B, which test for word boundaries, partial matching with PCRE_PARTIAL_SOFT can give counter- intuitive results. Consider this pattern: /\bcat\b/ This matches "cat", provided there is a word boundary at either end. If the subject string is "the cat", the comparison of the final "t" with a following character cannot take place, so a partial match is found. However, normal matching carries on, and \b matches at the end of the subject when the last character is a letter, so a complete match is found. The result, therefore, is not PCRE_ERROR_PARTIAL. Using PCRE_PARTIAL_HARD in this case does yield PCRE_ERROR_PARTIAL, because then the partial match takes precedence. FORMERLY RESTRICTED PATTERNS For releases of PCRE prior to 8.00, because of the way certain internal optimizations were implemented in the pcre_exec() function, the PCRE_PARTIAL option (predecessor of PCRE_PARTIAL_SOFT) could not be used with all patterns. From release 8.00 onwards, the restrictions no longer apply, and partial matching with can be requested for any pat- tern. Items that were formerly restricted were repeated single characters and repeated metasequences. If PCRE_PARTIAL was set for a pattern that did not conform to the restrictions, pcre_exec() returned the error code PCRE_ERROR_BADPARTIAL (-13). This error code is no longer in use. The PCRE_INFO_OKPARTIAL call to pcre_fullinfo() to find out if a compiled pattern can be used for partial matching now always returns 1. EXAMPLE OF PARTIAL MATCHING USING PCRETEST If the escape sequence \P is present in a pcretest data line, the PCRE_PARTIAL_SOFT option is used for the match. Here is a run of pcretest that uses the date example quoted above: re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/ data> 25jun04\P 0: 25jun04 1: jun data> 25dec3\P Partial match: 23dec3 data> 3ju\P Partial match: 3ju data> 3juj\P No match data> j\P No match The first data string is matched completely, so pcretest shows the matched substrings. The remaining four strings do not match the com- plete pattern, but the first two are partial matches. Similar output is obtained if DFA matching is used. If the escape sequence \P is present more than once in a pcretest data line, the PCRE_PARTIAL_HARD option is set for the match. MULTI-SEGMENT MATCHING WITH pcre_dfa_exec() OR pcre[16|32]_dfa_exec() When a partial match has been found using a DFA matching function, it is possible to continue the match by providing additional subject data and calling the function again with the same compiled regular expres- sion, this time setting the PCRE_DFA_RESTART option. You must pass the same working space as before, because this is where details of the pre- vious partial match are stored. Here is an example using pcretest, using the \R escape sequence to set the PCRE_DFA_RESTART option (\D specifies the use of the DFA matching function): re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/ data> 23ja\P\D Partial match: 23ja data> n05\R\D 0: n05 The first call has "23ja" as the subject, and requests partial match- ing; the second call has "n05" as the subject for the continued (restarted) match. Notice that when the match is complete, only the last part is shown; PCRE does not retain the previously partially- matched string. It is up to the calling program to do that if it needs to. That means that, for an unanchored pattern, if a continued match fails, it is not possible to try again at a new starting point. All this facility is capable of doing is continuing with the previous match attempt. In the previous example, if the second set of data is "ug23" the result is no match, even though there would be a match for "aug23" if the entire string were given at once. Depending on the application, this may or may not be what you want. The only way to allow for start- ing again at the next character is to retain the matched part of the subject and try a new complete match. You can set the PCRE_PARTIAL_SOFT or PCRE_PARTIAL_HARD options with PCRE_DFA_RESTART to continue partial matching over multiple segments. This facility can be used to pass very long subject strings to the DFA matching functions. MULTI-SEGMENT MATCHING WITH pcre_exec() OR pcre[16|32]_exec() From release 8.00, the standard matching functions can also be used to do multi-segment matching. Unlike the DFA functions, it is not possible to restart the previous match with a new segment of data. Instead, new data must be added to the previous subject string, and the entire match re-run, starting from the point where the partial match occurred. Ear- lier data can be discarded. It is best to use PCRE_PARTIAL_HARD in this situation, because it does not treat the end of a segment as the end of the subject when matching \z, \Z, \b, \B, and $. Consider an unanchored pattern that matches dates: re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/ data> The date is 23ja\P\P Partial match: 23ja At this stage, an application could discard the text preceding "23ja", add on text from the next segment, and call the matching function again. Unlike the DFA matching functions, the entire matching string must always be available, and the complete matching process occurs for each call, so more memory and more processing time is needed. Note: If the pattern contains lookbehind assertions, or \K, or starts with \b or \B, the string that is returned for a partial match includes characters that precede the start of what would be returned for a com- plete match, because it contains all the characters that were inspected during the partial match. ISSUES WITH MULTI-SEGMENT MATCHING Certain types of pattern may give problems with multi-segment matching, whichever matching function is used. 1. If the pattern contains a test for the beginning of a line, you need to pass the PCRE_NOTBOL option when the subject string for any call does start at the beginning of a line. There is also a PCRE_NOTEOL option, but in practice when doing multi-segment matching you should be using PCRE_PARTIAL_HARD, which includes the effect of PCRE_NOTEOL. 2. Lookbehind assertions that have already been obeyed are catered for in the offsets that are returned for a partial match. However a lookbe- hind assertion later in the pattern could require even earlier charac- ters to be inspected. You can handle this case by using the PCRE_INFO_MAXLOOKBEHIND option of the pcre_fullinfo() or pcre[16|32]_fullinfo() functions to obtain the length of the longest lookbehind in the pattern. This length is given in characters, not bytes. If you always retain at least that many characters before the partially matched string, all should be well. (Of course, near the start of the subject, fewer characters may be present; in that case all characters should be retained.) From release 8.33, there is a more accurate way of deciding which char- acters to retain. Instead of subtracting the length of the longest lookbehind from the earliest inspected character (offsets[0]), the match start position (offsets[2]) should be used, and the next match attempt started at the offsets[2] character by setting the startoffset argument of pcre_exec() or pcre_dfa_exec(). For example, if the pattern "(?<=123)abc" is partially matched against the string "xx123a", the three offset values returned are 2, 6, and 5. This indicates that the matching process that gave a partial match started at offset 5, but the characters "123a" were all inspected. The maximum lookbehind for that pattern is 3, so taking that away from 5 shows that we need only keep "123a", and the next match attempt can be started at offset 3 (that is, at "a") when further characters have been added. When the match start is not the earliest inspected character, pcretest shows it explicitly: re> "(?<=123)abc" data> xx123a\P\P Partial match at offset 5: 123a 3. Because a partial match must always contain at least one character, what might be considered a partial match of an empty string actually gives a "no match" result. For example: re> /c(?<=abc)x/ data> ab\P No match If the next segment begins "cx", a match should be found, but this will only happen if characters from the previous segment are retained. For this reason, a "no match" result should be interpreted as "partial match of an empty string" when the pattern contains lookbehinds. 4. Matching a subject string that is split into multiple segments may not always produce exactly the same result as matching over one single long string, especially when PCRE_PARTIAL_SOFT is used. The section "Partial Matching and Word Boundaries" above describes an issue that arises if the pattern ends with \b or \B. Another kind of difference may occur when there are multiple matching possibilities, because (for PCRE_PARTIAL_SOFT) a partial match result is given only when there are no completed matches. This means that as soon as the shortest match has been found, continuation to a new subject segment is no longer possi- ble. Consider again this pcretest example: re> /dog(sbody)?/ data> dogsb\P 0: dog data> do\P\D Partial match: do data> gsb\R\P\D 0: g data> dogsbody\D 0: dogsbody 1: dog The first data line passes the string "dogsb" to a standard matching function, setting the PCRE_PARTIAL_SOFT option. Although the string is a partial match for "dogsbody", the result is not PCRE_ERROR_PARTIAL, because the shorter string "dog" is a complete match. Similarly, when the subject is presented to a DFA matching function in several parts ("do" and "gsb" being the first two) the match stops when "dog" has been found, and it is not possible to continue. On the other hand, if "dogsbody" is presented as a single string, a DFA matching function finds both matches. Because of these problems, it is best to use PCRE_PARTIAL_HARD when matching multi-segment data. The example above then behaves differ- ently: re> /dog(sbody)?/ data> dogsb\P\P Partial match: dogsb data> do\P\D Partial match: do data> gsb\R\P\P\D Partial match: gsb 5. Patterns that contain alternatives at the top level which do not all start with the same pattern item may not work as expected when PCRE_DFA_RESTART is used. For example, consider this pattern: 1234|3789 If the first part of the subject is "ABC123", a partial match of the first alternative is found at offset 3. There is no partial match for the second alternative, because such a match does not start at the same point in the subject string. Attempting to continue with the string "7890" does not yield a match because only those alternatives that match at one point in the subject are remembered. The problem arises because the start of the second alternative matches within the first alternative. There is no problem with anchored patterns or patterns such as: 1234|ABCD where no string can be a partial match for both alternatives. This is not a problem if a standard matching function is used, because the entire match has to be rerun each time: re> /1234|3789/ data> ABC123\P\P Partial match: 123 data> 1237890 0: 3789 Of course, instead of using PCRE_DFA_RESTART, the same technique of re- running the entire match can also be used with the DFA matching func- tions. Another possibility is to work with two buffers. If a partial match at offset n in the first buffer is followed by "no match" when PCRE_DFA_RESTART is used on the second buffer, you can then try a new match starting at offset n+1 in the first buffer. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 02 July 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCREPRECOMPILE(3) Library Functions Manual PCREPRECOMPILE(3) NAME PCRE - Perl-compatible regular expressions SAVING AND RE-USING PRECOMPILED PCRE PATTERNS If you are running an application that uses a large number of regular expression patterns, it may be useful to store them in a precompiled form instead of having to compile them every time the application is run. If you are not using any private character tables (see the pcre_maketables() documentation), this is relatively straightforward. If you are using private tables, it is a little bit more complicated. However, if you are using the just-in-time optimization feature, it is not possible to save and reload the JIT data. If you save compiled patterns to a file, you can copy them to a differ- ent host and run them there. If the two hosts have different endianness (byte order), you should run the pcre[16|32]_pat- tern_to_host_byte_order() function on the new host before trying to match the pattern. The matching functions return PCRE_ERROR_BADENDIAN- NESS if they detect a pattern with the wrong endianness. Compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes, and saving and restoring a compiled pattern loses any JIT optimization data. SAVING A COMPILED PATTERN The value returned by pcre[16|32]_compile() points to a single block of memory that holds the compiled pattern and associated data. You can find the length of this block in bytes by calling pcre[16|32]_fullinfo() with an argument of PCRE_INFO_SIZE. You can then save the data in any appropriate manner. Here is sample code for the 8-bit library that compiles a pattern and writes it to a file. It assumes that the variable fd refers to a file that is open for output: int erroroffset, rc, size; char *error; pcre *re; re = pcre_compile("my pattern", 0, &error, &erroroffset, NULL); if (re == NULL) { ... handle errors ... } rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); if (rc < 0) { ... handle errors ... } rc = fwrite(re, 1, size, fd); if (rc != size) { ... handle errors ... } In this example, the bytes that comprise the compiled pattern are copied exactly. Note that this is binary data that may contain any of the 256 possible byte values. On systems that make a distinction between binary and non-binary data, be sure that the file is opened for binary output. If you want to write more than one pattern to a file, you will have to devise a way of separating them. For binary data, preceding each pat- tern with its length is probably the most straightforward approach. Another possibility is to write out the data in hexadecimal instead of binary, one pattern to a line. Saving compiled patterns in a file is only one possible way of storing them for later use. They could equally well be saved in a database, or in the memory of some daemon process that passes them via sockets to the processes that want them. If the pattern has been studied, it is also possible to save the normal study data in a similar way to the compiled pattern itself. However, if the PCRE_STUDY_JIT_COMPILE was used, the just-in-time data that is cre- ated cannot be saved because it is too dependent on the current envi- ronment. When studying generates additional information, pcre[16|32]_study() returns a pointer to a pcre[16|32]_extra data block. Its format is defined in the section on matching a pattern in the pcreapi documentation. The study_data field points to the binary study data, and this is what you must save (not the pcre[16|32]_extra block itself). The length of the study data can be obtained by calling pcre[16|32]_fullinfo() with an argument of PCRE_INFO_STUDYSIZE. Remem- ber to check that pcre[16|32]_study() did return a non-NULL value before trying to save the study data. RE-USING A PRECOMPILED PATTERN Re-using a precompiled pattern is straightforward. Having reloaded it into main memory, called pcre[16|32]_pattern_to_host_byte_order() if necessary, you pass its pointer to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() in the usual way. However, if you passed a pointer to custom character tables when the pattern was compiled (the tableptr argument of pcre[16|32]_compile()), you must now pass a similar pointer to pcre[16|32]_exec() or pcre[16|32]_dfa_exec(), because the value saved with the compiled pat- tern will obviously be nonsense. A field in a pcre[16|32]_extra() block is used to pass this data, as described in the section on matching a pattern in the pcreapi documentation. Warning: The tables that pcre_exec() and pcre_dfa_exec() use must be the same as those that were used when the pattern was compiled. If this is not the case, the behaviour is undefined. If you did not provide custom character tables when the pattern was compiled, the pointer in the compiled pattern is NULL, which causes the matching functions to use PCRE's internal tables. Thus, you do not need to take any special action at run time in this case. If you saved study data with the compiled pattern, you need to create your own pcre[16|32]_extra data block and set the study_data field to point to the reloaded study data. You must also set the PCRE_EXTRA_STUDY_DATA bit in the flags field to indicate that study data is present. Then pass the pcre[16|32]_extra block to the matching function in the usual way. If the pattern was studied for just-in-time optimization, that data cannot be saved, and so is lost by a save/restore cycle. COMPATIBILITY WITH DIFFERENT PCRE RELEASES In general, it is safest to recompile all saved patterns when you update to a new PCRE release, though not all updates actually require this. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 12 November 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCREPERFORM(3) Library Functions Manual PCREPERFORM(3) NAME PCRE - Perl-compatible regular expressions PCRE PERFORMANCE Two aspects of performance are discussed below: memory usage and pro- cessing time. The way you express your pattern as a regular expression can affect both of them. COMPILED PATTERN MEMORY USAGE Patterns are compiled by PCRE into a reasonably efficient interpretive code, so that most simple patterns do not use much memory. However, there is one case where the memory usage of a compiled pattern can be unexpectedly large. If a parenthesized subpattern has a quantifier with a minimum greater than 1 and/or a limited maximum, the whole subpattern is repeated in the compiled code. For example, the pattern (abc|def){2,4} is compiled as if it were (abc|def)(abc|def)((abc|def)(abc|def)?)? (Technical aside: It is done this way so that backtrack points within each of the repetitions can be independently maintained.) For regular expressions whose quantifiers use only small numbers, this is not usually a problem. However, if the numbers are large, and par- ticularly if such repetitions are nested, the memory usage can become an embarrassment. For example, the very simple pattern ((ab){1,1000}c){1,3} uses 51K bytes when compiled using the 8-bit library. When PCRE is com- piled with its default internal pointer size of two bytes, the size limit on a compiled pattern is 64K data units, and this is reached with the above pattern if the outer repetition is increased from 3 to 4. PCRE can be compiled to use larger internal pointers and thus handle larger compiled patterns, but it is better to try to rewrite your pat- tern to use less memory if you can. One way of reducing the memory usage for such patterns is to make use of PCRE's "subroutine" facility. Re-writing the above pattern as ((ab)(?2){0,999}c)(?1){0,2} reduces the memory requirements to 18K, and indeed it remains under 20K even with the outer repetition increased to 100. However, this pattern is not exactly equivalent, because the "subroutine" calls are treated as atomic groups into which there can be no backtracking if there is a subsequent matching failure. Therefore, PCRE cannot do this kind of rewriting automatically. Furthermore, there is a noticeable loss of speed when executing the modified pattern. Nevertheless, if the atomic grouping is not a problem and the loss of speed is acceptable, this kind of rewriting will allow you to process patterns that PCRE cannot otherwise handle. STACK USAGE AT RUN TIME When pcre_exec() or pcre[16|32]_exec() is used for matching, certain kinds of pattern can cause it to use large amounts of the process stack. In some environments the default process stack is quite small, and if it runs out the result is often SIGSEGV. This issue is probably the most frequently raised problem with PCRE. Rewriting your pattern can often help. The pcrestack documentation discusses this issue in detail. PROCESSING TIME Certain items in regular expression patterns are processed more effi- ciently than others. It is more efficient to use a character class like [aeiou] than a set of single-character alternatives such as (a|e|i|o|u). In general, the simplest construction that provides the required behaviour is usually the most efficient. Jeffrey Friedl's book contains a lot of useful general discussion about optimizing regular expressions for efficient performance. This document contains a few observations about PCRE. Using Unicode character properties (the \p, \P, and \X escapes) is slow, because PCRE has to use a multi-stage table lookup whenever it needs a character's property. If you can find an alternative pattern that does not use character properties, it will probably be faster. By default, the escape sequences \b, \d, \s, and \w, and the POSIX character classes such as [:alpha:] do not use Unicode properties, partly for backwards compatibility, and partly for performance reasons. However, you can set PCRE_UCP if you want Unicode character properties to be used. This can double the matching time for items such as \d, when matched with a traditional matching function; the performance loss is less with a DFA matching function, and in both cases there is not much difference for \b. When a pattern begins with .* not in parentheses, or in parentheses that are not the subject of a backreference, and the PCRE_DOTALL option is set, the pattern is implicitly anchored by PCRE, since it can match only at the start of a subject string. However, if PCRE_DOTALL is not set, PCRE cannot make this optimization, because the . metacharacter does not then match a newline, and if the subject string contains new- lines, the pattern may match from the character immediately following one of them instead of from the very start. For example, the pattern .*second matches the subject "first\nand second" (where \n stands for a newline character), with the match starting at the seventh character. In order to do this, PCRE has to retry the match starting after every newline in the subject. If you are using such a pattern with subject strings that do not con- tain newlines, the best performance is obtained by setting PCRE_DOTALL, or starting the pattern with ^.* or ^.*? to indicate explicit anchor- ing. That saves PCRE from having to scan along the subject looking for a newline to restart at. Beware of patterns that contain nested indefinite repeats. These can take a long time to run when applied to a string that does not match. Consider the pattern fragment ^(a+)* This can match "aaaa" in 16 different ways, and this number increases very rapidly as the string gets longer. (The * repeat can match 0, 1, 2, 3, or 4 times, and for each of those cases other than 0 or 4, the + repeats can match different numbers of times.) When the remainder of the pattern is such that the entire match is going to fail, PCRE has in principle to try every possible variation, and this can take an extremely long time, even for relatively short strings. An optimization catches some of the more simple cases such as (a+)*b where a literal character follows. Before embarking on the standard matching procedure, PCRE checks that there is a "b" later in the sub- ject string, and if there is not, it fails the match immediately. How- ever, when there is no following literal this optimization cannot be used. You can see the difference by comparing the behaviour of (a+)*\d with the pattern above. The former gives a failure almost instantly when applied to a whole line of "a" characters, whereas the latter takes an appreciable time with strings longer than about 20 characters. In many cases, the solution to this kind of performance issue is to use an atomic group or a possessive quantifier. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 25 August 2012 Copyright (c) 1997-2012 University of Cambridge. ------------------------------------------------------------------------------ PCREPOSIX(3) Library Functions Manual PCREPOSIX(3) NAME PCRE - Perl-compatible regular expressions. SYNOPSIS #include int regcomp(regex_t *preg, const char *pattern, int cflags); int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); void regfree(regex_t *preg); DESCRIPTION This set of functions provides a POSIX-style API for the PCRE regular expression 8-bit library. See the pcreapi documentation for a descrip- tion of PCRE's native API, which contains much additional functional- ity. There is no POSIX-style wrapper for PCRE's 16-bit and 32-bit library. The functions described here are just wrapper functions that ultimately call the PCRE native API. Their prototypes are defined in the pcreposix.h header file, and on Unix systems the library itself is called pcreposix.a, so can be accessed by adding -lpcreposix to the command for linking an application that uses them. Because the POSIX functions call the native ones, it is also necessary to add -lpcre. I have implemented only those POSIX option bits that can be reasonably mapped to PCRE native options. In addition, the option REG_EXTENDED is defined with the value zero. This has no effect, but since programs that are written to the POSIX interface often use it, this makes it easier to slot in PCRE as a replacement library. Other POSIX options are not even defined. There are also some other options that are not defined by POSIX. These have been added at the request of users who want to make use of certain PCRE-specific features via the POSIX calling interface. When PCRE is called via these functions, it is only the API that is POSIX-like in style. The syntax and semantics of the regular expres- sions themselves are still those of Perl, subject to the setting of various PCRE options, as described below. "POSIX-like in style" means that the API approximates to the POSIX definition; it is not fully POSIX-compatible, and in multi-byte encoding domains it is probably even less compatible. The header for these functions is supplied as pcreposix.h to avoid any potential clash with other POSIX libraries. It can, of course, be renamed or aliased as regex.h, which is the "correct" name. It provides two structure types, regex_t for compiled internal forms, and reg- match_t for returning captured substrings. It also defines some con- stants whose names start with "REG_"; these are used for setting options and identifying error codes. COMPILING A PATTERN The function regcomp() is called to compile a pattern into an internal form. The pattern is a C string terminated by a binary zero, and is passed in the argument pattern. The preg argument is a pointer to a regex_t structure that is used as a base for storing information about the compiled regular expression. The argument cflags is either zero, or contains one or more of the bits defined by the following macros: REG_DOTALL The PCRE_DOTALL option is set when the regular expression is passed for compilation to the native function. Note that REG_DOTALL is not part of the POSIX standard. REG_ICASE The PCRE_CASELESS option is set when the regular expression is passed for compilation to the native function. REG_NEWLINE The PCRE_MULTILINE option is set when the regular expression is passed for compilation to the native function. Note that this does not mimic the defined POSIX behaviour for REG_NEWLINE (see the following sec- tion). REG_NOSUB The PCRE_NO_AUTO_CAPTURE option is set when the regular expression is passed for compilation to the native function. In addition, when a pat- tern that is compiled with this flag is passed to regexec() for match- ing, the nmatch and pmatch arguments are ignored, and no captured strings are returned. REG_UCP The PCRE_UCP option is set when the regular expression is passed for compilation to the native function. This causes PCRE to use Unicode properties when matchine \d, \w, etc., instead of just recognizing ASCII values. Note that REG_UTF8 is not part of the POSIX standard. REG_UNGREEDY The PCRE_UNGREEDY option is set when the regular expression is passed for compilation to the native function. Note that REG_UNGREEDY is not part of the POSIX standard. REG_UTF8 The PCRE_UTF8 option is set when the regular expression is passed for compilation to the native function. This causes the pattern itself and all data strings used for matching it to be treated as UTF-8 strings. Note that REG_UTF8 is not part of the POSIX standard. In the absence of these flags, no options are passed to the native function. This means the the regex is compiled with PCRE default semantics. In particular, the way it handles newline characters in the subject string is the Perl way, not the POSIX way. Note that setting PCRE_MULTILINE has only some of the effects specified for REG_NEWLINE. It does not affect the way newlines are matched by . (they are not) or by a negative class such as [^a] (they are). The yield of regcomp() is zero on success, and non-zero otherwise. The preg structure is filled in on success, and one member of the structure is public: re_nsub contains the number of capturing subpatterns in the regular expression. Various error codes are defined in the header file. NOTE: If the yield of regcomp() is non-zero, you must not attempt to use the contents of the preg structure. If, for example, you pass it to regexec(), the result is undefined and your program is likely to crash. MATCHING NEWLINE CHARACTERS This area is not simple, because POSIX and Perl take different views of things. It is not possible to get PCRE to obey POSIX semantics, but then PCRE was never intended to be a POSIX engine. The following table lists the different possibilities for matching newline characters in PCRE: Default Change with . matches newline no PCRE_DOTALL newline matches [^a] yes not changeable $ matches \n at end yes PCRE_DOLLARENDONLY $ matches \n in middle no PCRE_MULTILINE ^ matches \n in middle no PCRE_MULTILINE This is the equivalent table for POSIX: Default Change with . matches newline yes REG_NEWLINE newline matches [^a] yes REG_NEWLINE $ matches \n at end no REG_NEWLINE $ matches \n in middle no REG_NEWLINE ^ matches \n in middle no REG_NEWLINE PCRE's behaviour is the same as Perl's, except that there is no equiva- lent for PCRE_DOLLAR_ENDONLY in Perl. In both PCRE and Perl, there is no way to stop newline from matching [^a]. The default POSIX newline handling can be obtained by setting PCRE_DOTALL and PCRE_DOLLAR_ENDONLY, but there is no way to make PCRE behave exactly as for the REG_NEWLINE action. MATCHING A PATTERN The function regexec() is called to match a compiled pattern preg against a given string, which is by default terminated by a zero byte (but see REG_STARTEND below), subject to the options in eflags. These can be: REG_NOTBOL The PCRE_NOTBOL option is set when calling the underlying PCRE matching function. REG_NOTEMPTY The PCRE_NOTEMPTY option is set when calling the underlying PCRE match- ing function. Note that REG_NOTEMPTY is not part of the POSIX standard. However, setting this option can give more POSIX-like behaviour in some situations. REG_NOTEOL The PCRE_NOTEOL option is set when calling the underlying PCRE matching function. REG_STARTEND The string is considered to start at string + pmatch[0].rm_so and to have a terminating NUL located at string + pmatch[0].rm_eo (there need not actually be a NUL at that location), regardless of the value of nmatch. This is a BSD extension, compatible with but not specified by IEEE Standard 1003.2 (POSIX.2), and should be used with caution in software intended to be portable to other systems. Note that a non-zero rm_so does not imply REG_NOTBOL; REG_STARTEND affects only the location of the string, not how it is matched. If the pattern was compiled with the REG_NOSUB flag, no data about any matched strings is returned. The nmatch and pmatch arguments of regexec() are ignored. If the value of nmatch is zero, or if the value pmatch is NULL, no data about any matched strings is returned. Otherwise,the portion of the string that was matched, and also any cap- tured substrings, are returned via the pmatch argument, which points to an array of nmatch structures of type regmatch_t, containing the mem- bers rm_so and rm_eo. These contain the offset to the first character of each substring and the offset to the first character after the end of each substring, respectively. The 0th element of the vector relates to the entire portion of string that was matched; subsequent elements relate to the capturing subpatterns of the regular expression. Unused entries in the array have both structure members set to -1. A successful match yields a zero return; various error codes are defined in the header file, of which REG_NOMATCH is the "expected" failure code. ERROR MESSAGES The regerror() function maps a non-zero errorcode from either regcomp() or regexec() to a printable message. If preg is not NULL, the error should have arisen from the use of that structure. A message terminated by a binary zero is placed in errbuf. The length of the message, including the zero, is limited to errbuf_size. The yield of the func- tion is the size of buffer needed to hold the whole message. MEMORY USAGE Compiling a regular expression causes memory to be allocated and asso- ciated with the preg structure. The function regfree() frees all such memory, after which preg may no longer be used as a compiled expres- sion. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 09 January 2012 Copyright (c) 1997-2012 University of Cambridge. ------------------------------------------------------------------------------ PCRECPP(3) Library Functions Manual PCRECPP(3) NAME PCRE - Perl-compatible regular expressions. SYNOPSIS OF C++ WRAPPER #include DESCRIPTION The C++ wrapper for PCRE was provided by Google Inc. Some additional functionality was added by Giuseppe Maxia. This brief man page was con- structed from the notes in the pcrecpp.h file, which should be con- sulted for further details. Note that the C++ wrapper supports only the original 8-bit PCRE library. There is no 16-bit or 32-bit support at present. MATCHING INTERFACE The "FullMatch" operation checks that supplied text matches a supplied pattern exactly. If pointer arguments are supplied, it copies matched sub-strings that match sub-patterns into them. Example: successful match pcrecpp::RE re("h.*o"); re.FullMatch("hello"); Example: unsuccessful match (requires full match): pcrecpp::RE re("e"); !re.FullMatch("hello"); Example: creating a temporary RE object: pcrecpp::RE("h.*o").FullMatch("hello"); You can pass in a "const char*" or a "string" for "text". The examples below tend to use a const char*. You can, as in the different examples above, store the RE object explicitly in a variable or use a temporary RE object. The examples below use one mode or the other arbitrarily. Either could correctly be used for any of these examples. You must supply extra pointer arguments to extract matched subpieces. Example: extracts "ruby" into "s" and 1234 into "i" int i; string s; pcrecpp::RE re("(\\w+):(\\d+)"); re.FullMatch("ruby:1234", &s, &i); Example: does not try to extract any extra sub-patterns re.FullMatch("ruby:1234", &s); Example: does not try to extract into NULL re.FullMatch("ruby:1234", NULL, &i); Example: integer overflow causes failure !re.FullMatch("ruby:1234567891234", NULL, &i); Example: fails because there aren't enough sub-patterns: !pcrecpp::RE("\\w+:\\d+").FullMatch("ruby:1234", &s); Example: fails because string cannot be stored in integer !pcrecpp::RE("(.*)").FullMatch("ruby", &i); The provided pointer arguments can be pointers to any scalar numeric type, or one of: string (matched piece is copied to string) StringPiece (StringPiece is mutated to point to matched piece) T (where "bool T::ParseFrom(const char*, int)" exists) NULL (the corresponding matched sub-pattern is not copied) The function returns true iff all of the following conditions are sat- isfied: a. "text" matches "pattern" exactly; b. The number of matched sub-patterns is >= number of supplied pointers; c. The "i"th argument has a suitable type for holding the string captured as the "i"th sub-pattern. If you pass in void * NULL for the "i"th argument, or a non-void * NULL of the correct type, or pass fewer arguments than the number of sub-patterns, "i"th captured sub-pattern is ignored. CAVEAT: An optional sub-pattern that does not exist in the matched string is assigned the empty string. Therefore, the following will return false (because the empty string is not a valid number): int number; pcrecpp::RE::FullMatch("abc", "[a-z]+(\\d+)?", &number); The matching interface supports at most 16 arguments per call. If you need more, consider using the more general interface pcrecpp::RE::DoMatch. See pcrecpp.h for the signature for DoMatch. NOTE: Do not use no_arg, which is used internally to mark the end of a list of optional arguments, as a placeholder for missing arguments, as this can lead to segfaults. QUOTING METACHARACTERS You can use the "QuoteMeta" operation to insert backslashes before all potentially meaningful characters in a string. The returned string, used as a regular expression, will exactly match the original string. Example: string quoted = RE::QuoteMeta(unquoted); Note that it's legal to escape a character even if it has no special meaning in a regular expression -- so this function does that. (This also makes it identical to the perl function of the same name; see "perldoc -f quotemeta".) For example, "1.5-2.0?" becomes "1\.5\-2\.0\?". PARTIAL MATCHES You can use the "PartialMatch" operation when you want the pattern to match any substring of the text. Example: simple search for a string: pcrecpp::RE("ell").PartialMatch("hello"); Example: find first number in a string: int number; pcrecpp::RE re("(\\d+)"); re.PartialMatch("x*100 + 20", &number); assert(number == 100); UTF-8 AND THE MATCHING INTERFACE By default, pattern and text are plain text, one byte per character. The UTF8 flag, passed to the constructor, causes both pattern and string to be treated as UTF-8 text, still a byte stream but potentially multiple bytes per character. In practice, the text is likelier to be UTF-8 than the pattern, but the match returned may depend on the UTF8 flag, so always use it when matching UTF8 text. For example, "." will match one byte normally but with UTF8 set may match up to three bytes of a multi-byte character. Example: pcrecpp::RE_Options options; options.set_utf8(); pcrecpp::RE re(utf8_pattern, options); re.FullMatch(utf8_string); Example: using the convenience function UTF8(): pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8()); re.FullMatch(utf8_string); NOTE: The UTF8 flag is ignored if pcre was not configured with the --enable-utf8 flag. PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE PCRE defines some modifiers to change the behavior of the regular expression engine. The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle to pass such modifiers to a RE class. Cur- rently, the following modifiers are supported: modifier description Perl corresponding PCRE_CASELESS case insensitive match /i PCRE_MULTILINE multiple lines match /m PCRE_DOTALL dot matches newlines /s PCRE_DOLLAR_ENDONLY $ matches only at end N/A PCRE_EXTRA strict escape parsing N/A PCRE_EXTENDED ignore white spaces /x PCRE_UTF8 handles UTF8 chars built-in PCRE_UNGREEDY reverses * and *? N/A PCRE_NO_AUTO_CAPTURE disables capturing parens N/A (*) (*) Both Perl and PCRE allow non capturing parentheses by means of the "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not cap- ture, while (ab|cd) does. For a full account on how each modifier works, please check the PCRE API reference page. For each modifier, there are two member functions whose name is made out of the modifier in lowercase, without the "PCRE_" prefix. For instance, PCRE_CASELESS is handled by bool caseless() which returns true if the modifier is set, and RE_Options & set_caseless(bool) which sets or unsets the modifier. Moreover, PCRE_EXTRA_MATCH_LIMIT can be accessed through the set_match_limit() and match_limit() member functions. Setting match_limit to a non-zero value will limit the exe- cution of pcre to keep it from doing bad things like blowing the stack or taking an eternity to return a result. A value of 5000 is good enough to stop stack blowup in a 2MB thread stack. Setting match_limit to zero disables match limiting. Alternatively, you can call match_limit_recursion() which uses PCRE_EXTRA_MATCH_LIMIT_RECURSION to limit how much PCRE recurses. match_limit() limits the number of matches PCRE does; match_limit_recursion() limits the depth of internal recursion, and therefore the amount of stack that is used. Normally, to pass one or more modifiers to a RE class, you declare a RE_Options object, set the appropriate options, and pass this object to a RE constructor. Example: RE_Options opt; opt.set_caseless(true); if (RE("HELLO", opt).PartialMatch("hello world")) ... RE_options has two constructors. The default constructor takes no argu- ments and creates a set of flags that are off by default. The optional parameter option_flags is to facilitate transfer of legacy code from C programs. This lets you do RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); However, new code is better off doing RE(pattern, RE_Options().set_caseless(true).set_multiline(true)) .PartialMatch(str); If you are going to pass one of the most used modifiers, there are some convenience functions that return a RE_Options class with the appropri- ate modifier already set: CASELESS(), UTF8(), MULTILINE(), DOTALL(), and EXTENDED(). If you need to set several options at once, and you don't want to go through the pains of declaring a RE_Options object and setting several options, there is a parallel method that give you such ability on the fly. You can concatenate several set_xxxxx() member functions, since each of them returns a reference to its class object. For example, to pass PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one statement, you may write: RE(" ^ xyz \\s+ .* blah$", RE_Options() .set_caseless(true) .set_extended(true) .set_multiline(true)).PartialMatch(sometext); SCANNING TEXT INCREMENTALLY The "Consume" operation may be useful if you want to repeatedly match regular expressions at the front of a string and skip over them as they match. This requires use of the "StringPiece" type, which represents a sub-range of a real string. Like RE, StringPiece is defined in the pcrecpp namespace. Example: read lines of the form "var = value" from a string. string contents = ...; // Fill string somehow pcrecpp::StringPiece input(contents); // Wrap in a StringPiece string var; int value; pcrecpp::RE re("(\\w+) = (\\d+)\n"); while (re.Consume(&input, &var, &value)) { ...; } Each successful call to "Consume" will set "var/value", and also advance "input" so it points past the matched text. The "FindAndConsume" operation is similar to "Consume" but does not anchor your match at the beginning of the string. For example, you could extract all words from a string by repeatedly calling pcrecpp::RE("(\\w+)").FindAndConsume(&input, &word) PARSING HEX/OCTAL/C-RADIX NUMBERS By default, if you pass a pointer to a numeric value, the corresponding text is interpreted as a base-10 number. You can instead wrap the pointer with a call to one of the operators Hex(), Octal(), or CRadix() to interpret the text in another base. The CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) prefixes, but defaults to base-10. Example: int a, b, c, d; pcrecpp::RE re("(.*) (.*) (.*) (.*)"); re.FullMatch("100 40 0100 0x40", pcrecpp::Octal(&a), pcrecpp::Hex(&b), pcrecpp::CRadix(&c), pcrecpp::CRadix(&d)); will leave 64 in a, b, c, and d. REPLACING PARTS OF STRINGS You can replace the first match of "pattern" in "str" with "rewrite". Within "rewrite", backslash-escaped digits (\1 to \9) can be used to insert text matching corresponding parenthesized group from the pat- tern. \0 in "rewrite" refers to the entire matching text. For example: string s = "yabba dabba doo"; pcrecpp::RE("b+").Replace("d", &s); will leave "s" containing "yada dabba doo". The result is true if the pattern matches and a replacement occurs, false otherwise. GlobalReplace is like Replace except that it replaces all occurrences of the pattern in the string with the rewrite. Replacements are not subject to re-matching. For example: string s = "yabba dabba doo"; pcrecpp::RE("b+").GlobalReplace("d", &s); will leave "s" containing "yada dada doo". It returns the number of replacements made. Extract is like Replace, except that if the pattern matches, "rewrite" is copied into "out" (an additional argument) with substitutions. The non-matching portions of "text" are ignored. Returns true iff a match occurred and the extraction happened successfully; if no match occurs, the string is left unaffected. AUTHOR The C++ wrapper was contributed by Google Inc. Copyright (c) 2007 Google Inc. REVISION Last updated: 08 January 2012 ------------------------------------------------------------------------------ PCRESAMPLE(3) Library Functions Manual PCRESAMPLE(3) NAME PCRE - Perl-compatible regular expressions PCRE SAMPLE PROGRAM A simple, complete demonstration program, to get you started with using PCRE, is supplied in the file pcredemo.c in the PCRE distribution. A listing of this program is given in the pcredemo documentation. If you do not have a copy of the PCRE distribution, you can save this listing to re-create pcredemo.c. The demonstration program, which uses the original PCRE 8-bit library, compiles the regular expression that is its first argument, and matches it against the subject string in its second argument. No PCRE options are set, and default character tables are used. If matching succeeds, the program outputs the portion of the subject that matched, together with the contents of any captured substrings. If the -g option is given on the command line, the program then goes on to check for further matches of the same regular expression in the same subject string. The logic is a little bit tricky because of the possi- bility of matching an empty string. Comments in the code explain what is going on. If PCRE is installed in the standard include and library directories for your operating system, you should be able to compile the demonstra- tion program using this command: gcc -o pcredemo pcredemo.c -lpcre If PCRE is installed elsewhere, you may need to add additional options to the command line. For example, on a Unix-like system that has PCRE installed in /usr/local, you can compile the demonstration program using a command like this: gcc -o pcredemo -I/usr/local/include pcredemo.c \ -L/usr/local/lib -lpcre In a Windows environment, if you want to statically link the program against a non-dll pcre.a file, you must uncomment the line that defines PCRE_STATIC before including pcre.h, because otherwise the pcre_mal- loc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results. Once you have compiled and linked the demonstration program, you can run simple tests like this: ./pcredemo 'cat|dog' 'the cat sat on the mat' ./pcredemo -g 'cat|dog' 'the dog sat on the cat' Note that there is a much more comprehensive test program, called pcretest, which supports many more facilities for testing regular expressions and both PCRE libraries. The pcredemo program is provided as a simple coding example. If you try to run pcredemo when PCRE is not installed in the standard library directory, you may get an error like this on some operating systems (e.g. Solaris): ld.so.1: a.out: fatal: libpcre.so.0: open failed: No such file or directory This is caused by the way shared library support works on those sys- tems. You need to add -R/usr/local/lib (for example) to the compile command to get round this problem. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 10 January 2012 Copyright (c) 1997-2012 University of Cambridge. ------------------------------------------------------------------------------ PCRELIMITS(3) Library Functions Manual PCRELIMITS(3) NAME PCRE - Perl-compatible regular expressions SIZE AND OTHER LIMITATIONS There are some size limitations in PCRE but it is hoped that they will never in practice be relevant. The maximum length of a compiled pattern is approximately 64K data units (bytes for the 8-bit library, 16-bit units for the 16-bit library, and 32-bit units for the 32-bit library) if PCRE is compiled with the default internal linkage size, which is 2 bytes for the 8-bit and 16-bit libraries, and 4 bytes for the 32-bit library. If you want to process regular expressions that are truly enormous, you can compile PCRE with an internal linkage size of 3 or 4 (when building the 16-bit or 32-bit library, 3 is rounded up to 4). See the README file in the source distribution and the pcrebuild documentation for details. In these cases the limit is substantially larger. However, the speed of execution is slower. All values in repeating quantifiers must be less than 65536. There is no limit to the number of parenthesized subpatterns, but there can be no more than 65535 capturing subpatterns. There is, however, a limit to the depth of nesting of parenthesized subpatterns of all kinds. This is imposed in order to limit the amount of system stack used at compile time. The limit can be specified when PCRE is built; the default is 250. There is a limit to the number of forward references to subsequent sub- patterns of around 200,000. Repeated forward references with fixed upper limits, for example, (?2){0,100} when subpattern number 2 is to the right, are included in the count. There is no limit to the number of backward references. The maximum length of name for a named subpattern is 32 characters, and the maximum number of named subpatterns is 10000. The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb is 255 for the 8-bit library and 65535 for the 16-bit and 32-bit libraries. The maximum length of a subject string is the largest positive number that an integer variable can hold. However, when using the traditional matching function, PCRE uses recursion to handle subpatterns and indef- inite repetition. This means that the available stack space may limit the size of a subject string that can be processed by certain patterns. For a discussion of stack issues, see the pcrestack documentation. AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 05 November 2013 Copyright (c) 1997-2013 University of Cambridge. ------------------------------------------------------------------------------ PCRESTACK(3) Library Functions Manual PCRESTACK(3) NAME PCRE - Perl-compatible regular expressions PCRE DISCUSSION OF STACK USAGE When you call pcre[16|32]_exec(), it makes use of an internal function called match(). This calls itself recursively at branch points in the pattern, in order to remember the state of the match so that it can back up and try a different alternative if the first one fails. As matching proceeds deeper and deeper into the tree of possibilities, the recursion depth increases. The match() function is also called in other circumstances, for example, whenever a parenthesized sub-pattern is entered, and in certain cases of repetition. Not all calls of match() increase the recursion depth; for an item such as a* it may be called several times at the same level, after matching different numbers of a's. Furthermore, in a number of cases where the result of the recursive call would immediately be passed back as the result of the current call (a "tail recursion"), the function is just restarted instead. The above comments apply when pcre[16|32]_exec() is run in its normal interpretive manner. If the pattern was studied with the PCRE_STUDY_JIT_COMPILE option, and just-in-time compiling was success- ful, and the options passed to pcre[16|32]_exec() were not incompati- ble, the matching process uses the JIT-compiled code instead of the match() function. In this case, the memory requirements are handled entirely differently. See the pcrejit documentation for details. The pcre[16|32]_dfa_exec() function operates in an entirely different way, and uses recursion only when there is a regular expression recur- sion or subroutine call in the pattern. This includes the processing of assertion and "once-only" subpatterns, which are handled like subrou- tine calls. Normally, these are never very deep, and the limit on the complexity of pcre[16|32]_dfa_exec() is controlled by the amount of workspace it is given. However, it is possible to write patterns with runaway infinite recursions; such patterns will cause pcre[16|32]_dfa_exec() to run out of stack. At present, there is no protection against this. The comments that follow do NOT apply to pcre[16|32]_dfa_exec(); they are relevant only for pcre[16|32]_exec() without the JIT optimization. Reducing pcre[16|32]_exec()'s stack usage Each time that match() is actually called recursively, it uses memory from the process stack. For certain kinds of pattern and data, very large amounts of stack may be needed, despite the recognition of "tail recursion". You can often reduce the amount of recursion, and there- fore the amount of stack used, by modifying the pattern that is being matched. Consider, for example, this pattern: ([^<]|<(?!inet))+ It matches from wherever it starts until it encounters " . . .SH "PCRE 16-BIT API BASIC FUNCTIONS" .rs .sp .nf .B pcre16 *pcre16_compile(PCRE_SPTR16 \fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre16 *pcre16_compile2(PCRE_SPTR16 \fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP," .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre16_extra *pcre16_study(const pcre16 *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .sp .B void pcre16_free_study(pcre16_extra *\fIextra\fP); .sp .B int pcre16_exec(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " PCRE_SPTR16 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .sp .B int pcre16_dfa_exec(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " PCRE_SPTR16 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .fi . . .SH "PCRE 16-BIT API STRING EXTRACTION FUNCTIONS" .rs .sp .nf .B int pcre16_copy_named_substring(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR16 \fIstringname\fP," .B " PCRE_UCHAR16 *\fIbuffer\fP, int \fIbuffersize\fP);" .sp .B int pcre16_copy_substring(PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, PCRE_UCHAR16 *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .sp .B int pcre16_get_named_substring(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR16 \fIstringname\fP," .B " PCRE_SPTR16 *\fIstringptr\fP);" .sp .B int pcre16_get_stringnumber(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIname\fP); .sp .B int pcre16_get_stringtable_entries(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIname\fP, PCRE_UCHAR16 **\fIfirst\fP, PCRE_UCHAR16 **\fIlast\fP);" .sp .B int pcre16_get_substring(PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " PCRE_SPTR16 *\fIstringptr\fP);" .sp .B int pcre16_get_substring_list(PCRE_SPTR16 \fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, PCRE_SPTR16 **\fIlistptr\fP);" .sp .B void pcre16_free_substring(PCRE_SPTR16 \fIstringptr\fP); .sp .B void pcre16_free_substring_list(PCRE_SPTR16 *\fIstringptr\fP); .fi . . .SH "PCRE 16-BIT API AUXILIARY FUNCTIONS" .rs .sp .nf .B pcre16_jit_stack *pcre16_jit_stack_alloc(int \fIstartsize\fP, int \fImaxsize\fP); .sp .B void pcre16_jit_stack_free(pcre16_jit_stack *\fIstack\fP); .sp .B void pcre16_assign_jit_stack(pcre16_extra *\fIextra\fP, .B " pcre16_jit_callback \fIcallback\fP, void *\fIdata\fP);" .sp .B const unsigned char *pcre16_maketables(void); .sp .B int pcre16_fullinfo(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .sp .B int pcre16_refcount(pcre16 *\fIcode\fP, int \fIadjust\fP); .sp .B int pcre16_config(int \fIwhat\fP, void *\fIwhere\fP); .sp .B const char *pcre16_version(void); .sp .B int pcre16_pattern_to_host_byte_order(pcre16 *\fIcode\fP, .B " pcre16_extra *\fIextra\fP, const unsigned char *\fItables\fP);" .fi . . .SH "PCRE 16-BIT API INDIRECTED FUNCTIONS" .rs .sp .nf .B void *(*pcre16_malloc)(size_t); .sp .B void (*pcre16_free)(void *); .sp .B void *(*pcre16_stack_malloc)(size_t); .sp .B void (*pcre16_stack_free)(void *); .sp .B int (*pcre16_callout)(pcre16_callout_block *); .fi . . .SH "PCRE 16-BIT API 16-BIT-ONLY FUNCTION" .rs .sp .nf .B int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *\fIoutput\fP, .B " PCRE_SPTR16 \fIinput\fP, int \fIlength\fP, int *\fIbyte_order\fP," .B " int \fIkeep_boms\fP);" .fi . . .SH "THE PCRE 16-BIT LIBRARY" .rs .sp Starting with release 8.30, it is possible to compile a PCRE library that supports 16-bit character strings, including UTF-16 strings, as well as or instead of the original 8-bit library. The majority of the work to make this possible was done by Zoltan Herczeg. The two libraries contain identical sets of functions, used in exactly the same way. Only the names of the functions and the data types of their arguments and results are different. To avoid over-complication and reduce the documentation maintenance load, most of the PCRE documentation describes the 8-bit library, with only occasional references to the 16-bit library. This page describes what is different when you use the 16-bit library. .P WARNING: A single application can be linked with both libraries, but you must take care when processing any particular pattern to use functions from just one library. For example, if you want to study a pattern that was compiled with \fBpcre16_compile()\fP, you must do so with \fBpcre16_study()\fP, not \fBpcre_study()\fP, and you must free the study data with \fBpcre16_free_study()\fP. . . .SH "THE HEADER FILE" .rs .sp There is only one header file, \fBpcre.h\fP. It contains prototypes for all the functions in all libraries, as well as definitions of flags, structures, error codes, etc. . . .SH "THE LIBRARY NAME" .rs .sp In Unix-like systems, the 16-bit library is called \fBlibpcre16\fP, and can normally be accesss by adding \fB-lpcre16\fP to the command for linking an application that uses PCRE. . . .SH "STRING TYPES" .rs .sp In the 8-bit library, strings are passed to PCRE library functions as vectors of bytes with the C type "char *". In the 16-bit library, strings are passed as vectors of unsigned 16-bit quantities. The macro PCRE_UCHAR16 specifies an appropriate data type, and PCRE_SPTR16 is defined as "const PCRE_UCHAR16 *". In very many environments, "short int" is a 16-bit data type. When PCRE is built, it defines PCRE_UCHAR16 as "unsigned short int", but checks that it really is a 16-bit data type. If it is not, the build fails with an error message telling the maintainer to modify the definition appropriately. . . .SH "STRUCTURE TYPES" .rs .sp The types of the opaque structures that are used for compiled 16-bit patterns and JIT stacks are \fBpcre16\fP and \fBpcre16_jit_stack\fP respectively. The type of the user-accessible structure that is returned by \fBpcre16_study()\fP is \fBpcre16_extra\fP, and the type of the structure that is used for passing data to a callout function is \fBpcre16_callout_block\fP. These structures contain the same fields, with the same names, as their 8-bit counterparts. The only difference is that pointers to character strings are 16-bit instead of 8-bit types. . . .SH "16-BIT FUNCTIONS" .rs .sp For every function in the 8-bit library there is a corresponding function in the 16-bit library with a name that starts with \fBpcre16_\fP instead of \fBpcre_\fP. The prototypes are listed above. In addition, there is one extra function, \fBpcre16_utf16_to_host_byte_order()\fP. This is a utility function that converts a UTF-16 character string to host byte order if necessary. The other 16-bit functions expect the strings they are passed to be in host byte order. .P The \fIinput\fP and \fIoutput\fP arguments of \fBpcre16_utf16_to_host_byte_order()\fP may point to the same address, that is, conversion in place is supported. The output buffer must be at least as long as the input. .P The \fIlength\fP argument specifies the number of 16-bit data units in the input string; a negative value specifies a zero-terminated string. .P If \fIbyte_order\fP is NULL, it is assumed that the string starts off in host byte order. This may be changed by byte-order marks (BOMs) anywhere in the string (commonly as the first character). .P If \fIbyte_order\fP is not NULL, a non-zero value of the integer to which it points means that the input starts off in host byte order, otherwise the opposite order is assumed. Again, BOMs in the string can change this. The final byte order is passed back at the end of processing. .P If \fIkeep_boms\fP is not zero, byte-order mark characters (0xfeff) are copied into the output string. Otherwise they are discarded. .P The result of the function is the number of 16-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated. . . .SH "SUBJECT STRING OFFSETS" .rs .sp The lengths and starting offsets of subject strings must be specified in 16-bit data units, and the offsets within subject strings that are returned by the matching functions are in also 16-bit units rather than bytes. . . .SH "NAMED SUBPATTERNS" .rs .sp The name-to-number translation table that is maintained for named subpatterns uses 16-bit characters. The \fBpcre16_get_stringtable_entries()\fP function returns the length of each entry in the table as the number of 16-bit data units. . . .SH "OPTION NAMES" .rs .sp There are two new general option names, PCRE_UTF16 and PCRE_NO_UTF16_CHECK, which correspond to PCRE_UTF8 and PCRE_NO_UTF8_CHECK in the 8-bit library. In fact, these new options define the same bits in the options word. There is a discussion about the .\" HTML .\" validity of UTF-16 strings .\" in the .\" HREF \fBpcreunicode\fP .\" page. .P For the \fBpcre16_config()\fP function there is an option PCRE_CONFIG_UTF16 that returns 1 if UTF-16 support is configured, otherwise 0. If this option is given to \fBpcre_config()\fP or \fBpcre32_config()\fP, or if the PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF32 option is given to \fBpcre16_config()\fP, the result is the PCRE_ERROR_BADOPTION error. . . .SH "CHARACTER CODES" .rs .sp In 16-bit mode, when PCRE_UTF16 is not set, character values are treated in the same way as in 8-bit, non UTF-8 mode, except, of course, that they can range from 0 to 0xffff instead of 0 to 0xff. Character types for characters less than 0xff can therefore be influenced by the locale in the same way as before. Characters greater than 0xff have only one case, and no "type" (such as letter or digit). .P In UTF-16 mode, the character code is Unicode, in the range 0 to 0x10ffff, with the exception of values in the range 0xd800 to 0xdfff because those are "surrogate" values that are used in pairs to encode values greater than 0xffff. .P A UTF-16 string can indicate its endianness by special code knows as a byte-order mark (BOM). The PCRE functions do not handle this, expecting strings to be in host byte order. A utility function called \fBpcre16_utf16_to_host_byte_order()\fP is provided to help with this (see above). . . .SH "ERROR NAMES" .rs .sp The errors PCRE_ERROR_BADUTF16_OFFSET and PCRE_ERROR_SHORTUTF16 correspond to their 8-bit counterparts. The error PCRE_ERROR_BADMODE is given when a compiled pattern is passed to a function that processes patterns in the other mode, for example, if a pattern compiled with \fBpcre_compile()\fP is passed to \fBpcre16_exec()\fP. .P There are new error codes whose names begin with PCRE_UTF16_ERR for invalid UTF-16 strings, corresponding to the PCRE_UTF8_ERR codes for UTF-8 strings that are described in the section entitled .\" HTML .\" "Reason codes for invalid UTF-8 strings" .\" in the main .\" HREF \fBpcreapi\fP .\" page. The UTF-16 errors are: .sp PCRE_UTF16_ERR1 Missing low surrogate at end of string PCRE_UTF16_ERR2 Invalid low surrogate follows high surrogate PCRE_UTF16_ERR3 Isolated low surrogate PCRE_UTF16_ERR4 Non-character . . .SH "ERROR TEXTS" .rs .sp If there is an error while compiling a pattern, the error text that is passed back by \fBpcre16_compile()\fP or \fBpcre16_compile2()\fP is still an 8-bit character string, zero-terminated. . . .SH "CALLOUTS" .rs .sp The \fIsubject\fP and \fImark\fP fields in the callout block that is passed to a callout function point to 16-bit vectors. . . .SH "TESTING" .rs .sp The \fBpcretest\fP program continues to operate with 8-bit input and output files, but it can be used for testing the 16-bit library. If it is run with the command line option \fB-16\fP, patterns and subject strings are converted from 8-bit to 16-bit before being passed to PCRE, and the 16-bit library functions are used instead of the 8-bit ones. Returned 16-bit strings are converted to 8-bit for output. If both the 8-bit and the 32-bit libraries were not compiled, \fBpcretest\fP defaults to 16-bit and the \fB-16\fP option is ignored. .P When PCRE is being built, the \fBRunTest\fP script that is called by "make check" uses the \fBpcretest\fP \fB-C\fP option to discover which of the 8-bit, 16-bit and 32-bit libraries has been built, and runs the tests appropriately. . . .SH "NOT SUPPORTED IN 16-BIT MODE" .rs .sp Not all the features of the 8-bit library are available with the 16-bit library. The C++ and POSIX wrapper functions support only the 8-bit library, and the \fBpcregrep\fP program is at present 8-bit only. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 12 May 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcre32.3 ================================================ .TH PCRE 3 "12 May 2013" "PCRE 8.33" .SH NAME PCRE - Perl-compatible regular expressions .sp .B #include . . .SH "PCRE 32-BIT API BASIC FUNCTIONS" .rs .sp .nf .B pcre32 *pcre32_compile(PCRE_SPTR32 \fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre32 *pcre32_compile2(PCRE_SPTR32 \fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre32_extra *pcre32_study(const pcre32 *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .sp .B void pcre32_free_study(pcre32_extra *\fIextra\fP); .sp .B int pcre32_exec(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " PCRE_SPTR32 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .sp .B int pcre32_dfa_exec(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " PCRE_SPTR32 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .fi . . .SH "PCRE 32-BIT API STRING EXTRACTION FUNCTIONS" .rs .sp .nf .B int pcre32_copy_named_substring(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR32 \fIstringname\fP," .B " PCRE_UCHAR32 *\fIbuffer\fP, int \fIbuffersize\fP);" .sp .B int pcre32_copy_substring(PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, PCRE_UCHAR32 *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .sp .B int pcre32_get_named_substring(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR32 \fIstringname\fP," .B " PCRE_SPTR32 *\fIstringptr\fP);" .sp .B int pcre32_get_stringnumber(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIname\fP);" .sp .B int pcre32_get_stringtable_entries(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIname\fP, PCRE_UCHAR32 **\fIfirst\fP, PCRE_UCHAR32 **\fIlast\fP);" .sp .B int pcre32_get_substring(PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " PCRE_SPTR32 *\fIstringptr\fP);" .sp .B int pcre32_get_substring_list(PCRE_SPTR32 \fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, PCRE_SPTR32 **\fIlistptr\fP);" .sp .B void pcre32_free_substring(PCRE_SPTR32 \fIstringptr\fP); .sp .B void pcre32_free_substring_list(PCRE_SPTR32 *\fIstringptr\fP); .fi . . .SH "PCRE 32-BIT API AUXILIARY FUNCTIONS" .rs .sp .nf .B pcre32_jit_stack *pcre32_jit_stack_alloc(int \fIstartsize\fP, int \fImaxsize\fP); .sp .B void pcre32_jit_stack_free(pcre32_jit_stack *\fIstack\fP); .sp .B void pcre32_assign_jit_stack(pcre32_extra *\fIextra\fP, .B " pcre32_jit_callback \fIcallback\fP, void *\fIdata\fP);" .sp .B const unsigned char *pcre32_maketables(void); .sp .B int pcre32_fullinfo(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .sp .B int pcre32_refcount(pcre32 *\fIcode\fP, int \fIadjust\fP); .sp .B int pcre32_config(int \fIwhat\fP, void *\fIwhere\fP); .sp .B const char *pcre32_version(void); .sp .B int pcre32_pattern_to_host_byte_order(pcre32 *\fIcode\fP, .B " pcre32_extra *\fIextra\fP, const unsigned char *\fItables\fP);" .fi . . .SH "PCRE 32-BIT API INDIRECTED FUNCTIONS" .rs .sp .nf .B void *(*pcre32_malloc)(size_t); .sp .B void (*pcre32_free)(void *); .sp .B void *(*pcre32_stack_malloc)(size_t); .sp .B void (*pcre32_stack_free)(void *); .sp .B int (*pcre32_callout)(pcre32_callout_block *); .fi . . .SH "PCRE 32-BIT API 32-BIT-ONLY FUNCTION" .rs .sp .nf .B int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *\fIoutput\fP, .B " PCRE_SPTR32 \fIinput\fP, int \fIlength\fP, int *\fIbyte_order\fP," .B " int \fIkeep_boms\fP);" .fi . . .SH "THE PCRE 32-BIT LIBRARY" .rs .sp Starting with release 8.32, it is possible to compile a PCRE library that supports 32-bit character strings, including UTF-32 strings, as well as or instead of the original 8-bit library. This work was done by Christian Persch, based on the work done by Zoltan Herczeg for the 16-bit library. All three libraries contain identical sets of functions, used in exactly the same way. Only the names of the functions and the data types of their arguments and results are different. To avoid over-complication and reduce the documentation maintenance load, most of the PCRE documentation describes the 8-bit library, with only occasional references to the 16-bit and 32-bit libraries. This page describes what is different when you use the 32-bit library. .P WARNING: A single application can be linked with all or any of the three libraries, but you must take care when processing any particular pattern to use functions from just one library. For example, if you want to study a pattern that was compiled with \fBpcre32_compile()\fP, you must do so with \fBpcre32_study()\fP, not \fBpcre_study()\fP, and you must free the study data with \fBpcre32_free_study()\fP. . . .SH "THE HEADER FILE" .rs .sp There is only one header file, \fBpcre.h\fP. It contains prototypes for all the functions in all libraries, as well as definitions of flags, structures, error codes, etc. . . .SH "THE LIBRARY NAME" .rs .sp In Unix-like systems, the 32-bit library is called \fBlibpcre32\fP, and can normally be accesss by adding \fB-lpcre32\fP to the command for linking an application that uses PCRE. . . .SH "STRING TYPES" .rs .sp In the 8-bit library, strings are passed to PCRE library functions as vectors of bytes with the C type "char *". In the 32-bit library, strings are passed as vectors of unsigned 32-bit quantities. The macro PCRE_UCHAR32 specifies an appropriate data type, and PCRE_SPTR32 is defined as "const PCRE_UCHAR32 *". In very many environments, "unsigned int" is a 32-bit data type. When PCRE is built, it defines PCRE_UCHAR32 as "unsigned int", but checks that it really is a 32-bit data type. If it is not, the build fails with an error message telling the maintainer to modify the definition appropriately. . . .SH "STRUCTURE TYPES" .rs .sp The types of the opaque structures that are used for compiled 32-bit patterns and JIT stacks are \fBpcre32\fP and \fBpcre32_jit_stack\fP respectively. The type of the user-accessible structure that is returned by \fBpcre32_study()\fP is \fBpcre32_extra\fP, and the type of the structure that is used for passing data to a callout function is \fBpcre32_callout_block\fP. These structures contain the same fields, with the same names, as their 8-bit counterparts. The only difference is that pointers to character strings are 32-bit instead of 8-bit types. . . .SH "32-BIT FUNCTIONS" .rs .sp For every function in the 8-bit library there is a corresponding function in the 32-bit library with a name that starts with \fBpcre32_\fP instead of \fBpcre_\fP. The prototypes are listed above. In addition, there is one extra function, \fBpcre32_utf32_to_host_byte_order()\fP. This is a utility function that converts a UTF-32 character string to host byte order if necessary. The other 32-bit functions expect the strings they are passed to be in host byte order. .P The \fIinput\fP and \fIoutput\fP arguments of \fBpcre32_utf32_to_host_byte_order()\fP may point to the same address, that is, conversion in place is supported. The output buffer must be at least as long as the input. .P The \fIlength\fP argument specifies the number of 32-bit data units in the input string; a negative value specifies a zero-terminated string. .P If \fIbyte_order\fP is NULL, it is assumed that the string starts off in host byte order. This may be changed by byte-order marks (BOMs) anywhere in the string (commonly as the first character). .P If \fIbyte_order\fP is not NULL, a non-zero value of the integer to which it points means that the input starts off in host byte order, otherwise the opposite order is assumed. Again, BOMs in the string can change this. The final byte order is passed back at the end of processing. .P If \fIkeep_boms\fP is not zero, byte-order mark characters (0xfeff) are copied into the output string. Otherwise they are discarded. .P The result of the function is the number of 32-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated. . . .SH "SUBJECT STRING OFFSETS" .rs .sp The lengths and starting offsets of subject strings must be specified in 32-bit data units, and the offsets within subject strings that are returned by the matching functions are in also 32-bit units rather than bytes. . . .SH "NAMED SUBPATTERNS" .rs .sp The name-to-number translation table that is maintained for named subpatterns uses 32-bit characters. The \fBpcre32_get_stringtable_entries()\fP function returns the length of each entry in the table as the number of 32-bit data units. . . .SH "OPTION NAMES" .rs .sp There are two new general option names, PCRE_UTF32 and PCRE_NO_UTF32_CHECK, which correspond to PCRE_UTF8 and PCRE_NO_UTF8_CHECK in the 8-bit library. In fact, these new options define the same bits in the options word. There is a discussion about the .\" HTML .\" validity of UTF-32 strings .\" in the .\" HREF \fBpcreunicode\fP .\" page. .P For the \fBpcre32_config()\fP function there is an option PCRE_CONFIG_UTF32 that returns 1 if UTF-32 support is configured, otherwise 0. If this option is given to \fBpcre_config()\fP or \fBpcre16_config()\fP, or if the PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF16 option is given to \fBpcre32_config()\fP, the result is the PCRE_ERROR_BADOPTION error. . . .SH "CHARACTER CODES" .rs .sp In 32-bit mode, when PCRE_UTF32 is not set, character values are treated in the same way as in 8-bit, non UTF-8 mode, except, of course, that they can range from 0 to 0x7fffffff instead of 0 to 0xff. Character types for characters less than 0xff can therefore be influenced by the locale in the same way as before. Characters greater than 0xff have only one case, and no "type" (such as letter or digit). .P In UTF-32 mode, the character code is Unicode, in the range 0 to 0x10ffff, with the exception of values in the range 0xd800 to 0xdfff because those are "surrogate" values that are ill-formed in UTF-32. .P A UTF-32 string can indicate its endianness by special code knows as a byte-order mark (BOM). The PCRE functions do not handle this, expecting strings to be in host byte order. A utility function called \fBpcre32_utf32_to_host_byte_order()\fP is provided to help with this (see above). . . .SH "ERROR NAMES" .rs .sp The error PCRE_ERROR_BADUTF32 corresponds to its 8-bit counterpart. The error PCRE_ERROR_BADMODE is given when a compiled pattern is passed to a function that processes patterns in the other mode, for example, if a pattern compiled with \fBpcre_compile()\fP is passed to \fBpcre32_exec()\fP. .P There are new error codes whose names begin with PCRE_UTF32_ERR for invalid UTF-32 strings, corresponding to the PCRE_UTF8_ERR codes for UTF-8 strings that are described in the section entitled .\" HTML .\" "Reason codes for invalid UTF-8 strings" .\" in the main .\" HREF \fBpcreapi\fP .\" page. The UTF-32 errors are: .sp PCRE_UTF32_ERR1 Surrogate character (range from 0xd800 to 0xdfff) PCRE_UTF32_ERR2 Non-character PCRE_UTF32_ERR3 Character > 0x10ffff . . .SH "ERROR TEXTS" .rs .sp If there is an error while compiling a pattern, the error text that is passed back by \fBpcre32_compile()\fP or \fBpcre32_compile2()\fP is still an 8-bit character string, zero-terminated. . . .SH "CALLOUTS" .rs .sp The \fIsubject\fP and \fImark\fP fields in the callout block that is passed to a callout function point to 32-bit vectors. . . .SH "TESTING" .rs .sp The \fBpcretest\fP program continues to operate with 8-bit input and output files, but it can be used for testing the 32-bit library. If it is run with the command line option \fB-32\fP, patterns and subject strings are converted from 8-bit to 32-bit before being passed to PCRE, and the 32-bit library functions are used instead of the 8-bit ones. Returned 32-bit strings are converted to 8-bit for output. If both the 8-bit and the 16-bit libraries were not compiled, \fBpcretest\fP defaults to 32-bit and the \fB-32\fP option is ignored. .P When PCRE is being built, the \fBRunTest\fP script that is called by "make check" uses the \fBpcretest\fP \fB-C\fP option to discover which of the 8-bit, 16-bit and 32-bit libraries has been built, and runs the tests appropriately. . . .SH "NOT SUPPORTED IN 32-BIT MODE" .rs .sp Not all the features of the 8-bit library are available with the 32-bit library. The C++ and POSIX wrapper functions support only the 8-bit library, and the \fBpcregrep\fP program is at present 8-bit only. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 12 May 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcre_assign_jit_stack.3 ================================================ .TH PCRE_ASSIGN_JIT_STACK 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B void pcre_assign_jit_stack(pcre_extra *\fIextra\fP, .B " pcre_jit_callback \fIcallback\fP, void *\fIdata\fP);" .sp .B void pcre16_assign_jit_stack(pcre16_extra *\fIextra\fP, .B " pcre16_jit_callback \fIcallback\fP, void *\fIdata\fP);" .sp .B void pcre32_assign_jit_stack(pcre32_extra *\fIextra\fP, .B " pcre32_jit_callback \fIcallback\fP, void *\fIdata\fP);" .fi . .SH DESCRIPTION .rs .sp This function provides control over the memory used as a stack at run-time by a call to \fBpcre[16|32]_exec()\fP with a pattern that has been successfully compiled with JIT optimization. The arguments are: .sp extra the data pointer returned by \fBpcre[16|32]_study()\fP callback a callback function data a JIT stack or a value to be passed to the callback function .P If \fIcallback\fP is NULL and \fIdata\fP is NULL, an internal 32K block on the machine stack is used. .P If \fIcallback\fP is NULL and \fIdata\fP is not NULL, \fIdata\fP must be a valid JIT stack, the result of calling \fBpcre[16|32]_jit_stack_alloc()\fP. .P If \fIcallback\fP not NULL, it is called with \fIdata\fP as an argument at the start of matching, in order to set up a JIT stack. If the result is NULL, the internal 32K stack is used; otherwise the return value must be a valid JIT stack, the result of calling \fBpcre[16|32]_jit_stack_alloc()\fP. .P You may safely assign the same JIT stack to multiple patterns, as long as they are all matched in the same thread. In a multithread application, each thread must use its own JIT stack. For more details, see the .\" HREF \fBpcrejit\fP .\" page. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_compile.3 ================================================ .TH PCRE_COMPILE 3 "01 October 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B pcre *pcre_compile(const char *\fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre16 *pcre16_compile(PCRE_SPTR16 \fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre32 *pcre32_compile(PCRE_SPTR32 \fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .fi . .SH DESCRIPTION .rs .sp This function compiles a regular expression into an internal form. It is the same as \fBpcre[16|32]_compile2()\fP, except for the absence of the \fIerrorcodeptr\fP argument. Its arguments are: .sp \fIpattern\fP A zero-terminated string containing the regular expression to be compiled \fIoptions\fP Zero or more option bits \fIerrptr\fP Where to put an error message \fIerroffset\fP Offset in pattern where error was found \fItableptr\fP Pointer to character tables, or NULL to use the built-in default .sp The option bits are: .sp PCRE_ANCHORED Force pattern anchoring PCRE_AUTO_CALLOUT Compile automatic callouts PCRE_BSR_ANYCRLF \eR matches only CR, LF, or CRLF PCRE_BSR_UNICODE \eR matches all Unicode line endings PCRE_CASELESS Do caseless matching PCRE_DOLLAR_ENDONLY $ not to match newline at end PCRE_DOTALL . matches anything including NL PCRE_DUPNAMES Allow duplicate names for subpatterns PCRE_EXTENDED Ignore white space and # comments PCRE_EXTRA PCRE extra features (not much use currently) PCRE_FIRSTLINE Force matching to be before newline PCRE_JAVASCRIPT_COMPAT JavaScript compatibility PCRE_MULTILINE ^ and $ match newlines within data PCRE_NEVER_UTF Lock out UTF, e.g. via (*UTF) PCRE_NEWLINE_ANY Recognize any Unicode newline sequence PCRE_NEWLINE_ANYCRLF Recognize CR, LF, and CRLF as newline sequences PCRE_NEWLINE_CR Set CR as the newline sequence PCRE_NEWLINE_CRLF Set CRLF as the newline sequence PCRE_NEWLINE_LF Set LF as the newline sequence PCRE_NO_AUTO_CAPTURE Disable numbered capturing paren- theses (named ones available) PCRE_NO_AUTO_POSSESS Disable auto-possessification PCRE_NO_START_OPTIMIZE Disable match-time start optimizations PCRE_NO_UTF16_CHECK Do not check the pattern for UTF-16 validity (only relevant if PCRE_UTF16 is set) PCRE_NO_UTF32_CHECK Do not check the pattern for UTF-32 validity (only relevant if PCRE_UTF32 is set) PCRE_NO_UTF8_CHECK Do not check the pattern for UTF-8 validity (only relevant if PCRE_UTF8 is set) PCRE_UCP Use Unicode properties for \ed, \ew, etc. PCRE_UNGREEDY Invert greediness of quantifiers PCRE_UTF16 Run in \fBpcre16_compile()\fP UTF-16 mode PCRE_UTF32 Run in \fBpcre32_compile()\fP UTF-32 mode PCRE_UTF8 Run in \fBpcre_compile()\fP UTF-8 mode .sp PCRE must be built with UTF support in order to use PCRE_UTF8/16/32 and PCRE_NO_UTF8/16/32_CHECK, and with UCP support if PCRE_UCP is used. .P The yield of the function is a pointer to a private data structure that contains the compiled pattern, or NULL if an error was detected. Note that compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_compile2.3 ================================================ .TH PCRE_COMPILE2 3 "01 October 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B pcre *pcre_compile2(const char *\fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP," .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre16 *pcre16_compile2(PCRE_SPTR16 \fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP," .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre32 *pcre32_compile2(PCRE_SPTR32 \fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP,£ .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .fi . .SH DESCRIPTION .rs .sp This function compiles a regular expression into an internal form. It is the same as \fBpcre[16|32]_compile()\fP, except for the addition of the \fIerrorcodeptr\fP argument. The arguments are: . .sp \fIpattern\fP A zero-terminated string containing the regular expression to be compiled \fIoptions\fP Zero or more option bits \fIerrorcodeptr\fP Where to put an error code \fIerrptr\fP Where to put an error message \fIerroffset\fP Offset in pattern where error was found \fItableptr\fP Pointer to character tables, or NULL to use the built-in default .sp The option bits are: .sp PCRE_ANCHORED Force pattern anchoring PCRE_AUTO_CALLOUT Compile automatic callouts PCRE_BSR_ANYCRLF \eR matches only CR, LF, or CRLF PCRE_BSR_UNICODE \eR matches all Unicode line endings PCRE_CASELESS Do caseless matching PCRE_DOLLAR_ENDONLY $ not to match newline at end PCRE_DOTALL . matches anything including NL PCRE_DUPNAMES Allow duplicate names for subpatterns PCRE_EXTENDED Ignore white space and # comments PCRE_EXTRA PCRE extra features (not much use currently) PCRE_FIRSTLINE Force matching to be before newline PCRE_JAVASCRIPT_COMPAT JavaScript compatibility PCRE_MULTILINE ^ and $ match newlines within data PCRE_NEVER_UTF Lock out UTF, e.g. via (*UTF) PCRE_NEWLINE_ANY Recognize any Unicode newline sequence PCRE_NEWLINE_ANYCRLF Recognize CR, LF, and CRLF as newline sequences PCRE_NEWLINE_CR Set CR as the newline sequence PCRE_NEWLINE_CRLF Set CRLF as the newline sequence PCRE_NEWLINE_LF Set LF as the newline sequence PCRE_NO_AUTO_CAPTURE Disable numbered capturing paren- theses (named ones available) PCRE_NO_AUTO_POSSESS Disable auto-possessification PCRE_NO_START_OPTIMIZE Disable match-time start optimizations PCRE_NO_UTF16_CHECK Do not check the pattern for UTF-16 validity (only relevant if PCRE_UTF16 is set) PCRE_NO_UTF32_CHECK Do not check the pattern for UTF-32 validity (only relevant if PCRE_UTF32 is set) PCRE_NO_UTF8_CHECK Do not check the pattern for UTF-8 validity (only relevant if PCRE_UTF8 is set) PCRE_UCP Use Unicode properties for \ed, \ew, etc. PCRE_UNGREEDY Invert greediness of quantifiers PCRE_UTF16 Run \fBpcre16_compile()\fP in UTF-16 mode PCRE_UTF32 Run \fBpcre32_compile()\fP in UTF-32 mode PCRE_UTF8 Run \fBpcre_compile()\fP in UTF-8 mode .sp PCRE must be built with UTF support in order to use PCRE_UTF8/16/32 and PCRE_NO_UTF8/16/32_CHECK, and with UCP support if PCRE_UCP is used. .P The yield of the function is a pointer to a private data structure that contains the compiled pattern, or NULL if an error was detected. Note that compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_config.3 ================================================ .TH PCRE_CONFIG 3 "20 April 2014" "PCRE 8.36" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B int pcre_config(int \fIwhat\fP, void *\fIwhere\fP); .PP .B int pcre16_config(int \fIwhat\fP, void *\fIwhere\fP); .PP .B int pcre32_config(int \fIwhat\fP, void *\fIwhere\fP); . .SH DESCRIPTION .rs .sp This function makes it possible for a client program to find out which optional features are available in the version of the PCRE library it is using. The arguments are as follows: .sp \fIwhat\fP A code specifying what information is required \fIwhere\fP Points to where to put the data .sp The \fIwhere\fP argument must point to an integer variable, except for PCRE_CONFIG_MATCH_LIMIT, PCRE_CONFIG_MATCH_LIMIT_RECURSION, and PCRE_CONFIG_PARENS_LIMIT, when it must point to an unsigned long integer, and for PCRE_CONFIG_JITTARGET, when it must point to a const char*. The available codes are: .sp PCRE_CONFIG_JIT Availability of just-in-time compiler support (1=yes 0=no) PCRE_CONFIG_JITTARGET String containing information about the target architecture for the JIT compiler, or NULL if there is no JIT support PCRE_CONFIG_LINK_SIZE Internal link size: 2, 3, or 4 PCRE_CONFIG_PARENS_LIMIT Parentheses nesting limit PCRE_CONFIG_MATCH_LIMIT Internal resource limit PCRE_CONFIG_MATCH_LIMIT_RECURSION Internal recursion depth limit PCRE_CONFIG_NEWLINE Value of the default newline sequence: 13 (0x000d) for CR 10 (0x000a) for LF 3338 (0x0d0a) for CRLF -2 for ANYCRLF -1 for ANY PCRE_CONFIG_BSR Indicates what \eR matches by default: 0 all Unicode line endings 1 CR, LF, or CRLF only PCRE_CONFIG_POSIX_MALLOC_THRESHOLD Threshold of return slots, above which \fBmalloc()\fP is used by the POSIX API PCRE_CONFIG_STACKRECURSE Recursion implementation (1=stack 0=heap) PCRE_CONFIG_UTF16 Availability of UTF-16 support (1=yes 0=no); option for \fBpcre16_config()\fP PCRE_CONFIG_UTF32 Availability of UTF-32 support (1=yes 0=no); option for \fBpcre32_config()\fP PCRE_CONFIG_UTF8 Availability of UTF-8 support (1=yes 0=no); option for \fBpcre_config()\fP PCRE_CONFIG_UNICODE_PROPERTIES Availability of Unicode property support (1=yes 0=no) .sp The function yields 0 on success or PCRE_ERROR_BADOPTION otherwise. That error is also given if PCRE_CONFIG_UTF16 or PCRE_CONFIG_UTF32 is passed to \fBpcre_config()\fP, if PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF32 is passed to \fBpcre16_config()\fP, or if PCRE_CONFIG_UTF8 or PCRE_CONFIG_UTF16 is passed to \fBpcre32_config()\fP. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_copy_named_substring.3 ================================================ .TH PCRE_COPY_NAMED_SUBSTRING 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_copy_named_substring(const pcre *\fIcode\fP, .B " const char *\fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, const char *\fIstringname\fP," .B " char *\fIbuffer\fP, int \fIbuffersize\fP);" .sp .B int pcre16_copy_named_substring(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR16 \fIstringname\fP," .B " PCRE_UCHAR16 *\fIbuffer\fP, int \fIbuffersize\fP);" .sp .B int pcre32_copy_named_substring(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR32 \fIstringname\fP," .B " PCRE_UCHAR32 *\fIbuffer\fP, int \fIbuffersize\fP);" .fi . .SH DESCRIPTION .rs .sp This is a convenience function for extracting a captured substring, identified by name, into a given buffer. The arguments are: .sp \fIcode\fP Pattern that was successfully matched \fIsubject\fP Subject that has been successfully matched \fIovector\fP Offset vector that \fBpcre[16|32]_exec()\fP used \fIstringcount\fP Value returned by \fBpcre[16|32]_exec()\fP \fIstringname\fP Name of the required substring \fIbuffer\fP Buffer to receive the string \fIbuffersize\fP Size of buffer .sp The yield is the length of the substring, PCRE_ERROR_NOMEMORY if the buffer was too small, or PCRE_ERROR_NOSUBSTRING if the string name is invalid. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_copy_substring.3 ================================================ .TH PCRE_COPY_SUBSTRING 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_copy_substring(const char *\fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, char *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .sp .B int pcre16_copy_substring(PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, PCRE_UCHAR16 *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .sp .B int pcre32_copy_substring(PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, PCRE_UCHAR32 *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .fi . .SH DESCRIPTION .rs .sp This is a convenience function for extracting a captured substring into a given buffer. The arguments are: .sp \fIsubject\fP Subject that has been successfully matched \fIovector\fP Offset vector that \fBpcre[16|32]_exec()\fP used \fIstringcount\fP Value returned by \fBpcre[16|32]_exec()\fP \fIstringnumber\fP Number of the required substring \fIbuffer\fP Buffer to receive the string \fIbuffersize\fP Size of buffer .sp The yield is the length of the string, PCRE_ERROR_NOMEMORY if the buffer was too small, or PCRE_ERROR_NOSUBSTRING if the string number is invalid. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_dfa_exec.3 ================================================ .TH PCRE_DFA_EXEC 3 "12 May 2013" "PCRE 8.33" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_dfa_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .sp .B int pcre16_dfa_exec(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " PCRE_SPTR16 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .sp .B int pcre32_dfa_exec(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " PCRE_SPTR32 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .fi . .SH DESCRIPTION .rs .sp This function matches a compiled regular expression against a given subject string, using an alternative matching algorithm that scans the subject string just once (\fInot\fP Perl-compatible). Note that the main, Perl-compatible, matching function is \fBpcre[16|32]_exec()\fP. The arguments for this function are: .sp \fIcode\fP Points to the compiled pattern \fIextra\fP Points to an associated \fBpcre[16|32]_extra\fP structure, or is NULL \fIsubject\fP Points to the subject string \fIlength\fP Length of the subject string \fIstartoffset\fP Offset in the subject at which to start matching \fIoptions\fP Option bits \fIovector\fP Points to a vector of ints for result offsets \fIovecsize\fP Number of elements in the vector \fIworkspace\fP Points to a vector of ints used as working space \fIwscount\fP Number of elements in the vector .sp The units for \fIlength\fP and \fIstartoffset\fP are bytes for \fBpcre_exec()\fP, 16-bit data items for \fBpcre16_exec()\fP, and 32-bit items for \fBpcre32_exec()\fP. The options are: .sp PCRE_ANCHORED Match only at the first position PCRE_BSR_ANYCRLF \eR matches only CR, LF, or CRLF PCRE_BSR_UNICODE \eR matches all Unicode line endings PCRE_NEWLINE_ANY Recognize any Unicode newline sequence PCRE_NEWLINE_ANYCRLF Recognize CR, LF, & CRLF as newline sequences PCRE_NEWLINE_CR Recognize CR as the only newline sequence PCRE_NEWLINE_CRLF Recognize CRLF as the only newline sequence PCRE_NEWLINE_LF Recognize LF as the only newline sequence PCRE_NOTBOL Subject is not the beginning of a line PCRE_NOTEOL Subject is not the end of a line PCRE_NOTEMPTY An empty string is not a valid match PCRE_NOTEMPTY_ATSTART An empty string at the start of the subject is not a valid match PCRE_NO_START_OPTIMIZE Do not do "start-match" optimizations PCRE_NO_UTF16_CHECK Do not check the subject for UTF-16 validity (only relevant if PCRE_UTF16 was set at compile time) PCRE_NO_UTF32_CHECK Do not check the subject for UTF-32 validity (only relevant if PCRE_UTF32 was set at compile time) PCRE_NO_UTF8_CHECK Do not check the subject for UTF-8 validity (only relevant if PCRE_UTF8 was set at compile time) PCRE_PARTIAL ) Return PCRE_ERROR_PARTIAL for a partial PCRE_PARTIAL_SOFT ) match if no full matches are found PCRE_PARTIAL_HARD Return PCRE_ERROR_PARTIAL for a partial match even if there is a full match as well PCRE_DFA_SHORTEST Return only the shortest match PCRE_DFA_RESTART Restart after a partial match .sp There are restrictions on what may appear in a pattern when using this matching function. Details are given in the .\" HREF \fBpcrematching\fP .\" documentation. For details of partial matching, see the .\" HREF \fBpcrepartial\fP .\" page. .P A \fBpcre[16|32]_extra\fP structure contains the following fields: .sp \fIflags\fP Bits indicating which fields are set \fIstudy_data\fP Opaque data from \fBpcre[16|32]_study()\fP \fImatch_limit\fP Limit on internal resource use \fImatch_limit_recursion\fP Limit on internal recursion depth \fIcallout_data\fP Opaque data passed back to callouts \fItables\fP Points to character tables or is NULL \fImark\fP For passing back a *MARK pointer \fIexecutable_jit\fP Opaque data from JIT compilation .sp The flag bits are PCRE_EXTRA_STUDY_DATA, PCRE_EXTRA_MATCH_LIMIT, PCRE_EXTRA_MATCH_LIMIT_RECURSION, PCRE_EXTRA_CALLOUT_DATA, PCRE_EXTRA_TABLES, PCRE_EXTRA_MARK and PCRE_EXTRA_EXECUTABLE_JIT. For this matching function, the \fImatch_limit\fP and \fImatch_limit_recursion\fP fields are not used, and must not be set. The PCRE_EXTRA_EXECUTABLE_JIT flag and the corresponding variable are ignored. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_exec.3 ================================================ .TH PCRE_EXEC 3 "12 May 2013" "PCRE 8.33" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .sp .B int pcre16_exec(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " PCRE_SPTR16 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .sp .B int pcre32_exec(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " PCRE_SPTR32 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .fi . .SH DESCRIPTION .rs .sp This function matches a compiled regular expression against a given subject string, using a matching algorithm that is similar to Perl's. It returns offsets to captured substrings. Its arguments are: .sp \fIcode\fP Points to the compiled pattern \fIextra\fP Points to an associated \fBpcre[16|32]_extra\fP structure, or is NULL \fIsubject\fP Points to the subject string \fIlength\fP Length of the subject string \fIstartoffset\fP Offset in the subject at which to start matching \fIoptions\fP Option bits \fIovector\fP Points to a vector of ints for result offsets \fIovecsize\fP Number of elements in the vector (a multiple of 3) .sp The units for \fIlength\fP and \fIstartoffset\fP are bytes for \fBpcre_exec()\fP, 16-bit data items for \fBpcre16_exec()\fP, and 32-bit items for \fBpcre32_exec()\fP. The options are: .sp PCRE_ANCHORED Match only at the first position PCRE_BSR_ANYCRLF \eR matches only CR, LF, or CRLF PCRE_BSR_UNICODE \eR matches all Unicode line endings PCRE_NEWLINE_ANY Recognize any Unicode newline sequence PCRE_NEWLINE_ANYCRLF Recognize CR, LF, & CRLF as newline sequences PCRE_NEWLINE_CR Recognize CR as the only newline sequence PCRE_NEWLINE_CRLF Recognize CRLF as the only newline sequence PCRE_NEWLINE_LF Recognize LF as the only newline sequence PCRE_NOTBOL Subject string is not the beginning of a line PCRE_NOTEOL Subject string is not the end of a line PCRE_NOTEMPTY An empty string is not a valid match PCRE_NOTEMPTY_ATSTART An empty string at the start of the subject is not a valid match PCRE_NO_START_OPTIMIZE Do not do "start-match" optimizations PCRE_NO_UTF16_CHECK Do not check the subject for UTF-16 validity (only relevant if PCRE_UTF16 was set at compile time) PCRE_NO_UTF32_CHECK Do not check the subject for UTF-32 validity (only relevant if PCRE_UTF32 was set at compile time) PCRE_NO_UTF8_CHECK Do not check the subject for UTF-8 validity (only relevant if PCRE_UTF8 was set at compile time) PCRE_PARTIAL ) Return PCRE_ERROR_PARTIAL for a partial PCRE_PARTIAL_SOFT ) match if no full matches are found PCRE_PARTIAL_HARD Return PCRE_ERROR_PARTIAL for a partial match if that is found before a full match .sp For details of partial matching, see the .\" HREF \fBpcrepartial\fP .\" page. A \fBpcre_extra\fP structure contains the following fields: .sp \fIflags\fP Bits indicating which fields are set \fIstudy_data\fP Opaque data from \fBpcre[16|32]_study()\fP \fImatch_limit\fP Limit on internal resource use \fImatch_limit_recursion\fP Limit on internal recursion depth \fIcallout_data\fP Opaque data passed back to callouts \fItables\fP Points to character tables or is NULL \fImark\fP For passing back a *MARK pointer \fIexecutable_jit\fP Opaque data from JIT compilation .sp The flag bits are PCRE_EXTRA_STUDY_DATA, PCRE_EXTRA_MATCH_LIMIT, PCRE_EXTRA_MATCH_LIMIT_RECURSION, PCRE_EXTRA_CALLOUT_DATA, PCRE_EXTRA_TABLES, PCRE_EXTRA_MARK and PCRE_EXTRA_EXECUTABLE_JIT. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_free_study.3 ================================================ .TH PCRE_FREE_STUDY 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B void pcre_free_study(pcre_extra *\fIextra\fP); .PP .B void pcre16_free_study(pcre16_extra *\fIextra\fP); .PP .B void pcre32_free_study(pcre32_extra *\fIextra\fP); . .SH DESCRIPTION .rs .sp This function is used to free the memory used for the data generated by a call to \fBpcre[16|32]_study()\fP when it is no longer needed. The argument must be the result of such a call. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_free_substring.3 ================================================ .TH PCRE_FREE_SUBSTRING 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B void pcre_free_substring(const char *\fIstringptr\fP); .PP .B void pcre16_free_substring(PCRE_SPTR16 \fIstringptr\fP); .PP .B void pcre32_free_substring(PCRE_SPTR32 \fIstringptr\fP); . .SH DESCRIPTION .rs .sp This is a convenience function for freeing the store obtained by a previous call to \fBpcre[16|32]_get_substring()\fP or \fBpcre[16|32]_get_named_substring()\fP. Its only argument is a pointer to the string. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_free_substring_list.3 ================================================ .TH PCRE_FREE_SUBSTRING_LIST 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B void pcre_free_substring_list(const char **\fIstringptr\fP); .PP .B void pcre16_free_substring_list(PCRE_SPTR16 *\fIstringptr\fP); .PP .B void pcre32_free_substring_list(PCRE_SPTR32 *\fIstringptr\fP); . .SH DESCRIPTION .rs .sp This is a convenience function for freeing the store obtained by a previous call to \fBpcre[16|32]_get_substring_list()\fP. Its only argument is a pointer to the list of string pointers. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_fullinfo.3 ================================================ .TH PCRE_FULLINFO 3 "21 April 2014" "PCRE 8.36" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_fullinfo(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .sp .B int pcre16_fullinfo(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .sp .B int pcre32_fullinfo(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .fi . .SH DESCRIPTION .rs .sp This function returns information about a compiled pattern. Its arguments are: .sp \fIcode\fP Compiled regular expression \fIextra\fP Result of \fBpcre[16|32]_study()\fP or NULL \fIwhat\fP What information is required \fIwhere\fP Where to put the information .sp The following information is available: .sp PCRE_INFO_BACKREFMAX Number of highest back reference PCRE_INFO_CAPTURECOUNT Number of capturing subpatterns PCRE_INFO_DEFAULT_TABLES Pointer to default tables PCRE_INFO_FIRSTBYTE Fixed first data unit for a match, or -1 for start of string or after newline, or -2 otherwise PCRE_INFO_FIRSTTABLE Table of first data units (after studying) PCRE_INFO_HASCRORLF Return 1 if explicit CR or LF matches exist PCRE_INFO_JCHANGED Return 1 if (?J) or (?-J) was used PCRE_INFO_JIT Return 1 after successful JIT compilation PCRE_INFO_JITSIZE Size of JIT compiled code PCRE_INFO_LASTLITERAL Literal last data unit required PCRE_INFO_MINLENGTH Lower bound length of matching strings PCRE_INFO_MATCHEMPTY Return 1 if the pattern can match an empty string, 0 otherwise PCRE_INFO_MATCHLIMIT Match limit if set, otherwise PCRE_RROR_UNSET PCRE_INFO_MAXLOOKBEHIND Length (in characters) of the longest lookbehind assertion PCRE_INFO_NAMECOUNT Number of named subpatterns PCRE_INFO_NAMEENTRYSIZE Size of name table entry PCRE_INFO_NAMETABLE Pointer to name table PCRE_INFO_OKPARTIAL Return 1 if partial matching can be tried (always returns 1 after release 8.00) PCRE_INFO_OPTIONS Option bits used for compilation PCRE_INFO_SIZE Size of compiled pattern PCRE_INFO_STUDYSIZE Size of study data PCRE_INFO_FIRSTCHARACTER Fixed first data unit for a match PCRE_INFO_FIRSTCHARACTERFLAGS Returns 1 if there is a first data character set, which can then be retrieved using PCRE_INFO_FIRSTCHARACTER, 2 if the first character is at the start of the data string or after a newline, and 0 otherwise PCRE_INFO_RECURSIONLIMIT Recursion limit if set, otherwise PCRE_ERROR_UNSET PCRE_INFO_REQUIREDCHAR Literal last data unit required PCRE_INFO_REQUIREDCHARFLAGS Returns 1 if the last data character is set (which can then be retrieved using PCRE_INFO_REQUIREDCHAR); 0 otherwise .sp The \fIwhere\fP argument must point to an integer variable, except for the following \fIwhat\fP values: .sp PCRE_INFO_DEFAULT_TABLES const uint8_t * PCRE_INFO_FIRSTCHARACTER uint32_t PCRE_INFO_FIRSTTABLE const uint8_t * PCRE_INFO_JITSIZE size_t PCRE_INFO_MATCHLIMIT uint32_t PCRE_INFO_NAMETABLE PCRE_SPTR16 (16-bit library) PCRE_INFO_NAMETABLE PCRE_SPTR32 (32-bit library) PCRE_INFO_NAMETABLE const unsigned char * (8-bit library) PCRE_INFO_OPTIONS unsigned long int PCRE_INFO_SIZE size_t PCRE_INFO_STUDYSIZE size_t PCRE_INFO_RECURSIONLIMIT uint32_t PCRE_INFO_REQUIREDCHAR uint32_t .sp The yield of the function is zero on success or: .sp PCRE_ERROR_NULL the argument \fIcode\fP was NULL the argument \fIwhere\fP was NULL PCRE_ERROR_BADMAGIC the "magic number" was not found PCRE_ERROR_BADOPTION the value of \fIwhat\fP was invalid PCRE_ERROR_UNSET the option was not set .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_get_named_substring.3 ================================================ .TH PCRE_GET_NAMED_SUBSTRING 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_get_named_substring(const pcre *\fIcode\fP, .B " const char *\fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, const char *\fIstringname\fP," .B " const char **\fIstringptr\fP);" .sp .B int pcre16_get_named_substring(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR16 \fIstringname\fP," .B " PCRE_SPTR16 *\fIstringptr\fP);" .sp .B int pcre32_get_named_substring(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, PCRE_SPTR32 \fIstringname\fP," .B " PCRE_SPTR32 *\fIstringptr\fP);" .fi . .SH DESCRIPTION .rs .sp This is a convenience function for extracting a captured substring by name. The arguments are: .sp \fIcode\fP Compiled pattern \fIsubject\fP Subject that has been successfully matched \fIovector\fP Offset vector that \fBpcre[16|32]_exec()\fP used \fIstringcount\fP Value returned by \fBpcre[16|32]_exec()\fP \fIstringname\fP Name of the required substring \fIstringptr\fP Where to put the string pointer .sp The memory in which the substring is placed is obtained by calling \fBpcre[16|32]_malloc()\fP. The convenience function \fBpcre[16|32]_free_substring()\fP can be used to free it when it is no longer needed. The yield of the function is the length of the extracted substring, PCRE_ERROR_NOMEMORY if sufficient memory could not be obtained, or PCRE_ERROR_NOSUBSTRING if the string name is invalid. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_get_stringnumber.3 ================================================ .TH PCRE_GET_STRINGNUMBER 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_get_stringnumber(const pcre *\fIcode\fP, .B " const char *\fIname\fP);" .sp .B int pcre16_get_stringnumber(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIname\fP);" .sp .B int pcre32_get_stringnumber(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIname\fP);" .fi . .SH DESCRIPTION .rs .sp This convenience function finds the number of a named substring capturing parenthesis in a compiled pattern. Its arguments are: .sp \fIcode\fP Compiled regular expression \fIname\fP Name whose number is required .sp The yield of the function is the number of the parenthesis if the name is found, or PCRE_ERROR_NOSUBSTRING otherwise. When duplicate names are allowed (PCRE_DUPNAMES is set), it is not defined which of the numbers is returned by \fBpcre[16|32]_get_stringnumber()\fP. You can obtain the complete list by calling \fBpcre[16|32]_get_stringtable_entries()\fP. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_get_stringtable_entries.3 ================================================ .TH PCRE_GET_STRINGTABLE_ENTRIES 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_get_stringtable_entries(const pcre *\fIcode\fP, .B " const char *\fIname\fP, char **\fIfirst\fP, char **\fIlast\fP);" .sp .B int pcre16_get_stringtable_entries(const pcre16 *\fIcode\fP, .B " PCRE_SPTR16 \fIname\fP, PCRE_UCHAR16 **\fIfirst\fP, PCRE_UCHAR16 **\fIlast\fP);" .sp .B int pcre32_get_stringtable_entries(const pcre32 *\fIcode\fP, .B " PCRE_SPTR32 \fIname\fP, PCRE_UCHAR32 **\fIfirst\fP, PCRE_UCHAR32 **\fIlast\fP);" .fi . .SH DESCRIPTION .rs .sp This convenience function finds, for a compiled pattern, the first and last entries for a given name in the table that translates capturing parenthesis names into numbers. When names are required to be unique (PCRE_DUPNAMES is \fInot\fP set), it is usually easier to use \fBpcre[16|32]_get_stringnumber()\fP instead. .sp \fIcode\fP Compiled regular expression \fIname\fP Name whose entries required \fIfirst\fP Where to return a pointer to the first entry \fIlast\fP Where to return a pointer to the last entry .sp The yield of the function is the length of each entry, or PCRE_ERROR_NOSUBSTRING if none are found. .P There is a complete description of the PCRE native API, including the format of the table entries, in the .\" HREF \fBpcreapi\fP .\" page, and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_get_substring.3 ================================================ .TH PCRE_GET_SUBSTRING 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_get_substring(const char *\fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " const char **\fIstringptr\fP);" .sp .B int pcre16_get_substring(PCRE_SPTR16 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " PCRE_SPTR16 *\fIstringptr\fP);" .sp .B int pcre32_get_substring(PCRE_SPTR32 \fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " PCRE_SPTR32 *\fIstringptr\fP);" .fi . .SH DESCRIPTION .rs .sp This is a convenience function for extracting a captured substring. The arguments are: .sp \fIsubject\fP Subject that has been successfully matched \fIovector\fP Offset vector that \fBpcre[16|32]_exec()\fP used \fIstringcount\fP Value returned by \fBpcre[16|32]_exec()\fP \fIstringnumber\fP Number of the required substring \fIstringptr\fP Where to put the string pointer .sp The memory in which the substring is placed is obtained by calling \fBpcre[16|32]_malloc()\fP. The convenience function \fBpcre[16|32]_free_substring()\fP can be used to free it when it is no longer needed. The yield of the function is the length of the substring, PCRE_ERROR_NOMEMORY if sufficient memory could not be obtained, or PCRE_ERROR_NOSUBSTRING if the string number is invalid. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_get_substring_list.3 ================================================ .TH PCRE_GET_SUBSTRING_LIST 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_get_substring_list(const char *\fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, const char ***\fIlistptr\fP);" .sp .B int pcre16_get_substring_list(PCRE_SPTR16 \fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, PCRE_SPTR16 **\fIlistptr\fP);" .sp .B int pcre32_get_substring_list(PCRE_SPTR32 \fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, PCRE_SPTR32 **\fIlistptr\fP);" .fi . .SH DESCRIPTION .rs .sp This is a convenience function for extracting a list of all the captured substrings. The arguments are: .sp \fIsubject\fP Subject that has been successfully matched \fIovector\fP Offset vector that \fBpcre[16|32]_exec\fP used \fIstringcount\fP Value returned by \fBpcre[16|32]_exec\fP \fIlistptr\fP Where to put a pointer to the list .sp The memory in which the substrings and the list are placed is obtained by calling \fBpcre[16|32]_malloc()\fP. The convenience function \fBpcre[16|32]_free_substring_list()\fP can be used to free it when it is no longer needed. A pointer to a list of pointers is put in the variable whose address is in \fIlistptr\fP. The list is terminated by a NULL pointer. The yield of the function is zero on success or PCRE_ERROR_NOMEMORY if sufficient memory could not be obtained. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_jit_exec.3 ================================================ .TH PCRE_EXEC 3 "31 October 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_jit_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " pcre_jit_stack *\fIjstack\fP);" .sp .B int pcre16_jit_exec(const pcre16 *\fIcode\fP, "const pcre16_extra *\fIextra\fP," .B " PCRE_SPTR16 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " pcre_jit_stack *\fIjstack\fP);" .sp .B int pcre32_jit_exec(const pcre32 *\fIcode\fP, "const pcre32_extra *\fIextra\fP," .B " PCRE_SPTR32 \fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " pcre_jit_stack *\fIjstack\fP);" .fi . .SH DESCRIPTION .rs .sp This function matches a compiled regular expression that has been successfully studied with one of the JIT options against a given subject string, using a matching algorithm that is similar to Perl's. It is a "fast path" interface to JIT, and it bypasses some of the sanity checks that \fBpcre_exec()\fP applies. It returns offsets to captured substrings. Its arguments are: .sp \fIcode\fP Points to the compiled pattern \fIextra\fP Points to an associated \fBpcre[16|32]_extra\fP structure, or is NULL \fIsubject\fP Points to the subject string \fIlength\fP Length of the subject string, in bytes \fIstartoffset\fP Offset in bytes in the subject at which to start matching \fIoptions\fP Option bits \fIovector\fP Points to a vector of ints for result offsets \fIovecsize\fP Number of elements in the vector (a multiple of 3) \fIjstack\fP Pointer to a JIT stack .sp The allowed options are: .sp PCRE_NOTBOL Subject string is not the beginning of a line PCRE_NOTEOL Subject string is not the end of a line PCRE_NOTEMPTY An empty string is not a valid match PCRE_NOTEMPTY_ATSTART An empty string at the start of the subject is not a valid match PCRE_NO_UTF16_CHECK Do not check the subject for UTF-16 validity (only relevant if PCRE_UTF16 was set at compile time) PCRE_NO_UTF32_CHECK Do not check the subject for UTF-32 validity (only relevant if PCRE_UTF32 was set at compile time) PCRE_NO_UTF8_CHECK Do not check the subject for UTF-8 validity (only relevant if PCRE_UTF8 was set at compile time) PCRE_PARTIAL ) Return PCRE_ERROR_PARTIAL for a partial PCRE_PARTIAL_SOFT ) match if no full matches are found PCRE_PARTIAL_HARD Return PCRE_ERROR_PARTIAL for a partial match if that is found before a full match .sp However, the PCRE_NO_UTF[8|16|32]_CHECK options have no effect, as this check is never applied. For details of partial matching, see the .\" HREF \fBpcrepartial\fP .\" page. A \fBpcre_extra\fP structure contains the following fields: .sp \fIflags\fP Bits indicating which fields are set \fIstudy_data\fP Opaque data from \fBpcre[16|32]_study()\fP \fImatch_limit\fP Limit on internal resource use \fImatch_limit_recursion\fP Limit on internal recursion depth \fIcallout_data\fP Opaque data passed back to callouts \fItables\fP Points to character tables or is NULL \fImark\fP For passing back a *MARK pointer \fIexecutable_jit\fP Opaque data from JIT compilation .sp The flag bits are PCRE_EXTRA_STUDY_DATA, PCRE_EXTRA_MATCH_LIMIT, PCRE_EXTRA_MATCH_LIMIT_RECURSION, PCRE_EXTRA_CALLOUT_DATA, PCRE_EXTRA_TABLES, PCRE_EXTRA_MARK and PCRE_EXTRA_EXECUTABLE_JIT. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the JIT API in the .\" HREF \fBpcrejit\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_jit_stack_alloc.3 ================================================ .TH PCRE_JIT_STACK_ALLOC 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B pcre_jit_stack *pcre_jit_stack_alloc(int \fIstartsize\fP, .B " int \fImaxsize\fP);" .sp .B pcre16_jit_stack *pcre16_jit_stack_alloc(int \fIstartsize\fP, .B " int \fImaxsize\fP);" .sp .B pcre32_jit_stack *pcre32_jit_stack_alloc(int \fIstartsize\fP, .B " int \fImaxsize\fP);" .fi . .SH DESCRIPTION .rs .sp This function is used to create a stack for use by the code compiled by the JIT optimization of \fBpcre[16|32]_study()\fP. The arguments are a starting size for the stack, and a maximum size to which it is allowed to grow. The result can be passed to the JIT run-time code by \fBpcre[16|32]_assign_jit_stack()\fP, or that function can set up a callback for obtaining a stack. A maximum stack size of 512K to 1M should be more than enough for any pattern. For more details, see the .\" HREF \fBpcrejit\fP .\" page. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_jit_stack_free.3 ================================================ .TH PCRE_JIT_STACK_FREE 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B void pcre_jit_stack_free(pcre_jit_stack *\fIstack\fP); .PP .B void pcre16_jit_stack_free(pcre16_jit_stack *\fIstack\fP); .PP .B void pcre32_jit_stack_free(pcre32_jit_stack *\fIstack\fP); . .SH DESCRIPTION .rs .sp This function is used to free a JIT stack that was created by \fBpcre[16|32]_jit_stack_alloc()\fP when it is no longer needed. For more details, see the .\" HREF \fBpcrejit\fP .\" page. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_maketables.3 ================================================ .TH PCRE_MAKETABLES 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B const unsigned char *pcre_maketables(void); .PP .B const unsigned char *pcre16_maketables(void); .PP .B const unsigned char *pcre32_maketables(void); . .SH DESCRIPTION .rs .sp This function builds a set of character tables for character values less than 256. These can be passed to \fBpcre[16|32]_compile()\fP to override PCRE's internal, built-in tables (which were made by \fBpcre[16|32]_maketables()\fP when PCRE was compiled). You might want to do this if you are using a non-standard locale. The function yields a pointer to the tables. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_pattern_to_host_byte_order.3 ================================================ .TH PCRE_PATTERN_TO_HOST_BYTE_ORDER 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre_pattern_to_host_byte_order(pcre *\fIcode\fP, .B " pcre_extra *\fIextra\fP, const unsigned char *\fItables\fP);" .sp .B int pcre16_pattern_to_host_byte_order(pcre16 *\fIcode\fP, .B " pcre16_extra *\fIextra\fP, const unsigned char *\fItables\fP);" .sp .B int pcre32_pattern_to_host_byte_order(pcre32 *\fIcode\fP, .B " pcre32_extra *\fIextra\fP, const unsigned char *\fItables\fP);" .fi . .SH DESCRIPTION .rs .sp This function ensures that the bytes in 2-byte and 4-byte values in a compiled pattern are in the correct order for the current host. It is useful when a pattern that has been compiled on one host is transferred to another that might have different endianness. The arguments are: .sp \fIcode\fP A compiled regular expression \fIextra\fP Points to an associated \fBpcre[16|32]_extra\fP structure, or is NULL \fItables\fP Pointer to character tables, or NULL to set the built-in default .sp The result is 0 for success, a negative PCRE_ERROR_xxx value otherwise. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_refcount.3 ================================================ .TH PCRE_REFCOUNT 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B int pcre_refcount(pcre *\fIcode\fP, int \fIadjust\fP); .PP .B int pcre16_refcount(pcre16 *\fIcode\fP, int \fIadjust\fP); .PP .B int pcre32_refcount(pcre32 *\fIcode\fP, int \fIadjust\fP); . .SH DESCRIPTION .rs .sp This function is used to maintain a reference count inside a data block that contains a compiled pattern. Its arguments are: .sp \fIcode\fP Compiled regular expression \fIadjust\fP Adjustment to reference value .sp The yield of the function is the adjusted reference value, which is constrained to lie between 0 and 65535. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_study.3 ================================================ .TH PCRE_STUDY 3 " 24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B pcre_extra *pcre_study(const pcre *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .sp .B pcre16_extra *pcre16_study(const pcre16 *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .sp .B pcre32_extra *pcre32_study(const pcre32 *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .fi . .SH DESCRIPTION .rs .sp This function studies a compiled pattern, to see if additional information can be extracted that might speed up matching. Its arguments are: .sp \fIcode\fP A compiled regular expression \fIoptions\fP Options for \fBpcre[16|32]_study()\fP \fIerrptr\fP Where to put an error message .sp If the function succeeds, it returns a value that can be passed to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP via their \fIextra\fP arguments. .P If the function returns NULL, either it could not find any additional information, or there was an error. You can tell the difference by looking at the error value. It is NULL in first case. .P The only option is PCRE_STUDY_JIT_COMPILE. It requests just-in-time compilation if possible. If PCRE has been compiled without JIT support, this option is ignored. See the .\" HREF \fBpcrejit\fP .\" page for further details. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_utf16_to_host_byte_order.3 ================================================ .TH PCRE_UTF16_TO_HOST_BYTE_ORDER 3 "21 January 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *\fIoutput\fP, .B " PCRE_SPTR16 \fIinput\fP, int \fIlength\fP, int *\fIhost_byte_order\fP," .B " int \fIkeep_boms\fP);" .fi . . .SH DESCRIPTION .rs .sp This function, which exists only in the 16-bit library, converts a UTF-16 string to the correct order for the current host, taking account of any byte order marks (BOMs) within the string. Its arguments are: .sp \fIoutput\fP pointer to output buffer, may be the same as \fIinput\fP \fIinput\fP pointer to input buffer \fIlength\fP number of 16-bit units in the input, or negative for a zero-terminated string \fIhost_byte_order\fP a NULL value or a non-zero value pointed to means start in host byte order \fIkeep_boms\fP if non-zero, BOMs are copied to the output string .sp The result of the function is the number of 16-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated. .P If \fIhost_byte_order\fP is not NULL, it is set to indicate the byte order that is current at the end of the string. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_utf32_to_host_byte_order.3 ================================================ .TH PCRE_UTF32_TO_HOST_BYTE_ORDER 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .nf .B int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *\fIoutput\fP, .B " PCRE_SPTR32 \fIinput\fP, int \fIlength\fP, int *\fIhost_byte_order\fP," .B " int \fIkeep_boms\fP);" .fi . . .SH DESCRIPTION .rs .sp This function, which exists only in the 32-bit library, converts a UTF-32 string to the correct order for the current host, taking account of any byte order marks (BOMs) within the string. Its arguments are: .sp \fIoutput\fP pointer to output buffer, may be the same as \fIinput\fP \fIinput\fP pointer to input buffer \fIlength\fP number of 32-bit units in the input, or negative for a zero-terminated string \fIhost_byte_order\fP a NULL value or a non-zero value pointed to means start in host byte order \fIkeep_boms\fP if non-zero, BOMs are copied to the output string .sp The result of the function is the number of 32-bit units placed into the output buffer, including the zero terminator if the string was zero-terminated. .P If \fIhost_byte_order\fP is not NULL, it is set to indicate the byte order that is current at the end of the string. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcre_version.3 ================================================ .TH PCRE_VERSION 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B const char *pcre_version(void); .PP .B const char *pcre16_version(void); .PP .B const char *pcre32_version(void); . .SH DESCRIPTION .rs .sp This function (even in the 16-bit and 32-bit libraries) returns a zero-terminated, 8-bit character string that gives the version number of the PCRE library and the date of its release. .P There is a complete description of the PCRE native API in the .\" HREF \fBpcreapi\fP .\" page and a description of the POSIX API in the .\" HREF \fBpcreposix\fP .\" page. ================================================ FILE: src/pcre/doc/pcreapi.3 ================================================ .TH PCREAPI 3 "18 December 2015" "PCRE 8.39" .SH NAME PCRE - Perl-compatible regular expressions .sp .B #include . . .SH "PCRE NATIVE API BASIC FUNCTIONS" .rs .sp .nf .B pcre *pcre_compile(const char *\fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre *pcre_compile2(const char *\fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP," .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre_extra *pcre_study(const pcre *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .sp .B void pcre_free_study(pcre_extra *\fIextra\fP); .sp .B int pcre_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .sp .B int pcre_dfa_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .fi . . .SH "PCRE NATIVE API STRING EXTRACTION FUNCTIONS" .rs .sp .nf .B int pcre_copy_named_substring(const pcre *\fIcode\fP, .B " const char *\fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, const char *\fIstringname\fP," .B " char *\fIbuffer\fP, int \fIbuffersize\fP);" .sp .B int pcre_copy_substring(const char *\fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, char *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .sp .B int pcre_get_named_substring(const pcre *\fIcode\fP, .B " const char *\fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, const char *\fIstringname\fP," .B " const char **\fIstringptr\fP);" .sp .B int pcre_get_stringnumber(const pcre *\fIcode\fP, .B " const char *\fIname\fP);" .sp .B int pcre_get_stringtable_entries(const pcre *\fIcode\fP, .B " const char *\fIname\fP, char **\fIfirst\fP, char **\fIlast\fP);" .sp .B int pcre_get_substring(const char *\fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " const char **\fIstringptr\fP);" .sp .B int pcre_get_substring_list(const char *\fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, const char ***\fIlistptr\fP);" .sp .B void pcre_free_substring(const char *\fIstringptr\fP); .sp .B void pcre_free_substring_list(const char **\fIstringptr\fP); .fi . . .SH "PCRE NATIVE API AUXILIARY FUNCTIONS" .rs .sp .nf .B int pcre_jit_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " pcre_jit_stack *\fIjstack\fP);" .sp .B pcre_jit_stack *pcre_jit_stack_alloc(int \fIstartsize\fP, int \fImaxsize\fP); .sp .B void pcre_jit_stack_free(pcre_jit_stack *\fIstack\fP); .sp .B void pcre_assign_jit_stack(pcre_extra *\fIextra\fP, .B " pcre_jit_callback \fIcallback\fP, void *\fIdata\fP);" .sp .B const unsigned char *pcre_maketables(void); .sp .B int pcre_fullinfo(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .sp .B int pcre_refcount(pcre *\fIcode\fP, int \fIadjust\fP); .sp .B int pcre_config(int \fIwhat\fP, void *\fIwhere\fP); .sp .B const char *pcre_version(void); .sp .B int pcre_pattern_to_host_byte_order(pcre *\fIcode\fP, .B " pcre_extra *\fIextra\fP, const unsigned char *\fItables\fP);" .fi . . .SH "PCRE NATIVE API INDIRECTED FUNCTIONS" .rs .sp .nf .B void *(*pcre_malloc)(size_t); .sp .B void (*pcre_free)(void *); .sp .B void *(*pcre_stack_malloc)(size_t); .sp .B void (*pcre_stack_free)(void *); .sp .B int (*pcre_callout)(pcre_callout_block *); .sp .B int (*pcre_stack_guard)(void); .fi . . .SH "PCRE 8-BIT, 16-BIT, AND 32-BIT LIBRARIES" .rs .sp As well as support for 8-bit character strings, PCRE also supports 16-bit strings (from release 8.30) and 32-bit strings (from release 8.32), by means of two additional libraries. They can be built as well as, or instead of, the 8-bit library. To avoid too much complication, this document describes the 8-bit versions of the functions, with only occasional references to the 16-bit and 32-bit libraries. .P The 16-bit and 32-bit functions operate in the same way as their 8-bit counterparts; they just use different data types for their arguments and results, and their names start with \fBpcre16_\fP or \fBpcre32_\fP instead of \fBpcre_\fP. For every option that has UTF8 in its name (for example, PCRE_UTF8), there are corresponding 16-bit and 32-bit names with UTF8 replaced by UTF16 or UTF32, respectively. This facility is in fact just cosmetic; the 16-bit and 32-bit option names define the same bit values. .P References to bytes and UTF-8 in this document should be read as references to 16-bit data units and UTF-16 when using the 16-bit library, or 32-bit data units and UTF-32 when using the 32-bit library, unless specified otherwise. More details of the specific differences for the 16-bit and 32-bit libraries are given in the .\" HREF \fBpcre16\fP .\" and .\" HREF \fBpcre32\fP .\" pages. . . .SH "PCRE API OVERVIEW" .rs .sp PCRE has its own native API, which is described in this document. There are also some wrapper functions (for the 8-bit library only) that correspond to the POSIX regular expression API, but they do not give access to all the functionality. They are described in the .\" HREF \fBpcreposix\fP .\" documentation. Both of these APIs define a set of C function calls. A C++ wrapper (again for the 8-bit library only) is also distributed with PCRE. It is documented in the .\" HREF \fBpcrecpp\fP .\" page. .P The native API C function prototypes are defined in the header file \fBpcre.h\fP, and on Unix-like systems the (8-bit) library itself is called \fBlibpcre\fP. It can normally be accessed by adding \fB-lpcre\fP to the command for linking an application that uses PCRE. The header file defines the macros PCRE_MAJOR and PCRE_MINOR to contain the major and minor release numbers for the library. Applications can use these to include support for different releases of PCRE. .P In a Windows environment, if you want to statically link an application program against a non-dll \fBpcre.a\fP file, you must define PCRE_STATIC before including \fBpcre.h\fP or \fBpcrecpp.h\fP, because otherwise the \fBpcre_malloc()\fP and \fBpcre_free()\fP exported functions will be declared \fB__declspec(dllimport)\fP, with unwanted results. .P The functions \fBpcre_compile()\fP, \fBpcre_compile2()\fP, \fBpcre_study()\fP, and \fBpcre_exec()\fP are used for compiling and matching regular expressions in a Perl-compatible manner. A sample program that demonstrates the simplest way of using them is provided in the file called \fIpcredemo.c\fP in the PCRE source distribution. A listing of this program is given in the .\" HREF \fBpcredemo\fP .\" documentation, and the .\" HREF \fBpcresample\fP .\" documentation describes how to compile and run it. .P Just-in-time compiler support is an optional feature of PCRE that can be built in appropriate hardware environments. It greatly speeds up the matching performance of many patterns. Simple programs can easily request that it be used if available, by setting an option that is ignored when it is not relevant. More complicated programs might need to make use of the functions \fBpcre_jit_stack_alloc()\fP, \fBpcre_jit_stack_free()\fP, and \fBpcre_assign_jit_stack()\fP in order to control the JIT code's memory usage. .P From release 8.32 there is also a direct interface for JIT execution, which gives improved performance. The JIT-specific functions are discussed in the .\" HREF \fBpcrejit\fP .\" documentation. .P A second matching function, \fBpcre_dfa_exec()\fP, which is not Perl-compatible, is also provided. This uses a different algorithm for the matching. The alternative algorithm finds all possible matches (at a given point in the subject), and scans the subject just once (unless there are lookbehind assertions). However, this algorithm does not return captured substrings. A description of the two matching algorithms and their advantages and disadvantages is given in the .\" HREF \fBpcrematching\fP .\" documentation. .P In addition to the main compiling and matching functions, there are convenience functions for extracting captured substrings from a subject string that is matched by \fBpcre_exec()\fP. They are: .sp \fBpcre_copy_substring()\fP \fBpcre_copy_named_substring()\fP \fBpcre_get_substring()\fP \fBpcre_get_named_substring()\fP \fBpcre_get_substring_list()\fP \fBpcre_get_stringnumber()\fP \fBpcre_get_stringtable_entries()\fP .sp \fBpcre_free_substring()\fP and \fBpcre_free_substring_list()\fP are also provided, to free the memory used for extracted strings. .P The function \fBpcre_maketables()\fP is used to build a set of character tables in the current locale for passing to \fBpcre_compile()\fP, \fBpcre_exec()\fP, or \fBpcre_dfa_exec()\fP. This is an optional facility that is provided for specialist use. Most commonly, no special tables are passed, in which case internal tables that are generated when PCRE is built are used. .P The function \fBpcre_fullinfo()\fP is used to find out information about a compiled pattern. The function \fBpcre_version()\fP returns a pointer to a string containing the version of PCRE and its date of release. .P The function \fBpcre_refcount()\fP maintains a reference count in a data block containing a compiled pattern. This is provided for the benefit of object-oriented applications. .P The global variables \fBpcre_malloc\fP and \fBpcre_free\fP initially contain the entry points of the standard \fBmalloc()\fP and \fBfree()\fP functions, respectively. PCRE calls the memory management functions via these variables, so a calling program can replace them if it wishes to intercept the calls. This should be done before calling any PCRE functions. .P The global variables \fBpcre_stack_malloc\fP and \fBpcre_stack_free\fP are also indirections to memory management functions. These special functions are used only when PCRE is compiled to use the heap for remembering data, instead of recursive function calls, when running the \fBpcre_exec()\fP function. See the .\" HREF \fBpcrebuild\fP .\" documentation for details of how to do this. It is a non-standard way of building PCRE, for use in environments that have limited stacks. Because of the greater use of memory management, it runs more slowly. Separate functions are provided so that special-purpose external code can be used for this case. When used, these functions always allocate memory blocks of the same size. There is a discussion about PCRE's stack usage in the .\" HREF \fBpcrestack\fP .\" documentation. .P The global variable \fBpcre_callout\fP initially contains NULL. It can be set by the caller to a "callout" function, which PCRE will then call at specified points during a matching operation. Details are given in the .\" HREF \fBpcrecallout\fP .\" documentation. .P The global variable \fBpcre_stack_guard\fP initially contains NULL. It can be set by the caller to a function that is called by PCRE whenever it starts to compile a parenthesized part of a pattern. When parentheses are nested, PCRE uses recursive function calls, which use up the system stack. This function is provided so that applications with restricted stacks can force a compilation error if the stack runs out. The function should return zero if all is well, or non-zero to force an error. . . .\" HTML .SH NEWLINES .rs .sp PCRE supports five different conventions for indicating line breaks in strings: a single CR (carriage return) character, a single LF (linefeed) character, the two-character sequence CRLF, any of the three preceding, or any Unicode newline sequence. The Unicode newline sequences are the three just mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029). .P Each of the first three conventions is used by at least one operating system as its standard newline sequence. When PCRE is built, a default can be specified. The default default is LF, which is the Unix standard. When PCRE is run, the default can be overridden, either when a pattern is compiled, or when it is matched. .P At compile time, the newline convention can be specified by the \fIoptions\fP argument of \fBpcre_compile()\fP, or it can be specified by special text at the start of the pattern itself; this overrides any other settings. See the .\" HREF \fBpcrepattern\fP .\" page for details of the special character sequences. .P In the PCRE documentation the word "newline" is used to mean "the character or pair of characters that indicate a line break". The choice of newline convention affects the handling of the dot, circumflex, and dollar metacharacters, the handling of #-comments in /x mode, and, when CRLF is a recognized line ending sequence, the match position advancement for a non-anchored pattern. There is more detail about this in the .\" HTML .\" section on \fBpcre_exec()\fP options .\" below. .P The choice of newline convention does not affect the interpretation of the \en or \er escape sequences, nor does it affect what \eR matches, which is controlled in a similar way, but by separate options. . . .SH MULTITHREADING .rs .sp The PCRE functions can be used in multi-threading applications, with the proviso that the memory management functions pointed to by \fBpcre_malloc\fP, \fBpcre_free\fP, \fBpcre_stack_malloc\fP, and \fBpcre_stack_free\fP, and the callout and stack-checking functions pointed to by \fBpcre_callout\fP and \fBpcre_stack_guard\fP, are shared by all threads. .P The compiled form of a regular expression is not altered during matching, so the same compiled pattern can safely be used by several threads at once. .P If the just-in-time optimization feature is being used, it needs separate memory stack areas for each thread. See the .\" HREF \fBpcrejit\fP .\" documentation for more details. . . .SH "SAVING PRECOMPILED PATTERNS FOR LATER USE" .rs .sp The compiled form of a regular expression can be saved and re-used at a later time, possibly by a different program, and even on a host other than the one on which it was compiled. Details are given in the .\" HREF \fBpcreprecompile\fP .\" documentation, which includes a description of the \fBpcre_pattern_to_host_byte_order()\fP function. However, compiling a regular expression with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes. . . .SH "CHECKING BUILD-TIME OPTIONS" .rs .sp .B int pcre_config(int \fIwhat\fP, void *\fIwhere\fP); .PP The function \fBpcre_config()\fP makes it possible for a PCRE client to discover which optional features have been compiled into the PCRE library. The .\" HREF \fBpcrebuild\fP .\" documentation has more details about these optional features. .P The first argument for \fBpcre_config()\fP is an integer, specifying which information is required; the second argument is a pointer to a variable into which the information is placed. The returned value is zero on success, or the negative error code PCRE_ERROR_BADOPTION if the value in the first argument is not recognized. The following information is available: .sp PCRE_CONFIG_UTF8 .sp The output is an integer that is set to one if UTF-8 support is available; otherwise it is set to zero. This value should normally be given to the 8-bit version of this function, \fBpcre_config()\fP. If it is given to the 16-bit or 32-bit version of this function, the result is PCRE_ERROR_BADOPTION. .sp PCRE_CONFIG_UTF16 .sp The output is an integer that is set to one if UTF-16 support is available; otherwise it is set to zero. This value should normally be given to the 16-bit version of this function, \fBpcre16_config()\fP. If it is given to the 8-bit or 32-bit version of this function, the result is PCRE_ERROR_BADOPTION. .sp PCRE_CONFIG_UTF32 .sp The output is an integer that is set to one if UTF-32 support is available; otherwise it is set to zero. This value should normally be given to the 32-bit version of this function, \fBpcre32_config()\fP. If it is given to the 8-bit or 16-bit version of this function, the result is PCRE_ERROR_BADOPTION. .sp PCRE_CONFIG_UNICODE_PROPERTIES .sp The output is an integer that is set to one if support for Unicode character properties is available; otherwise it is set to zero. .sp PCRE_CONFIG_JIT .sp The output is an integer that is set to one if support for just-in-time compiling is available; otherwise it is set to zero. .sp PCRE_CONFIG_JITTARGET .sp The output is a pointer to a zero-terminated "const char *" string. If JIT support is available, the string contains the name of the architecture for which the JIT compiler is configured, for example "x86 32bit (little endian + unaligned)". If JIT support is not available, the result is NULL. .sp PCRE_CONFIG_NEWLINE .sp The output is an integer whose value specifies the default character sequence that is recognized as meaning "newline". The values that are supported in ASCII/Unicode environments are: 10 for LF, 13 for CR, 3338 for CRLF, -2 for ANYCRLF, and -1 for ANY. In EBCDIC environments, CR, ANYCRLF, and ANY yield the same values. However, the value for LF is normally 21, though some EBCDIC environments use 37. The corresponding values for CRLF are 3349 and 3365. The default should normally correspond to the standard sequence for your operating system. .sp PCRE_CONFIG_BSR .sp The output is an integer whose value indicates what character sequences the \eR escape sequence matches by default. A value of 0 means that \eR matches any Unicode line ending sequence; a value of 1 means that \eR matches only CR, LF, or CRLF. The default can be overridden when a pattern is compiled or matched. .sp PCRE_CONFIG_LINK_SIZE .sp The output is an integer that contains the number of bytes used for internal linkage in compiled regular expressions. For the 8-bit library, the value can be 2, 3, or 4. For the 16-bit library, the value is either 2 or 4 and is still a number of bytes. For the 32-bit library, the value is either 2 or 4 and is still a number of bytes. The default value of 2 is sufficient for all but the most massive patterns, since it allows the compiled pattern to be up to 64K in size. Larger values allow larger regular expressions to be compiled, at the expense of slower matching. .sp PCRE_CONFIG_POSIX_MALLOC_THRESHOLD .sp The output is an integer that contains the threshold above which the POSIX interface uses \fBmalloc()\fP for output vectors. Further details are given in the .\" HREF \fBpcreposix\fP .\" documentation. .sp PCRE_CONFIG_PARENS_LIMIT .sp The output is a long integer that gives the maximum depth of nesting of parentheses (of any kind) in a pattern. This limit is imposed to cap the amount of system stack used when a pattern is compiled. It is specified when PCRE is built; the default is 250. This limit does not take into account the stack that may already be used by the calling application. For finer control over compilation stack usage, you can set a pointer to an external checking function in \fBpcre_stack_guard\fP. .sp PCRE_CONFIG_MATCH_LIMIT .sp The output is a long integer that gives the default limit for the number of internal matching function calls in a \fBpcre_exec()\fP execution. Further details are given with \fBpcre_exec()\fP below. .sp PCRE_CONFIG_MATCH_LIMIT_RECURSION .sp The output is a long integer that gives the default limit for the depth of recursion when calling the internal matching function in a \fBpcre_exec()\fP execution. Further details are given with \fBpcre_exec()\fP below. .sp PCRE_CONFIG_STACKRECURSE .sp The output is an integer that is set to one if internal recursion when running \fBpcre_exec()\fP is implemented by recursive function calls that use the stack to remember their state. This is the usual way that PCRE is compiled. The output is zero if PCRE was compiled to use blocks of data on the heap instead of recursive function calls. In this case, \fBpcre_stack_malloc\fP and \fBpcre_stack_free\fP are called to manage memory blocks on the heap, thus avoiding the use of the stack. . . .SH "COMPILING A PATTERN" .rs .sp .nf .B pcre *pcre_compile(const char *\fIpattern\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .sp .B pcre *pcre_compile2(const char *\fIpattern\fP, int \fIoptions\fP, .B " int *\fIerrorcodeptr\fP," .B " const char **\fIerrptr\fP, int *\fIerroffset\fP," .B " const unsigned char *\fItableptr\fP);" .fi .P Either of the functions \fBpcre_compile()\fP or \fBpcre_compile2()\fP can be called to compile a pattern into an internal form. The only difference between the two interfaces is that \fBpcre_compile2()\fP has an additional argument, \fIerrorcodeptr\fP, via which a numerical error code can be returned. To avoid too much repetition, we refer just to \fBpcre_compile()\fP below, but the information applies equally to \fBpcre_compile2()\fP. .P The pattern is a C string terminated by a binary zero, and is passed in the \fIpattern\fP argument. A pointer to a single block of memory that is obtained via \fBpcre_malloc\fP is returned. This contains the compiled code and related data. The \fBpcre\fP type is defined for the returned block; this is a typedef for a structure whose contents are not externally defined. It is up to the caller to free the memory (via \fBpcre_free\fP) when it is no longer required. .P Although the compiled code of a PCRE regex is relocatable, that is, it does not depend on memory location, the complete \fBpcre\fP data block is not fully relocatable, because it may contain a copy of the \fItableptr\fP argument, which is an address (see below). .P The \fIoptions\fP argument contains various bit settings that affect the compilation. It should be zero if no options are required. The available options are described below. Some of them (in particular, those that are compatible with Perl, but some others as well) can also be set and unset from within the pattern (see the detailed description in the .\" HREF \fBpcrepattern\fP .\" documentation). For those options that can be different in different parts of the pattern, the contents of the \fIoptions\fP argument specifies their settings at the start of compilation and execution. The PCRE_ANCHORED, PCRE_BSR_\fIxxx\fP, PCRE_NEWLINE_\fIxxx\fP, PCRE_NO_UTF8_CHECK, and PCRE_NO_START_OPTIMIZE options can be set at the time of matching as well as at compile time. .P If \fIerrptr\fP is NULL, \fBpcre_compile()\fP returns NULL immediately. Otherwise, if compilation of a pattern fails, \fBpcre_compile()\fP returns NULL, and sets the variable pointed to by \fIerrptr\fP to point to a textual error message. This is a static string that is part of the library. You must not try to free it. Normally, the offset from the start of the pattern to the data unit that was being processed when the error was discovered is placed in the variable pointed to by \fIerroffset\fP, which must not be NULL (if it is, an immediate error is given). However, for an invalid UTF-8 or UTF-16 string, the offset is that of the first data unit of the failing character. .P Some errors are not detected until the whole pattern has been scanned; in these cases, the offset passed back is the length of the pattern. Note that the offset is in data units, not characters, even in a UTF mode. It may sometimes point into the middle of a UTF-8 or UTF-16 character. .P If \fBpcre_compile2()\fP is used instead of \fBpcre_compile()\fP, and the \fIerrorcodeptr\fP argument is not NULL, a non-zero error code number is returned via this argument in the event of an error. This is in addition to the textual error message. Error codes and messages are listed below. .P If the final argument, \fItableptr\fP, is NULL, PCRE uses a default set of character tables that are built when PCRE is compiled, using the default C locale. Otherwise, \fItableptr\fP must be an address that is the result of a call to \fBpcre_maketables()\fP. This value is stored with the compiled pattern, and used again by \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP when the pattern is matched. For more discussion, see the section on locale support below. .P This code fragment shows a typical straightforward call to \fBpcre_compile()\fP: .sp pcre *re; const char *error; int erroffset; re = pcre_compile( "^A.*Z", /* the pattern */ 0, /* default options */ &error, /* for error message */ &erroffset, /* for error offset */ NULL); /* use default character tables */ .sp The following names for option bits are defined in the \fBpcre.h\fP header file: .sp PCRE_ANCHORED .sp If this bit is set, the pattern is forced to be "anchored", that is, it is constrained to match only at the first matching point in the string that is being searched (the "subject string"). This effect can also be achieved by appropriate constructs in the pattern itself, which is the only way to do it in Perl. .sp PCRE_AUTO_CALLOUT .sp If this bit is set, \fBpcre_compile()\fP automatically inserts callout items, all with number 255, before each pattern item. For discussion of the callout facility, see the .\" HREF \fBpcrecallout\fP .\" documentation. .sp PCRE_BSR_ANYCRLF PCRE_BSR_UNICODE .sp These options (which are mutually exclusive) control what the \eR escape sequence matches. The choice is either to match only CR, LF, or CRLF, or to match any Unicode newline sequence. The default is specified when PCRE is built. It can be overridden from within the pattern, or by setting an option when a compiled pattern is matched. .sp PCRE_CASELESS .sp If this bit is set, letters in the pattern match both upper and lower case letters. It is equivalent to Perl's /i option, and it can be changed within a pattern by a (?i) option setting. In UTF-8 mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF-8 support. .sp PCRE_DOLLAR_ENDONLY .sp If this bit is set, a dollar metacharacter in the pattern matches only at the end of the subject string. Without this option, a dollar also matches immediately before a newline at the end of the string (but not before any other newlines). The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. There is no equivalent to this option in Perl, and no way to set it within a pattern. .sp PCRE_DOTALL .sp If this bit is set, a dot metacharacter in the pattern matches a character of any value, including one that indicates a newline. However, it only ever matches one character, even if newlines are coded as CRLF. Without this option, a dot does not match when the current position is at a newline. This option is equivalent to Perl's /s option, and it can be changed within a pattern by a (?s) option setting. A negative class such as [^a] always matches newline characters, independent of the setting of this option. .sp PCRE_DUPNAMES .sp If this bit is set, names used to identify capturing subpatterns need not be unique. This can be helpful for certain types of pattern when it is known that only one instance of the named subpattern can ever be matched. There are more details of named subpatterns below; see also the .\" HREF \fBpcrepattern\fP .\" documentation. .sp PCRE_EXTENDED .sp If this bit is set, most white space characters in the pattern are totally ignored except when escaped or inside a character class. However, white space is not allowed within sequences such as (?> that introduce various parenthesized subpatterns, nor within a numerical quantifier such as {1,3}. However, ignorable white space is permitted between an item and a following quantifier and between a quantifier and a following + that indicates possessiveness. .P White space did not used to include the VT character (code 11), because Perl did not treat this character as white space. However, Perl changed at release 5.18, so PCRE followed at release 8.34, and VT is now treated as white space. .P PCRE_EXTENDED also causes characters between an unescaped # outside a character class and the next newline, inclusive, to be ignored. PCRE_EXTENDED is equivalent to Perl's /x option, and it can be changed within a pattern by a (?x) option setting. .P Which characters are interpreted as newlines is controlled by the options passed to \fBpcre_compile()\fP or by a special sequence at the start of the pattern, as described in the section entitled .\" HTML .\" "Newline conventions" .\" in the \fBpcrepattern\fP documentation. Note that the end of this type of comment is a literal newline sequence in the pattern; escape sequences that happen to represent a newline do not count. .P This option makes it possible to include comments inside complicated patterns. Note, however, that this applies only to data characters. White space characters may never appear within special character sequences in a pattern, for example within the sequence (?( that introduces a conditional subpattern. .sp PCRE_EXTRA .sp This option was invented in order to turn on additional functionality of PCRE that is incompatible with Perl, but it is currently of very little use. When set, any backslash in a pattern that is followed by a letter that has no special meaning causes an error, thus reserving these combinations for future expansion. By default, as in Perl, a backslash followed by a letter with no special meaning is treated as a literal. (Perl can, however, be persuaded to give an error for this, by running it with the -w option.) There are at present no other features controlled by this option. It can also be set by a (?X) option setting within a pattern. .sp PCRE_FIRSTLINE .sp If this option is set, an unanchored pattern is required to match before or at the first newline in the subject string, though the matched text may continue over the newline. .sp PCRE_JAVASCRIPT_COMPAT .sp If this option is set, PCRE's behaviour is changed in some ways so that it is compatible with JavaScript rather than Perl. The changes are as follows: .P (1) A lone closing square bracket in a pattern causes a compile-time error, because this is illegal in JavaScript (by default it is treated as a data character). Thus, the pattern AB]CD becomes illegal when this option is set. .P (2) At run time, a back reference to an unset subpattern group matches an empty string (by default this causes the current matching alternative to fail). A pattern such as (\e1)(a) succeeds when this option is set (assuming it can find an "a" in the subject), whereas it fails by default, for Perl compatibility. .P (3) \eU matches an upper case "U" character; by default \eU causes a compile time error (Perl uses \eU to upper case subsequent characters). .P (4) \eu matches a lower case "u" character unless it is followed by four hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, \eu causes a compile time error (Perl uses it to upper case the following character). .P (5) \ex matches a lower case "x" character unless it is followed by two hexadecimal digits, in which case the hexadecimal number defines the code point to match. By default, as in Perl, a hexadecimal number is always expected after \ex, but it may have zero, one, or two digits (so, for example, \exz matches a binary zero character followed by z). .sp PCRE_MULTILINE .sp By default, for the purposes of matching "start of line" and "end of line", PCRE treats the subject string as consisting of a single line of characters, even if it actually contains newlines. The "start of line" metacharacter (^) matches only at the start of the string, and the "end of line" metacharacter ($) matches only at the end of the string, or before a terminating newline (except when PCRE_DOLLAR_ENDONLY is set). Note, however, that unless PCRE_DOTALL is set, the "any character" metacharacter (.) does not match at a newline. This behaviour (for ^, $, and dot) is the same as Perl. .P When PCRE_MULTILINE it is set, the "start of line" and "end of line" constructs match immediately following or immediately before internal newlines in the subject string, respectively, as well as at the very start and end. This is equivalent to Perl's /m option, and it can be changed within a pattern by a (?m) option setting. If there are no newlines in a subject string, or no occurrences of ^ or $ in a pattern, setting PCRE_MULTILINE has no effect. .sp PCRE_NEVER_UTF .sp This option locks out interpretation of the pattern as UTF-8 (or UTF-16 or UTF-32 in the 16-bit and 32-bit libraries). In particular, it prevents the creator of the pattern from switching to UTF interpretation by starting the pattern with (*UTF). This may be useful in applications that process patterns from external sources. The combination of PCRE_UTF8 and PCRE_NEVER_UTF also causes an error. .sp PCRE_NEWLINE_CR PCRE_NEWLINE_LF PCRE_NEWLINE_CRLF PCRE_NEWLINE_ANYCRLF PCRE_NEWLINE_ANY .sp These options override the default newline definition that was chosen when PCRE was built. Setting the first or the second specifies that a newline is indicated by a single character (CR or LF, respectively). Setting PCRE_NEWLINE_CRLF specifies that a newline is indicated by the two-character CRLF sequence. Setting PCRE_NEWLINE_ANYCRLF specifies that any of the three preceding sequences should be recognized. Setting PCRE_NEWLINE_ANY specifies that any Unicode newline sequence should be recognized. .P In an ASCII/Unicode environment, the Unicode newline sequences are the three just mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029). For the 8-bit library, the last two are recognized only in UTF-8 mode. .P When PCRE is compiled to run in an EBCDIC (mainframe) environment, the code for CR is 0x0d, the same as ASCII. However, the character code for LF is normally 0x15, though in some EBCDIC environments 0x25 is used. Whichever of these is not LF is made to correspond to Unicode's NEL character. EBCDIC codes are all less than 256. For more details, see the .\" HREF \fBpcrebuild\fP .\" documentation. .P The newline setting in the options word uses three bits that are treated as a number, giving eight possibilities. Currently only six are used (default plus the five values above). This means that if you set more than one newline option, the combination may or may not be sensible. For example, PCRE_NEWLINE_CR with PCRE_NEWLINE_LF is equivalent to PCRE_NEWLINE_CRLF, but other combinations may yield unused numbers and cause an error. .P The only time that a line break in a pattern is specially recognized when compiling is when PCRE_EXTENDED is set. CR and LF are white space characters, and so are ignored in this mode. Also, an unescaped # outside a character class indicates a comment that lasts until after the next line break sequence. In other circumstances, line break sequences in patterns are treated as literal data. .P The newline option that is set at compile time becomes the default that is used for \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP, but it can be overridden. .sp PCRE_NO_AUTO_CAPTURE .sp If this option is set, it disables the use of numbered capturing parentheses in the pattern. Any opening parenthesis that is not followed by ? behaves as if it were followed by ?: but named parentheses can still be used for capturing (and they acquire numbers in the usual way). There is no equivalent of this option in Perl. .sp PCRE_NO_AUTO_POSSESS .sp If this option is set, it disables "auto-possessification". This is an optimization that, for example, turns a+b into a++b in order to avoid backtracks into a+ that can never be successful. However, if callouts are in use, auto-possessification means that some of them are never taken. You can set this option if you want the matching functions to do a full unoptimized search and run all the callouts, but it is mainly provided for testing purposes. .sp PCRE_NO_START_OPTIMIZE .sp This is an option that acts at matching time; that is, it is really an option for \fBpcre_exec()\fP or \fBpcre_dfa_exec()\fP. If it is set at compile time, it is remembered with the compiled pattern and assumed at matching time. This is necessary if you want to use JIT execution, because the JIT compiler needs to know whether or not this option is set. For details see the discussion of PCRE_NO_START_OPTIMIZE .\" HTML .\" below. .\" .sp PCRE_UCP .sp This option changes the way PCRE processes \eB, \eb, \eD, \ed, \eS, \es, \eW, \ew, and some of the POSIX character classes. By default, only ASCII characters are recognized, but if PCRE_UCP is set, Unicode properties are used instead to classify characters. More details are given in the section on .\" HTML .\" generic character types .\" in the .\" HREF \fBpcrepattern\fP .\" page. If you set PCRE_UCP, matching one of the items it affects takes much longer. The option is available only if PCRE has been compiled with Unicode property support. .sp PCRE_UNGREEDY .sp This option inverts the "greediness" of the quantifiers so that they are not greedy by default, but become greedy if followed by "?". It is not compatible with Perl. It can also be set by a (?U) option setting within the pattern. .sp PCRE_UTF8 .sp This option causes PCRE to regard both the pattern and the subject as strings of UTF-8 characters instead of single-byte strings. However, it is available only when PCRE is built to include UTF support. If not, the use of this option provokes an error. Details of how this option changes the behaviour of PCRE are given in the .\" HREF \fBpcreunicode\fP .\" page. .sp PCRE_NO_UTF8_CHECK .sp When PCRE_UTF8 is set, the validity of the pattern as a UTF-8 string is automatically checked. There is a discussion about the .\" HTML .\" validity of UTF-8 strings .\" in the .\" HREF \fBpcreunicode\fP .\" page. If an invalid UTF-8 sequence is found, \fBpcre_compile()\fP returns an error. If you already know that your pattern is valid, and you want to skip this check for performance reasons, you can set the PCRE_NO_UTF8_CHECK option. When it is set, the effect of passing an invalid UTF-8 string as a pattern is undefined. It may cause your program to crash or loop. Note that this option can also be passed to \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP, to suppress the validity checking of subject strings only. If the same string is being matched many times, the option can be safely set for the second and subsequent matchings to improve performance. . . .SH "COMPILATION ERROR CODES" .rs .sp The following table lists the error codes than may be returned by \fBpcre_compile2()\fP, along with the error messages that may be returned by both compiling functions. Note that error messages are always 8-bit ASCII strings, even in 16-bit or 32-bit mode. As PCRE has developed, some error codes have fallen out of use. To avoid confusion, they have not been re-used. .sp 0 no error 1 \e at end of pattern 2 \ec at end of pattern 3 unrecognized character follows \e 4 numbers out of order in {} quantifier 5 number too big in {} quantifier 6 missing terminating ] for character class 7 invalid escape sequence in character class 8 range out of order in character class 9 nothing to repeat 10 [this code is not in use] 11 internal error: unexpected repeat 12 unrecognized character after (? or (?- 13 POSIX named classes are supported only within a class 14 missing ) 15 reference to non-existent subpattern 16 erroffset passed as NULL 17 unknown option bit(s) set 18 missing ) after comment 19 [this code is not in use] 20 regular expression is too large 21 failed to get memory 22 unmatched parentheses 23 internal error: code overflow 24 unrecognized character after (?< 25 lookbehind assertion is not fixed length 26 malformed number or name after (?( 27 conditional group contains more than two branches 28 assertion expected after (?( 29 (?R or (?[+-]digits must be followed by ) 30 unknown POSIX class name 31 POSIX collating elements are not supported 32 this version of PCRE is compiled without UTF support 33 [this code is not in use] 34 character value in \ex{} or \eo{} is too large 35 invalid condition (?(0) 36 \eC not allowed in lookbehind assertion 37 PCRE does not support \eL, \el, \eN{name}, \eU, or \eu 38 number after (?C is > 255 39 closing ) for (?C expected 40 recursive call could loop indefinitely 41 unrecognized character after (?P 42 syntax error in subpattern name (missing terminator) 43 two named subpatterns have the same name 44 invalid UTF-8 string (specifically UTF-8) 45 support for \eP, \ep, and \eX has not been compiled 46 malformed \eP or \ep sequence 47 unknown property name after \eP or \ep 48 subpattern name is too long (maximum 32 characters) 49 too many named subpatterns (maximum 10000) 50 [this code is not in use] 51 octal value is greater than \e377 in 8-bit non-UTF-8 mode 52 internal error: overran compiling workspace 53 internal error: previously-checked referenced subpattern not found 54 DEFINE group contains more than one branch 55 repeating a DEFINE group is not allowed 56 inconsistent NEWLINE options 57 \eg is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number 58 a numbered reference must not be zero 59 an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) 60 (*VERB) not recognized or malformed 61 number is too big 62 subpattern name expected 63 digit expected after (?+ 64 ] is an invalid data character in JavaScript compatibility mode 65 different names for subpatterns of the same number are not allowed 66 (*MARK) must have an argument 67 this version of PCRE is not compiled with Unicode property support 68 \ec must be followed by an ASCII character 69 \ek is not followed by a braced, angle-bracketed, or quoted name 70 internal error: unknown opcode in find_fixedlength() 71 \eN is not supported in a class 72 too many forward references 73 disallowed Unicode code point (>= 0xd800 && <= 0xdfff) 74 invalid UTF-16 string (specifically UTF-16) 75 name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN) 76 character value in \eu.... sequence is too large 77 invalid UTF-32 string (specifically UTF-32) 78 setting UTF is disabled by the application 79 non-hex character in \ex{} (closing brace missing?) 80 non-octal character in \eo{} (closing brace missing?) 81 missing opening brace after \eo 82 parentheses are too deeply nested 83 invalid range in character class 84 group name must start with a non-digit 85 parentheses are too deeply nested (stack check) .sp The numbers 32 and 10000 in errors 48 and 49 are defaults; different values may be used if the limits were changed when PCRE was built. . . .\" HTML .SH "STUDYING A PATTERN" .rs .sp .nf .B pcre_extra *pcre_study(const pcre *\fIcode\fP, int \fIoptions\fP, .B " const char **\fIerrptr\fP);" .fi .PP If a compiled pattern is going to be used several times, it is worth spending more time analyzing it in order to speed up the time taken for matching. The function \fBpcre_study()\fP takes a pointer to a compiled pattern as its first argument. If studying the pattern produces additional information that will help speed up matching, \fBpcre_study()\fP returns a pointer to a \fBpcre_extra\fP block, in which the \fIstudy_data\fP field points to the results of the study. .P The returned value from \fBpcre_study()\fP can be passed directly to \fBpcre_exec()\fP or \fBpcre_dfa_exec()\fP. However, a \fBpcre_extra\fP block also contains other fields that can be set by the caller before the block is passed; these are described .\" HTML .\" below .\" in the section on matching a pattern. .P If studying the pattern does not produce any useful information, \fBpcre_study()\fP returns NULL by default. In that circumstance, if the calling program wants to pass any of the other fields to \fBpcre_exec()\fP or \fBpcre_dfa_exec()\fP, it must set up its own \fBpcre_extra\fP block. However, if \fBpcre_study()\fP is called with the PCRE_STUDY_EXTRA_NEEDED option, it returns a \fBpcre_extra\fP block even if studying did not find any additional information. It may still return NULL, however, if an error occurs in \fBpcre_study()\fP. .P The second argument of \fBpcre_study()\fP contains option bits. There are three further options in addition to PCRE_STUDY_EXTRA_NEEDED: .sp PCRE_STUDY_JIT_COMPILE PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE .sp If any of these are set, and the just-in-time compiler is available, the pattern is further compiled into machine code that executes much faster than the \fBpcre_exec()\fP interpretive matching function. If the just-in-time compiler is not available, these options are ignored. All undefined bits in the \fIoptions\fP argument must be zero. .P JIT compilation is a heavyweight optimization. It can take some time for patterns to be analyzed, and for one-off matches and simple patterns the benefit of faster execution might be offset by a much slower study time. Not all patterns can be optimized by the JIT compiler. For those that cannot be handled, matching automatically falls back to the \fBpcre_exec()\fP interpreter. For more details, see the .\" HREF \fBpcrejit\fP .\" documentation. .P The third argument for \fBpcre_study()\fP is a pointer for an error message. If studying succeeds (even if no data is returned), the variable it points to is set to NULL. Otherwise it is set to point to a textual error message. This is a static string that is part of the library. You must not try to free it. You should test the error pointer for NULL after calling \fBpcre_study()\fP, to be sure that it has run successfully. .P When you are finished with a pattern, you can free the memory used for the study data by calling \fBpcre_free_study()\fP. This function was added to the API for release 8.20. For earlier versions, the memory could be freed with \fBpcre_free()\fP, just like the pattern itself. This will still work in cases where JIT optimization is not used, but it is advisable to change to the new function when convenient. .P This is a typical way in which \fBpcre_study\fP() is used (except that in a real application there should be tests for errors): .sp int rc; pcre *re; pcre_extra *sd; re = pcre_compile("pattern", 0, &error, &erroroffset, NULL); sd = pcre_study( re, /* result of pcre_compile() */ 0, /* no options */ &error); /* set to NULL or points to a message */ rc = pcre_exec( /* see below for details of pcre_exec() options */ re, sd, "subject", 7, 0, 0, ovector, 30); ... pcre_free_study(sd); pcre_free(re); .sp Studying a pattern does two things: first, a lower bound for the length of subject string that is needed to match the pattern is computed. This does not mean that there are any strings of that length that match, but it does guarantee that no shorter strings match. The value is used to avoid wasting time by trying to match strings that are shorter than the lower bound. You can find out the value in a calling program via the \fBpcre_fullinfo()\fP function. .P Studying a pattern is also useful for non-anchored patterns that do not have a single fixed starting character. A bitmap of possible starting bytes is created. This speeds up finding a position in the subject at which to start matching. (In 16-bit mode, the bitmap is used for 16-bit values less than 256. In 32-bit mode, the bitmap is used for 32-bit values less than 256.) .P These two optimizations apply to both \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP, and the information is also used by the JIT compiler. The optimizations can be disabled by setting the PCRE_NO_START_OPTIMIZE option. You might want to do this if your pattern contains callouts or (*MARK) and you want to make use of these facilities in cases where matching fails. .P PCRE_NO_START_OPTIMIZE can be specified at either compile time or execution time. However, if PCRE_NO_START_OPTIMIZE is passed to \fBpcre_exec()\fP, (that is, after any JIT compilation has happened) JIT execution is disabled. For JIT execution to work with PCRE_NO_START_OPTIMIZE, the option must be set at compile time. .P There is a longer discussion of PCRE_NO_START_OPTIMIZE .\" HTML .\" below. .\" . . .\" HTML .SH "LOCALE SUPPORT" .rs .sp PCRE handles caseless matching, and determines whether characters are letters, digits, or whatever, by reference to a set of tables, indexed by character code point. When running in UTF-8 mode, or in the 16- or 32-bit libraries, this applies only to characters with code points less than 256. By default, higher-valued code points never match escapes such as \ew or \ed. However, if PCRE is built with Unicode property support, all characters can be tested with \ep and \eP, or, alternatively, the PCRE_UCP option can be set when a pattern is compiled; this causes \ew and friends to use Unicode property support instead of the built-in tables. .P The use of locales with Unicode is discouraged. If you are handling characters with code points greater than 128, you should either use Unicode support, or use locales, but not try to mix the two. .P PCRE contains an internal set of tables that are used when the final argument of \fBpcre_compile()\fP is NULL. These are sufficient for many applications. Normally, the internal tables recognize only ASCII characters. However, when PCRE is built, it is possible to cause the internal tables to be rebuilt in the default "C" locale of the local system, which may cause them to be different. .P The internal tables can always be overridden by tables supplied by the application that calls PCRE. These may be created in a different locale from the default. As more and more applications change to using Unicode, the need for this locale support is expected to die away. .P External tables are built by calling the \fBpcre_maketables()\fP function, which has no arguments, in the relevant locale. The result can then be passed to \fBpcre_compile()\fP as often as necessary. For example, to build and use tables that are appropriate for the French locale (where accented characters with values greater than 128 are treated as letters), the following code could be used: .sp setlocale(LC_CTYPE, "fr_FR"); tables = pcre_maketables(); re = pcre_compile(..., tables); .sp The locale name "fr_FR" is used on Linux and other Unix-like systems; if you are using Windows, the name for the French locale is "french". .P When \fBpcre_maketables()\fP runs, the tables are built in memory that is obtained via \fBpcre_malloc\fP. It is the caller's responsibility to ensure that the memory containing the tables remains available for as long as it is needed. .P The pointer that is passed to \fBpcre_compile()\fP is saved with the compiled pattern, and the same tables are used via this pointer by \fBpcre_study()\fP and also by \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP. Thus, for any single pattern, compilation, studying and matching all happen in the same locale, but different patterns can be processed in different locales. .P It is possible to pass a table pointer or NULL (indicating the use of the internal tables) to \fBpcre_exec()\fP or \fBpcre_dfa_exec()\fP (see the discussion below in the section on matching a pattern). This facility is provided for use with pre-compiled patterns that have been saved and reloaded. Character tables are not saved with patterns, so if a non-standard table was used at compile time, it must be provided again when the reloaded pattern is matched. Attempting to use this facility to match a pattern in a different locale from the one in which it was compiled is likely to lead to anomalous (usually incorrect) results. . . .\" HTML .SH "INFORMATION ABOUT A PATTERN" .rs .sp .nf .B int pcre_fullinfo(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " int \fIwhat\fP, void *\fIwhere\fP);" .fi .PP The \fBpcre_fullinfo()\fP function returns information about a compiled pattern. It replaces the \fBpcre_info()\fP function, which was removed from the library at version 8.30, after more than 10 years of obsolescence. .P The first argument for \fBpcre_fullinfo()\fP is a pointer to the compiled pattern. The second argument is the result of \fBpcre_study()\fP, or NULL if the pattern was not studied. The third argument specifies which piece of information is required, and the fourth argument is a pointer to a variable to receive the data. The yield of the function is zero for success, or one of the following negative numbers: .sp PCRE_ERROR_NULL the argument \fIcode\fP was NULL the argument \fIwhere\fP was NULL PCRE_ERROR_BADMAGIC the "magic number" was not found PCRE_ERROR_BADENDIANNESS the pattern was compiled with different endianness PCRE_ERROR_BADOPTION the value of \fIwhat\fP was invalid PCRE_ERROR_UNSET the requested field is not set .sp The "magic number" is placed at the start of each compiled pattern as an simple check against passing an arbitrary memory pointer. The endianness error can occur if a compiled pattern is saved and reloaded on a different host. Here is a typical call of \fBpcre_fullinfo()\fP, to obtain the length of the compiled pattern: .sp int rc; size_t length; rc = pcre_fullinfo( re, /* result of pcre_compile() */ sd, /* result of pcre_study(), or NULL */ PCRE_INFO_SIZE, /* what is required */ &length); /* where to put the data */ .sp The possible values for the third argument are defined in \fBpcre.h\fP, and are as follows: .sp PCRE_INFO_BACKREFMAX .sp Return the number of the highest back reference in the pattern. The fourth argument should point to an \fBint\fP variable. Zero is returned if there are no back references. .sp PCRE_INFO_CAPTURECOUNT .sp Return the number of capturing subpatterns in the pattern. The fourth argument should point to an \fBint\fP variable. .sp PCRE_INFO_DEFAULT_TABLES .sp Return a pointer to the internal default character tables within PCRE. The fourth argument should point to an \fBunsigned char *\fP variable. This information call is provided for internal use by the \fBpcre_study()\fP function. External callers can cause PCRE to use its internal tables by passing a NULL table pointer. .sp PCRE_INFO_FIRSTBYTE (deprecated) .sp Return information about the first data unit of any matched string, for a non-anchored pattern. The name of this option refers to the 8-bit library, where data units are bytes. The fourth argument should point to an \fBint\fP variable. Negative values are used for special cases. However, this means that when the 32-bit library is in non-UTF-32 mode, the full 32-bit range of characters cannot be returned. For this reason, this value is deprecated; use PCRE_INFO_FIRSTCHARACTERFLAGS and PCRE_INFO_FIRSTCHARACTER instead. .P If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), its value is returned. In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library the value can be up to 0x10ffff. .P If there is no fixed first value, and if either .sp (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or .sp (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored), .sp -1 is returned, indicating that the pattern matches only at the start of a subject string or after any newline within the string. Otherwise -2 is returned. For anchored patterns, -2 is returned. .sp PCRE_INFO_FIRSTCHARACTER .sp Return the value of the first data unit (non-UTF character) of any matched string in the situation where PCRE_INFO_FIRSTCHARACTERFLAGS returns 1; otherwise return 0. The fourth argument should point to an \fBuint_t\fP variable. .P In the 8-bit library, the value is always less than 256. In the 16-bit library the value can be up to 0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff, and up to 0xffffffff when not using UTF-32 mode. .sp PCRE_INFO_FIRSTCHARACTERFLAGS .sp Return information about the first data unit of any matched string, for a non-anchored pattern. The fourth argument should point to an \fBint\fP variable. .P If there is a fixed first value, for example, the letter "c" from a pattern such as (cat|cow|coyote), 1 is returned, and the character value can be retrieved using PCRE_INFO_FIRSTCHARACTER. If there is no fixed first value, and if either .sp (a) the pattern was compiled with the PCRE_MULTILINE option, and every branch starts with "^", or .sp (b) every branch of the pattern starts with ".*" and PCRE_DOTALL is not set (if it were set, the pattern would be anchored), .sp 2 is returned, indicating that the pattern matches only at the start of a subject string or after any newline within the string. Otherwise 0 is returned. For anchored patterns, 0 is returned. .sp PCRE_INFO_FIRSTTABLE .sp If the pattern was studied, and this resulted in the construction of a 256-bit table indicating a fixed set of values for the first data unit in any matching string, a pointer to the table is returned. Otherwise NULL is returned. The fourth argument should point to an \fBunsigned char *\fP variable. .sp PCRE_INFO_HASCRORLF .sp Return 1 if the pattern contains any explicit matches for CR or LF characters, otherwise 0. The fourth argument should point to an \fBint\fP variable. An explicit match is either a literal CR or LF character, or \er or \en. .sp PCRE_INFO_JCHANGED .sp Return 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise 0. The fourth argument should point to an \fBint\fP variable. (?J) and (?-J) set and unset the local PCRE_DUPNAMES option, respectively. .sp PCRE_INFO_JIT .sp Return 1 if the pattern was studied with one of the JIT options, and just-in-time compiling was successful. The fourth argument should point to an \fBint\fP variable. A return value of 0 means that JIT support is not available in this version of PCRE, or that the pattern was not studied with a JIT option, or that the JIT compiler could not handle this particular pattern. See the .\" HREF \fBpcrejit\fP .\" documentation for details of what can and cannot be handled. .sp PCRE_INFO_JITSIZE .sp If the pattern was successfully studied with a JIT option, return the size of the JIT compiled code, otherwise return zero. The fourth argument should point to a \fBsize_t\fP variable. .sp PCRE_INFO_LASTLITERAL .sp Return the value of the rightmost literal data unit that must exist in any matched string, other than at its start, if such a value has been recorded. The fourth argument should point to an \fBint\fP variable. If there is no such value, -1 is returned. For anchored patterns, a last literal value is recorded only if it follows something of variable length. For example, for the pattern /^a\ed+z\ed+/ the returned value is "z", but for /^a\edz\ed/ the returned value is -1. .P Since for the 32-bit library using the non-UTF-32 mode, this function is unable to return the full 32-bit range of characters, this value is deprecated; instead the PCRE_INFO_REQUIREDCHARFLAGS and PCRE_INFO_REQUIREDCHAR values should be used. .sp PCRE_INFO_MATCH_EMPTY .sp Return 1 if the pattern can match an empty string, otherwise 0. The fourth argument should point to an \fBint\fP variable. .sp PCRE_INFO_MATCHLIMIT .sp If the pattern set a match limit by including an item of the form (*LIMIT_MATCH=nnnn) at the start, the value is returned. The fourth argument should point to an unsigned 32-bit integer. If no such value has been set, the call to \fBpcre_fullinfo()\fP returns the error PCRE_ERROR_UNSET. .sp PCRE_INFO_MAXLOOKBEHIND .sp Return the number of characters (NB not data units) in the longest lookbehind assertion in the pattern. This information is useful when doing multi-segment matching using the partial matching facilities. Note that the simple assertions \eb and \eB require a one-character lookbehind. \eA also registers a one-character lookbehind, though it does not actually inspect the previous character. This is to ensure that at least one character from the old segment is retained when a new segment is processed. Otherwise, if there are no lookbehinds in the pattern, \eA might match incorrectly at the start of a new segment. .sp PCRE_INFO_MINLENGTH .sp If the pattern was studied and a minimum length for matching subject strings was computed, its value is returned. Otherwise the returned value is -1. The value is a number of characters, which in UTF mode may be different from the number of data units. The fourth argument should point to an \fBint\fP variable. A non-negative value is a lower bound to the length of any matching string. There may not be any strings of that length that do actually match, but every string that does match is at least that long. .sp PCRE_INFO_NAMECOUNT PCRE_INFO_NAMEENTRYSIZE PCRE_INFO_NAMETABLE .sp PCRE supports the use of named as well as numbered capturing parentheses. The names are just an additional way of identifying the parentheses, which still acquire numbers. Several convenience functions such as \fBpcre_get_named_substring()\fP are provided for extracting captured substrings by name. It is also possible to extract the data directly, by first converting the name to a number in order to access the correct pointers in the output vector (described with \fBpcre_exec()\fP below). To do the conversion, you need to use the name-to-number map, which is described by these three values. .P The map consists of a number of fixed-size entries. PCRE_INFO_NAMECOUNT gives the number of entries, and PCRE_INFO_NAMEENTRYSIZE gives the size of each entry; both of these return an \fBint\fP value. The entry size depends on the length of the longest name. PCRE_INFO_NAMETABLE returns a pointer to the first entry of the table. This is a pointer to \fBchar\fP in the 8-bit library, where the first two bytes of each entry are the number of the capturing parenthesis, most significant byte first. In the 16-bit library, the pointer points to 16-bit data units, the first of which contains the parenthesis number. In the 32-bit library, the pointer points to 32-bit data units, the first of which contains the parenthesis number. The rest of the entry is the corresponding name, zero terminated. .P The names are in alphabetical order. If (?| is used to create multiple groups with the same number, as described in the .\" HTML .\" section on duplicate subpattern numbers .\" in the .\" HREF \fBpcrepattern\fP .\" page, the groups may be given the same name, but there is only one entry in the table. Different names for groups of the same number are not permitted. Duplicate names for subpatterns with different numbers are permitted, but only if PCRE_DUPNAMES is set. They appear in the table in the order in which they were found in the pattern. In the absence of (?| this is the order of increasing number; when (?| is used this is not necessarily the case because later subpatterns may have lower numbers. .P As a simple example of the name/number table, consider the following pattern after compilation by the 8-bit library (assume PCRE_EXTENDED is set, so white space - including newlines - is ignored): .sp .\" JOIN (? (?(\ed\ed)?\ed\ed) - (?\ed\ed) - (?\ed\ed) ) .sp There are four named subpatterns, so the table has four entries, and each entry in the table is eight bytes long. The table is as follows, with non-printing bytes shows in hexadecimal, and undefined bytes shown as ??: .sp 00 01 d a t e 00 ?? 00 05 d a y 00 ?? ?? 00 04 m o n t h 00 00 02 y e a r 00 ?? .sp When writing code to extract data from named subpatterns using the name-to-number map, remember that the length of the entries is likely to be different for each compiled pattern. .sp PCRE_INFO_OKPARTIAL .sp Return 1 if the pattern can be used for partial matching with \fBpcre_exec()\fP, otherwise 0. The fourth argument should point to an \fBint\fP variable. From release 8.00, this always returns 1, because the restrictions that previously applied to partial matching have been lifted. The .\" HREF \fBpcrepartial\fP .\" documentation gives details of partial matching. .sp PCRE_INFO_OPTIONS .sp Return a copy of the options with which the pattern was compiled. The fourth argument should point to an \fBunsigned long int\fP variable. These option bits are those specified in the call to \fBpcre_compile()\fP, modified by any top-level option settings at the start of the pattern itself. In other words, they are the options that will be in force when matching starts. For example, if the pattern /(?im)abc(?-i)d/ is compiled with the PCRE_EXTENDED option, the result is PCRE_CASELESS, PCRE_MULTILINE, and PCRE_EXTENDED. .P A pattern is automatically anchored by PCRE if all of its top-level alternatives begin with one of the following: .sp ^ unless PCRE_MULTILINE is set \eA always \eG always .\" JOIN .* if PCRE_DOTALL is set and there are no back references to the subpattern in which .* appears .sp For such patterns, the PCRE_ANCHORED bit is set in the options returned by \fBpcre_fullinfo()\fP. .sp PCRE_INFO_RECURSIONLIMIT .sp If the pattern set a recursion limit by including an item of the form (*LIMIT_RECURSION=nnnn) at the start, the value is returned. The fourth argument should point to an unsigned 32-bit integer. If no such value has been set, the call to \fBpcre_fullinfo()\fP returns the error PCRE_ERROR_UNSET. .sp PCRE_INFO_SIZE .sp Return the size of the compiled pattern in bytes (for all three libraries). The fourth argument should point to a \fBsize_t\fP variable. This value does not include the size of the \fBpcre\fP structure that is returned by \fBpcre_compile()\fP. The value that is passed as the argument to \fBpcre_malloc()\fP when \fBpcre_compile()\fP is getting memory in which to place the compiled data is the value returned by this option plus the size of the \fBpcre\fP structure. Studying a compiled pattern, with or without JIT, does not alter the value returned by this option. .sp PCRE_INFO_STUDYSIZE .sp Return the size in bytes (for all three libraries) of the data block pointed to by the \fIstudy_data\fP field in a \fBpcre_extra\fP block. If \fBpcre_extra\fP is NULL, or there is no study data, zero is returned. The fourth argument should point to a \fBsize_t\fP variable. The \fIstudy_data\fP field is set by \fBpcre_study()\fP to record information that will speed up matching (see the section entitled .\" HTML .\" "Studying a pattern" .\" above). The format of the \fIstudy_data\fP block is private, but its length is made available via this option so that it can be saved and restored (see the .\" HREF \fBpcreprecompile\fP .\" documentation for details). .sp PCRE_INFO_REQUIREDCHARFLAGS .sp Returns 1 if there is a rightmost literal data unit that must exist in any matched string, other than at its start. The fourth argument should point to an \fBint\fP variable. If there is no such value, 0 is returned. If returning 1, the character value itself can be retrieved using PCRE_INFO_REQUIREDCHAR. .P For anchored patterns, a last literal value is recorded only if it follows something of variable length. For example, for the pattern /^a\ed+z\ed+/ the returned value 1 (with "z" returned from PCRE_INFO_REQUIREDCHAR), but for /^a\edz\ed/ the returned value is 0. .sp PCRE_INFO_REQUIREDCHAR .sp Return the value of the rightmost literal data unit that must exist in any matched string, other than at its start, if such a value has been recorded. The fourth argument should point to an \fBuint32_t\fP variable. If there is no such value, 0 is returned. . . .SH "REFERENCE COUNTS" .rs .sp .B int pcre_refcount(pcre *\fIcode\fP, int \fIadjust\fP); .PP The \fBpcre_refcount()\fP function is used to maintain a reference count in the data block that contains a compiled pattern. It is provided for the benefit of applications that operate in an object-oriented manner, where different parts of the application may be using the same compiled pattern, but you want to free the block when they are all done. .P When a pattern is compiled, the reference count field is initialized to zero. It is changed only by calling this function, whose action is to add the \fIadjust\fP value (which may be positive or negative) to it. The yield of the function is the new value. However, the value of the count is constrained to lie between 0 and 65535, inclusive. If the new value is outside these limits, it is forced to the appropriate limit value. .P Except when it is zero, the reference count is not correctly preserved if a pattern is compiled on one host and then transferred to a host whose byte-order is different. (This seems a highly unlikely scenario.) . . .SH "MATCHING A PATTERN: THE TRADITIONAL FUNCTION" .rs .sp .nf .B int pcre_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP," int \fIlength\fP, int \fIstartoffset\fP, .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP);" .fi .P The function \fBpcre_exec()\fP is called to match a subject string against a compiled pattern, which is passed in the \fIcode\fP argument. If the pattern was studied, the result of the study should be passed in the \fIextra\fP argument. You can call \fBpcre_exec()\fP with the same \fIcode\fP and \fIextra\fP arguments as many times as you like, in order to match different subject strings with the same pattern. .P This function is the main matching facility of the library, and it operates in a Perl-like manner. For specialist use there is also an alternative matching function, which is described .\" HTML .\" below .\" in the section about the \fBpcre_dfa_exec()\fP function. .P In most applications, the pattern will have been compiled (and optionally studied) in the same process that calls \fBpcre_exec()\fP. However, it is possible to save compiled patterns and study data, and then use them later in different processes, possibly even on different hosts. For a discussion about this, see the .\" HREF \fBpcreprecompile\fP .\" documentation. .P Here is an example of a simple call to \fBpcre_exec()\fP: .sp int rc; int ovector[30]; rc = pcre_exec( re, /* result of pcre_compile() */ NULL, /* we didn't study the pattern */ "some string", /* the subject string */ 11, /* the length of the subject string */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* vector of integers for substring information */ 30); /* number of elements (NOT size in bytes) */ . . .\" HTML .SS "Extra data for \fBpcre_exec()\fR" .rs .sp If the \fIextra\fP argument is not NULL, it must point to a \fBpcre_extra\fP data block. The \fBpcre_study()\fP function returns such a block (when it doesn't return NULL), but you can also create one for yourself, and pass additional information in it. The \fBpcre_extra\fP block contains the following fields (not necessarily in this order): .sp unsigned long int \fIflags\fP; void *\fIstudy_data\fP; void *\fIexecutable_jit\fP; unsigned long int \fImatch_limit\fP; unsigned long int \fImatch_limit_recursion\fP; void *\fIcallout_data\fP; const unsigned char *\fItables\fP; unsigned char **\fImark\fP; .sp In the 16-bit version of this structure, the \fImark\fP field has type "PCRE_UCHAR16 **". .sp In the 32-bit version of this structure, the \fImark\fP field has type "PCRE_UCHAR32 **". .P The \fIflags\fP field is used to specify which of the other fields are set. The flag bits are: .sp PCRE_EXTRA_CALLOUT_DATA PCRE_EXTRA_EXECUTABLE_JIT PCRE_EXTRA_MARK PCRE_EXTRA_MATCH_LIMIT PCRE_EXTRA_MATCH_LIMIT_RECURSION PCRE_EXTRA_STUDY_DATA PCRE_EXTRA_TABLES .sp Other flag bits should be set to zero. The \fIstudy_data\fP field and sometimes the \fIexecutable_jit\fP field are set in the \fBpcre_extra\fP block that is returned by \fBpcre_study()\fP, together with the appropriate flag bits. You should not set these yourself, but you may add to the block by setting other fields and their corresponding flag bits. .P The \fImatch_limit\fP field provides a means of preventing PCRE from using up a vast amount of resources when running patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is a pattern that uses nested unlimited repeats. .P Internally, \fBpcre_exec()\fP uses a function called \fBmatch()\fP, which it calls repeatedly (sometimes recursively). The limit set by \fImatch_limit\fP is imposed on the number of times this function is called during a match, which has the effect of limiting the amount of backtracking that can take place. For patterns that are not anchored, the count restarts from zero for each position in the subject string. .P When \fBpcre_exec()\fP is called with a pattern that was successfully studied with a JIT option, the way that the matching is executed is entirely different. However, there is still the possibility of runaway matching that goes on for a very long time, and so the \fImatch_limit\fP value is also used in this case (but in a different way) to limit how long the matching can continue. .P The default value for the limit can be set when PCRE is built; the default default is 10 million, which handles all but the most extreme cases. You can override the default by suppling \fBpcre_exec()\fP with a \fBpcre_extra\fP block in which \fImatch_limit\fP is set, and PCRE_EXTRA_MATCH_LIMIT is set in the \fIflags\fP field. If the limit is exceeded, \fBpcre_exec()\fP returns PCRE_ERROR_MATCHLIMIT. .P A value for the match limit may also be supplied by an item at the start of a pattern of the form .sp (*LIMIT_MATCH=d) .sp where d is a decimal number. However, such a setting is ignored unless d is less than the limit set by the caller of \fBpcre_exec()\fP or, if no such limit is set, less than the default. .P The \fImatch_limit_recursion\fP field is similar to \fImatch_limit\fP, but instead of limiting the total number of times that \fBmatch()\fP is called, it limits the depth of recursion. The recursion depth is a smaller number than the total number of calls, because not all calls to \fBmatch()\fP are recursive. This limit is of use only if it is set smaller than \fImatch_limit\fP. .P Limiting the recursion depth limits the amount of machine stack that can be used, or, when PCRE has been compiled to use memory on the heap instead of the stack, the amount of heap memory that can be used. This limit is not relevant, and is ignored, when matching is done using JIT compiled code. .P The default value for \fImatch_limit_recursion\fP can be set when PCRE is built; the default default is the same value as the default for \fImatch_limit\fP. You can override the default by suppling \fBpcre_exec()\fP with a \fBpcre_extra\fP block in which \fImatch_limit_recursion\fP is set, and PCRE_EXTRA_MATCH_LIMIT_RECURSION is set in the \fIflags\fP field. If the limit is exceeded, \fBpcre_exec()\fP returns PCRE_ERROR_RECURSIONLIMIT. .P A value for the recursion limit may also be supplied by an item at the start of a pattern of the form .sp (*LIMIT_RECURSION=d) .sp where d is a decimal number. However, such a setting is ignored unless d is less than the limit set by the caller of \fBpcre_exec()\fP or, if no such limit is set, less than the default. .P The \fIcallout_data\fP field is used in conjunction with the "callout" feature, and is described in the .\" HREF \fBpcrecallout\fP .\" documentation. .P The \fItables\fP field is provided for use with patterns that have been pre-compiled using custom character tables, saved to disc or elsewhere, and then reloaded, because the tables that were used to compile a pattern are not saved with it. See the .\" HREF \fBpcreprecompile\fP .\" documentation for a discussion of saving compiled patterns for later use. If NULL is passed using this mechanism, it forces PCRE's internal tables to be used. .P \fBWarning:\fP The tables that \fBpcre_exec()\fP uses must be the same as those that were used when the pattern was compiled. If this is not the case, the behaviour of \fBpcre_exec()\fP is undefined. Therefore, when a pattern is compiled and matched in the same process, this field should never be set. In this (the most common) case, the correct table pointer is automatically passed with the compiled pattern from \fBpcre_compile()\fP to \fBpcre_exec()\fP. .P If PCRE_EXTRA_MARK is set in the \fIflags\fP field, the \fImark\fP field must be set to point to a suitable variable. If the pattern contains any backtracking control verbs such as (*MARK:NAME), and the execution ends up with a name to pass back, a pointer to the name string (zero terminated) is placed in the variable pointed to by the \fImark\fP field. The names are within the compiled pattern; if you wish to retain such a name you must copy it before freeing the memory of a compiled pattern. If there is no name to pass back, the variable pointed to by the \fImark\fP field is set to NULL. For details of the backtracking control verbs, see the section entitled .\" HTML .\" "Backtracking control" .\" in the .\" HREF \fBpcrepattern\fP .\" documentation. . . .\" HTML .SS "Option bits for \fBpcre_exec()\fP" .rs .sp The unused bits of the \fIoptions\fP argument for \fBpcre_exec()\fP must be zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NEWLINE_\fIxxx\fP, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_NO_START_OPTIMIZE, PCRE_NO_UTF8_CHECK, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. .P If the pattern was successfully studied with one of the just-in-time (JIT) compile options, the only supported options for JIT execution are PCRE_NO_UTF8_CHECK, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. If an unsupported option is used, JIT execution is disabled and the normal interpretive code in \fBpcre_exec()\fP is run. .sp PCRE_ANCHORED .sp The PCRE_ANCHORED option limits \fBpcre_exec()\fP to matching at the first matching position. If a pattern was compiled with PCRE_ANCHORED, or turned out to be anchored by virtue of its contents, it cannot be made unachored at matching time. .sp PCRE_BSR_ANYCRLF PCRE_BSR_UNICODE .sp These options (which are mutually exclusive) control what the \eR escape sequence matches. The choice is either to match only CR, LF, or CRLF, or to match any Unicode newline sequence. These options override the choice that was made or defaulted when the pattern was compiled. .sp PCRE_NEWLINE_CR PCRE_NEWLINE_LF PCRE_NEWLINE_CRLF PCRE_NEWLINE_ANYCRLF PCRE_NEWLINE_ANY .sp These options override the newline definition that was chosen or defaulted when the pattern was compiled. For details, see the description of \fBpcre_compile()\fP above. During matching, the newline choice affects the behaviour of the dot, circumflex, and dollar metacharacters. It may also alter the way the match position is advanced after a match failure for an unanchored pattern. .P When PCRE_NEWLINE_CRLF, PCRE_NEWLINE_ANYCRLF, or PCRE_NEWLINE_ANY is set, and a match attempt for an unanchored pattern fails when the current position is at a CRLF sequence, and the pattern contains no explicit matches for CR or LF characters, the match position is advanced by two characters instead of one, in other words, to after the CRLF. .P The above rule is a compromise that makes the most common cases work as expected. For example, if the pattern is .+A (and the PCRE_DOTALL option is not set), it does not match the string "\er\enA" because, after failing at the start, it skips both the CR and the LF before retrying. However, the pattern [\er\en]A does match that string, because it contains an explicit CR or LF reference, and so advances only by one character after the first failure. .P An explicit match for CR of LF is either a literal appearance of one of those characters, or one of the \er or \en escape sequences. Implicit matches such as [^X] do not count, nor does \es (which includes CR and LF in the characters that it matches). .P Notwithstanding the above, anomalous effects may still occur when CRLF is a valid newline sequence and explicit \er or \en escapes appear in the pattern. .sp PCRE_NOTBOL .sp This option specifies that first character of the subject string is not the beginning of a line, so the circumflex metacharacter should not match before it. Setting this without PCRE_MULTILINE (at compile time) causes circumflex never to match. This option affects only the behaviour of the circumflex metacharacter. It does not affect \eA. .sp PCRE_NOTEOL .sp This option specifies that the end of the subject string is not the end of a line, so the dollar metacharacter should not match it nor (except in multiline mode) a newline immediately before it. Setting this without PCRE_MULTILINE (at compile time) causes dollar never to match. This option affects only the behaviour of the dollar metacharacter. It does not affect \eZ or \ez. .sp PCRE_NOTEMPTY .sp An empty string is not considered to be a valid match if this option is set. If there are alternatives in the pattern, they are tried. If all the alternatives match the empty string, the entire match fails. For example, if the pattern .sp a?b? .sp is applied to a string not beginning with "a" or "b", it matches an empty string at the start of the subject. With PCRE_NOTEMPTY set, this match is not valid, so PCRE searches further into the string for occurrences of "a" or "b". .sp PCRE_NOTEMPTY_ATSTART .sp This is like PCRE_NOTEMPTY, except that an empty string match that is not at the start of the subject is permitted. If the pattern is anchored, such a match can occur only if the pattern contains \eK. .P Perl has no direct equivalent of PCRE_NOTEMPTY or PCRE_NOTEMPTY_ATSTART, but it does make a special case of a pattern match of the empty string within its \fBsplit()\fP function, and when using the /g modifier. It is possible to emulate Perl's behaviour after matching a null string by first trying the match again at the same offset with PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED, and then if that fails, by advancing the starting offset (see below) and trying an ordinary match again. There is some code that demonstrates how to do this in the .\" HREF \fBpcredemo\fP .\" sample program. In the most general case, you have to check to see if the newline convention recognizes CRLF as a newline, and if so, and the current character is CR followed by LF, advance the starting offset by two characters instead of one. .sp PCRE_NO_START_OPTIMIZE .sp There are a number of optimizations that \fBpcre_exec()\fP uses at the start of a match, in order to speed up the process. For example, if it is known that an unanchored match must start with a specific character, it searches the subject for that character, and fails immediately if it cannot find it, without actually running the main matching function. This means that a special item such as (*COMMIT) at the start of a pattern is not considered until after a suitable starting point for the match has been found. Also, when callouts or (*MARK) items are in use, these "start-up" optimizations can cause them to be skipped if the pattern is never actually used. The start-up optimizations are in effect a pre-scan of the subject that takes place before the pattern is run. .P The PCRE_NO_START_OPTIMIZE option disables the start-up optimizations, possibly causing performance to suffer, but ensuring that in cases where the result is "no match", the callouts do occur, and that items such as (*COMMIT) and (*MARK) are considered at every possible starting position in the subject string. If PCRE_NO_START_OPTIMIZE is set at compile time, it cannot be unset at matching time. The use of PCRE_NO_START_OPTIMIZE at matching time (that is, passing it to \fBpcre_exec()\fP) disables JIT execution; in this situation, matching is always done using interpretively. .P Setting PCRE_NO_START_OPTIMIZE can change the outcome of a matching operation. Consider the pattern .sp (*COMMIT)ABC .sp When this is compiled, PCRE records the fact that a match must start with the character "A". Suppose the subject string is "DEFABC". The start-up optimization scans along the subject, finds "A" and runs the first match attempt from there. The (*COMMIT) item means that the pattern must match the current starting position, which in this case, it does. However, if the same match is run with PCRE_NO_START_OPTIMIZE set, the initial scan along the subject string does not happen. The first match attempt is run starting from "D" and when this fails, (*COMMIT) prevents any further matches being tried, so the overall result is "no match". If the pattern is studied, more start-up optimizations may be used. For example, a minimum length for the subject may be recorded. Consider the pattern .sp (*MARK:A)(X|Y) .sp The minimum length for a match is one character. If the subject is "ABC", there will be attempts to match "ABC", "BC", "C", and then finally an empty string. If the pattern is studied, the final attempt does not take place, because PCRE knows that the subject is too short, and so the (*MARK) is never encountered. In this case, studying the pattern does not affect the overall match result, which is still "no match", but it does affect the auxiliary information that is returned. .sp PCRE_NO_UTF8_CHECK .sp When PCRE_UTF8 is set at compile time, the validity of the subject as a UTF-8 string is automatically checked when \fBpcre_exec()\fP is subsequently called. The entire string is checked before any other processing takes place. The value of \fIstartoffset\fP is also checked to ensure that it points to the start of a UTF-8 character. There is a discussion about the .\" HTML .\" validity of UTF-8 strings .\" in the .\" HREF \fBpcreunicode\fP .\" page. If an invalid sequence of bytes is found, \fBpcre_exec()\fP returns the error PCRE_ERROR_BADUTF8 or, if PCRE_PARTIAL_HARD is set and the problem is a truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8. In both cases, information about the precise nature of the error may also be returned (see the descriptions of these errors in the section entitled \fIError return values from\fP \fBpcre_exec()\fP .\" HTML .\" below). .\" If \fIstartoffset\fP contains a value that does not point to the start of a UTF-8 character (or to the end of the subject), PCRE_ERROR_BADUTF8_OFFSET is returned. .P If you already know that your subject is valid, and you want to skip these checks for performance reasons, you can set the PCRE_NO_UTF8_CHECK option when calling \fBpcre_exec()\fP. You might want to do this for the second and subsequent calls to \fBpcre_exec()\fP if you are making repeated calls to find all the matches in a single subject string. However, you should be sure that the value of \fIstartoffset\fP points to the start of a character (or the end of the subject). When PCRE_NO_UTF8_CHECK is set, the effect of passing an invalid string as a subject or an invalid value of \fIstartoffset\fP is undefined. Your program may crash or loop. .sp PCRE_PARTIAL_HARD PCRE_PARTIAL_SOFT .sp These options turn on the partial matching feature. For backwards compatibility, PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. A partial match occurs if the end of the subject string is reached successfully, but there are not enough subject characters to complete the match. If this happens when PCRE_PARTIAL_SOFT (but not PCRE_PARTIAL_HARD) is set, matching continues by testing any remaining alternatives. Only if no complete match can be found is PCRE_ERROR_PARTIAL returned instead of PCRE_ERROR_NOMATCH. In other words, PCRE_PARTIAL_SOFT says that the caller is prepared to handle a partial match, but only if no complete match can be found. .P If PCRE_PARTIAL_HARD is set, it overrides PCRE_PARTIAL_SOFT. In this case, if a partial match is found, \fBpcre_exec()\fP immediately returns PCRE_ERROR_PARTIAL, without considering any other alternatives. In other words, when PCRE_PARTIAL_HARD is set, a partial match is considered to be more important that an alternative complete match. .P In both cases, the portion of the string that was inspected when the partial match was found is set as the first matching string. There is a more detailed discussion of partial and multi-segment matching, with examples, in the .\" HREF \fBpcrepartial\fP .\" documentation. . . .SS "The string to be matched by \fBpcre_exec()\fP" .rs .sp The subject string is passed to \fBpcre_exec()\fP as a pointer in \fIsubject\fP, a length in \fIlength\fP, and a starting offset in \fIstartoffset\fP. The units for \fIlength\fP and \fIstartoffset\fP are bytes for the 8-bit library, 16-bit data items for the 16-bit library, and 32-bit data items for the 32-bit library. .P If \fIstartoffset\fP is negative or greater than the length of the subject, \fBpcre_exec()\fP returns PCRE_ERROR_BADOFFSET. When the starting offset is zero, the search for a match starts at the beginning of the subject, and this is by far the most common case. In UTF-8 or UTF-16 mode, the offset must point to the start of a character, or the end of the subject (in UTF-32 mode, one data unit equals one character, so all offsets are valid). Unlike the pattern string, the subject may contain binary zeroes. .P A non-zero starting offset is useful when searching for another match in the same subject by calling \fBpcre_exec()\fP again after a previous success. Setting \fIstartoffset\fP differs from just passing over a shortened string and setting PCRE_NOTBOL in the case of a pattern that begins with any kind of lookbehind. For example, consider the pattern .sp \eBiss\eB .sp which finds occurrences of "iss" in the middle of words. (\eB matches only if the current position in the subject is not a word boundary.) When applied to the string "Mississipi" the first call to \fBpcre_exec()\fP finds the first occurrence. If \fBpcre_exec()\fP is called again with just the remainder of the subject, namely "issipi", it does not match, because \eB is always false at the start of the subject, which is deemed to be a word boundary. However, if \fBpcre_exec()\fP is passed the entire string again, but with \fIstartoffset\fP set to 4, it finds the second occurrence of "iss" because it is able to look behind the starting point to discover that it is preceded by a letter. .P Finding all the matches in a subject is tricky when the pattern can match an empty string. It is possible to emulate Perl's /g behaviour by first trying the match again at the same offset, with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED options, and then if that fails, advancing the starting offset and trying an ordinary match again. There is some code that demonstrates how to do this in the .\" HREF \fBpcredemo\fP .\" sample program. In the most general case, you have to check to see if the newline convention recognizes CRLF as a newline, and if so, and the current character is CR followed by LF, advance the starting offset by two characters instead of one. .P If a non-zero starting offset is passed when the pattern is anchored, one attempt to match at the given offset is made. This can only succeed if the pattern does not require the match to be at the start of the subject. . . .SS "How \fBpcre_exec()\fP returns captured substrings" .rs .sp In general, a pattern matches a certain portion of the subject, and in addition, further substrings from the subject may be picked out by parts of the pattern. Following the usage in Jeffrey Friedl's book, this is called "capturing" in what follows, and the phrase "capturing subpattern" is used for a fragment of a pattern that picks out a substring. PCRE supports several other kinds of parenthesized subpattern that do not cause substrings to be captured. .P Captured substrings are returned to the caller via a vector of integers whose address is passed in \fIovector\fP. The number of elements in the vector is passed in \fIovecsize\fP, which must be a non-negative number. \fBNote\fP: this argument is NOT the size of \fIovector\fP in bytes. .P The first two-thirds of the vector is used to pass back captured substrings, each substring using a pair of integers. The remaining third of the vector is used as workspace by \fBpcre_exec()\fP while matching capturing subpatterns, and is not available for passing back information. The number passed in \fIovecsize\fP should always be a multiple of three. If it is not, it is rounded down. .P When a match is successful, information about captured substrings is returned in pairs of integers, starting at the beginning of \fIovector\fP, and continuing up to two-thirds of its length at the most. The first element of each pair is set to the offset of the first character in a substring, and the second is set to the offset of the first character after the end of a substring. These values are always data unit offsets, even in UTF mode. They are byte offsets in the 8-bit library, 16-bit data item offsets in the 16-bit library, and 32-bit data item offsets in the 32-bit library. \fBNote\fP: they are not character counts. .P The first pair of integers, \fIovector[0]\fP and \fIovector[1]\fP, identify the portion of the subject string matched by the entire pattern. The next pair is used for the first capturing subpattern, and so on. The value returned by \fBpcre_exec()\fP is one more than the highest numbered pair that has been set. For example, if two substrings have been captured, the returned value is 3. If there are no capturing subpatterns, the return value from a successful match is 1, indicating that just the first pair of offsets has been set. .P If a capturing subpattern is matched repeatedly, it is the last portion of the string that it matched that is returned. .P If the vector is too small to hold all the captured substring offsets, it is used as far as possible (up to two-thirds of its length), and the function returns a value of zero. If neither the actual string matched nor any captured substrings are of interest, \fBpcre_exec()\fP may be called with \fIovector\fP passed as NULL and \fIovecsize\fP as zero. However, if the pattern contains back references and the \fIovector\fP is not big enough to remember the related substrings, PCRE has to get additional memory for use during matching. Thus it is usually advisable to supply an \fIovector\fP of reasonable size. .P There are some cases where zero is returned (indicating vector overflow) when in fact the vector is exactly the right size for the final match. For example, consider the pattern .sp (a)(?:(b)c|bd) .sp If a vector of 6 elements (allowing for only 1 captured substring) is given with subject string "abd", \fBpcre_exec()\fP will try to set the second captured string, thereby recording a vector overflow, before failing to match "c" and backing up to try the second alternative. The zero return, however, does correctly indicate that the maximum number of slots (namely 2) have been filled. In similar cases where there is temporary overflow, but the final number of used slots is actually less than the maximum, a non-zero value is returned. .P The \fBpcre_fullinfo()\fP function can be used to find out how many capturing subpatterns there are in a compiled pattern. The smallest size for \fIovector\fP that will allow for \fIn\fP captured substrings, in addition to the offsets of the substring matched by the whole pattern, is (\fIn\fP+1)*3. .P It is possible for capturing subpattern number \fIn+1\fP to match some part of the subject when subpattern \fIn\fP has not been used at all. For example, if the string "abc" is matched against the pattern (a|(z))(bc) the return from the function is 4, and subpatterns 1 and 3 are matched, but 2 is not. When this happens, both values in the offset pairs corresponding to unused subpatterns are set to -1. .P Offset values that correspond to unused subpatterns at the end of the expression are also set to -1. For example, if the string "abc" is matched against the pattern (abc)(x(yz)?)? subpatterns 2 and 3 are not matched. The return from the function is 2, because the highest used capturing subpattern number is 1, and the offsets for for the second and third capturing subpatterns (assuming the vector is large enough, of course) are set to -1. .P \fBNote\fP: Elements in the first two-thirds of \fIovector\fP that do not correspond to capturing parentheses in the pattern are never changed. That is, if a pattern contains \fIn\fP capturing parentheses, no more than \fIovector[0]\fP to \fIovector[2n+1]\fP are set by \fBpcre_exec()\fP. The other elements (in the first two-thirds) retain whatever values they previously had. .P Some convenience functions are provided for extracting the captured substrings as separate strings. These are described below. . . .\" HTML .SS "Error return values from \fBpcre_exec()\fP" .rs .sp If \fBpcre_exec()\fP fails, it returns a negative number. The following are defined in the header file: .sp PCRE_ERROR_NOMATCH (-1) .sp The subject string did not match the pattern. .sp PCRE_ERROR_NULL (-2) .sp Either \fIcode\fP or \fIsubject\fP was passed as NULL, or \fIovector\fP was NULL and \fIovecsize\fP was not zero. .sp PCRE_ERROR_BADOPTION (-3) .sp An unrecognized bit was set in the \fIoptions\fP argument. .sp PCRE_ERROR_BADMAGIC (-4) .sp PCRE stores a 4-byte "magic number" at the start of the compiled code, to catch the case when it is passed a junk pointer and to detect when a pattern that was compiled in an environment of one endianness is run in an environment with the other endianness. This is the error that PCRE gives when the magic number is not present. .sp PCRE_ERROR_UNKNOWN_OPCODE (-5) .sp While running the pattern match, an unknown item was encountered in the compiled pattern. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern. .sp PCRE_ERROR_NOMEMORY (-6) .sp If a pattern contains back references, but the \fIovector\fP that is passed to \fBpcre_exec()\fP is not big enough to remember the referenced substrings, PCRE gets a block of memory at the start of matching to use for this purpose. If the call via \fBpcre_malloc()\fP fails, this error is given. The memory is automatically freed at the end of matching. .P This error is also given if \fBpcre_stack_malloc()\fP fails in \fBpcre_exec()\fP. This can happen only when PCRE has been compiled with \fB--disable-stack-for-recursion\fP. .sp PCRE_ERROR_NOSUBSTRING (-7) .sp This error is used by the \fBpcre_copy_substring()\fP, \fBpcre_get_substring()\fP, and \fBpcre_get_substring_list()\fP functions (see below). It is never returned by \fBpcre_exec()\fP. .sp PCRE_ERROR_MATCHLIMIT (-8) .sp The backtracking limit, as specified by the \fImatch_limit\fP field in a \fBpcre_extra\fP structure (or defaulted) was reached. See the description above. .sp PCRE_ERROR_CALLOUT (-9) .sp This error is never generated by \fBpcre_exec()\fP itself. It is provided for use by callout functions that want to yield a distinctive error code. See the .\" HREF \fBpcrecallout\fP .\" documentation for details. .sp PCRE_ERROR_BADUTF8 (-10) .sp A string that contains an invalid UTF-8 byte sequence was passed as a subject, and the PCRE_NO_UTF8_CHECK option was not set. If the size of the output vector (\fIovecsize\fP) is at least 2, the byte offset to the start of the the invalid UTF-8 character is placed in the first element, and a reason code is placed in the second element. The reason codes are listed in the .\" HTML .\" following section. .\" For backward compatibility, if PCRE_PARTIAL_HARD is set and the problem is a truncated UTF-8 character at the end of the subject (reason codes 1 to 5), PCRE_ERROR_SHORTUTF8 is returned instead of PCRE_ERROR_BADUTF8. .sp PCRE_ERROR_BADUTF8_OFFSET (-11) .sp The UTF-8 byte sequence that was passed as a subject was checked and found to be valid (the PCRE_NO_UTF8_CHECK option was not set), but the value of \fIstartoffset\fP did not point to the beginning of a UTF-8 character or the end of the subject. .sp PCRE_ERROR_PARTIAL (-12) .sp The subject string did not match, but it did match partially. See the .\" HREF \fBpcrepartial\fP .\" documentation for details of partial matching. .sp PCRE_ERROR_BADPARTIAL (-13) .sp This code is no longer in use. It was formerly returned when the PCRE_PARTIAL option was used with a compiled pattern containing items that were not supported for partial matching. From release 8.00 onwards, there are no restrictions on partial matching. .sp PCRE_ERROR_INTERNAL (-14) .sp An unexpected internal error has occurred. This error could be caused by a bug in PCRE or by overwriting of the compiled pattern. .sp PCRE_ERROR_BADCOUNT (-15) .sp This error is given if the value of the \fIovecsize\fP argument is negative. .sp PCRE_ERROR_RECURSIONLIMIT (-21) .sp The internal recursion limit, as specified by the \fImatch_limit_recursion\fP field in a \fBpcre_extra\fP structure (or defaulted) was reached. See the description above. .sp PCRE_ERROR_BADNEWLINE (-23) .sp An invalid combination of PCRE_NEWLINE_\fIxxx\fP options was given. .sp PCRE_ERROR_BADOFFSET (-24) .sp The value of \fIstartoffset\fP was negative or greater than the length of the subject, that is, the value in \fIlength\fP. .sp PCRE_ERROR_SHORTUTF8 (-25) .sp This error is returned instead of PCRE_ERROR_BADUTF8 when the subject string ends with a truncated UTF-8 character and the PCRE_PARTIAL_HARD option is set. Information about the failure is returned as for PCRE_ERROR_BADUTF8. It is in fact sufficient to detect this case, but this special error code for PCRE_PARTIAL_HARD precedes the implementation of returned information; it is retained for backwards compatibility. .sp PCRE_ERROR_RECURSELOOP (-26) .sp This error is returned when \fBpcre_exec()\fP detects a recursion loop within the pattern. Specifically, it means that either the whole pattern or a subpattern has been called recursively for the second time at the same position in the subject string. Some simple patterns that might do this are detected and faulted at compile time, but more complicated cases, in particular mutual recursions between two different subpatterns, cannot be detected until run time. .sp PCRE_ERROR_JIT_STACKLIMIT (-27) .sp This error is returned when a pattern that was successfully studied using a JIT compile option is being matched, but the memory available for the just-in-time processing stack is not large enough. See the .\" HREF \fBpcrejit\fP .\" documentation for more details. .sp PCRE_ERROR_BADMODE (-28) .sp This error is given if a pattern that was compiled by the 8-bit library is passed to a 16-bit or 32-bit library function, or vice versa. .sp PCRE_ERROR_BADENDIANNESS (-29) .sp This error is given if a pattern that was compiled and saved is reloaded on a host with different endianness. The utility function \fBpcre_pattern_to_host_byte_order()\fP can be used to convert such a pattern so that it runs on the new host. .sp PCRE_ERROR_JIT_BADOPTION .sp This error is returned when a pattern that was successfully studied using a JIT compile option is being matched, but the matching mode (partial or complete match) does not correspond to any JIT compilation mode. When the JIT fast path function is used, this error may be also given for invalid options. See the .\" HREF \fBpcrejit\fP .\" documentation for more details. .sp PCRE_ERROR_BADLENGTH (-32) .sp This error is given if \fBpcre_exec()\fP is called with a negative value for the \fIlength\fP argument. .P Error numbers -16 to -20, -22, and 30 are not used by \fBpcre_exec()\fP. . . .\" HTML .SS "Reason codes for invalid UTF-8 strings" .rs .sp This section applies only to the 8-bit library. The corresponding information for the 16-bit and 32-bit libraries is given in the .\" HREF \fBpcre16\fP .\" and .\" HREF \fBpcre32\fP .\" pages. .P When \fBpcre_exec()\fP returns either PCRE_ERROR_BADUTF8 or PCRE_ERROR_SHORTUTF8, and the size of the output vector (\fIovecsize\fP) is at least 2, the offset of the start of the invalid UTF-8 character is placed in the first output vector element (\fIovector[0]\fP) and a reason code is placed in the second element (\fIovector[1]\fP). The reason codes are given names in the \fBpcre.h\fP header file: .sp PCRE_UTF8_ERR1 PCRE_UTF8_ERR2 PCRE_UTF8_ERR3 PCRE_UTF8_ERR4 PCRE_UTF8_ERR5 .sp The string ends with a truncated UTF-8 character; the code specifies how many bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8 characters to be no longer than 4 bytes, the encoding scheme (originally defined by RFC 2279) allows for up to 6 bytes, and this is checked first; hence the possibility of 4 or 5 missing bytes. .sp PCRE_UTF8_ERR6 PCRE_UTF8_ERR7 PCRE_UTF8_ERR8 PCRE_UTF8_ERR9 PCRE_UTF8_ERR10 .sp The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of the character do not have the binary value 0b10 (that is, either the most significant bit is 0, or the next bit is 1). .sp PCRE_UTF8_ERR11 PCRE_UTF8_ERR12 .sp A character that is valid by the RFC 2279 rules is either 5 or 6 bytes long; these code points are excluded by RFC 3629. .sp PCRE_UTF8_ERR13 .sp A 4-byte character has a value greater than 0x10fff; these code points are excluded by RFC 3629. .sp PCRE_UTF8_ERR14 .sp A 3-byte character has a value in the range 0xd800 to 0xdfff; this range of code points are reserved by RFC 3629 for use with UTF-16, and so are excluded from UTF-8. .sp PCRE_UTF8_ERR15 PCRE_UTF8_ERR16 PCRE_UTF8_ERR17 PCRE_UTF8_ERR18 PCRE_UTF8_ERR19 .sp A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes for a value that can be represented by fewer bytes, which is invalid. For example, the two bytes 0xc0, 0xae give the value 0x2e, whose correct coding uses just one byte. .sp PCRE_UTF8_ERR20 .sp The two most significant bits of the first byte of a character have the binary value 0b10 (that is, the most significant bit is 1 and the second is 0). Such a byte can only validly occur as the second or subsequent byte of a multi-byte character. .sp PCRE_UTF8_ERR21 .sp The first byte of a character has the value 0xfe or 0xff. These values can never occur in a valid UTF-8 string. .sp PCRE_UTF8_ERR22 .sp This error code was formerly used when the presence of a so-called "non-character" caused an error. Unicode corrigendum #9 makes it clear that such characters should not cause a string to be rejected, and so this code is no longer in use and is never returned. . . .SH "EXTRACTING CAPTURED SUBSTRINGS BY NUMBER" .rs .sp .nf .B int pcre_copy_substring(const char *\fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP, char *\fIbuffer\fP," .B " int \fIbuffersize\fP);" .sp .B int pcre_get_substring(const char *\fIsubject\fP, int *\fIovector\fP, .B " int \fIstringcount\fP, int \fIstringnumber\fP," .B " const char **\fIstringptr\fP);" .sp .B int pcre_get_substring_list(const char *\fIsubject\fP, .B " int *\fIovector\fP, int \fIstringcount\fP, const char ***\fIlistptr\fP);" .fi .PP Captured substrings can be accessed directly by using the offsets returned by \fBpcre_exec()\fP in \fIovector\fP. For convenience, the functions \fBpcre_copy_substring()\fP, \fBpcre_get_substring()\fP, and \fBpcre_get_substring_list()\fP are provided for extracting captured substrings as new, separate, zero-terminated strings. These functions identify substrings by number. The next section describes functions for extracting named substrings. .P A substring that contains a binary zero is correctly extracted and has a further zero added on the end, but the result is not, of course, a C string. However, you can process such a string by referring to the length that is returned by \fBpcre_copy_substring()\fP and \fBpcre_get_substring()\fP. Unfortunately, the interface to \fBpcre_get_substring_list()\fP is not adequate for handling strings containing binary zeros, because the end of the final string is not independently indicated. .P The first three arguments are the same for all three of these functions: \fIsubject\fP is the subject string that has just been successfully matched, \fIovector\fP is a pointer to the vector of integer offsets that was passed to \fBpcre_exec()\fP, and \fIstringcount\fP is the number of substrings that were captured by the match, including the substring that matched the entire regular expression. This is the value returned by \fBpcre_exec()\fP if it is greater than zero. If \fBpcre_exec()\fP returned zero, indicating that it ran out of space in \fIovector\fP, the value passed as \fIstringcount\fP should be the number of elements in the vector divided by three. .P The functions \fBpcre_copy_substring()\fP and \fBpcre_get_substring()\fP extract a single substring, whose number is given as \fIstringnumber\fP. A value of zero extracts the substring that matched the entire pattern, whereas higher values extract the captured substrings. For \fBpcre_copy_substring()\fP, the string is placed in \fIbuffer\fP, whose length is given by \fIbuffersize\fP, while for \fBpcre_get_substring()\fP a new block of memory is obtained via \fBpcre_malloc\fP, and its address is returned via \fIstringptr\fP. The yield of the function is the length of the string, not including the terminating zero, or one of these error codes: .sp PCRE_ERROR_NOMEMORY (-6) .sp The buffer was too small for \fBpcre_copy_substring()\fP, or the attempt to get memory failed for \fBpcre_get_substring()\fP. .sp PCRE_ERROR_NOSUBSTRING (-7) .sp There is no substring whose number is \fIstringnumber\fP. .P The \fBpcre_get_substring_list()\fP function extracts all available substrings and builds a list of pointers to them. All this is done in a single block of memory that is obtained via \fBpcre_malloc\fP. The address of the memory block is returned via \fIlistptr\fP, which is also the start of the list of string pointers. The end of the list is marked by a NULL pointer. The yield of the function is zero if all went well, or the error code .sp PCRE_ERROR_NOMEMORY (-6) .sp if the attempt to get the memory block failed. .P When any of these functions encounter a substring that is unset, which can happen when capturing subpattern number \fIn+1\fP matches some part of the subject, but subpattern \fIn\fP has not been used at all, they return an empty string. This can be distinguished from a genuine zero-length substring by inspecting the appropriate offset in \fIovector\fP, which is negative for unset substrings. .P The two convenience functions \fBpcre_free_substring()\fP and \fBpcre_free_substring_list()\fP can be used to free the memory returned by a previous call of \fBpcre_get_substring()\fP or \fBpcre_get_substring_list()\fP, respectively. They do nothing more than call the function pointed to by \fBpcre_free\fP, which of course could be called directly from a C program. However, PCRE is used in some situations where it is linked via a special interface to another programming language that cannot use \fBpcre_free\fP directly; it is for these cases that the functions are provided. . . .SH "EXTRACTING CAPTURED SUBSTRINGS BY NAME" .rs .sp .nf .B int pcre_get_stringnumber(const pcre *\fIcode\fP, .B " const char *\fIname\fP);" .sp .B int pcre_copy_named_substring(const pcre *\fIcode\fP, .B " const char *\fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, const char *\fIstringname\fP," .B " char *\fIbuffer\fP, int \fIbuffersize\fP);" .sp .B int pcre_get_named_substring(const pcre *\fIcode\fP, .B " const char *\fIsubject\fP, int *\fIovector\fP," .B " int \fIstringcount\fP, const char *\fIstringname\fP," .B " const char **\fIstringptr\fP);" .fi .PP To extract a substring by name, you first have to find associated number. For example, for this pattern .sp (a+)b(?\ed+)... .sp the number of the subpattern called "xxx" is 2. If the name is known to be unique (PCRE_DUPNAMES was not set), you can find the number from the name by calling \fBpcre_get_stringnumber()\fP. The first argument is the compiled pattern, and the second is the name. The yield of the function is the subpattern number, or PCRE_ERROR_NOSUBSTRING (-7) if there is no subpattern of that name. .P Given the number, you can extract the substring directly, or use one of the functions described in the previous section. For convenience, there are also two functions that do the whole job. .P Most of the arguments of \fBpcre_copy_named_substring()\fP and \fBpcre_get_named_substring()\fP are the same as those for the similarly named functions that extract by number. As these are described in the previous section, they are not re-described here. There are just two differences: .P First, instead of a substring number, a substring name is given. Second, there is an extra argument, given at the start, which is a pointer to the compiled pattern. This is needed in order to gain access to the name-to-number translation table. .P These functions call \fBpcre_get_stringnumber()\fP, and if it succeeds, they then call \fBpcre_copy_substring()\fP or \fBpcre_get_substring()\fP, as appropriate. \fBNOTE:\fP If PCRE_DUPNAMES is set and there are duplicate names, the behaviour may not be what you want (see the next section). .P \fBWarning:\fP If the pattern uses the (?| feature to set up multiple subpatterns with the same number, as described in the .\" HTML .\" section on duplicate subpattern numbers .\" in the .\" HREF \fBpcrepattern\fP .\" page, you cannot use names to distinguish the different subpatterns, because names are not included in the compiled code. The matching process uses only numbers. For this reason, the use of different names for subpatterns of the same number causes an error at compile time. . . .SH "DUPLICATE SUBPATTERN NAMES" .rs .sp .nf .B int pcre_get_stringtable_entries(const pcre *\fIcode\fP, .B " const char *\fIname\fP, char **\fIfirst\fP, char **\fIlast\fP);" .fi .PP When a pattern is compiled with the PCRE_DUPNAMES option, names for subpatterns are not required to be unique. (Duplicate names are always allowed for subpatterns with the same number, created by using the (?| feature. Indeed, if such subpatterns are named, they are required to use the same names.) .P Normally, patterns with duplicate names are such that in any one match, only one of the named subpatterns participates. An example is shown in the .\" HREF \fBpcrepattern\fP .\" documentation. .P When duplicates are present, \fBpcre_copy_named_substring()\fP and \fBpcre_get_named_substring()\fP return the first substring corresponding to the given name that is set. If none are set, PCRE_ERROR_NOSUBSTRING (-7) is returned; no data is returned. The \fBpcre_get_stringnumber()\fP function returns one of the numbers that are associated with the name, but it is not defined which it is. .P If you want to get full details of all captured substrings for a given name, you must use the \fBpcre_get_stringtable_entries()\fP function. The first argument is the compiled pattern, and the second is the name. The third and fourth are pointers to variables which are updated by the function. After it has run, they point to the first and last entries in the name-to-number table for the given name. The function itself returns the length of each entry, or PCRE_ERROR_NOSUBSTRING (-7) if there are none. The format of the table is described above in the section entitled \fIInformation about a pattern\fP .\" HTML .\" above. .\" Given all the relevant entries for the name, you can extract each of their numbers, and hence the captured data, if any. . . .SH "FINDING ALL POSSIBLE MATCHES" .rs .sp The traditional matching function uses a similar algorithm to Perl, which stops when it finds the first match, starting at a given point in the subject. If you want to find all possible matches, or the longest possible match, consider using the alternative matching function (see below) instead. If you cannot use the alternative function, but still need to find all possible matches, you can kludge it up by making use of the callout facility, which is described in the .\" HREF \fBpcrecallout\fP .\" documentation. .P What you have to do is to insert a callout right at the end of the pattern. When your callout function is called, extract and save the current matched substring. Then return 1, which forces \fBpcre_exec()\fP to backtrack and try other alternatives. Ultimately, when it runs out of matches, \fBpcre_exec()\fP will yield PCRE_ERROR_NOMATCH. . . .SH "OBTAINING AN ESTIMATE OF STACK USAGE" .rs .sp Matching certain patterns using \fBpcre_exec()\fP can use a lot of process stack, which in certain environments can be rather limited in size. Some users find it helpful to have an estimate of the amount of stack that is used by \fBpcre_exec()\fP, to help them set recursion limits, as described in the .\" HREF \fBpcrestack\fP .\" documentation. The estimate that is output by \fBpcretest\fP when called with the \fB-m\fP and \fB-C\fP options is obtained by calling \fBpcre_exec\fP with the values NULL, NULL, NULL, -999, and -999 for its first five arguments. .P Normally, if its first argument is NULL, \fBpcre_exec()\fP immediately returns the negative error code PCRE_ERROR_NULL, but with this special combination of arguments, it returns instead a negative number whose absolute value is the approximate stack frame size in bytes. (A negative number is used so that it is clear that no match has happened.) The value is approximate because in some cases, recursive calls to \fBpcre_exec()\fP occur when there are one or two additional variables on the stack. .P If PCRE has been compiled to use the heap instead of the stack for recursion, the value returned is the size of each block that is obtained from the heap. . . .\" HTML .SH "MATCHING A PATTERN: THE ALTERNATIVE FUNCTION" .rs .sp .nf .B int pcre_dfa_exec(const pcre *\fIcode\fP, "const pcre_extra *\fIextra\fP," .B " const char *\fIsubject\fP, int \fIlength\fP, int \fIstartoffset\fP," .B " int \fIoptions\fP, int *\fIovector\fP, int \fIovecsize\fP," .B " int *\fIworkspace\fP, int \fIwscount\fP);" .fi .P The function \fBpcre_dfa_exec()\fP is called to match a subject string against a compiled pattern, using a matching algorithm that scans the subject string just once, and does not backtrack. This has different characteristics to the normal algorithm, and is not compatible with Perl. Some of the features of PCRE patterns are not supported. Nevertheless, there are times when this kind of matching can be useful. For a discussion of the two matching algorithms, and a list of features that \fBpcre_dfa_exec()\fP does not support, see the .\" HREF \fBpcrematching\fP .\" documentation. .P The arguments for the \fBpcre_dfa_exec()\fP function are the same as for \fBpcre_exec()\fP, plus two extras. The \fIovector\fP argument is used in a different way, and this is described below. The other common arguments are used in the same way as for \fBpcre_exec()\fP, so their description is not repeated here. .P The two additional arguments provide workspace for the function. The workspace vector should contain at least 20 elements. It is used for keeping track of multiple paths through the pattern tree. More workspace will be needed for patterns and subjects where there are a lot of potential matches. .P Here is an example of a simple call to \fBpcre_dfa_exec()\fP: .sp int rc; int ovector[10]; int wspace[20]; rc = pcre_dfa_exec( re, /* result of pcre_compile() */ NULL, /* we didn't study the pattern */ "some string", /* the subject string */ 11, /* the length of the subject string */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* vector of integers for substring information */ 10, /* number of elements (NOT size in bytes) */ wspace, /* working space vector */ 20); /* number of elements (NOT size in bytes) */ . .SS "Option bits for \fBpcre_dfa_exec()\fP" .rs .sp The unused bits of the \fIoptions\fP argument for \fBpcre_dfa_exec()\fP must be zero. The only bits that may be set are PCRE_ANCHORED, PCRE_NEWLINE_\fIxxx\fP, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_NO_UTF8_CHECK, PCRE_BSR_ANYCRLF, PCRE_BSR_UNICODE, PCRE_NO_START_OPTIMIZE, PCRE_PARTIAL_HARD, PCRE_PARTIAL_SOFT, PCRE_DFA_SHORTEST, and PCRE_DFA_RESTART. All but the last four of these are exactly the same as for \fBpcre_exec()\fP, so their description is not repeated here. .sp PCRE_PARTIAL_HARD PCRE_PARTIAL_SOFT .sp These have the same general effect as they do for \fBpcre_exec()\fP, but the details are slightly different. When PCRE_PARTIAL_HARD is set for \fBpcre_dfa_exec()\fP, it returns PCRE_ERROR_PARTIAL if the end of the subject is reached and there is still at least one matching possibility that requires additional characters. This happens even if some complete matches have also been found. When PCRE_PARTIAL_SOFT is set, the return code PCRE_ERROR_NOMATCH is converted into PCRE_ERROR_PARTIAL if the end of the subject is reached, there have been no complete matches, but there is still at least one matching possibility. The portion of the string that was inspected when the longest partial match was found is set as the first matching string in both cases. There is a more detailed discussion of partial and multi-segment matching, with examples, in the .\" HREF \fBpcrepartial\fP .\" documentation. .sp PCRE_DFA_SHORTEST .sp Setting the PCRE_DFA_SHORTEST option causes the matching algorithm to stop as soon as it has found one match. Because of the way the alternative algorithm works, this is necessarily the shortest possible match at the first possible matching point in the subject string. .sp PCRE_DFA_RESTART .sp When \fBpcre_dfa_exec()\fP returns a partial match, it is possible to call it again, with additional subject characters, and have it continue with the same match. The PCRE_DFA_RESTART option requests this action; when it is set, the \fIworkspace\fP and \fIwscount\fP options must reference the same vector as before because data about the match so far is left in them after a partial match. There is more discussion of this facility in the .\" HREF \fBpcrepartial\fP .\" documentation. . . .SS "Successful returns from \fBpcre_dfa_exec()\fP" .rs .sp When \fBpcre_dfa_exec()\fP succeeds, it may have matched more than one substring in the subject. Note, however, that all the matches from one run of the function start at the same point in the subject. The shorter matches are all initial substrings of the longer matches. For example, if the pattern .sp <.*> .sp is matched against the string .sp This is no more .sp the three matched strings are .sp .sp On success, the yield of the function is a number greater than zero, which is the number of matched substrings. The substrings themselves are returned in \fIovector\fP. Each string uses two elements; the first is the offset to the start, and the second is the offset to the end. In fact, all the strings have the same start offset. (Space could have been saved by giving this only once, but it was decided to retain some compatibility with the way \fBpcre_exec()\fP returns data, even though the meaning of the strings is different.) .P The strings are returned in reverse order of length; that is, the longest matching string is given first. If there were too many matches to fit into \fIovector\fP, the yield of the function is zero, and the vector is filled with the longest matches. Unlike \fBpcre_exec()\fP, \fBpcre_dfa_exec()\fP can use the entire \fIovector\fP for returning matched strings. .P NOTE: PCRE's "auto-possessification" optimization usually applies to character repeats at the end of a pattern (as well as internally). For example, the pattern "a\ed+" is compiled as if it were "a\ed++" because there is no point even considering the possibility of backtracking into the repeated digits. For DFA matching, this means that only one possible match is found. If you really do want multiple matches in such cases, either use an ungreedy repeat ("a\ed+?") or set the PCRE_NO_AUTO_POSSESS option when compiling. . . .SS "Error returns from \fBpcre_dfa_exec()\fP" .rs .sp The \fBpcre_dfa_exec()\fP function returns a negative number when it fails. Many of the errors are the same as for \fBpcre_exec()\fP, and these are described .\" HTML .\" above. .\" There are in addition the following errors that are specific to \fBpcre_dfa_exec()\fP: .sp PCRE_ERROR_DFA_UITEM (-16) .sp This return is given if \fBpcre_dfa_exec()\fP encounters an item in the pattern that it does not support, for instance, the use of \eC or a back reference. .sp PCRE_ERROR_DFA_UCOND (-17) .sp This return is given if \fBpcre_dfa_exec()\fP encounters a condition item that uses a back reference for the condition, or a test for recursion in a specific group. These are not supported. .sp PCRE_ERROR_DFA_UMLIMIT (-18) .sp This return is given if \fBpcre_dfa_exec()\fP is called with an \fIextra\fP block that contains a setting of the \fImatch_limit\fP or \fImatch_limit_recursion\fP fields. This is not supported (these fields are meaningless for DFA matching). .sp PCRE_ERROR_DFA_WSSIZE (-19) .sp This return is given if \fBpcre_dfa_exec()\fP runs out of space in the \fIworkspace\fP vector. .sp PCRE_ERROR_DFA_RECURSE (-20) .sp When a recursive subpattern is processed, the matching function calls itself recursively, using private vectors for \fIovector\fP and \fIworkspace\fP. This error is given if the output vector is not large enough. This should be extremely rare, as a vector of size 1000 is used. .sp PCRE_ERROR_DFA_BADRESTART (-30) .sp When \fBpcre_dfa_exec()\fP is called with the \fBPCRE_DFA_RESTART\fP option, some plausibility checks are made on the contents of the workspace, which should contain data about the previous partial match. If any of these checks fail, this error is given. . . .SH "SEE ALSO" .rs .sp \fBpcre16\fP(3), \fBpcre32\fP(3), \fBpcrebuild\fP(3), \fBpcrecallout\fP(3), \fBpcrecpp(3)\fP(3), \fBpcrematching\fP(3), \fBpcrepartial\fP(3), \fBpcreposix\fP(3), \fBpcreprecompile\fP(3), \fBpcresample\fP(3), \fBpcrestack\fP(3). . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 18 December 2015 Copyright (c) 1997-2015 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrebuild.3 ================================================ .TH PCREBUILD 3 "12 May 2013" "PCRE 8.33" .SH NAME PCRE - Perl-compatible regular expressions . . .SH "BUILDING PCRE" .rs .sp PCRE is distributed with a \fBconfigure\fP script that can be used to build the library in Unix-like environments using the applications known as Autotools. Also in the distribution are files to support building using \fBCMake\fP instead of \fBconfigure\fP. The text file .\" HTML .\" \fBREADME\fP .\" contains general information about building with Autotools (some of which is repeated below), and also has some comments about building on various operating systems. There is a lot more information about building PCRE without using Autotools (including information about using \fBCMake\fP and building "by hand") in the text file called .\" HTML .\" \fBNON-AUTOTOOLS-BUILD\fP. .\" You should consult this file as well as the .\" HTML .\" \fBREADME\fP .\" file if you are building in a non-Unix-like environment. . . .SH "PCRE BUILD-TIME OPTIONS" .rs .sp The rest of this document describes the optional features of PCRE that can be selected when the library is compiled. It assumes use of the \fBconfigure\fP script, where the optional features are selected or deselected by providing options to \fBconfigure\fP before running the \fBmake\fP command. However, the same options can be selected in both Unix-like and non-Unix-like environments using the GUI facility of \fBcmake-gui\fP if you are using \fBCMake\fP instead of \fBconfigure\fP to build PCRE. .P If you are not using Autotools or \fBCMake\fP, option selection can be done by editing the \fBconfig.h\fP file, or by passing parameter settings to the compiler, as described in .\" HTML .\" \fBNON-AUTOTOOLS-BUILD\fP. .\" .P The complete list of options for \fBconfigure\fP (which includes the standard ones such as the selection of the installation directory) can be obtained by running .sp ./configure --help .sp The following sections include descriptions of options whose names begin with --enable or --disable. These settings specify changes to the defaults for the \fBconfigure\fP command. Because of the way that \fBconfigure\fP works, --enable and --disable always come in pairs, so the complementary option always exists as well, but as it specifies the default, it is not described. . . .SH "BUILDING 8-BIT, 16-BIT AND 32-BIT LIBRARIES" .rs .sp By default, a library called \fBlibpcre\fP is built, containing functions that take string arguments contained in vectors of bytes, either as single-byte characters, or interpreted as UTF-8 strings. You can also build a separate library, called \fBlibpcre16\fP, in which strings are contained in vectors of 16-bit data units and interpreted either as single-unit characters or UTF-16 strings, by adding .sp --enable-pcre16 .sp to the \fBconfigure\fP command. You can also build yet another separate library, called \fBlibpcre32\fP, in which strings are contained in vectors of 32-bit data units and interpreted either as single-unit characters or UTF-32 strings, by adding .sp --enable-pcre32 .sp to the \fBconfigure\fP command. If you do not want the 8-bit library, add .sp --disable-pcre8 .sp as well. At least one of the three libraries must be built. Note that the C++ and POSIX wrappers are for the 8-bit library only, and that \fBpcregrep\fP is an 8-bit program. None of these are built if you select only the 16-bit or 32-bit libraries. . . .SH "BUILDING SHARED AND STATIC LIBRARIES" .rs .sp The Autotools PCRE building process uses \fBlibtool\fP to build both shared and static libraries by default. You can suppress one of these by adding one of .sp --disable-shared --disable-static .sp to the \fBconfigure\fP command, as required. . . .SH "C++ SUPPORT" .rs .sp By default, if the 8-bit library is being built, the \fBconfigure\fP script will search for a C++ compiler and C++ header files. If it finds them, it automatically builds the C++ wrapper library (which supports only 8-bit strings). You can disable this by adding .sp --disable-cpp .sp to the \fBconfigure\fP command. . . .SH "UTF-8, UTF-16 AND UTF-32 SUPPORT" .rs .sp To build PCRE with support for UTF Unicode character strings, add .sp --enable-utf .sp to the \fBconfigure\fP command. This setting applies to all three libraries, adding support for UTF-8 to the 8-bit library, support for UTF-16 to the 16-bit library, and support for UTF-32 to the to the 32-bit library. There are no separate options for enabling UTF-8, UTF-16 and UTF-32 independently because that would allow ridiculous settings such as requesting UTF-16 support while building only the 8-bit library. It is not possible to build one library with UTF support and another without in the same configuration. (For backwards compatibility, --enable-utf8 is a synonym of --enable-utf.) .P Of itself, this setting does not make PCRE treat strings as UTF-8, UTF-16 or UTF-32. As well as compiling PCRE with this option, you also have have to set the PCRE_UTF8, PCRE_UTF16 or PCRE_UTF32 option (as appropriate) when you call one of the pattern compiling functions. .P If you set --enable-utf when compiling in an EBCDIC environment, PCRE expects its input to be either ASCII or UTF-8 (depending on the run-time option). It is not possible to support both EBCDIC and UTF-8 codes in the same version of the library. Consequently, --enable-utf and --enable-ebcdic are mutually exclusive. . . .SH "UNICODE CHARACTER PROPERTY SUPPORT" .rs .sp UTF support allows the libraries to process character codepoints up to 0x10ffff in the strings that they handle. On its own, however, it does not provide any facilities for accessing the properties of such characters. If you want to be able to use the pattern escapes \eP, \ep, and \eX, which refer to Unicode character properties, you must add .sp --enable-unicode-properties .sp to the \fBconfigure\fP command. This implies UTF support, even if you have not explicitly requested it. .P Including Unicode property support adds around 30K of tables to the PCRE library. Only the general category properties such as \fILu\fP and \fINd\fP are supported. Details are given in the .\" HREF \fBpcrepattern\fP .\" documentation. . . .SH "JUST-IN-TIME COMPILER SUPPORT" .rs .sp Just-in-time compiler support is included in the build by specifying .sp --enable-jit .sp This support is available only for certain hardware architectures. If this option is set for an unsupported architecture, a compile time error occurs. See the .\" HREF \fBpcrejit\fP .\" documentation for a discussion of JIT usage. When JIT support is enabled, pcregrep automatically makes use of it, unless you add .sp --disable-pcregrep-jit .sp to the "configure" command. . . .SH "CODE VALUE OF NEWLINE" .rs .sp By default, PCRE interprets the linefeed (LF) character as indicating the end of a line. This is the normal newline character on Unix-like systems. You can compile PCRE to use carriage return (CR) instead, by adding .sp --enable-newline-is-cr .sp to the \fBconfigure\fP command. There is also a --enable-newline-is-lf option, which explicitly specifies linefeed as the newline character. .sp Alternatively, you can specify that line endings are to be indicated by the two character sequence CRLF. If you want this, add .sp --enable-newline-is-crlf .sp to the \fBconfigure\fP command. There is a fourth option, specified by .sp --enable-newline-is-anycrlf .sp which causes PCRE to recognize any of the three sequences CR, LF, or CRLF as indicating a line ending. Finally, a fifth option, specified by .sp --enable-newline-is-any .sp causes PCRE to recognize any Unicode newline sequence. .P Whatever line ending convention is selected when PCRE is built can be overridden when the library functions are called. At build time it is conventional to use the standard for your operating system. . . .SH "WHAT \eR MATCHES" .rs .sp By default, the sequence \eR in a pattern matches any Unicode newline sequence, whatever has been selected as the line ending sequence. If you specify .sp --enable-bsr-anycrlf .sp the default is changed so that \eR matches only CR, LF, or CRLF. Whatever is selected when PCRE is built can be overridden when the library functions are called. . . .SH "POSIX MALLOC USAGE" .rs .sp When the 8-bit library is called through the POSIX interface (see the .\" HREF \fBpcreposix\fP .\" documentation), additional working storage is required for holding the pointers to capturing substrings, because PCRE requires three integers per substring, whereas the POSIX interface provides only two. If the number of expected substrings is small, the wrapper function uses space on the stack, because this is faster than using \fBmalloc()\fP for each call. The default threshold above which the stack is no longer used is 10; it can be changed by adding a setting such as .sp --with-posix-malloc-threshold=20 .sp to the \fBconfigure\fP command. . . .SH "HANDLING VERY LARGE PATTERNS" .rs .sp Within a compiled pattern, offset values are used to point from one part to another (for example, from an opening parenthesis to an alternation metacharacter). By default, in the 8-bit and 16-bit libraries, two-byte values are used for these offsets, leading to a maximum size for a compiled pattern of around 64K. This is sufficient to handle all but the most gigantic patterns. Nevertheless, some people do want to process truly enormous patterns, so it is possible to compile PCRE to use three-byte or four-byte offsets by adding a setting such as .sp --with-link-size=3 .sp to the \fBconfigure\fP command. The value given must be 2, 3, or 4. For the 16-bit library, a value of 3 is rounded up to 4. In these libraries, using longer offsets slows down the operation of PCRE because it has to load additional data when handling them. For the 32-bit library the value is always 4 and cannot be overridden; the value of --with-link-size is ignored. . . .SH "AVOIDING EXCESSIVE STACK USAGE" .rs .sp When matching with the \fBpcre_exec()\fP function, PCRE implements backtracking by making recursive calls to an internal function called \fBmatch()\fP. In environments where the size of the stack is limited, this can severely limit PCRE's operation. (The Unix environment does not usually suffer from this problem, but it may sometimes be necessary to increase the maximum stack size. There is a discussion in the .\" HREF \fBpcrestack\fP .\" documentation.) An alternative approach to recursion that uses memory from the heap to remember data, instead of using recursive function calls, has been implemented to work round the problem of limited stack size. If you want to build a version of PCRE that works this way, add .sp --disable-stack-for-recursion .sp to the \fBconfigure\fP command. With this configuration, PCRE will use the \fBpcre_stack_malloc\fP and \fBpcre_stack_free\fP variables to call memory management functions. By default these point to \fBmalloc()\fP and \fBfree()\fP, but you can replace the pointers so that your own functions are used instead. .P Separate functions are provided rather than using \fBpcre_malloc\fP and \fBpcre_free\fP because the usage is very predictable: the block sizes requested are always the same, and the blocks are always freed in reverse order. A calling program might be able to implement optimized functions that perform better than \fBmalloc()\fP and \fBfree()\fP. PCRE runs noticeably more slowly when built in this way. This option affects only the \fBpcre_exec()\fP function; it is not relevant for \fBpcre_dfa_exec()\fP. . . .SH "LIMITING PCRE RESOURCE USAGE" .rs .sp Internally, PCRE has a function called \fBmatch()\fP, which it calls repeatedly (sometimes recursively) when matching a pattern with the \fBpcre_exec()\fP function. By controlling the maximum number of times this function may be called during a single matching operation, a limit can be placed on the resources used by a single call to \fBpcre_exec()\fP. The limit can be changed at run time, as described in the .\" HREF \fBpcreapi\fP .\" documentation. The default is 10 million, but this can be changed by adding a setting such as .sp --with-match-limit=500000 .sp to the \fBconfigure\fP command. This setting has no effect on the \fBpcre_dfa_exec()\fP matching function. .P In some environments it is desirable to limit the depth of recursive calls of \fBmatch()\fP more strictly than the total number of calls, in order to restrict the maximum amount of stack (or heap, if --disable-stack-for-recursion is specified) that is used. A second limit controls this; it defaults to the value that is set for --with-match-limit, which imposes no additional constraints. However, you can set a lower limit by adding, for example, .sp --with-match-limit-recursion=10000 .sp to the \fBconfigure\fP command. This value can also be overridden at run time. . . .SH "CREATING CHARACTER TABLES AT BUILD TIME" .rs .sp PCRE uses fixed tables for processing characters whose code values are less than 256. By default, PCRE is built with a set of tables that are distributed in the file \fIpcre_chartables.c.dist\fP. These tables are for ASCII codes only. If you add .sp --enable-rebuild-chartables .sp to the \fBconfigure\fP command, the distributed tables are no longer used. Instead, a program called \fBdftables\fP is compiled and run. This outputs the source for new set of tables, created in the default locale of your C run-time system. (This method of replacing the tables does not work if you are cross compiling, because \fBdftables\fP is run on the local host. If you need to create alternative tables when cross compiling, you will have to do so "by hand".) . . .SH "USING EBCDIC CODE" .rs .sp PCRE assumes by default that it will run in an environment where the character code is ASCII (or Unicode, which is a superset of ASCII). This is the case for most computer operating systems. PCRE can, however, be compiled to run in an EBCDIC environment by adding .sp --enable-ebcdic .sp to the \fBconfigure\fP command. This setting implies --enable-rebuild-chartables. You should only use it if you know that you are in an EBCDIC environment (for example, an IBM mainframe operating system). The --enable-ebcdic option is incompatible with --enable-utf. .P The EBCDIC character that corresponds to an ASCII LF is assumed to have the value 0x15 by default. However, in some EBCDIC environments, 0x25 is used. In such an environment you should use .sp --enable-ebcdic-nl25 .sp as well as, or instead of, --enable-ebcdic. The EBCDIC character for CR has the same value as in ASCII, namely, 0x0d. Whichever of 0x15 and 0x25 is \fInot\fP chosen as LF is made to correspond to the Unicode NEL character (which, in Unicode, is 0x85). .P The options that select newline behaviour, such as --enable-newline-is-cr, and equivalent run-time options, refer to these character values in an EBCDIC environment. . . .SH "PCREGREP OPTIONS FOR COMPRESSED FILE SUPPORT" .rs .sp By default, \fBpcregrep\fP reads all files as plain text. You can build it so that it recognizes files whose names end in \fB.gz\fP or \fB.bz2\fP, and reads them with \fBlibz\fP or \fBlibbz2\fP, respectively, by adding one or both of .sp --enable-pcregrep-libz --enable-pcregrep-libbz2 .sp to the \fBconfigure\fP command. These options naturally require that the relevant libraries are installed on your system. Configuration will fail if they are not. . . .SH "PCREGREP BUFFER SIZE" .rs .sp \fBpcregrep\fP uses an internal buffer to hold a "window" on the file it is scanning, in order to be able to output "before" and "after" lines when it finds a match. The size of the buffer is controlled by a parameter whose default value is 20K. The buffer itself is three times this size, but because of the way it is used for holding "before" lines, the longest line that is guaranteed to be processable is the parameter size. You can change the default parameter value by adding, for example, .sp --with-pcregrep-bufsize=50K .sp to the \fBconfigure\fP command. The caller of \fPpcregrep\fP can, however, override this value by specifying a run-time option. . . .SH "PCRETEST OPTION FOR LIBREADLINE SUPPORT" .rs .sp If you add .sp --enable-pcretest-libreadline .sp to the \fBconfigure\fP command, \fBpcretest\fP is linked with the \fBlibreadline\fP library, and when its input is from a terminal, it reads it using the \fBreadline()\fP function. This provides line-editing and history facilities. Note that \fBlibreadline\fP is GPL-licensed, so if you distribute a binary of \fBpcretest\fP linked in this way, there may be licensing issues. .P Setting this option causes the \fB-lreadline\fP option to be added to the \fBpcretest\fP build. In many operating environments with a sytem-installed \fBlibreadline\fP this is sufficient. However, in some environments (e.g. if an unmodified distribution version of readline is in use), some extra configuration may be necessary. The INSTALL file for \fBlibreadline\fP says this: .sp "Readline uses the termcap functions, but does not link with the termcap or curses library itself, allowing applications which link with readline the to choose an appropriate library." .sp If your environment has not been set up so that an appropriate library is automatically included, you may need to add something like .sp LIBS="-ncurses" .sp immediately before the \fBconfigure\fP command. . . .SH "DEBUGGING WITH VALGRIND SUPPORT" .rs .sp By adding the .sp --enable-valgrind .sp option to to the \fBconfigure\fP command, PCRE will use valgrind annotations to mark certain memory regions as unaddressable. This allows it to detect invalid memory accesses, and is mostly useful for debugging PCRE itself. . . .SH "CODE COVERAGE REPORTING" .rs .sp If your C compiler is gcc, you can build a version of PCRE that can generate a code coverage report for its test suite. To enable this, you must install \fBlcov\fP version 1.6 or above. Then specify .sp --enable-coverage .sp to the \fBconfigure\fP command and build PCRE in the usual way. .P Note that using \fBccache\fP (a caching C compiler) is incompatible with code coverage reporting. If you have configured \fBccache\fP to run automatically on your system, you must set the environment variable .sp CCACHE_DISABLE=1 .sp before running \fBmake\fP to build PCRE, so that \fBccache\fP is not used. .P When --enable-coverage is used, the following addition targets are added to the \fIMakefile\fP: .sp make coverage .sp This creates a fresh coverage report for the PCRE test suite. It is equivalent to running "make coverage-reset", "make coverage-baseline", "make check", and then "make coverage-report". .sp make coverage-reset .sp This zeroes the coverage counters, but does nothing else. .sp make coverage-baseline .sp This captures baseline coverage information. .sp make coverage-report .sp This creates the coverage report. .sp make coverage-clean-report .sp This removes the generated coverage report without cleaning the coverage data itself. .sp make coverage-clean-data .sp This removes the captured coverage data without removing the coverage files created at compile time (*.gcno). .sp make coverage-clean .sp This cleans all coverage data including the generated coverage report. For more information about code coverage, see the \fBgcov\fP and \fBlcov\fP documentation. . . .SH "SEE ALSO" .rs .sp \fBpcreapi\fP(3), \fBpcre16\fP, \fBpcre32\fP, \fBpcre_config\fP(3). . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 12 May 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrecallout.3 ================================================ .TH PCRECALLOUT 3 "12 November 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH SYNOPSIS .rs .sp .B #include .PP .SM .B int (*pcre_callout)(pcre_callout_block *); .PP .B int (*pcre16_callout)(pcre16_callout_block *); .PP .B int (*pcre32_callout)(pcre32_callout_block *); . .SH DESCRIPTION .rs .sp PCRE provides a feature called "callout", which is a means of temporarily passing control to the caller of PCRE in the middle of pattern matching. The caller of PCRE provides an external function by putting its entry point in the global variable \fIpcre_callout\fP (\fIpcre16_callout\fP for the 16-bit library, \fIpcre32_callout\fP for the 32-bit library). By default, this variable contains NULL, which disables all calling out. .P Within a regular expression, (?C) indicates the points at which the external function is to be called. Different callout points can be identified by putting a number less than 256 after the letter C. The default value is zero. For example, this pattern has two callout points: .sp (?C1)abc(?C2)def .sp If the PCRE_AUTO_CALLOUT option bit is set when a pattern is compiled, PCRE automatically inserts callouts, all with number 255, before each item in the pattern. For example, if PCRE_AUTO_CALLOUT is used with the pattern .sp A(\ed{2}|--) .sp it is processed as if it were .sp (?C255)A(?C255)((?C255)\ed{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255) .sp Notice that there is a callout before and after each parenthesis and alternation bar. If the pattern contains a conditional group whose condition is an assertion, an automatic callout is inserted immediately before the condition. Such a callout may also be inserted explicitly, for example: .sp (?(?C9)(?=a)ab|de) .sp This applies only to assertion conditions (because they are themselves independent groups). .P Automatic callouts can be used for tracking the progress of pattern matching. The .\" HREF \fBpcretest\fP .\" program has a pattern qualifier (/C) that sets automatic callouts; when it is used, the output indicates how the pattern is being matched. This is useful information when you are trying to optimize the performance of a particular pattern. . . .SH "MISSING CALLOUTS" .rs .sp You should be aware that, because of optimizations in the way PCRE compiles and matches patterns, callouts sometimes do not happen exactly as you might expect. .P At compile time, PCRE "auto-possessifies" repeated items when it knows that what follows cannot be part of the repeat. For example, a+[bc] is compiled as if it were a++[bc]. The \fBpcretest\fP output when this pattern is anchored and then applied with automatic callouts to the string "aaaa" is: .sp --->aaaa +0 ^ ^ +1 ^ a+ +3 ^ ^ [bc] No match .sp This indicates that when matching [bc] fails, there is no backtracking into a+ and therefore the callouts that would be taken for the backtracks do not occur. You can disable the auto-possessify feature by passing PCRE_NO_AUTO_POSSESS to \fBpcre_compile()\fP, or starting the pattern with (*NO_AUTO_POSSESS). If this is done in \fBpcretest\fP (using the /O qualifier), the output changes to this: .sp --->aaaa +0 ^ ^ +1 ^ a+ +3 ^ ^ [bc] +3 ^ ^ [bc] +3 ^ ^ [bc] +3 ^^ [bc] No match .sp This time, when matching [bc] fails, the matcher backtracks into a+ and tries again, repeatedly, until a+ itself fails. .P Other optimizations that provide fast "no match" results also affect callouts. For example, if the pattern is .sp ab(?C4)cd .sp PCRE knows that any matching string must contain the letter "d". If the subject string is "abyz", the lack of "d" means that matching doesn't ever start, and the callout is never reached. However, with "abyd", though the result is still no match, the callout is obeyed. .P If the pattern is studied, PCRE knows the minimum length of a matching string, and will immediately give a "no match" return without actually running a match if the subject is not long enough, or, for unanchored patterns, if it has been scanned far enough. .P You can disable these optimizations by passing the PCRE_NO_START_OPTIMIZE option to the matching function, or by starting the pattern with (*NO_START_OPT). This slows down the matching process, but does ensure that callouts such as the example above are obeyed. . . .SH "THE CALLOUT INTERFACE" .rs .sp During matching, when PCRE reaches a callout point, the external function defined by \fIpcre_callout\fP or \fIpcre[16|32]_callout\fP is called (if it is set). This applies to both normal and DFA matching. The only argument to the callout function is a pointer to a \fBpcre_callout\fP or \fBpcre[16|32]_callout\fP block. These structures contains the following fields: .sp int \fIversion\fP; int \fIcallout_number\fP; int *\fIoffset_vector\fP; const char *\fIsubject\fP; (8-bit version) PCRE_SPTR16 \fIsubject\fP; (16-bit version) PCRE_SPTR32 \fIsubject\fP; (32-bit version) int \fIsubject_length\fP; int \fIstart_match\fP; int \fIcurrent_position\fP; int \fIcapture_top\fP; int \fIcapture_last\fP; void *\fIcallout_data\fP; int \fIpattern_position\fP; int \fInext_item_length\fP; const unsigned char *\fImark\fP; (8-bit version) const PCRE_UCHAR16 *\fImark\fP; (16-bit version) const PCRE_UCHAR32 *\fImark\fP; (32-bit version) .sp The \fIversion\fP field is an integer containing the version number of the block format. The initial version was 0; the current version is 2. The version number will change again in future if additional fields are added, but the intention is never to remove any of the existing fields. .P The \fIcallout_number\fP field contains the number of the callout, as compiled into the pattern (that is, the number after ?C for manual callouts, and 255 for automatically generated callouts). .P The \fIoffset_vector\fP field is a pointer to the vector of offsets that was passed by the caller to the matching function. When \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP is used, the contents can be inspected, in order to extract substrings that have been matched so far, in the same way as for extracting substrings after a match has completed. For the DFA matching functions, this field is not useful. .P The \fIsubject\fP and \fIsubject_length\fP fields contain copies of the values that were passed to the matching function. .P The \fIstart_match\fP field normally contains the offset within the subject at which the current match attempt started. However, if the escape sequence \eK has been encountered, this value is changed to reflect the modified starting point. If the pattern is not anchored, the callout function may be called several times from the same point in the pattern for different starting points in the subject. .P The \fIcurrent_position\fP field contains the offset within the subject of the current match pointer. .P When the \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP is used, the \fIcapture_top\fP field contains one more than the number of the highest numbered captured substring so far. If no substrings have been captured, the value of \fIcapture_top\fP is one. This is always the case when the DFA functions are used, because they do not support captured substrings. .P The \fIcapture_last\fP field contains the number of the most recently captured substring. However, when a recursion exits, the value reverts to what it was outside the recursion, as do the values of all captured substrings. If no substrings have been captured, the value of \fIcapture_last\fP is -1. This is always the case for the DFA matching functions. .P The \fIcallout_data\fP field contains a value that is passed to a matching function specifically so that it can be passed back in callouts. It is passed in the \fIcallout_data\fP field of a \fBpcre_extra\fP or \fBpcre[16|32]_extra\fP data structure. If no such data was passed, the value of \fIcallout_data\fP in a callout block is NULL. There is a description of the \fBpcre_extra\fP structure in the .\" HREF \fBpcreapi\fP .\" documentation. .P The \fIpattern_position\fP field is present from version 1 of the callout structure. It contains the offset to the next item to be matched in the pattern string. .P The \fInext_item_length\fP field is present from version 1 of the callout structure. It contains the length of the next item to be matched in the pattern string. When the callout immediately precedes an alternation bar, a closing parenthesis, or the end of the pattern, the length is zero. When the callout precedes an opening parenthesis, the length is that of the entire subpattern. .P The \fIpattern_position\fP and \fInext_item_length\fP fields are intended to help in distinguishing between different automatic callouts, which all have the same callout number. However, they are set for all callouts. .P The \fImark\fP field is present from version 2 of the callout structure. In callouts from \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP it contains a pointer to the zero-terminated name of the most recently passed (*MARK), (*PRUNE), or (*THEN) item in the match, or NULL if no such items have been passed. Instances of (*PRUNE) or (*THEN) without a name do not obliterate a previous (*MARK). In callouts from the DFA matching functions this field always contains NULL. . . .SH "RETURN VALUES" .rs .sp The external callout function returns an integer to PCRE. If the value is zero, matching proceeds as normal. If the value is greater than zero, matching fails at the current point, but the testing of other matching possibilities goes ahead, just as if a lookahead assertion had failed. If the value is less than zero, the match is abandoned, the matching function returns the negative value. .P Negative values should normally be chosen from the set of PCRE_ERROR_xxx values. In particular, PCRE_ERROR_NOMATCH forces a standard "no match" failure. The error number PCRE_ERROR_CALLOUT is reserved for use by callout functions; it will never be used by PCRE itself. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 12 November 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrecompat.3 ================================================ .TH PCRECOMPAT 3 "10 November 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH "DIFFERENCES BETWEEN PCRE AND PERL" .rs .sp This document describes the differences in the ways that PCRE and Perl handle regular expressions. The differences described here are with respect to Perl versions 5.10 and above. .P 1. PCRE has only a subset of Perl's Unicode support. Details of what it does have are given in the .\" HREF \fBpcreunicode\fP .\" page. .P 2. PCRE allows repeat quantifiers only on parenthesized assertions, but they do not mean what you might think. For example, (?!a){3} does not assert that the next three characters are not "a". It just asserts that the next character is not "a" three times (in principle: PCRE optimizes this to run the assertion just once). Perl allows repeat quantifiers on other assertions such as \eb, but these do not seem to have any use. .P 3. Capturing subpatterns that occur inside negative lookahead assertions are counted, but their entries in the offsets vector are never set. Perl sometimes (but not always) sets its numerical variables from inside negative assertions. .P 4. Though binary zero characters are supported in the subject string, they are not allowed in a pattern string because it is passed as a normal C string, terminated by zero. The escape sequence \e0 can be used in the pattern to represent a binary zero. .P 5. The following Perl escape sequences are not supported: \el, \eu, \eL, \eU, and \eN when followed by a character name or Unicode value. (\eN on its own, matching a non-newline character, is supported.) In fact these are implemented by Perl's general string-handling and are not part of its pattern matching engine. If any of these are encountered by PCRE, an error is generated by default. However, if the PCRE_JAVASCRIPT_COMPAT option is set, \eU and \eu are interpreted as JavaScript interprets them. .P 6. The Perl escape sequences \ep, \eP, and \eX are supported only if PCRE is built with Unicode character property support. The properties that can be tested with \ep and \eP are limited to the general category properties such as Lu and Nd, script names such as Greek or Han, and the derived properties Any and L&. PCRE does support the Cs (surrogate) property, which Perl does not; the Perl documentation says "Because Perl hides the need for the user to understand the internal representation of Unicode characters, there is no need to implement the somewhat messy concept of surrogates." .P 7. PCRE does support the \eQ...\eE escape for quoting substrings. Characters in between are treated as literals. This is slightly different from Perl in that $ and @ are also handled as literals inside the quotes. In Perl, they cause variable interpolation (but of course PCRE does not have variables). Note the following examples: .sp Pattern PCRE matches Perl matches .sp .\" JOIN \eQabc$xyz\eE abc$xyz abc followed by the contents of $xyz \eQabc\e$xyz\eE abc\e$xyz abc\e$xyz \eQabc\eE\e$\eQxyz\eE abc$xyz abc$xyz .sp The \eQ...\eE sequence is recognized both inside and outside character classes. .P 8. Fairly obviously, PCRE does not support the (?{code}) and (??{code}) constructions. However, there is support for recursive patterns. This is not available in Perl 5.8, but it is in Perl 5.10. Also, the PCRE "callout" feature allows an external function to be called during pattern matching. See the .\" HREF \fBpcrecallout\fP .\" documentation for details. .P 9. Subpatterns that are called as subroutines (whether or not recursively) are always treated as atomic groups in PCRE. This is like Python, but unlike Perl. Captured values that are set outside a subroutine call can be reference from inside in PCRE, but not in Perl. There is a discussion that explains these differences in more detail in the .\" HTML .\" section on recursion differences from Perl .\" in the .\" HREF \fBpcrepattern\fP .\" page. .P 10. If any of the backtracking control verbs are used in a subpattern that is called as a subroutine (whether or not recursively), their effect is confined to that subpattern; it does not extend to the surrounding pattern. This is not always the case in Perl. In particular, if (*THEN) is present in a group that is called as a subroutine, its action is limited to that group, even if the group does not contain any | characters. Note that such subpatterns are processed as anchored at the point where they are tested. .P 11. If a pattern contains more than one backtracking control verb, the first one that is backtracked onto acts. For example, in the pattern A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure in C triggers (*PRUNE). Perl's behaviour is more complex; in many cases it is the same as PCRE, but there are examples where it differs. .P 12. Most backtracking verbs in assertions have their normal actions. They are not confined to the assertion. .P 13. There are some differences that are concerned with the settings of captured strings when part of a pattern is repeated. For example, matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE it is set to "b". .P 14. PCRE's handling of duplicate subpattern numbers and duplicate subpattern names is not as general as Perl's. This is a consequence of the fact the PCRE works internally just with numbers, using an external table to translate between numbers and names. In particular, a pattern such as (?|(?A)|(?B), where the two capturing parentheses have the same number but different names, is not supported, and causes an error at compile time. If it were allowed, it would not be possible to distinguish which parentheses matched, because both names map to capturing subpattern number 1. To avoid this confusing situation, an error is given at compile time. .P 15. Perl recognizes comments in some places that PCRE does not, for example, between the ( and ? at the start of a subpattern. If the /x modifier is set, Perl allows white space between ( and ? (though current Perls warn that this is deprecated) but PCRE never does, even if the PCRE_EXTENDED option is set. .P 16. Perl, when in warning mode, gives warnings for character classes such as [A-\ed] or [a-[:digit:]]. It then treats the hyphens as literals. PCRE has no warning features, so it gives an error in these cases because they are almost certainly user mistakes. .P 17. In PCRE, the upper/lower case character properties Lu and Ll are not affected when case-independent matching is specified. For example, \ep{Lu} always matches an upper case letter. I think Perl has changed in this respect; in the release at the time of writing (5.16), \ep{Lu} and \ep{Ll} match all letters, regardless of case, when case independence is specified. .P 18. PCRE provides some extensions to the Perl regular expression facilities. Perl 5.10 includes new features that are not in earlier versions of Perl, some of which (such as named parentheses) have been in PCRE for some time. This list is with respect to Perl 5.10: .sp (a) Although lookbehind assertions in PCRE must match fixed length strings, each alternative branch of a lookbehind assertion can match a different length of string. Perl requires them all to have the same length. .sp (b) If PCRE_DOLLAR_ENDONLY is set and PCRE_MULTILINE is not set, the $ meta-character matches only at the very end of the string. .sp (c) If PCRE_EXTRA is set, a backslash followed by a letter with no special meaning is faulted. Otherwise, like Perl, the backslash is quietly ignored. (Perl can be made to issue a warning.) .sp (d) If PCRE_UNGREEDY is set, the greediness of the repetition quantifiers is inverted, that is, by default they are not greedy, but if followed by a question mark they are. .sp (e) PCRE_ANCHORED can be used at matching time to force a pattern to be tried only at the first matching position in the subject string. .sp (f) The PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, and PCRE_NO_AUTO_CAPTURE options for \fBpcre_exec()\fP have no Perl equivalents. .sp (g) The \eR escape sequence can be restricted to match only CR, LF, or CRLF by the PCRE_BSR_ANYCRLF option. .sp (h) The callout facility is PCRE-specific. .sp (i) The partial matching facility is PCRE-specific. .sp (j) Patterns compiled by PCRE can be saved and re-used at a later time, even on different hosts that have the other endianness. However, this does not apply to optimized data created by the just-in-time compiler. .sp (k) The alternative matching functions (\fBpcre_dfa_exec()\fP, \fBpcre16_dfa_exec()\fP and \fBpcre32_dfa_exec()\fP,) match in a different way and are not Perl-compatible. .sp (l) PCRE recognizes some special sequences such as (*CR) at the start of a pattern that set overall options that cannot be changed within the pattern. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 10 November 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrecpp.3 ================================================ .TH PCRECPP 3 "08 January 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions. .SH "SYNOPSIS OF C++ WRAPPER" .rs .sp .B #include . .SH DESCRIPTION .rs .sp The C++ wrapper for PCRE was provided by Google Inc. Some additional functionality was added by Giuseppe Maxia. This brief man page was constructed from the notes in the \fIpcrecpp.h\fP file, which should be consulted for further details. Note that the C++ wrapper supports only the original 8-bit PCRE library. There is no 16-bit or 32-bit support at present. . . .SH "MATCHING INTERFACE" .rs .sp The "FullMatch" operation checks that supplied text matches a supplied pattern exactly. If pointer arguments are supplied, it copies matched sub-strings that match sub-patterns into them. .sp Example: successful match pcrecpp::RE re("h.*o"); re.FullMatch("hello"); .sp Example: unsuccessful match (requires full match): pcrecpp::RE re("e"); !re.FullMatch("hello"); .sp Example: creating a temporary RE object: pcrecpp::RE("h.*o").FullMatch("hello"); .sp You can pass in a "const char*" or a "string" for "text". The examples below tend to use a const char*. You can, as in the different examples above, store the RE object explicitly in a variable or use a temporary RE object. The examples below use one mode or the other arbitrarily. Either could correctly be used for any of these examples. .P You must supply extra pointer arguments to extract matched subpieces. .sp Example: extracts "ruby" into "s" and 1234 into "i" int i; string s; pcrecpp::RE re("(\e\ew+):(\e\ed+)"); re.FullMatch("ruby:1234", &s, &i); .sp Example: does not try to extract any extra sub-patterns re.FullMatch("ruby:1234", &s); .sp Example: does not try to extract into NULL re.FullMatch("ruby:1234", NULL, &i); .sp Example: integer overflow causes failure !re.FullMatch("ruby:1234567891234", NULL, &i); .sp Example: fails because there aren't enough sub-patterns: !pcrecpp::RE("\e\ew+:\e\ed+").FullMatch("ruby:1234", &s); .sp Example: fails because string cannot be stored in integer !pcrecpp::RE("(.*)").FullMatch("ruby", &i); .sp The provided pointer arguments can be pointers to any scalar numeric type, or one of: .sp string (matched piece is copied to string) StringPiece (StringPiece is mutated to point to matched piece) T (where "bool T::ParseFrom(const char*, int)" exists) NULL (the corresponding matched sub-pattern is not copied) .sp The function returns true iff all of the following conditions are satisfied: .sp a. "text" matches "pattern" exactly; .sp b. The number of matched sub-patterns is >= number of supplied pointers; .sp c. The "i"th argument has a suitable type for holding the string captured as the "i"th sub-pattern. If you pass in void * NULL for the "i"th argument, or a non-void * NULL of the correct type, or pass fewer arguments than the number of sub-patterns, "i"th captured sub-pattern is ignored. .sp CAVEAT: An optional sub-pattern that does not exist in the matched string is assigned the empty string. Therefore, the following will return false (because the empty string is not a valid number): .sp int number; pcrecpp::RE::FullMatch("abc", "[a-z]+(\e\ed+)?", &number); .sp The matching interface supports at most 16 arguments per call. If you need more, consider using the more general interface \fBpcrecpp::RE::DoMatch\fP. See \fBpcrecpp.h\fP for the signature for \fBDoMatch\fP. .P NOTE: Do not use \fBno_arg\fP, which is used internally to mark the end of a list of optional arguments, as a placeholder for missing arguments, as this can lead to segfaults. . . .SH "QUOTING METACHARACTERS" .rs .sp You can use the "QuoteMeta" operation to insert backslashes before all potentially meaningful characters in a string. The returned string, used as a regular expression, will exactly match the original string. .sp Example: string quoted = RE::QuoteMeta(unquoted); .sp Note that it's legal to escape a character even if it has no special meaning in a regular expression -- so this function does that. (This also makes it identical to the perl function of the same name; see "perldoc -f quotemeta".) For example, "1.5-2.0?" becomes "1\e.5\e-2\e.0\e?". . .SH "PARTIAL MATCHES" .rs .sp You can use the "PartialMatch" operation when you want the pattern to match any substring of the text. .sp Example: simple search for a string: pcrecpp::RE("ell").PartialMatch("hello"); .sp Example: find first number in a string: int number; pcrecpp::RE re("(\e\ed+)"); re.PartialMatch("x*100 + 20", &number); assert(number == 100); . . .SH "UTF-8 AND THE MATCHING INTERFACE" .rs .sp By default, pattern and text are plain text, one byte per character. The UTF8 flag, passed to the constructor, causes both pattern and string to be treated as UTF-8 text, still a byte stream but potentially multiple bytes per character. In practice, the text is likelier to be UTF-8 than the pattern, but the match returned may depend on the UTF8 flag, so always use it when matching UTF8 text. For example, "." will match one byte normally but with UTF8 set may match up to three bytes of a multi-byte character. .sp Example: pcrecpp::RE_Options options; options.set_utf8(); pcrecpp::RE re(utf8_pattern, options); re.FullMatch(utf8_string); .sp Example: using the convenience function UTF8(): pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8()); re.FullMatch(utf8_string); .sp NOTE: The UTF8 flag is ignored if pcre was not configured with the --enable-utf8 flag. . . .SH "PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE" .rs .sp PCRE defines some modifiers to change the behavior of the regular expression engine. The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle to pass such modifiers to a RE class. Currently, the following modifiers are supported: .sp modifier description Perl corresponding .sp PCRE_CASELESS case insensitive match /i PCRE_MULTILINE multiple lines match /m PCRE_DOTALL dot matches newlines /s PCRE_DOLLAR_ENDONLY $ matches only at end N/A PCRE_EXTRA strict escape parsing N/A PCRE_EXTENDED ignore white spaces /x PCRE_UTF8 handles UTF8 chars built-in PCRE_UNGREEDY reverses * and *? N/A PCRE_NO_AUTO_CAPTURE disables capturing parens N/A (*) .sp (*) Both Perl and PCRE allow non capturing parentheses by means of the "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not capture, while (ab|cd) does. .P For a full account on how each modifier works, please check the PCRE API reference page. .P For each modifier, there are two member functions whose name is made out of the modifier in lowercase, without the "PCRE_" prefix. For instance, PCRE_CASELESS is handled by .sp bool caseless() .sp which returns true if the modifier is set, and .sp RE_Options & set_caseless(bool) .sp which sets or unsets the modifier. Moreover, PCRE_EXTRA_MATCH_LIMIT can be accessed through the \fBset_match_limit()\fP and \fBmatch_limit()\fP member functions. Setting \fImatch_limit\fP to a non-zero value will limit the execution of pcre to keep it from doing bad things like blowing the stack or taking an eternity to return a result. A value of 5000 is good enough to stop stack blowup in a 2MB thread stack. Setting \fImatch_limit\fP to zero disables match limiting. Alternatively, you can call \fBmatch_limit_recursion()\fP which uses PCRE_EXTRA_MATCH_LIMIT_RECURSION to limit how much PCRE recurses. \fBmatch_limit()\fP limits the number of matches PCRE does; \fBmatch_limit_recursion()\fP limits the depth of internal recursion, and therefore the amount of stack that is used. .P Normally, to pass one or more modifiers to a RE class, you declare a \fIRE_Options\fP object, set the appropriate options, and pass this object to a RE constructor. Example: .sp RE_Options opt; opt.set_caseless(true); if (RE("HELLO", opt).PartialMatch("hello world")) ... .sp RE_options has two constructors. The default constructor takes no arguments and creates a set of flags that are off by default. The optional parameter \fIoption_flags\fP is to facilitate transfer of legacy code from C programs. This lets you do .sp RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); .sp However, new code is better off doing .sp RE(pattern, RE_Options().set_caseless(true).set_multiline(true)) .PartialMatch(str); .sp If you are going to pass one of the most used modifiers, there are some convenience functions that return a RE_Options class with the appropriate modifier already set: \fBCASELESS()\fP, \fBUTF8()\fP, \fBMULTILINE()\fP, \fBDOTALL\fP(), and \fBEXTENDED()\fP. .P If you need to set several options at once, and you don't want to go through the pains of declaring a RE_Options object and setting several options, there is a parallel method that give you such ability on the fly. You can concatenate several \fBset_xxxxx()\fP member functions, since each of them returns a reference to its class object. For example, to pass PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one statement, you may write: .sp RE(" ^ xyz \e\es+ .* blah$", RE_Options() .set_caseless(true) .set_extended(true) .set_multiline(true)).PartialMatch(sometext); .sp . . .SH "SCANNING TEXT INCREMENTALLY" .rs .sp The "Consume" operation may be useful if you want to repeatedly match regular expressions at the front of a string and skip over them as they match. This requires use of the "StringPiece" type, which represents a sub-range of a real string. Like RE, StringPiece is defined in the pcrecpp namespace. .sp Example: read lines of the form "var = value" from a string. string contents = ...; // Fill string somehow pcrecpp::StringPiece input(contents); // Wrap in a StringPiece .sp string var; int value; pcrecpp::RE re("(\e\ew+) = (\e\ed+)\en"); while (re.Consume(&input, &var, &value)) { ...; } .sp Each successful call to "Consume" will set "var/value", and also advance "input" so it points past the matched text. .P The "FindAndConsume" operation is similar to "Consume" but does not anchor your match at the beginning of the string. For example, you could extract all words from a string by repeatedly calling .sp pcrecpp::RE("(\e\ew+)").FindAndConsume(&input, &word) . . .SH "PARSING HEX/OCTAL/C-RADIX NUMBERS" .rs .sp By default, if you pass a pointer to a numeric value, the corresponding text is interpreted as a base-10 number. You can instead wrap the pointer with a call to one of the operators Hex(), Octal(), or CRadix() to interpret the text in another base. The CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) prefixes, but defaults to base-10. .sp Example: int a, b, c, d; pcrecpp::RE re("(.*) (.*) (.*) (.*)"); re.FullMatch("100 40 0100 0x40", pcrecpp::Octal(&a), pcrecpp::Hex(&b), pcrecpp::CRadix(&c), pcrecpp::CRadix(&d)); .sp will leave 64 in a, b, c, and d. . . .SH "REPLACING PARTS OF STRINGS" .rs .sp You can replace the first match of "pattern" in "str" with "rewrite". Within "rewrite", backslash-escaped digits (\e1 to \e9) can be used to insert text matching corresponding parenthesized group from the pattern. \e0 in "rewrite" refers to the entire matching text. For example: .sp string s = "yabba dabba doo"; pcrecpp::RE("b+").Replace("d", &s); .sp will leave "s" containing "yada dabba doo". The result is true if the pattern matches and a replacement occurs, false otherwise. .P \fBGlobalReplace\fP is like \fBReplace\fP except that it replaces all occurrences of the pattern in the string with the rewrite. Replacements are not subject to re-matching. For example: .sp string s = "yabba dabba doo"; pcrecpp::RE("b+").GlobalReplace("d", &s); .sp will leave "s" containing "yada dada doo". It returns the number of replacements made. .P \fBExtract\fP is like \fBReplace\fP, except that if the pattern matches, "rewrite" is copied into "out" (an additional argument) with substitutions. The non-matching portions of "text" are ignored. Returns true iff a match occurred and the extraction happened successfully; if no match occurs, the string is left unaffected. . . .SH AUTHOR .rs .sp .nf The C++ wrapper was contributed by Google Inc. Copyright (c) 2007 Google Inc. .fi . . .SH REVISION .rs .sp .nf Last updated: 08 January 2012 .fi ================================================ FILE: src/pcre/doc/pcredemo.3 ================================================ .\" Start example. .de EX . nr mE \\n(.f . nf . nh . ft CW .. . . .\" End example. .de EE . ft \\n(mE . fi . hy \\n(HY .. . .EX /************************************************* * PCRE DEMONSTRATION PROGRAM * *************************************************/ /* This is a demonstration program to illustrate the most straightforward ways of calling the PCRE regular expression library from a C program. See the pcresample documentation for a short discussion ("man pcresample" if you have the PCRE man pages installed). In Unix-like environments, if PCRE is installed in your standard system libraries, you should be able to compile this program using this command: gcc -Wall pcredemo.c -lpcre -o pcredemo If PCRE is not installed in a standard place, it is likely to be installed with support for the pkg-config mechanism. If you have pkg-config, you can compile this program using this command: gcc -Wall pcredemo.c `pkg-config --cflags --libs libpcre` -o pcredemo If you do not have pkg-config, you may have to use this: gcc -Wall pcredemo.c -I/usr/local/include -L/usr/local/lib \e -R/usr/local/lib -lpcre -o pcredemo Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and library files for PCRE are installed on your system. Only some operating systems (e.g. Solaris) use the -R option. Building under Windows: If you want to statically link this program against a non-dll .a file, you must define PCRE_STATIC before including pcre.h, otherwise the pcre_malloc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results. So in this environment, uncomment the following line. */ /* #define PCRE_STATIC */ #include #include #include #define OVECCOUNT 30 /* should be a multiple of 3 */ int main(int argc, char **argv) { pcre *re; const char *error; char *pattern; char *subject; unsigned char *name_table; unsigned int option_bits; int erroffset; int find_all; int crlf_is_newline; int namecount; int name_entry_size; int ovector[OVECCOUNT]; int subject_length; int rc, i; int utf8; /************************************************************************** * First, sort out the command line. There is only one possible option at * * the moment, "-g" to request repeated matching to find all occurrences, * * like Perl's /g option. We set the variable find_all to a non-zero value * * if the -g option is present. Apart from that, there must be exactly two * * arguments. * **************************************************************************/ find_all = 0; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-g") == 0) find_all = 1; else break; } /* After the options, we require exactly two arguments, which are the pattern, and the subject string. */ if (argc - i != 2) { printf("Two arguments required: a regex and a subject string\en"); return 1; } pattern = argv[i]; subject = argv[i+1]; subject_length = (int)strlen(subject); /************************************************************************* * Now we are going to compile the regular expression pattern, and handle * * and errors that are detected. * *************************************************************************/ re = pcre_compile( pattern, /* the pattern */ 0, /* default options */ &error, /* for error message */ &erroffset, /* for error offset */ NULL); /* use default character tables */ /* Compilation failed: print the error message and exit */ if (re == NULL) { printf("PCRE compilation failed at offset %d: %s\en", erroffset, error); return 1; } /************************************************************************* * If the compilation succeeded, we call PCRE again, in order to do a * * pattern match against the subject string. This does just ONE match. If * * further matching is needed, it will be done below. * *************************************************************************/ rc = pcre_exec( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ subject, /* the subject string */ subject_length, /* the length of the subject */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* output vector for substring information */ OVECCOUNT); /* number of elements in the output vector */ /* Matching failed: handle error cases */ if (rc < 0) { switch(rc) { case PCRE_ERROR_NOMATCH: printf("No match\en"); break; /* Handle other special cases if you like */ default: printf("Matching error %d\en", rc); break; } pcre_free(re); /* Release memory used for the compiled pattern */ return 1; } /* Match succeded */ printf("\enMatch succeeded at offset %d\en", ovector[0]); /************************************************************************* * We have found the first match within the subject string. If the output * * vector wasn't big enough, say so. Then output any substrings that were * * captured. * *************************************************************************/ /* The output vector wasn't big enough */ if (rc == 0) { rc = OVECCOUNT/3; printf("ovector only has room for %d captured substrings\en", rc - 1); } /* Show substrings stored in the output vector by number. Obviously, in a real application you might want to do things other than print them. */ for (i = 0; i < rc; i++) { char *substring_start = subject + ovector[2*i]; int substring_length = ovector[2*i+1] - ovector[2*i]; printf("%2d: %.*s\en", i, substring_length, substring_start); } /************************************************************************** * That concludes the basic part of this demonstration program. We have * * compiled a pattern, and performed a single match. The code that follows * * shows first how to access named substrings, and then how to code for * * repeated matches on the same subject. * **************************************************************************/ /* See if there are any named substrings, and if so, show them by name. First we have to extract the count of named parentheses from the pattern. */ (void)pcre_fullinfo( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_NAMECOUNT, /* number of named substrings */ &namecount); /* where to put the answer */ if (namecount <= 0) printf("No named substrings\en"); else { unsigned char *tabptr; printf("Named substrings\en"); /* Before we can access the substrings, we must extract the table for translating names to numbers, and the size of each entry in the table. */ (void)pcre_fullinfo( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_NAMETABLE, /* address of the table */ &name_table); /* where to put the answer */ (void)pcre_fullinfo( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_NAMEENTRYSIZE, /* size of each entry in the table */ &name_entry_size); /* where to put the answer */ /* Now we can scan the table and, for each entry, print the number, the name, and the substring itself. */ tabptr = name_table; for (i = 0; i < namecount; i++) { int n = (tabptr[0] << 8) | tabptr[1]; printf("(%d) %*s: %.*s\en", n, name_entry_size - 3, tabptr + 2, ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]); tabptr += name_entry_size; } } /************************************************************************* * If the "-g" option was given on the command line, we want to continue * * to search for additional matches in the subject string, in a similar * * way to the /g option in Perl. This turns out to be trickier than you * * might think because of the possibility of matching an empty string. * * What happens is as follows: * * * * If the previous match was NOT for an empty string, we can just start * * the next match at the end of the previous one. * * * * If the previous match WAS for an empty string, we can't do that, as it * * would lead to an infinite loop. Instead, a special call of pcre_exec() * * is made with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set. * * The first of these tells PCRE that an empty string at the start of the * * subject is not a valid match; other possibilities must be tried. The * * second flag restricts PCRE to one match attempt at the initial string * * position. If this match succeeds, an alternative to the empty string * * match has been found, and we can print it and proceed round the loop, * * advancing by the length of whatever was found. If this match does not * * succeed, we still stay in the loop, advancing by just one character. * * In UTF-8 mode, which can be set by (*UTF8) in the pattern, this may be * * more than one byte. * * * * However, there is a complication concerned with newlines. When the * * newline convention is such that CRLF is a valid newline, we must * * advance by two characters rather than one. The newline convention can * * be set in the regex by (*CR), etc.; if not, we must find the default. * *************************************************************************/ if (!find_all) /* Check for -g */ { pcre_free(re); /* Release the memory used for the compiled pattern */ return 0; /* Finish unless -g was given */ } /* Before running the loop, check for UTF-8 and whether CRLF is a valid newline sequence. First, find the options with which the regex was compiled; extract the UTF-8 state, and mask off all but the newline options. */ (void)pcre_fullinfo(re, NULL, PCRE_INFO_OPTIONS, &option_bits); utf8 = option_bits & PCRE_UTF8; option_bits &= PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_CRLF| PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF; /* If no newline options were set, find the default newline convention from the build configuration. */ if (option_bits == 0) { int d; (void)pcre_config(PCRE_CONFIG_NEWLINE, &d); /* Note that these values are always the ASCII ones, even in EBCDIC environments. CR = 13, NL = 10. */ option_bits = (d == 13)? PCRE_NEWLINE_CR : (d == 10)? PCRE_NEWLINE_LF : (d == (13<<8 | 10))? PCRE_NEWLINE_CRLF : (d == -2)? PCRE_NEWLINE_ANYCRLF : (d == -1)? PCRE_NEWLINE_ANY : 0; } /* See if CRLF is a valid newline sequence. */ crlf_is_newline = option_bits == PCRE_NEWLINE_ANY || option_bits == PCRE_NEWLINE_CRLF || option_bits == PCRE_NEWLINE_ANYCRLF; /* Loop for second and subsequent matches */ for (;;) { int options = 0; /* Normally no options */ int start_offset = ovector[1]; /* Start at end of previous match */ /* If the previous match was for an empty string, we are finished if we are at the end of the subject. Otherwise, arrange to run another match at the same point to see if a non-empty match can be found. */ if (ovector[0] == ovector[1]) { if (ovector[0] == subject_length) break; options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED; } /* Run the next matching operation */ rc = pcre_exec( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ subject, /* the subject string */ subject_length, /* the length of the subject */ start_offset, /* starting offset in the subject */ options, /* options */ ovector, /* output vector for substring information */ OVECCOUNT); /* number of elements in the output vector */ /* This time, a result of NOMATCH isn't an error. If the value in "options" is zero, it just means we have found all possible matches, so the loop ends. Otherwise, it means we have failed to find a non-empty-string match at a point where there was a previous empty-string match. In this case, we do what Perl does: advance the matching position by one character, and continue. We do this by setting the "end of previous match" offset, because that is picked up at the top of the loop as the point at which to start again. There are two complications: (a) When CRLF is a valid newline sequence, and the current position is just before it, advance by an extra byte. (b) Otherwise we must ensure that we skip an entire UTF-8 character if we are in UTF-8 mode. */ if (rc == PCRE_ERROR_NOMATCH) { if (options == 0) break; /* All matches found */ ovector[1] = start_offset + 1; /* Advance one byte */ if (crlf_is_newline && /* If CRLF is newline & */ start_offset < subject_length - 1 && /* we are at CRLF, */ subject[start_offset] == '\er' && subject[start_offset + 1] == '\en') ovector[1] += 1; /* Advance by one more. */ else if (utf8) /* Otherwise, ensure we */ { /* advance a whole UTF-8 */ while (ovector[1] < subject_length) /* character. */ { if ((subject[ovector[1]] & 0xc0) != 0x80) break; ovector[1] += 1; } } continue; /* Go round the loop again */ } /* Other matching errors are not recoverable. */ if (rc < 0) { printf("Matching error %d\en", rc); pcre_free(re); /* Release memory used for the compiled pattern */ return 1; } /* Match succeded */ printf("\enMatch succeeded again at offset %d\en", ovector[0]); /* The match succeeded, but the output vector wasn't big enough. */ if (rc == 0) { rc = OVECCOUNT/3; printf("ovector only has room for %d captured substrings\en", rc - 1); } /* As before, show substrings stored in the output vector by number, and then also any named substrings. */ for (i = 0; i < rc; i++) { char *substring_start = subject + ovector[2*i]; int substring_length = ovector[2*i+1] - ovector[2*i]; printf("%2d: %.*s\en", i, substring_length, substring_start); } if (namecount <= 0) printf("No named substrings\en"); else { unsigned char *tabptr = name_table; printf("Named substrings\en"); for (i = 0; i < namecount; i++) { int n = (tabptr[0] << 8) | tabptr[1]; printf("(%d) %*s: %.*s\en", n, name_entry_size - 3, tabptr + 2, ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]); tabptr += name_entry_size; } } } /* End of loop to find second and subsequent matches */ printf("\en"); pcre_free(re); /* Release memory used for the compiled pattern */ return 0; } /* End of pcredemo.c */ .EE ================================================ FILE: src/pcre/doc/pcregrep.1 ================================================ .TH PCREGREP 1 "03 April 2014" "PCRE 8.35" .SH NAME pcregrep - a grep with Perl-compatible regular expressions. .SH SYNOPSIS .B pcregrep [options] [long options] [pattern] [path1 path2 ...] . .SH DESCRIPTION .rs .sp \fBpcregrep\fP searches files for character patterns, in the same way as other grep commands do, but it uses the PCRE regular expression library to support patterns that are compatible with the regular expressions of Perl 5. See .\" HREF \fBpcresyntax\fP(3) .\" for a quick-reference summary of pattern syntax, or .\" HREF \fBpcrepattern\fP(3) .\" for a full description of the syntax and semantics of the regular expressions that PCRE supports. .P Patterns, whether supplied on the command line or in a separate file, are given without delimiters. For example: .sp pcregrep Thursday /etc/motd .sp If you attempt to use delimiters (for example, by surrounding a pattern with slashes, as is common in Perl scripts), they are interpreted as part of the pattern. Quotes can of course be used to delimit patterns on the command line because they are interpreted by the shell, and indeed quotes are required if a pattern contains white space or shell metacharacters. .P The first argument that follows any option settings is treated as the single pattern to be matched when neither \fB-e\fP nor \fB-f\fP is present. Conversely, when one or both of these options are used to specify patterns, all arguments are treated as path names. At least one of \fB-e\fP, \fB-f\fP, or an argument pattern must be provided. .P If no files are specified, \fBpcregrep\fP reads the standard input. The standard input can also be referenced by a name consisting of a single hyphen. For example: .sp pcregrep some-pattern /file1 - /file3 .sp By default, each line that matches a pattern is copied to the standard output, and if there is more than one file, the file name is output at the start of each line, followed by a colon. However, there are options that can change how \fBpcregrep\fP behaves. In particular, the \fB-M\fP option makes it possible to search for patterns that span line boundaries. What defines a line boundary is controlled by the \fB-N\fP (\fB--newline\fP) option. .P The amount of memory used for buffering files that are being scanned is controlled by a parameter that can be set by the \fB--buffer-size\fP option. The default value for this parameter is specified when \fBpcregrep\fP is built, with the default default being 20K. A block of memory three times this size is used (to allow for buffering "before" and "after" lines). An error occurs if a line overflows the buffer. .P Patterns can be no longer than 8K or BUFSIZ bytes, whichever is the greater. BUFSIZ is defined in \fB\fP. When there is more than one pattern (specified by the use of \fB-e\fP and/or \fB-f\fP), each pattern is applied to each line in the order in which they are defined, except that all the \fB-e\fP patterns are tried before the \fB-f\fP patterns. .P By default, as soon as one pattern matches a line, no further patterns are considered. However, if \fB--colour\fP (or \fB--color\fP) is used to colour the matching substrings, or if \fB--only-matching\fP, \fB--file-offsets\fP, or \fB--line-offsets\fP is used to output only the part of the line that matched (either shown literally, or as an offset), scanning resumes immediately following the match, so that further matches on the same line can be found. If there are multiple patterns, they are all tried on the remainder of the line, but patterns that follow the one that matched are not tried on the earlier part of the line. .P This behaviour means that the order in which multiple patterns are specified can affect the output when one of the above options is used. This is no longer the same behaviour as GNU grep, which now manages to display earlier matches for later patterns (as long as there is no overlap). .P Patterns that can match an empty string are accepted, but empty string matches are never recognized. An example is the pattern "(super)?(man)?", in which all components are optional. This pattern finds all occurrences of both "super" and "man"; the output differs from matching with "super|man" when only the matching substrings are being shown. .P If the \fBLC_ALL\fP or \fBLC_CTYPE\fP environment variable is set, \fBpcregrep\fP uses the value to set a locale when calling the PCRE library. The \fB--locale\fP option can be used to override this. . . .SH "SUPPORT FOR COMPRESSED FILES" .rs .sp It is possible to compile \fBpcregrep\fP so that it uses \fBlibz\fP or \fBlibbz2\fP to read files whose names end in \fB.gz\fP or \fB.bz2\fP, respectively. You can find out whether your binary has support for one or both of these file types by running it with the \fB--help\fP option. If the appropriate support is not present, files are treated as plain text. The standard input is always so treated. . . .SH "BINARY FILES" .rs .sp By default, a file that contains a binary zero byte within the first 1024 bytes is identified as a binary file, and is processed specially. (GNU grep also identifies binary files in this manner.) See the \fB--binary-files\fP option for a means of changing the way binary files are handled. . . .SH OPTIONS .rs .sp The order in which some of the options appear can affect the output. For example, both the \fB-h\fP and \fB-l\fP options affect the printing of file names. Whichever comes later in the command line will be the one that takes effect. Similarly, except where noted below, if an option is given twice, the later setting is used. Numerical values for options may be followed by K or M, to signify multiplication by 1024 or 1024*1024 respectively. .TP 10 \fB--\fP This terminates the list of options. It is useful if the next item on the command line starts with a hyphen but is not an option. This allows for the processing of patterns and filenames that start with hyphens. .TP \fB-A\fP \fInumber\fP, \fB--after-context=\fP\fInumber\fP Output \fInumber\fP lines of context after each matching line. If filenames and/or line numbers are being output, a hyphen separator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file. The value of \fInumber\fP is expected to be relatively small. However, \fBpcregrep\fP guarantees to have up to 8K of following text available for context output. .TP \fB-a\fP, \fB--text\fP Treat binary files as text. This is equivalent to \fB--binary-files\fP=\fItext\fP. .TP \fB-B\fP \fInumber\fP, \fB--before-context=\fP\fInumber\fP Output \fInumber\fP lines of context before each matching line. If filenames and/or line numbers are being output, a hyphen separator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file. The value of \fInumber\fP is expected to be relatively small. However, \fBpcregrep\fP guarantees to have up to 8K of preceding text available for context output. .TP \fB--binary-files=\fP\fIword\fP Specify how binary files are to be processed. If the word is "binary" (the default), pattern matching is performed on binary files, but the only output is "Binary file matches" when a match succeeds. If the word is "text", which is equivalent to the \fB-a\fP or \fB--text\fP option, binary files are processed in the same way as any other file. In this case, when a match succeeds, the output may be binary garbage, which can have nasty effects if sent to a terminal. If the word is "without-match", which is equivalent to the \fB-I\fP option, binary files are not processed at all; they are assumed not to be of interest. .TP \fB--buffer-size=\fP\fInumber\fP Set the parameter that controls how much memory is used for buffering files that are being scanned. .TP \fB-C\fP \fInumber\fP, \fB--context=\fP\fInumber\fP Output \fInumber\fP lines of context both before and after each matching line. This is equivalent to setting both \fB-A\fP and \fB-B\fP to the same value. .TP \fB-c\fP, \fB--count\fP Do not output individual lines from the files that are being scanned; instead output the number of lines that would otherwise have been shown. If no lines are selected, the number zero is output. If several files are are being scanned, a count is output for each of them. However, if the \fB--files-with-matches\fP option is also used, only those files whose counts are greater than zero are listed. When \fB-c\fP is used, the \fB-A\fP, \fB-B\fP, and \fB-C\fP options are ignored. .TP \fB--colour\fP, \fB--color\fP If this option is given without any data, it is equivalent to "--colour=auto". If data is required, it must be given in the same shell item, separated by an equals sign. .TP \fB--colour=\fP\fIvalue\fP, \fB--color=\fP\fIvalue\fP This option specifies under what circumstances the parts of a line that matched a pattern should be coloured in the output. By default, the output is not coloured. The value (which is optional, see above) may be "never", "always", or "auto". In the latter case, colouring happens only if the standard output is connected to a terminal. More resources are used when colouring is enabled, because \fBpcregrep\fP has to search for all possible matches in a line, not just one, in order to colour them all. .sp The colour that is used can be specified by setting the environment variable PCREGREP_COLOUR or PCREGREP_COLOR. The value of this variable should be a string of two numbers, separated by a semicolon. They are copied directly into the control string for setting colour on a terminal, so it is your responsibility to ensure that they make sense. If neither of the environment variables is set, the default is "1;31", which gives red. .TP \fB-D\fP \fIaction\fP, \fB--devices=\fP\fIaction\fP If an input path is not a regular file or a directory, "action" specifies how it is to be processed. Valid values are "read" (the default) or "skip" (silently skip the path). .TP \fB-d\fP \fIaction\fP, \fB--directories=\fP\fIaction\fP If an input path is a directory, "action" specifies how it is to be processed. Valid values are "read" (the default in non-Windows environments, for compatibility with GNU grep), "recurse" (equivalent to the \fB-r\fP option), or "skip" (silently skip the path, the default in Windows environments). In the "read" case, directories are read as if they were ordinary files. In some operating systems the effect of reading a directory like this is an immediate end-of-file; in others it may provoke an error. .TP \fB-e\fP \fIpattern\fP, \fB--regex=\fP\fIpattern\fP, \fB--regexp=\fP\fIpattern\fP Specify a pattern to be matched. This option can be used multiple times in order to specify several patterns. It can also be used as a way of specifying a single pattern that starts with a hyphen. When \fB-e\fP is used, no argument pattern is taken from the command line; all arguments are treated as file names. There is no limit to the number of patterns. They are applied to each line in the order in which they are defined until one matches. .sp If \fB-f\fP is used with \fB-e\fP, the command line patterns are matched first, followed by the patterns from the file(s), independent of the order in which these options are specified. Note that multiple use of \fB-e\fP is not the same as a single pattern with alternatives. For example, X|Y finds the first character in a line that is X or Y, whereas if the two patterns are given separately, with X first, \fBpcregrep\fP finds X if it is present, even if it follows Y in the line. It finds Y only if there is no X in the line. This matters only if you are using \fB-o\fP or \fB--colo(u)r\fP to show the part(s) of the line that matched. .TP \fB--exclude\fP=\fIpattern\fP Files (but not directories) whose names match the pattern are skipped without being processed. This applies to all files, whether listed on the command line, obtained from \fB--file-list\fP, or by scanning a directory. The pattern is a PCRE regular expression, and is matched against the final component of the file name, not the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do not apply to this pattern. The option may be given any number of times in order to specify multiple patterns. If a file name matches both an \fB--include\fP and an \fB--exclude\fP pattern, it is excluded. There is no short form for this option. .TP \fB--exclude-from=\fP\fIfilename\fP Treat each non-empty line of the file as the data for an \fB--exclude\fP option. What constitutes a newline when reading the file is the operating system's default. The \fB--newline\fP option has no effect on this option. This option may be given more than once in order to specify a number of files to read. .TP \fB--exclude-dir\fP=\fIpattern\fP Directories whose names match the pattern are skipped without being processed, whatever the setting of the \fB--recursive\fP option. This applies to all directories, whether listed on the command line, obtained from \fB--file-list\fP, or by scanning a parent directory. The pattern is a PCRE regular expression, and is matched against the final component of the directory name, not the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do not apply to this pattern. The option may be given any number of times in order to specify more than one pattern. If a directory matches both \fB--include-dir\fP and \fB--exclude-dir\fP, it is excluded. There is no short form for this option. .TP \fB-F\fP, \fB--fixed-strings\fP Interpret each data-matching pattern as a list of fixed strings, separated by newlines, instead of as a regular expression. What constitutes a newline for this purpose is controlled by the \fB--newline\fP option. The \fB-w\fP (match as a word) and \fB-x\fP (match whole line) options can be used with \fB-F\fP. They apply to each of the fixed strings. A line is selected if any of the fixed strings are found in it (subject to \fB-w\fP or \fB-x\fP, if present). This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the \fB--include\fP or \fB--exclude\fP options. .TP \fB-f\fP \fIfilename\fP, \fB--file=\fP\fIfilename\fP Read patterns from the file, one per line, and match them against each line of input. What constitutes a newline when reading the file is the operating system's default. The \fB--newline\fP option has no effect on this option. Trailing white space is removed from each line, and blank lines are ignored. An empty file contains no patterns and therefore matches nothing. See also the comments about multiple patterns versus a single pattern with alternatives in the description of \fB-e\fP above. .sp If this option is given more than once, all the specified files are read. A data line is output if any of the patterns match it. A filename can be given as "-" to refer to the standard input. When \fB-f\fP is used, patterns specified on the command line using \fB-e\fP may also be present; they are tested before the file's patterns. However, no other pattern is taken from the command line; all arguments are treated as the names of paths to be searched. .TP \fB--file-list\fP=\fIfilename\fP Read a list of files and/or directories that are to be scanned from the given file, one per line. Trailing white space is removed from each line, and blank lines are ignored. These paths are processed before any that are listed on the command line. The filename can be given as "-" to refer to the standard input. If \fB--file\fP and \fB--file-list\fP are both specified as "-", patterns are read first. This is useful only when the standard input is a terminal, from which further lines (the list of files) can be read after an end-of-file indication. If this option is given more than once, all the specified files are read. .TP \fB--file-offsets\fP Instead of showing lines or parts of lines that match, show each match as an offset from the start of the file and a length, separated by a comma. In this mode, no context is shown. That is, the \fB-A\fP, \fB-B\fP, and \fB-C\fP options are ignored. If there is more than one match in a line, each of them is shown separately. This option is mutually exclusive with \fB--line-offsets\fP and \fB--only-matching\fP. .TP \fB-H\fP, \fB--with-filename\fP Force the inclusion of the filename at the start of output lines when searching a single file. By default, the filename is not shown in this case. For matching lines, the filename is followed by a colon; for context lines, a hyphen separator is used. If a line number is also being output, it follows the file name. .TP \fB-h\fP, \fB--no-filename\fP Suppress the output filenames when searching multiple files. By default, filenames are shown when multiple files are searched. For matching lines, the filename is followed by a colon; for context lines, a hyphen separator is used. If a line number is also being output, it follows the file name. .TP \fB--help\fP Output a help message, giving brief details of the command options and file type support, and then exit. Anything else on the command line is ignored. .TP \fB-I\fP Treat binary files as never matching. This is equivalent to \fB--binary-files\fP=\fIwithout-match\fP. .TP \fB-i\fP, \fB--ignore-case\fP Ignore upper/lower case distinctions during comparisons. .TP \fB--include\fP=\fIpattern\fP If any \fB--include\fP patterns are specified, the only files that are processed are those that match one of the patterns (and do not match an \fB--exclude\fP pattern). This option does not affect directories, but it applies to all files, whether listed on the command line, obtained from \fB--file-list\fP, or by scanning a directory. The pattern is a PCRE regular expression, and is matched against the final component of the file name, not the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do not apply to this pattern. The option may be given any number of times. If a file name matches both an \fB--include\fP and an \fB--exclude\fP pattern, it is excluded. There is no short form for this option. .TP \fB--include-from=\fP\fIfilename\fP Treat each non-empty line of the file as the data for an \fB--include\fP option. What constitutes a newline for this purpose is the operating system's default. The \fB--newline\fP option has no effect on this option. This option may be given any number of times; all the files are read. .TP \fB--include-dir\fP=\fIpattern\fP If any \fB--include-dir\fP patterns are specified, the only directories that are processed are those that match one of the patterns (and do not match an \fB--exclude-dir\fP pattern). This applies to all directories, whether listed on the command line, obtained from \fB--file-list\fP, or by scanning a parent directory. The pattern is a PCRE regular expression, and is matched against the final component of the directory name, not the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do not apply to this pattern. The option may be given any number of times. If a directory matches both \fB--include-dir\fP and \fB--exclude-dir\fP, it is excluded. There is no short form for this option. .TP \fB-L\fP, \fB--files-without-match\fP Instead of outputting lines from the files, just output the names of the files that do not contain any lines that would have been output. Each file name is output once, on a separate line. .TP \fB-l\fP, \fB--files-with-matches\fP Instead of outputting lines from the files, just output the names of the files containing lines that would have been output. Each file name is output once, on a separate line. Searching normally stops as soon as a matching line is found in a file. However, if the \fB-c\fP (count) option is also used, matching continues in order to obtain the correct count, and those files that have at least one match are listed along with their counts. Using this option with \fB-c\fP is a way of suppressing the listing of files with no matches. .TP \fB--label\fP=\fIname\fP This option supplies a name to be used for the standard input when file names are being output. If not supplied, "(standard input)" is used. There is no short form for this option. .TP \fB--line-buffered\fP When this option is given, input is read and processed line by line, and the output is flushed after each write. By default, input is read in large chunks, unless \fBpcregrep\fP can determine that it is reading from a terminal (which is currently possible only in Unix-like environments). Output to terminal is normally automatically flushed by the operating system. This option can be useful when the input or output is attached to a pipe and you do not want \fBpcregrep\fP to buffer up large amounts of data. However, its use will affect performance, and the \fB-M\fP (multiline) option ceases to work. .TP \fB--line-offsets\fP Instead of showing lines or parts of lines that match, show each match as a line number, the offset from the start of the line, and a length. The line number is terminated by a colon (as usual; see the \fB-n\fP option), and the offset and length are separated by a comma. In this mode, no context is shown. That is, the \fB-A\fP, \fB-B\fP, and \fB-C\fP options are ignored. If there is more than one match in a line, each of them is shown separately. This option is mutually exclusive with \fB--file-offsets\fP and \fB--only-matching\fP. .TP \fB--locale\fP=\fIlocale-name\fP This option specifies a locale to be used for pattern matching. It overrides the value in the \fBLC_ALL\fP or \fBLC_CTYPE\fP environment variables. If no locale is specified, the PCRE library's default (usually the "C" locale) is used. There is no short form for this option. .TP \fB--match-limit\fP=\fInumber\fP Processing some regular expression patterns can require a very large amount of memory, leading in some cases to a program crash if not enough is available. Other patterns may take a very long time to search for all possible matching strings. The \fBpcre_exec()\fP function that is called by \fBpcregrep\fP to do the matching has two parameters that can limit the resources that it uses. .sp The \fB--match-limit\fP option provides a means of limiting resource usage when processing patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is a pattern that uses nested unlimited repeats. Internally, PCRE uses a function called \fBmatch()\fP which it calls repeatedly (sometimes recursively). The limit set by \fB--match-limit\fP is imposed on the number of times this function is called during a match, which has the effect of limiting the amount of backtracking that can take place. .sp The \fB--recursion-limit\fP option is similar to \fB--match-limit\fP, but instead of limiting the total number of times that \fBmatch()\fP is called, it limits the depth of recursive calls, which in turn limits the amount of memory that can be used. The recursion depth is a smaller number than the total number of calls, because not all calls to \fBmatch()\fP are recursive. This limit is of use only if it is set smaller than \fB--match-limit\fP. .sp There are no short forms for these options. The default settings are specified when the PCRE library is compiled, with the default default being 10 million. .TP \fB-M\fP, \fB--multiline\fP Allow patterns to match more than one line. When this option is given, patterns may usefully contain literal newline characters and internal occurrences of ^ and $ characters. The output for a successful match may consist of more than one line, the last of which is the one in which the match ended. If the matched string ends with a newline sequence the output ends at the end of that line. .sp When this option is set, the PCRE library is called in "multiline" mode. There is a limit to the number of lines that can be matched, imposed by the way that \fBpcregrep\fP buffers the input file as it scans it. However, \fBpcregrep\fP ensures that at least 8K characters or the rest of the document (whichever is the shorter) are available for forward matching, and similarly the previous 8K characters (or all the previous characters, if fewer than 8K) are guaranteed to be available for lookbehind assertions. This option does not work when input is read line by line (see \fP--line-buffered\fP.) .TP \fB-N\fP \fInewline-type\fP, \fB--newline\fP=\fInewline-type\fP The PCRE library supports five different conventions for indicating the ends of lines. They are the single-character sequences CR (carriage return) and LF (linefeed), the two-character sequence CRLF, an "anycrlf" convention, which recognizes any of the preceding three types, and an "any" convention, in which any Unicode line ending sequence is assumed to end a line. The Unicode sequences are the three just mentioned, plus VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029). .sp When the PCRE library is built, a default line-ending sequence is specified. This is normally the standard sequence for the operating system. Unless otherwise specified by this option, \fBpcregrep\fP uses the library's default. The possible values for this option are CR, LF, CRLF, ANYCRLF, or ANY. This makes it possible to use \fBpcregrep\fP to scan files that have come from other environments without having to modify their line endings. If the data that is being scanned does not agree with the convention set by this option, \fBpcregrep\fP may behave in strange ways. Note that this option does not apply to files specified by the \fB-f\fP, \fB--exclude-from\fP, or \fB--include-from\fP options, which are expected to use the operating system's standard newline sequence. .TP \fB-n\fP, \fB--line-number\fP Precede each output line by its line number in the file, followed by a colon for matching lines or a hyphen for context lines. If the filename is also being output, it precedes the line number. This option is forced if \fB--line-offsets\fP is used. .TP \fB--no-jit\fP If the PCRE library is built with support for just-in-time compiling (which speeds up matching), \fBpcregrep\fP automatically makes use of this, unless it was explicitly disabled at build time. This option can be used to disable the use of JIT at run time. It is provided for testing and working round problems. It should never be needed in normal use. .TP \fB-o\fP, \fB--only-matching\fP Show only the part of the line that matched a pattern instead of the whole line. In this mode, no context is shown. That is, the \fB-A\fP, \fB-B\fP, and \fB-C\fP options are ignored. If there is more than one match in a line, each of them is shown separately. If \fB-o\fP is combined with \fB-v\fP (invert the sense of the match to find non-matching lines), no output is generated, but the return code is set appropriately. If the matched portion of the line is empty, nothing is output unless the file name or line number are being printed, in which case they are shown on an otherwise empty line. This option is mutually exclusive with \fB--file-offsets\fP and \fB--line-offsets\fP. .TP \fB-o\fP\fInumber\fP, \fB--only-matching\fP=\fInumber\fP Show only the part of the line that matched the capturing parentheses of the given number. Up to 32 capturing parentheses are supported, and -o0 is equivalent to \fB-o\fP without a number. Because these options can be given without an argument (see above), if an argument is present, it must be given in the same shell item, for example, -o3 or --only-matching=2. The comments given for the non-argument case above also apply to this case. If the specified capturing parentheses do not exist in the pattern, or were not set in the match, nothing is output unless the file name or line number are being printed. .sp If this option is given multiple times, multiple substrings are output, in the order the options are given. For example, -o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and then 3 again to be output. By default, there is no separator (but see the next option). .TP \fB--om-separator\fP=\fItext\fP Specify a separating string for multiple occurrences of \fB-o\fP. The default is an empty string. Separating strings are never coloured. .TP \fB-q\fP, \fB--quiet\fP Work quietly, that is, display nothing except error messages. The exit status indicates whether or not any matches were found. .TP \fB-r\fP, \fB--recursive\fP If any given path is a directory, recursively scan the files it contains, taking note of any \fB--include\fP and \fB--exclude\fP settings. By default, a directory is read as a normal file; in some operating systems this gives an immediate end-of-file. This option is a shorthand for setting the \fB-d\fP option to "recurse". .TP \fB--recursion-limit\fP=\fInumber\fP See \fB--match-limit\fP above. .TP \fB-s\fP, \fB--no-messages\fP Suppress error messages about non-existent or unreadable files. Such files are quietly skipped. However, the return code is still 2, even if matches were found in other files. .TP \fB-u\fP, \fB--utf-8\fP Operate in UTF-8 mode. This option is available only if PCRE has been compiled with UTF-8 support. All patterns (including those for any \fB--exclude\fP and \fB--include\fP options) and all subject lines that are scanned must be valid strings of UTF-8 characters. .TP \fB-V\fP, \fB--version\fP Write the version numbers of \fBpcregrep\fP and the PCRE library to the standard output and then exit. Anything else on the command line is ignored. .TP \fB-v\fP, \fB--invert-match\fP Invert the sense of the match, so that lines which do \fInot\fP match any of the patterns are the ones that are found. .TP \fB-w\fP, \fB--word-regex\fP, \fB--word-regexp\fP Force the patterns to match only whole words. This is equivalent to having \eb at the start and end of the pattern. This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the \fB--include\fP or \fB--exclude\fP options. .TP \fB-x\fP, \fB--line-regex\fP, \fB--line-regexp\fP Force the patterns to be anchored (each must start matching at the beginning of a line) and in addition, require them to match entire lines. This is equivalent to having ^ and $ characters at the start and end of each alternative branch in every pattern. This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the \fB--include\fP or \fB--exclude\fP options. . . .SH "ENVIRONMENT VARIABLES" .rs .sp The environment variables \fBLC_ALL\fP and \fBLC_CTYPE\fP are examined, in that order, for a locale. The first one that is set is used. This can be overridden by the \fB--locale\fP option. If no locale is set, the PCRE library's default (usually the "C" locale) is used. . . .SH "NEWLINES" .rs .sp The \fB-N\fP (\fB--newline\fP) option allows \fBpcregrep\fP to scan files with different newline conventions from the default. Any parts of the input files that are written to the standard output are copied identically, with whatever newline sequences they have in the input. However, the setting of this option does not affect the interpretation of files specified by the \fB-f\fP, \fB--exclude-from\fP, or \fB--include-from\fP options, which are assumed to use the operating system's standard newline sequence, nor does it affect the way in which \fBpcregrep\fP writes informational messages to the standard error and output streams. For these it uses the string "\en" to indicate newlines, relying on the C I/O library to convert this to an appropriate sequence. . . .SH "OPTIONS COMPATIBILITY" .rs .sp Many of the short and long forms of \fBpcregrep\fP's options are the same as in the GNU \fBgrep\fP program. Any long option of the form \fB--xxx-regexp\fP (GNU terminology) is also available as \fB--xxx-regex\fP (PCRE terminology). However, the \fB--file-list\fP, \fB--file-offsets\fP, \fB--include-dir\fP, \fB--line-offsets\fP, \fB--locale\fP, \fB--match-limit\fP, \fB-M\fP, \fB--multiline\fP, \fB-N\fP, \fB--newline\fP, \fB--om-separator\fP, \fB--recursion-limit\fP, \fB-u\fP, and \fB--utf-8\fP options are specific to \fBpcregrep\fP, as is the use of the \fB--only-matching\fP option with a capturing parentheses number. .P Although most of the common options work the same way, a few are different in \fBpcregrep\fP. For example, the \fB--include\fP option's argument is a glob for GNU \fBgrep\fP, but a regular expression for \fBpcregrep\fP. If both the \fB-c\fP and \fB-l\fP options are given, GNU grep lists only file names, without counts, but \fBpcregrep\fP gives the counts. . . .SH "OPTIONS WITH DATA" .rs .sp There are four different ways in which an option with data can be specified. If a short form option is used, the data may follow immediately, or (with one exception) in the next command line item. For example: .sp -f/some/file -f /some/file .sp The exception is the \fB-o\fP option, which may appear with or without data. Because of this, if data is present, it must follow immediately in the same item, for example -o3. .P If a long form option is used, the data may appear in the same command line item, separated by an equals character, or (with two exceptions) it may appear in the next command line item. For example: .sp --file=/some/file --file /some/file .sp Note, however, that if you want to supply a file name beginning with ~ as data in a shell command, and have the shell expand ~ to a home directory, you must separate the file name from the option, because the shell does not treat ~ specially unless it is at the start of an item. .P The exceptions to the above are the \fB--colour\fP (or \fB--color\fP) and \fB--only-matching\fP options, for which the data is optional. If one of these options does have data, it must be given in the first form, using an equals character. Otherwise \fBpcregrep\fP will assume that it has no data. . . .SH "MATCHING ERRORS" .rs .sp It is possible to supply a regular expression that takes a very long time to fail to match certain lines. Such patterns normally involve nested indefinite repeats, for example: (a+)*\ed when matched against a line of a's with no final digit. The PCRE matching function has a resource limit that causes it to abort in these circumstances. If this happens, \fBpcregrep\fP outputs an error message and the line that caused the problem to the standard error stream. If there are more than 20 such errors, \fBpcregrep\fP gives up. .P The \fB--match-limit\fP option of \fBpcregrep\fP can be used to set the overall resource limit; there is a second option called \fB--recursion-limit\fP that sets a limit on the amount of memory (usually stack) that is used (see the discussion of these options above). . . .SH DIAGNOSTICS .rs .sp Exit status is 0 if any matches were found, 1 if no matches were found, and 2 for syntax errors, overlong lines, non-existent or inaccessible files (even if matches were found in other files) or too many matching errors. Using the \fB-s\fP option to suppress error messages about inaccessible files does not affect the return code. . . .SH "SEE ALSO" .rs .sp \fBpcrepattern\fP(3), \fBpcresyntax\fP(3), \fBpcretest\fP(1). . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 03 April 2014 Copyright (c) 1997-2014 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcregrep.txt ================================================ PCREGREP(1) General Commands Manual PCREGREP(1) NAME pcregrep - a grep with Perl-compatible regular expressions. SYNOPSIS pcregrep [options] [long options] [pattern] [path1 path2 ...] DESCRIPTION pcregrep searches files for character patterns, in the same way as other grep commands do, but it uses the PCRE regular expression library to support patterns that are compatible with the regular expressions of Perl 5. See pcresyntax(3) for a quick-reference summary of pattern syn- tax, or pcrepattern(3) for a full description of the syntax and seman- tics of the regular expressions that PCRE supports. Patterns, whether supplied on the command line or in a separate file, are given without delimiters. For example: pcregrep Thursday /etc/motd If you attempt to use delimiters (for example, by surrounding a pattern with slashes, as is common in Perl scripts), they are interpreted as part of the pattern. Quotes can of course be used to delimit patterns on the command line because they are interpreted by the shell, and indeed quotes are required if a pattern contains white space or shell metacharacters. The first argument that follows any option settings is treated as the single pattern to be matched when neither -e nor -f is present. Con- versely, when one or both of these options are used to specify pat- terns, all arguments are treated as path names. At least one of -e, -f, or an argument pattern must be provided. If no files are specified, pcregrep reads the standard input. The stan- dard input can also be referenced by a name consisting of a single hyphen. For example: pcregrep some-pattern /file1 - /file3 By default, each line that matches a pattern is copied to the standard output, and if there is more than one file, the file name is output at the start of each line, followed by a colon. However, there are options that can change how pcregrep behaves. In particular, the -M option makes it possible to search for patterns that span line boundaries. What defines a line boundary is controlled by the -N (--newline) option. The amount of memory used for buffering files that are being scanned is controlled by a parameter that can be set by the --buffer-size option. The default value for this parameter is specified when pcregrep is built, with the default default being 20K. A block of memory three times this size is used (to allow for buffering "before" and "after" lines). An error occurs if a line overflows the buffer. Patterns can be no longer than 8K or BUFSIZ bytes, whichever is the greater. BUFSIZ is defined in . When there is more than one pattern (specified by the use of -e and/or -f), each pattern is applied to each line in the order in which they are defined, except that all the -e patterns are tried before the -f patterns. By default, as soon as one pattern matches a line, no further patterns are considered. However, if --colour (or --color) is used to colour the matching substrings, or if --only-matching, --file-offsets, or --line- offsets is used to output only the part of the line that matched (either shown literally, or as an offset), scanning resumes immediately following the match, so that further matches on the same line can be found. If there are multiple patterns, they are all tried on the remainder of the line, but patterns that follow the one that matched are not tried on the earlier part of the line. This behaviour means that the order in which multiple patterns are specified can affect the output when one of the above options is used. This is no longer the same behaviour as GNU grep, which now manages to display earlier matches for later patterns (as long as there is no overlap). Patterns that can match an empty string are accepted, but empty string matches are never recognized. An example is the pattern "(super)?(man)?", in which all components are optional. This pattern finds all occurrences of both "super" and "man"; the output differs from matching with "super|man" when only the matching substrings are being shown. If the LC_ALL or LC_CTYPE environment variable is set, pcregrep uses the value to set a locale when calling the PCRE library. The --locale option can be used to override this. SUPPORT FOR COMPRESSED FILES It is possible to compile pcregrep so that it uses libz or libbz2 to read files whose names end in .gz or .bz2, respectively. You can find out whether your binary has support for one or both of these file types by running it with the --help option. If the appropriate support is not present, files are treated as plain text. The standard input is always so treated. BINARY FILES By default, a file that contains a binary zero byte within the first 1024 bytes is identified as a binary file, and is processed specially. (GNU grep also identifies binary files in this manner.) See the --binary-files option for a means of changing the way binary files are handled. OPTIONS The order in which some of the options appear can affect the output. For example, both the -h and -l options affect the printing of file names. Whichever comes later in the command line will be the one that takes effect. Similarly, except where noted below, if an option is given twice, the later setting is used. Numerical values for options may be followed by K or M, to signify multiplication by 1024 or 1024*1024 respectively. -- This terminates the list of options. It is useful if the next item on the command line starts with a hyphen but is not an option. This allows for the processing of patterns and file- names that start with hyphens. -A number, --after-context=number Output number lines of context after each matching line. If filenames and/or line numbers are being output, a hyphen sep- arator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file. The value of number is expected to be relatively small. However, pcregrep guarantees to have up to 8K of following text avail- able for context output. -a, --text Treat binary files as text. This is equivalent to --binary- files=text. -B number, --before-context=number Output number lines of context before each matching line. If filenames and/or line numbers are being output, a hyphen sep- arator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file. The value of number is expected to be relatively small. However, pcregrep guarantees to have up to 8K of preceding text avail- able for context output. --binary-files=word Specify how binary files are to be processed. If the word is "binary" (the default), pattern matching is performed on binary files, but the only output is "Binary file matches" when a match succeeds. If the word is "text", which is equivalent to the -a or --text option, binary files are processed in the same way as any other file. In this case, when a match succeeds, the output may be binary garbage, which can have nasty effects if sent to a terminal. If the word is "without-match", which is equivalent to the -I option, binary files are not processed at all; they are assumed not to be of interest. --buffer-size=number Set the parameter that controls how much memory is used for buffering files that are being scanned. -C number, --context=number Output number lines of context both before and after each matching line. This is equivalent to setting both -A and -B to the same value. -c, --count Do not output individual lines from the files that are being scanned; instead output the number of lines that would other- wise have been shown. If no lines are selected, the number zero is output. If several files are are being scanned, a count is output for each of them. However, if the --files- with-matches option is also used, only those files whose counts are greater than zero are listed. When -c is used, the -A, -B, and -C options are ignored. --colour, --color If this option is given without any data, it is equivalent to "--colour=auto". If data is required, it must be given in the same shell item, separated by an equals sign. --colour=value, --color=value This option specifies under what circumstances the parts of a line that matched a pattern should be coloured in the output. By default, the output is not coloured. The value (which is optional, see above) may be "never", "always", or "auto". In the latter case, colouring happens only if the standard out- put is connected to a terminal. More resources are used when colouring is enabled, because pcregrep has to search for all possible matches in a line, not just one, in order to colour them all. The colour that is used can be specified by setting the envi- ronment variable PCREGREP_COLOUR or PCREGREP_COLOR. The value of this variable should be a string of two numbers, separated by a semicolon. They are copied directly into the control string for setting colour on a terminal, so it is your responsibility to ensure that they make sense. If neither of the environment variables is set, the default is "1;31", which gives red. -D action, --devices=action If an input path is not a regular file or a directory, "action" specifies how it is to be processed. Valid values are "read" (the default) or "skip" (silently skip the path). -d action, --directories=action If an input path is a directory, "action" specifies how it is to be processed. Valid values are "read" (the default in non-Windows environments, for compatibility with GNU grep), "recurse" (equivalent to the -r option), or "skip" (silently skip the path, the default in Windows environments). In the "read" case, directories are read as if they were ordinary files. In some operating systems the effect of reading a directory like this is an immediate end-of-file; in others it may provoke an error. -e pattern, --regex=pattern, --regexp=pattern Specify a pattern to be matched. This option can be used mul- tiple times in order to specify several patterns. It can also be used as a way of specifying a single pattern that starts with a hyphen. When -e is used, no argument pattern is taken from the command line; all arguments are treated as file names. There is no limit to the number of patterns. They are applied to each line in the order in which they are defined until one matches. If -f is used with -e, the command line patterns are matched first, followed by the patterns from the file(s), independent of the order in which these options are specified. Note that multiple use of -e is not the same as a single pattern with alternatives. For example, X|Y finds the first character in a line that is X or Y, whereas if the two patterns are given separately, with X first, pcregrep finds X if it is present, even if it follows Y in the line. It finds Y only if there is no X in the line. This matters only if you are using -o or --colo(u)r to show the part(s) of the line that matched. --exclude=pattern Files (but not directories) whose names match the pattern are skipped without being processed. This applies to all files, whether listed on the command line, obtained from --file- list, or by scanning a directory. The pattern is a PCRE regu- lar expression, and is matched against the final component of the file name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times in order to specify multiple patterns. If a file name matches both an --include and an --exclude pat- tern, it is excluded. There is no short form for this option. --exclude-from=filename Treat each non-empty line of the file as the data for an --exclude option. What constitutes a newline when reading the file is the operating system's default. The --newline option has no effect on this option. This option may be given more than once in order to specify a number of files to read. --exclude-dir=pattern Directories whose names match the pattern are skipped without being processed, whatever the setting of the --recursive option. This applies to all directories, whether listed on the command line, obtained from --file-list, or by scanning a parent directory. The pattern is a PCRE regular expression, and is matched against the final component of the directory name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times in order to specify more than one pattern. If a direc- tory matches both --include-dir and --exclude-dir, it is excluded. There is no short form for this option. -F, --fixed-strings Interpret each data-matching pattern as a list of fixed strings, separated by newlines, instead of as a regular expression. What constitutes a newline for this purpose is controlled by the --newline option. The -w (match as a word) and -x (match whole line) options can be used with -F. They apply to each of the fixed strings. A line is selected if any of the fixed strings are found in it (subject to -w or -x, if present). This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the --include or --exclude options. -f filename, --file=filename Read patterns from the file, one per line, and match them against each line of input. What constitutes a newline when reading the file is the operating system's default. The --newline option has no effect on this option. Trailing white space is removed from each line, and blank lines are ignored. An empty file contains no patterns and therefore matches nothing. See also the comments about multiple patterns versus a single pattern with alternatives in the description of -e above. If this option is given more than once, all the specified files are read. A data line is output if any of the patterns match it. A filename can be given as "-" to refer to the standard input. When -f is used, patterns specified on the command line using -e may also be present; they are tested before the file's patterns. However, no other pattern is taken from the command line; all arguments are treated as the names of paths to be searched. --file-list=filename Read a list of files and/or directories that are to be scanned from the given file, one per line. Trailing white space is removed from each line, and blank lines are ignored. These paths are processed before any that are listed on the command line. The filename can be given as "-" to refer to the standard input. If --file and --file-list are both spec- ified as "-", patterns are read first. This is useful only when the standard input is a terminal, from which further lines (the list of files) can be read after an end-of-file indication. If this option is given more than once, all the specified files are read. --file-offsets Instead of showing lines or parts of lines that match, show each match as an offset from the start of the file and a length, separated by a comma. In this mode, no context is shown. That is, the -A, -B, and -C options are ignored. If there is more than one match in a line, each of them is shown separately. This option is mutually exclusive with --line- offsets and --only-matching. -H, --with-filename Force the inclusion of the filename at the start of output lines when searching a single file. By default, the filename is not shown in this case. For matching lines, the filename is followed by a colon; for context lines, a hyphen separator is used. If a line number is also being output, it follows the file name. -h, --no-filename Suppress the output filenames when searching multiple files. By default, filenames are shown when multiple files are searched. For matching lines, the filename is followed by a colon; for context lines, a hyphen separator is used. If a line number is also being output, it follows the file name. --help Output a help message, giving brief details of the command options and file type support, and then exit. Anything else on the command line is ignored. -I Treat binary files as never matching. This is equivalent to --binary-files=without-match. -i, --ignore-case Ignore upper/lower case distinctions during comparisons. --include=pattern If any --include patterns are specified, the only files that are processed are those that match one of the patterns (and do not match an --exclude pattern). This option does not affect directories, but it applies to all files, whether listed on the command line, obtained from --file-list, or by scanning a directory. The pattern is a PCRE regular expres- sion, and is matched against the final component of the file name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times. If a file name matches both an --include and an --exclude pattern, it is excluded. There is no short form for this option. --include-from=filename Treat each non-empty line of the file as the data for an --include option. What constitutes a newline for this purpose is the operating system's default. The --newline option has no effect on this option. This option may be given any number of times; all the files are read. --include-dir=pattern If any --include-dir patterns are specified, the only direc- tories that are processed are those that match one of the patterns (and do not match an --exclude-dir pattern). This applies to all directories, whether listed on the command line, obtained from --file-list, or by scanning a parent directory. The pattern is a PCRE regular expression, and is matched against the final component of the directory name, not the entire path. The -F, -w, and -x options do not apply to this pattern. The option may be given any number of times. If a directory matches both --include-dir and --exclude-dir, it is excluded. There is no short form for this option. -L, --files-without-match Instead of outputting lines from the files, just output the names of the files that do not contain any lines that would have been output. Each file name is output once, on a sepa- rate line. -l, --files-with-matches Instead of outputting lines from the files, just output the names of the files containing lines that would have been out- put. Each file name is output once, on a separate line. Searching normally stops as soon as a matching line is found in a file. However, if the -c (count) option is also used, matching continues in order to obtain the correct count, and those files that have at least one match are listed along with their counts. Using this option with -c is a way of sup- pressing the listing of files with no matches. --label=name This option supplies a name to be used for the standard input when file names are being output. If not supplied, "(standard input)" is used. There is no short form for this option. --line-buffered When this option is given, input is read and processed line by line, and the output is flushed after each write. By default, input is read in large chunks, unless pcregrep can determine that it is reading from a terminal (which is cur- rently possible only in Unix-like environments). Output to terminal is normally automatically flushed by the operating system. This option can be useful when the input or output is attached to a pipe and you do not want pcregrep to buffer up large amounts of data. However, its use will affect perfor- mance, and the -M (multiline) option ceases to work. --line-offsets Instead of showing lines or parts of lines that match, show each match as a line number, the offset from the start of the line, and a length. The line number is terminated by a colon (as usual; see the -n option), and the offset and length are separated by a comma. In this mode, no context is shown. That is, the -A, -B, and -C options are ignored. If there is more than one match in a line, each of them is shown sepa- rately. This option is mutually exclusive with --file-offsets and --only-matching. --locale=locale-name This option specifies a locale to be used for pattern match- ing. It overrides the value in the LC_ALL or LC_CTYPE envi- ronment variables. If no locale is specified, the PCRE library's default (usually the "C" locale) is used. There is no short form for this option. --match-limit=number Processing some regular expression patterns can require a very large amount of memory, leading in some cases to a pro- gram crash if not enough is available. Other patterns may take a very long time to search for all possible matching strings. The pcre_exec() function that is called by pcregrep to do the matching has two parameters that can limit the resources that it uses. The --match-limit option provides a means of limiting resource usage when processing patterns that are not going to match, but which have a very large number of possibilities in their search trees. The classic example is a pattern that uses nested unlimited repeats. Internally, PCRE uses a func- tion called match() which it calls repeatedly (sometimes recursively). The limit set by --match-limit is imposed on the number of times this function is called during a match, which has the effect of limiting the amount of backtracking that can take place. The --recursion-limit option is similar to --match-limit, but instead of limiting the total number of times that match() is called, it limits the depth of recursive calls, which in turn limits the amount of memory that can be used. The recursion depth is a smaller number than the total number of calls, because not all calls to match() are recursive. This limit is of use only if it is set smaller than --match-limit. There are no short forms for these options. The default set- tings are specified when the PCRE library is compiled, with the default default being 10 million. -M, --multiline Allow patterns to match more than one line. When this option is given, patterns may usefully contain literal newline char- acters and internal occurrences of ^ and $ characters. The output for a successful match may consist of more than one line, the last of which is the one in which the match ended. If the matched string ends with a newline sequence the output ends at the end of that line. When this option is set, the PCRE library is called in "mul- tiline" mode. There is a limit to the number of lines that can be matched, imposed by the way that pcregrep buffers the input file as it scans it. However, pcregrep ensures that at least 8K characters or the rest of the document (whichever is the shorter) are available for forward matching, and simi- larly the previous 8K characters (or all the previous charac- ters, if fewer than 8K) are guaranteed to be available for lookbehind assertions. This option does not work when input is read line by line (see --line-buffered.) -N newline-type, --newline=newline-type The PCRE library supports five different conventions for indicating the ends of lines. They are the single-character sequences CR (carriage return) and LF (linefeed), the two- character sequence CRLF, an "anycrlf" convention, which rec- ognizes any of the preceding three types, and an "any" con- vention, in which any Unicode line ending sequence is assumed to end a line. The Unicode sequences are the three just men- tioned, plus VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS (paragraph separator, U+2029). When the PCRE library is built, a default line-ending sequence is specified. This is normally the standard sequence for the operating system. Unless otherwise specified by this option, pcregrep uses the library's default. The possible values for this option are CR, LF, CRLF, ANYCRLF, or ANY. This makes it possible to use pcregrep to scan files that have come from other environments without having to mod- ify their line endings. If the data that is being scanned does not agree with the convention set by this option, pcre- grep may behave in strange ways. Note that this option does not apply to files specified by the -f, --exclude-from, or --include-from options, which are expected to use the operat- ing system's standard newline sequence. -n, --line-number Precede each output line by its line number in the file, fol- lowed by a colon for matching lines or a hyphen for context lines. If the filename is also being output, it precedes the line number. This option is forced if --line-offsets is used. --no-jit If the PCRE library is built with support for just-in-time compiling (which speeds up matching), pcregrep automatically makes use of this, unless it was explicitly disabled at build time. This option can be used to disable the use of JIT at run time. It is provided for testing and working round prob- lems. It should never be needed in normal use. -o, --only-matching Show only the part of the line that matched a pattern instead of the whole line. In this mode, no context is shown. That is, the -A, -B, and -C options are ignored. If there is more than one match in a line, each of them is shown separately. If -o is combined with -v (invert the sense of the match to find non-matching lines), no output is generated, but the return code is set appropriately. If the matched portion of the line is empty, nothing is output unless the file name or line number are being printed, in which case they are shown on an otherwise empty line. This option is mutually exclusive with --file-offsets and --line-offsets. -onumber, --only-matching=number Show only the part of the line that matched the capturing parentheses of the given number. Up to 32 capturing parenthe- ses are supported, and -o0 is equivalent to -o without a num- ber. Because these options can be given without an argument (see above), if an argument is present, it must be given in the same shell item, for example, -o3 or --only-matching=2. The comments given for the non-argument case above also apply to this case. If the specified capturing parentheses do not exist in the pattern, or were not set in the match, nothing is output unless the file name or line number are being printed. If this option is given multiple times, multiple substrings are output, in the order the options are given. For example, -o3 -o1 -o3 causes the substrings matched by capturing paren- theses 3 and 1 and then 3 again to be output. By default, there is no separator (but see the next option). --om-separator=text Specify a separating string for multiple occurrences of -o. The default is an empty string. Separating strings are never coloured. -q, --quiet Work quietly, that is, display nothing except error messages. The exit status indicates whether or not any matches were found. -r, --recursive If any given path is a directory, recursively scan the files it contains, taking note of any --include and --exclude set- tings. By default, a directory is read as a normal file; in some operating systems this gives an immediate end-of-file. This option is a shorthand for setting the -d option to "recurse". --recursion-limit=number See --match-limit above. -s, --no-messages Suppress error messages about non-existent or unreadable files. Such files are quietly skipped. However, the return code is still 2, even if matches were found in other files. -u, --utf-8 Operate in UTF-8 mode. This option is available only if PCRE has been compiled with UTF-8 support. All patterns (including those for any --exclude and --include options) and all sub- ject lines that are scanned must be valid strings of UTF-8 characters. -V, --version Write the version numbers of pcregrep and the PCRE library to the standard output and then exit. Anything else on the com- mand line is ignored. -v, --invert-match Invert the sense of the match, so that lines which do not match any of the patterns are the ones that are found. -w, --word-regex, --word-regexp Force the patterns to match only whole words. This is equiva- lent to having \b at the start and end of the pattern. This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns speci- fied by any of the --include or --exclude options. -x, --line-regex, --line-regexp Force the patterns to be anchored (each must start matching at the beginning of a line) and in addition, require them to match entire lines. This is equivalent to having ^ and $ characters at the start and end of each alternative branch in every pattern. This option applies only to the patterns that are matched against the contents of files; it does not apply to patterns specified by any of the --include or --exclude options. ENVIRONMENT VARIABLES The environment variables LC_ALL and LC_CTYPE are examined, in that order, for a locale. The first one that is set is used. This can be overridden by the --locale option. If no locale is set, the PCRE library's default (usually the "C" locale) is used. NEWLINES The -N (--newline) option allows pcregrep to scan files with different newline conventions from the default. Any parts of the input files that are written to the standard output are copied identically, with what- ever newline sequences they have in the input. However, the setting of this option does not affect the interpretation of files specified by the -f, --exclude-from, or --include-from options, which are assumed to use the operating system's standard newline sequence, nor does it affect the way in which pcregrep writes informational messages to the standard error and output streams. For these it uses the string "\n" to indicate newlines, relying on the C I/O library to convert this to an appropriate sequence. OPTIONS COMPATIBILITY Many of the short and long forms of pcregrep's options are the same as in the GNU grep program. Any long option of the form --xxx-regexp (GNU terminology) is also available as --xxx-regex (PCRE terminology). How- ever, the --file-list, --file-offsets, --include-dir, --line-offsets, --locale, --match-limit, -M, --multiline, -N, --newline, --om-separa- tor, --recursion-limit, -u, and --utf-8 options are specific to pcre- grep, as is the use of the --only-matching option with a capturing parentheses number. Although most of the common options work the same way, a few are dif- ferent in pcregrep. For example, the --include option's argument is a glob for GNU grep, but a regular expression for pcregrep. If both the -c and -l options are given, GNU grep lists only file names, without counts, but pcregrep gives the counts. OPTIONS WITH DATA There are four different ways in which an option with data can be spec- ified. If a short form option is used, the data may follow immedi- ately, or (with one exception) in the next command line item. For exam- ple: -f/some/file -f /some/file The exception is the -o option, which may appear with or without data. Because of this, if data is present, it must follow immediately in the same item, for example -o3. If a long form option is used, the data may appear in the same command line item, separated by an equals character, or (with two exceptions) it may appear in the next command line item. For example: --file=/some/file --file /some/file Note, however, that if you want to supply a file name beginning with ~ as data in a shell command, and have the shell expand ~ to a home directory, you must separate the file name from the option, because the shell does not treat ~ specially unless it is at the start of an item. The exceptions to the above are the --colour (or --color) and --only- matching options, for which the data is optional. If one of these options does have data, it must be given in the first form, using an equals character. Otherwise pcregrep will assume that it has no data. MATCHING ERRORS It is possible to supply a regular expression that takes a very long time to fail to match certain lines. Such patterns normally involve nested indefinite repeats, for example: (a+)*\d when matched against a line of a's with no final digit. The PCRE matching function has a resource limit that causes it to abort in these circumstances. If this happens, pcregrep outputs an error message and the line that caused the problem to the standard error stream. If there are more than 20 such errors, pcregrep gives up. The --match-limit option of pcregrep can be used to set the overall resource limit; there is a second option called --recursion-limit that sets a limit on the amount of memory (usually stack) that is used (see the discussion of these options above). DIAGNOSTICS Exit status is 0 if any matches were found, 1 if no matches were found, and 2 for syntax errors, overlong lines, non-existent or inaccessible files (even if matches were found in other files) or too many matching errors. Using the -s option to suppress error messages about inaccessi- ble files does not affect the return code. SEE ALSO pcrepattern(3), pcresyntax(3), pcretest(1). AUTHOR Philip Hazel University Computing Service Cambridge CB2 3QH, England. REVISION Last updated: 03 April 2014 Copyright (c) 1997-2014 University of Cambridge. ================================================ FILE: src/pcre/doc/pcrejit.3 ================================================ .TH PCREJIT 3 "05 July 2017" "PCRE 8.41" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE JUST-IN-TIME COMPILER SUPPORT" .rs .sp Just-in-time compiling is a heavyweight optimization that can greatly speed up pattern matching. However, it comes at the cost of extra processing before the match is performed. Therefore, it is of most benefit when the same pattern is going to be matched many times. This does not necessarily mean many calls of a matching function; if the pattern is not anchored, matching attempts may take place many times at various positions in the subject, even for a single call. Therefore, if the subject string is very long, it may still pay to use JIT for one-off matches. .P JIT support applies only to the traditional Perl-compatible matching function. It does not apply when the DFA matching function is being used. The code for this support was written by Zoltan Herczeg. . . .SH "8-BIT, 16-BIT AND 32-BIT SUPPORT" .rs .sp JIT support is available for all of the 8-bit, 16-bit and 32-bit PCRE libraries. To keep this documentation simple, only the 8-bit interface is described in what follows. If you are using the 16-bit library, substitute the 16-bit functions and 16-bit structures (for example, \fIpcre16_jit_stack\fP instead of \fIpcre_jit_stack\fP). If you are using the 32-bit library, substitute the 32-bit functions and 32-bit structures (for example, \fIpcre32_jit_stack\fP instead of \fIpcre_jit_stack\fP). . . .SH "AVAILABILITY OF JIT SUPPORT" .rs .sp JIT support is an optional feature of PCRE. The "configure" option --enable-jit (or equivalent CMake option) must be set when PCRE is built if you want to use JIT. The support is limited to the following hardware platforms: .sp ARM v5, v7, and Thumb2 Intel x86 32-bit and 64-bit MIPS 32-bit Power PC 32-bit and 64-bit SPARC 32-bit (experimental) .sp If --enable-jit is set on an unsupported platform, compilation fails. .P A program that is linked with PCRE 8.20 or later can tell if JIT support is available by calling \fBpcre_config()\fP with the PCRE_CONFIG_JIT option. The result is 1 when JIT is available, and 0 otherwise. However, a simple program does not need to check this in order to use JIT. The normal API is implemented in a way that falls back to the interpretive code if JIT is not available. For programs that need the best possible performance, there is also a "fast path" API that is JIT-specific. .P If your program may sometimes be linked with versions of PCRE that are older than 8.20, but you want to use JIT when it is available, you can test the values of PCRE_MAJOR and PCRE_MINOR, or the existence of a JIT macro such as PCRE_CONFIG_JIT, for compile-time control of your code. Also beware that the \fBpcre_jit_exec()\fP function was not available at all before 8.32, and may not be available at all if PCRE isn't compiled with --enable-jit. See the "JIT FAST PATH API" section below for details. . . .SH "SIMPLE USE OF JIT" .rs .sp You have to do two things to make use of the JIT support in the simplest way: .sp (1) Call \fBpcre_study()\fP with the PCRE_STUDY_JIT_COMPILE option for each compiled pattern, and pass the resulting \fBpcre_extra\fP block to \fBpcre_exec()\fP. .sp (2) Use \fBpcre_free_study()\fP to free the \fBpcre_extra\fP block when it is no longer needed, instead of just freeing it yourself. This ensures that any JIT data is also freed. .sp For a program that may be linked with pre-8.20 versions of PCRE, you can insert .sp #ifndef PCRE_STUDY_JIT_COMPILE #define PCRE_STUDY_JIT_COMPILE 0 #endif .sp so that no option is passed to \fBpcre_study()\fP, and then use something like this to free the study data: .sp #ifdef PCRE_CONFIG_JIT pcre_free_study(study_ptr); #else pcre_free(study_ptr); #endif .sp PCRE_STUDY_JIT_COMPILE requests the JIT compiler to generate code for complete matches. If you want to run partial matches using the PCRE_PARTIAL_HARD or PCRE_PARTIAL_SOFT options of \fBpcre_exec()\fP, you should set one or both of the following options in addition to, or instead of, PCRE_STUDY_JIT_COMPILE when you call \fBpcre_study()\fP: .sp PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE .sp If using \fBpcre_jit_exec()\fP and supporting a pre-8.32 version of PCRE, you can insert: .sp #if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32 pcre_jit_exec(...); #else pcre_exec(...) #endif .sp but as described in the "JIT FAST PATH API" section below this assumes version 8.32 and later are compiled with --enable-jit, which may break. .sp The JIT compiler generates different optimized code for each of the three modes (normal, soft partial, hard partial). When \fBpcre_exec()\fP is called, the appropriate code is run if it is available. Otherwise, the pattern is matched using interpretive code. .P In some circumstances you may need to call additional functions. These are described in the section entitled .\" HTML .\" "Controlling the JIT stack" .\" below. .P If JIT support is not available, PCRE_STUDY_JIT_COMPILE etc. are ignored, and no JIT data is created. Otherwise, the compiled pattern is passed to the JIT compiler, which turns it into machine code that executes much faster than the normal interpretive code. When \fBpcre_exec()\fP is passed a \fBpcre_extra\fP block containing a pointer to JIT code of the appropriate mode (normal or hard/soft partial), it obeys that code instead of running the interpreter. The result is identical, but the compiled JIT code runs much faster. .P There are some \fBpcre_exec()\fP options that are not supported for JIT execution. There are also some pattern items that JIT cannot handle. Details are given below. In both cases, execution automatically falls back to the interpretive code. If you want to know whether JIT was actually used for a particular match, you should arrange for a JIT callback function to be set up as described in the section entitled .\" HTML .\" "Controlling the JIT stack" .\" below, even if you do not need to supply a non-default JIT stack. Such a callback function is called whenever JIT code is about to be obeyed. If the execution options are not right for JIT execution, the callback function is not obeyed. .P If the JIT compiler finds an unsupported item, no JIT data is generated. You can find out if JIT execution is available after studying a pattern by calling \fBpcre_fullinfo()\fP with the PCRE_INFO_JIT option. A result of 1 means that JIT compilation was successful. A result of 0 means that JIT support is not available, or the pattern was not studied with PCRE_STUDY_JIT_COMPILE etc., or the JIT compiler was not able to handle the pattern. .P Once a pattern has been studied, with or without JIT, it can be used as many times as you like for matching different subject strings. . . .SH "UNSUPPORTED OPTIONS AND PATTERN ITEMS" .rs .sp The only \fBpcre_exec()\fP options that are supported for JIT execution are PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK, PCRE_NO_UTF32_CHECK, PCRE_NOTBOL, PCRE_NOTEOL, PCRE_NOTEMPTY, PCRE_NOTEMPTY_ATSTART, PCRE_PARTIAL_HARD, and PCRE_PARTIAL_SOFT. .P The only unsupported pattern items are \eC (match a single data unit) when running in a UTF mode, and a callout immediately before an assertion condition in a conditional group. . . .SH "RETURN VALUES FROM JIT EXECUTION" .rs .sp When a pattern is matched using JIT execution, the return values are the same as those given by the interpretive \fBpcre_exec()\fP code, with the addition of one new error code: PCRE_ERROR_JIT_STACKLIMIT. This means that the memory used for the JIT stack was insufficient. See .\" HTML .\" "Controlling the JIT stack" .\" below for a discussion of JIT stack usage. For compatibility with the interpretive \fBpcre_exec()\fP code, no more than two-thirds of the \fIovector\fP argument is used for passing back captured substrings. .P The error code PCRE_ERROR_MATCHLIMIT is returned by the JIT code if searching a very large pattern tree goes on for too long, as it is in the same circumstance when JIT is not used, but the details of exactly what is counted are not the same. The PCRE_ERROR_RECURSIONLIMIT error code is never returned by JIT execution. . . .SH "SAVING AND RESTORING COMPILED PATTERNS" .rs .sp The code that is generated by the JIT compiler is architecture-specific, and is also position dependent. For those reasons it cannot be saved (in a file or database) and restored later like the bytecode and other data of a compiled pattern. Saving and restoring compiled patterns is not something many people do. More detail about this facility is given in the .\" HREF \fBpcreprecompile\fP .\" documentation. It should be possible to run \fBpcre_study()\fP on a saved and restored pattern, and thereby recreate the JIT data, but because JIT compilation uses significant resources, it is probably not worth doing this; you might as well recompile the original pattern. . . .\" HTML .SH "CONTROLLING THE JIT STACK" .rs .sp When the compiled JIT code runs, it needs a block of memory to use as a stack. By default, it uses 32K on the machine stack. However, some large or complicated patterns need more than this. The error PCRE_ERROR_JIT_STACKLIMIT is given when there is not enough stack. Three functions are provided for managing blocks of memory for use as JIT stacks. There is further discussion about the use of JIT stacks in the section entitled .\" HTML .\" "JIT stack FAQ" .\" below. .P The \fBpcre_jit_stack_alloc()\fP function creates a JIT stack. Its arguments are a starting size and a maximum size, and it returns a pointer to an opaque structure of type \fBpcre_jit_stack\fP, or NULL if there is an error. The \fBpcre_jit_stack_free()\fP function can be used to free a stack that is no longer needed. (For the technically minded: the address space is allocated by mmap or VirtualAlloc.) .P JIT uses far less memory for recursion than the interpretive code, and a maximum stack size of 512K to 1M should be more than enough for any pattern. .P The \fBpcre_assign_jit_stack()\fP function specifies which stack JIT code should use. Its arguments are as follows: .sp pcre_extra *extra pcre_jit_callback callback void *data .sp The \fIextra\fP argument must be the result of studying a pattern with PCRE_STUDY_JIT_COMPILE etc. There are three cases for the values of the other two options: .sp (1) If \fIcallback\fP is NULL and \fIdata\fP is NULL, an internal 32K block on the machine stack is used. .sp (2) If \fIcallback\fP is NULL and \fIdata\fP is not NULL, \fIdata\fP must be a valid JIT stack, the result of calling \fBpcre_jit_stack_alloc()\fP. .sp (3) If \fIcallback\fP is not NULL, it must point to a function that is called with \fIdata\fP as an argument at the start of matching, in order to set up a JIT stack. If the return from the callback function is NULL, the internal 32K stack is used; otherwise the return value must be a valid JIT stack, the result of calling \fBpcre_jit_stack_alloc()\fP. .sp A callback function is obeyed whenever JIT code is about to be run; it is not obeyed when \fBpcre_exec()\fP is called with options that are incompatible for JIT execution. A callback function can therefore be used to determine whether a match operation was executed by JIT or by the interpreter. .P You may safely use the same JIT stack for more than one pattern (either by assigning directly or by callback), as long as the patterns are all matched sequentially in the same thread. In a multithread application, if you do not specify a JIT stack, or if you assign or pass back NULL from a callback, that is thread-safe, because each thread has its own machine stack. However, if you assign or pass back a non-NULL JIT stack, this must be a different stack for each thread so that the application is thread-safe. .P Strictly speaking, even more is allowed. You can assign the same non-NULL stack to any number of patterns as long as they are not used for matching by multiple threads at the same time. For example, you can assign the same stack to all compiled patterns, and use a global mutex in the callback to wait until the stack is available for use. However, this is an inefficient solution, and not recommended. .P This is a suggestion for how a multithreaded program that needs to set up non-default JIT stacks might operate: .sp During thread initalization thread_local_var = pcre_jit_stack_alloc(...) .sp During thread exit pcre_jit_stack_free(thread_local_var) .sp Use a one-line callback function return thread_local_var .sp All the functions described in this section do nothing if JIT is not available, and \fBpcre_assign_jit_stack()\fP does nothing unless the \fBextra\fP argument is non-NULL and points to a \fBpcre_extra\fP block that is the result of a successful study with PCRE_STUDY_JIT_COMPILE etc. . . .\" HTML .SH "JIT STACK FAQ" .rs .sp (1) Why do we need JIT stacks? .sp PCRE (and JIT) is a recursive, depth-first engine, so it needs a stack where the local data of the current node is pushed before checking its child nodes. Allocating real machine stack on some platforms is difficult. For example, the stack chain needs to be updated every time if we extend the stack on PowerPC. Although it is possible, its updating time overhead decreases performance. So we do the recursion in memory. .P (2) Why don't we simply allocate blocks of memory with \fBmalloc()\fP? .sp Modern operating systems have a nice feature: they can reserve an address space instead of allocating memory. We can safely allocate memory pages inside this address space, so the stack could grow without moving memory data (this is important because of pointers). Thus we can allocate 1M address space, and use only a single memory page (usually 4K) if that is enough. However, we can still grow up to 1M anytime if needed. .P (3) Who "owns" a JIT stack? .sp The owner of the stack is the user program, not the JIT studied pattern or anything else. The user program must ensure that if a stack is used by \fBpcre_exec()\fP, (that is, it is assigned to the pattern currently running), that stack must not be used by any other threads (to avoid overwriting the same memory area). The best practice for multithreaded programs is to allocate a stack for each thread, and return this stack through the JIT callback function. .P (4) When should a JIT stack be freed? .sp You can free a JIT stack at any time, as long as it will not be used by \fBpcre_exec()\fP again. When you assign the stack to a pattern, only a pointer is set. There is no reference counting or any other magic. You can free the patterns and stacks in any order, anytime. Just \fIdo not\fP call \fBpcre_exec()\fP with a pattern pointing to an already freed stack, as that will cause SEGFAULT. (Also, do not free a stack currently used by \fBpcre_exec()\fP in another thread). You can also replace the stack for a pattern at any time. You can even free the previous stack before assigning a replacement. .P (5) Should I allocate/free a stack every time before/after calling \fBpcre_exec()\fP? .sp No, because this is too costly in terms of resources. However, you could implement some clever idea which release the stack if it is not used in let's say two minutes. The JIT callback can help to achieve this without keeping a list of the currently JIT studied patterns. .P (6) OK, the stack is for long term memory allocation. But what happens if a pattern causes stack overflow with a stack of 1M? Is that 1M kept until the stack is freed? .sp Especially on embedded sytems, it might be a good idea to release memory sometimes without freeing the stack. There is no API for this at the moment. Probably a function call which returns with the currently allocated memory for any stack and another which allows releasing memory (shrinking the stack) would be a good idea if someone needs this. .P (7) This is too much of a headache. Isn't there any better solution for JIT stack handling? .sp No, thanks to Windows. If POSIX threads were used everywhere, we could throw out this complicated API. . . .SH "EXAMPLE CODE" .rs .sp This is a single-threaded example that specifies a JIT stack without using a callback. .sp int rc; int ovector[30]; pcre *re; pcre_extra *extra; pcre_jit_stack *jit_stack; .sp re = pcre_compile(pattern, 0, &error, &erroffset, NULL); /* Check for errors */ extra = pcre_study(re, PCRE_STUDY_JIT_COMPILE, &error); jit_stack = pcre_jit_stack_alloc(32*1024, 512*1024); /* Check for error (NULL) */ pcre_assign_jit_stack(extra, NULL, jit_stack); rc = pcre_exec(re, extra, subject, length, 0, 0, ovector, 30); /* Check results */ pcre_free(re); pcre_free_study(extra); pcre_jit_stack_free(jit_stack); .sp . . .SH "JIT FAST PATH API" .rs .sp Because the API described above falls back to interpreted execution when JIT is not available, it is convenient for programs that are written for general use in many environments. However, calling JIT via \fBpcre_exec()\fP does have a performance impact. Programs that are written for use where JIT is known to be available, and which need the best possible performance, can instead use a "fast path" API to call JIT execution directly instead of calling \fBpcre_exec()\fP (obviously only for patterns that have been successfully studied by JIT). .P The fast path function is called \fBpcre_jit_exec()\fP, and it takes exactly the same arguments as \fBpcre_exec()\fP, plus one additional argument that must point to a JIT stack. The JIT stack arrangements described above do not apply. The return values are the same as for \fBpcre_exec()\fP. .P When you call \fBpcre_exec()\fP, as well as testing for invalid options, a number of other sanity checks are performed on the arguments. For example, if the subject pointer is NULL, or its length is negative, an immediate error is given. Also, unless PCRE_NO_UTF[8|16|32] is set, a UTF subject string is tested for validity. In the interests of speed, these checks do not happen on the JIT fast path, and if invalid data is passed, the result is undefined. .P Bypassing the sanity checks and the \fBpcre_exec()\fP wrapping can give speedups of more than 10%. .P Note that the \fBpcre_jit_exec()\fP function is not available in versions of PCRE before 8.32 (released in November 2012). If you need to support versions that old you must either use the slower \fBpcre_exec()\fP, or switch between the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR. .P Due to an unfortunate implementation oversight, even in versions 8.32 and later there will be no \fBpcre_jit_exec()\fP stub function defined when PCRE is compiled with --disable-jit, which is the default, and there's no way to detect whether PCRE was compiled with --enable-jit via a macro. .P If you need to support versions older than 8.32, or versions that may not build with --enable-jit, you must either use the slower \fBpcre_exec()\fP, or switch between the two codepaths by checking the values of PCRE_MAJOR and PCRE_MINOR. .P Switching between the two by checking the version assumes that all the versions being targeted are built with --enable-jit. To also support builds that may use --disable-jit either \fBpcre_exec()\fP must be used, or a compile-time check for JIT via \fBpcre_config()\fP (which assumes the runtime environment will be the same), or as the Git project decided to do, simply assume that \fBpcre_jit_exec()\fP is present in 8.32 or later unless a compile-time flag is provided, see the "grep: un-break building with PCRE >= 8.32 without --enable-jit" commit in git.git for an example of that. . . .SH "SEE ALSO" .rs .sp \fBpcreapi\fP(3) . . .SH AUTHOR .rs .sp .nf Philip Hazel (FAQ by Zoltan Herczeg) University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 05 July 2017 Copyright (c) 1997-2017 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrelimits.3 ================================================ .TH PCRELIMITS 3 "05 November 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH "SIZE AND OTHER LIMITATIONS" .rs .sp There are some size limitations in PCRE but it is hoped that they will never in practice be relevant. .P The maximum length of a compiled pattern is approximately 64K data units (bytes for the 8-bit library, 16-bit units for the 16-bit library, and 32-bit units for the 32-bit library) if PCRE is compiled with the default internal linkage size, which is 2 bytes for the 8-bit and 16-bit libraries, and 4 bytes for the 32-bit library. If you want to process regular expressions that are truly enormous, you can compile PCRE with an internal linkage size of 3 or 4 (when building the 16-bit or 32-bit library, 3 is rounded up to 4). See the \fBREADME\fP file in the source distribution and the .\" HREF \fBpcrebuild\fP .\" documentation for details. In these cases the limit is substantially larger. However, the speed of execution is slower. .P All values in repeating quantifiers must be less than 65536. .P There is no limit to the number of parenthesized subpatterns, but there can be no more than 65535 capturing subpatterns. There is, however, a limit to the depth of nesting of parenthesized subpatterns of all kinds. This is imposed in order to limit the amount of system stack used at compile time. The limit can be specified when PCRE is built; the default is 250. .P There is a limit to the number of forward references to subsequent subpatterns of around 200,000. Repeated forward references with fixed upper limits, for example, (?2){0,100} when subpattern number 2 is to the right, are included in the count. There is no limit to the number of backward references. .P The maximum length of name for a named subpattern is 32 characters, and the maximum number of named subpatterns is 10000. .P The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb is 255 for the 8-bit library and 65535 for the 16-bit and 32-bit libraries. .P The maximum length of a subject string is the largest positive number that an integer variable can hold. However, when using the traditional matching function, PCRE uses recursion to handle subpatterns and indefinite repetition. This means that the available stack space may limit the size of a subject string that can be processed by certain patterns. For a discussion of stack issues, see the .\" HREF \fBpcrestack\fP .\" documentation. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 05 November 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrematching.3 ================================================ .TH PCREMATCHING 3 "12 November 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE MATCHING ALGORITHMS" .rs .sp This document describes the two different algorithms that are available in PCRE for matching a compiled regular expression against a given subject string. The "standard" algorithm is the one provided by the \fBpcre_exec()\fP, \fBpcre16_exec()\fP and \fBpcre32_exec()\fP functions. These work in the same as as Perl's matching function, and provide a Perl-compatible matching operation. The just-in-time (JIT) optimization that is described in the .\" HREF \fBpcrejit\fP .\" documentation is compatible with these functions. .P An alternative algorithm is provided by the \fBpcre_dfa_exec()\fP, \fBpcre16_dfa_exec()\fP and \fBpcre32_dfa_exec()\fP functions; they operate in a different way, and are not Perl-compatible. This alternative has advantages and disadvantages compared with the standard algorithm, and these are described below. .P When there is only one possible way in which a given subject string can match a pattern, the two algorithms give the same answer. A difference arises, however, when there are multiple possibilities. For example, if the pattern .sp ^<.*> .sp is matched against the string .sp .sp there are three possible answers. The standard algorithm finds only one of them, whereas the alternative algorithm finds all three. . . .SH "REGULAR EXPRESSIONS AS TREES" .rs .sp The set of strings that are matched by a regular expression can be represented as a tree structure. An unlimited repetition in the pattern makes the tree of infinite size, but it is still a tree. Matching the pattern to a given subject string (from a given starting point) can be thought of as a search of the tree. There are two ways to search a tree: depth-first and breadth-first, and these correspond to the two matching algorithms provided by PCRE. . . .SH "THE STANDARD MATCHING ALGORITHM" .rs .sp In the terminology of Jeffrey Friedl's book "Mastering Regular Expressions", the standard algorithm is an "NFA algorithm". It conducts a depth-first search of the pattern tree. That is, it proceeds along a single path through the tree, checking that the subject matches what is required. When there is a mismatch, the algorithm tries any alternatives at the current point, and if they all fail, it backs up to the previous branch point in the tree, and tries the next alternative branch at that level. This often involves backing up (moving to the left) in the subject string as well. The order in which repetition branches are tried is controlled by the greedy or ungreedy nature of the quantifier. .P If a leaf node is reached, a matching string has been found, and at that point the algorithm stops. Thus, if there is more than one possible match, this algorithm returns the first one that it finds. Whether this is the shortest, the longest, or some intermediate length depends on the way the greedy and ungreedy repetition quantifiers are specified in the pattern. .P Because it ends up with a single path through the tree, it is relatively straightforward for this algorithm to keep track of the substrings that are matched by portions of the pattern in parentheses. This provides support for capturing parentheses and back references. . . .SH "THE ALTERNATIVE MATCHING ALGORITHM" .rs .sp This algorithm conducts a breadth-first search of the tree. Starting from the first matching point in the subject, it scans the subject string from left to right, once, character by character, and as it does this, it remembers all the paths through the tree that represent valid matches. In Friedl's terminology, this is a kind of "DFA algorithm", though it is not implemented as a traditional finite state machine (it keeps multiple states active simultaneously). .P Although the general principle of this matching algorithm is that it scans the subject string only once, without backtracking, there is one exception: when a lookaround assertion is encountered, the characters following or preceding the current point have to be independently inspected. .P The scan continues until either the end of the subject is reached, or there are no more unterminated paths. At this point, terminated paths represent the different matching possibilities (if there are none, the match has failed). Thus, if there is more than one possible match, this algorithm finds all of them, and in particular, it finds the longest. The matches are returned in decreasing order of length. There is an option to stop the algorithm after the first match (which is necessarily the shortest) is found. .P Note that all the matches that are found start at the same point in the subject. If the pattern .sp cat(er(pillar)?)? .sp is matched against the string "the caterpillar catchment", the result will be the three strings "caterpillar", "cater", and "cat" that start at the fifth character of the subject. The algorithm does not automatically move on to find matches that start at later positions. .P PCRE's "auto-possessification" optimization usually applies to character repeats at the end of a pattern (as well as internally). For example, the pattern "a\ed+" is compiled as if it were "a\ed++" because there is no point even considering the possibility of backtracking into the repeated digits. For DFA matching, this means that only one possible match is found. If you really do want multiple matches in such cases, either use an ungreedy repeat ("a\ed+?") or set the PCRE_NO_AUTO_POSSESS option when compiling. .P There are a number of features of PCRE regular expressions that are not supported by the alternative matching algorithm. They are as follows: .P 1. Because the algorithm finds all possible matches, the greedy or ungreedy nature of repetition quantifiers is not relevant. Greedy and ungreedy quantifiers are treated in exactly the same way. However, possessive quantifiers can make a difference when what follows could also match what is quantified, for example in a pattern like this: .sp ^a++\ew! .sp This pattern matches "aaab!" but not "aaa!", which would be matched by a non-possessive quantifier. Similarly, if an atomic group is present, it is matched as if it were a standalone pattern at the current point, and the longest match is then "locked in" for the rest of the overall pattern. .P 2. When dealing with multiple paths through the tree simultaneously, it is not straightforward to keep track of captured substrings for the different matching possibilities, and PCRE's implementation of this algorithm does not attempt to do this. This means that no captured substrings are available. .P 3. Because no substrings are captured, back references within the pattern are not supported, and cause errors if encountered. .P 4. For the same reason, conditional expressions that use a backreference as the condition or test for a specific group recursion are not supported. .P 5. Because many paths through the tree may be active, the \eK escape sequence, which resets the start of the match when encountered (but may be on some paths and not on others), is not supported. It causes an error if encountered. .P 6. Callouts are supported, but the value of the \fIcapture_top\fP field is always 1, and the value of the \fIcapture_last\fP field is always -1. .P 7. The \eC escape sequence, which (in the standard algorithm) always matches a single data unit, even in UTF-8, UTF-16 or UTF-32 modes, is not supported in these modes, because the alternative algorithm moves through the subject string one character (not data unit) at a time, for all active paths through the tree. .P 8. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not supported. (*FAIL) is supported, and behaves like a failing negative assertion. . . .SH "ADVANTAGES OF THE ALTERNATIVE ALGORITHM" .rs .sp Using the alternative matching algorithm provides the following advantages: .P 1. All possible matches (at a single point in the subject) are automatically found, and in particular, the longest match is found. To find more than one match using the standard algorithm, you have to do kludgy things with callouts. .P 2. Because the alternative algorithm scans the subject string just once, and never needs to backtrack (except for lookbehinds), it is possible to pass very long subject strings to the matching function in several pieces, checking for partial matching each time. Although it is possible to do multi-segment matching using the standard algorithm by retaining partially matched substrings, it is more complicated. The .\" HREF \fBpcrepartial\fP .\" documentation gives details of partial matching and discusses multi-segment matching. . . .SH "DISADVANTAGES OF THE ALTERNATIVE ALGORITHM" .rs .sp The alternative algorithm suffers from a number of disadvantages: .P 1. It is substantially slower than the standard algorithm. This is partly because it has to search for all possible matches, but is also because it is less susceptible to optimization. .P 2. Capturing parentheses and back references are not supported. .P 3. Although atomic groups are supported, their use does not provide the performance advantage that it does for the standard algorithm. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 12 November 2013 Copyright (c) 1997-2012 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrepartial.3 ================================================ .TH PCREPARTIAL 3 "02 July 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH "PARTIAL MATCHING IN PCRE" .rs .sp In normal use of PCRE, if the subject string that is passed to a matching function matches as far as it goes, but is too short to match the entire pattern, PCRE_ERROR_NOMATCH is returned. There are circumstances where it might be helpful to distinguish this case from other cases in which there is no match. .P Consider, for example, an application where a human is required to type in data for a field with specific formatting requirements. An example might be a date in the form \fIddmmmyy\fP, defined by this pattern: .sp ^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$ .sp If the application sees the user's keystrokes one by one, and can check that what has been typed so far is potentially valid, it is able to raise an error as soon as a mistake is made, by beeping and not reflecting the character that has been typed, for example. This immediate feedback is likely to be a better user interface than a check that is delayed until the entire string has been entered. Partial matching can also be useful when the subject string is very long and is not all available at once. .P PCRE supports partial matching by means of the PCRE_PARTIAL_SOFT and PCRE_PARTIAL_HARD options, which can be set when calling any of the matching functions. For backwards compatibility, PCRE_PARTIAL is a synonym for PCRE_PARTIAL_SOFT. The essential difference between the two options is whether or not a partial match is preferred to an alternative complete match, though the details differ between the two types of matching function. If both options are set, PCRE_PARTIAL_HARD takes precedence. .P If you want to use partial matching with just-in-time optimized code, you must call \fBpcre_study()\fP, \fBpcre16_study()\fP or \fBpcre32_study()\fP with one or both of these options: .sp PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE .sp PCRE_STUDY_JIT_COMPILE should also be set if you are going to run non-partial matches on the same pattern. If the appropriate JIT study mode has not been set for a match, the interpretive matching code is used. .P Setting a partial matching option disables two of PCRE's standard optimizations. PCRE remembers the last literal data unit in a pattern, and abandons matching immediately if it is not present in the subject string. This optimization cannot be used for a subject string that might match only partially. If the pattern was studied, PCRE knows the minimum length of a matching string, and does not bother to run the matching function on shorter strings. This optimization is also disabled for partial matching. . . .SH "PARTIAL MATCHING USING pcre_exec() OR pcre[16|32]_exec()" .rs .sp A partial match occurs during a call to \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP when the end of the subject string is reached successfully, but matching cannot continue because more characters are needed. However, at least one character in the subject must have been inspected. This character need not form part of the final matched string; lookbehind assertions and the \eK escape sequence provide ways of inspecting characters before the start of a matched substring. The requirement for inspecting at least one character exists because an empty string can always be matched; without such a restriction there would always be a partial match of an empty string at the end of the subject. .P If there are at least two slots in the offsets vector when a partial match is returned, the first slot is set to the offset of the earliest character that was inspected. For convenience, the second offset points to the end of the subject so that a substring can easily be identified. If there are at least three slots in the offsets vector, the third slot is set to the offset of the character where matching started. .P For the majority of patterns, the contents of the first and third slots will be the same. However, for patterns that contain lookbehind assertions, or begin with \eb or \eB, characters before the one where matching started may have been inspected while carrying out the match. For example, consider this pattern: .sp /(?<=abc)123/ .sp This pattern matches "123", but only if it is preceded by "abc". If the subject string is "xyzabc12", the first two offsets after a partial match are for the substring "abc12", because all these characters were inspected. However, the third offset is set to 6, because that is the offset where matching began. .P What happens when a partial match is identified depends on which of the two partial matching options are set. . . .SS "PCRE_PARTIAL_SOFT WITH pcre_exec() OR pcre[16|32]_exec()" .rs .sp If PCRE_PARTIAL_SOFT is set when \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP identifies a partial match, the partial match is remembered, but matching continues as normal, and other alternatives in the pattern are tried. If no complete match can be found, PCRE_ERROR_PARTIAL is returned instead of PCRE_ERROR_NOMATCH. .P This option is "soft" because it prefers a complete match over a partial match. All the various matching items in a pattern behave as if the subject string is potentially complete. For example, \ez, \eZ, and $ match at the end of the subject, as normal, and for \eb and \eB the end of the subject is treated as a non-alphanumeric. .P If there is more than one partial match, the first one that was found provides the data that is returned. Consider this pattern: .sp /123\ew+X|dogY/ .sp If this is matched against the subject string "abc123dog", both alternatives fail to match, but the end of the subject is reached during matching, so PCRE_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying "123dog" as the first partial match that was found. (In this example, there are two partial matches, because "dog" on its own partially matches the second alternative.) . . .SS "PCRE_PARTIAL_HARD WITH pcre_exec() OR pcre[16|32]_exec()" .rs .sp If PCRE_PARTIAL_HARD is set for \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP, PCRE_ERROR_PARTIAL is returned as soon as a partial match is found, without continuing to search for possible complete matches. This option is "hard" because it prefers an earlier partial match over a later complete match. For this reason, the assumption is made that the end of the supplied subject string may not be the true end of the available data, and so, if \ez, \eZ, \eb, \eB, or $ are encountered at the end of the subject, the result is PCRE_ERROR_PARTIAL, provided that at least one character in the subject has been inspected. .P Setting PCRE_PARTIAL_HARD also affects the way UTF-8 and UTF-16 subject strings are checked for validity. Normally, an invalid sequence causes the error PCRE_ERROR_BADUTF8 or PCRE_ERROR_BADUTF16. However, in the special case of a truncated character at the end of the subject, PCRE_ERROR_SHORTUTF8 or PCRE_ERROR_SHORTUTF16 is returned when PCRE_PARTIAL_HARD is set. . . .SS "Comparing hard and soft partial matching" .rs .sp The difference between the two partial matching options can be illustrated by a pattern such as: .sp /dog(sbody)?/ .sp This matches either "dog" or "dogsbody", greedily (that is, it prefers the longer string if possible). If it is matched against the string "dog" with PCRE_PARTIAL_SOFT, it yields a complete match for "dog". However, if PCRE_PARTIAL_HARD is set, the result is PCRE_ERROR_PARTIAL. On the other hand, if the pattern is made ungreedy the result is different: .sp /dog(sbody)??/ .sp In this case the result is always a complete match because that is found first, and matching never continues after finding a complete match. It might be easier to follow this explanation by thinking of the two patterns like this: .sp /dog(sbody)?/ is the same as /dogsbody|dog/ /dog(sbody)??/ is the same as /dog|dogsbody/ .sp The second pattern will never match "dogsbody", because it will always find the shorter match first. . . .SH "PARTIAL MATCHING USING pcre_dfa_exec() OR pcre[16|32]_dfa_exec()" .rs .sp The DFA functions move along the subject string character by character, without backtracking, searching for all possible matches simultaneously. If the end of the subject is reached before the end of the pattern, there is the possibility of a partial match, again provided that at least one character has been inspected. .P When PCRE_PARTIAL_SOFT is set, PCRE_ERROR_PARTIAL is returned only if there have been no complete matches. Otherwise, the complete matches are returned. However, if PCRE_PARTIAL_HARD is set, a partial match takes precedence over any complete matches. The portion of the string that was inspected when the longest partial match was found is set as the first matching string, provided there are at least two slots in the offsets vector. .P Because the DFA functions always search for all possible matches, and there is no difference between greedy and ungreedy repetition, their behaviour is different from the standard functions when PCRE_PARTIAL_HARD is set. Consider the string "dog" matched against the ungreedy pattern shown above: .sp /dog(sbody)??/ .sp Whereas the standard functions stop as soon as they find the complete match for "dog", the DFA functions also find the partial match for "dogsbody", and so return that when PCRE_PARTIAL_HARD is set. . . .SH "PARTIAL MATCHING AND WORD BOUNDARIES" .rs .sp If a pattern ends with one of sequences \eb or \eB, which test for word boundaries, partial matching with PCRE_PARTIAL_SOFT can give counter-intuitive results. Consider this pattern: .sp /\ebcat\eb/ .sp This matches "cat", provided there is a word boundary at either end. If the subject string is "the cat", the comparison of the final "t" with a following character cannot take place, so a partial match is found. However, normal matching carries on, and \eb matches at the end of the subject when the last character is a letter, so a complete match is found. The result, therefore, is \fInot\fP PCRE_ERROR_PARTIAL. Using PCRE_PARTIAL_HARD in this case does yield PCRE_ERROR_PARTIAL, because then the partial match takes precedence. . . .SH "FORMERLY RESTRICTED PATTERNS" .rs .sp For releases of PCRE prior to 8.00, because of the way certain internal optimizations were implemented in the \fBpcre_exec()\fP function, the PCRE_PARTIAL option (predecessor of PCRE_PARTIAL_SOFT) could not be used with all patterns. From release 8.00 onwards, the restrictions no longer apply, and partial matching with can be requested for any pattern. .P Items that were formerly restricted were repeated single characters and repeated metasequences. If PCRE_PARTIAL was set for a pattern that did not conform to the restrictions, \fBpcre_exec()\fP returned the error code PCRE_ERROR_BADPARTIAL (-13). This error code is no longer in use. The PCRE_INFO_OKPARTIAL call to \fBpcre_fullinfo()\fP to find out if a compiled pattern can be used for partial matching now always returns 1. . . .SH "EXAMPLE OF PARTIAL MATCHING USING PCRETEST" .rs .sp If the escape sequence \eP is present in a \fBpcretest\fP data line, the PCRE_PARTIAL_SOFT option is used for the match. Here is a run of \fBpcretest\fP that uses the date example quoted above: .sp re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/ data> 25jun04\eP 0: 25jun04 1: jun data> 25dec3\eP Partial match: 23dec3 data> 3ju\eP Partial match: 3ju data> 3juj\eP No match data> j\eP No match .sp The first data string is matched completely, so \fBpcretest\fP shows the matched substrings. The remaining four strings do not match the complete pattern, but the first two are partial matches. Similar output is obtained if DFA matching is used. .P If the escape sequence \eP is present more than once in a \fBpcretest\fP data line, the PCRE_PARTIAL_HARD option is set for the match. . . .SH "MULTI-SEGMENT MATCHING WITH pcre_dfa_exec() OR pcre[16|32]_dfa_exec()" .rs .sp When a partial match has been found using a DFA matching function, it is possible to continue the match by providing additional subject data and calling the function again with the same compiled regular expression, this time setting the PCRE_DFA_RESTART option. You must pass the same working space as before, because this is where details of the previous partial match are stored. Here is an example using \fBpcretest\fP, using the \eR escape sequence to set the PCRE_DFA_RESTART option (\eD specifies the use of the DFA matching function): .sp re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/ data> 23ja\eP\eD Partial match: 23ja data> n05\eR\eD 0: n05 .sp The first call has "23ja" as the subject, and requests partial matching; the second call has "n05" as the subject for the continued (restarted) match. Notice that when the match is complete, only the last part is shown; PCRE does not retain the previously partially-matched string. It is up to the calling program to do that if it needs to. .P That means that, for an unanchored pattern, if a continued match fails, it is not possible to try again at a new starting point. All this facility is capable of doing is continuing with the previous match attempt. In the previous example, if the second set of data is "ug23" the result is no match, even though there would be a match for "aug23" if the entire string were given at once. Depending on the application, this may or may not be what you want. The only way to allow for starting again at the next character is to retain the matched part of the subject and try a new complete match. .P You can set the PCRE_PARTIAL_SOFT or PCRE_PARTIAL_HARD options with PCRE_DFA_RESTART to continue partial matching over multiple segments. This facility can be used to pass very long subject strings to the DFA matching functions. . . .SH "MULTI-SEGMENT MATCHING WITH pcre_exec() OR pcre[16|32]_exec()" .rs .sp From release 8.00, the standard matching functions can also be used to do multi-segment matching. Unlike the DFA functions, it is not possible to restart the previous match with a new segment of data. Instead, new data must be added to the previous subject string, and the entire match re-run, starting from the point where the partial match occurred. Earlier data can be discarded. .P It is best to use PCRE_PARTIAL_HARD in this situation, because it does not treat the end of a segment as the end of the subject when matching \ez, \eZ, \eb, \eB, and $. Consider an unanchored pattern that matches dates: .sp re> /\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed/ data> The date is 23ja\eP\eP Partial match: 23ja .sp At this stage, an application could discard the text preceding "23ja", add on text from the next segment, and call the matching function again. Unlike the DFA matching functions, the entire matching string must always be available, and the complete matching process occurs for each call, so more memory and more processing time is needed. .P \fBNote:\fP If the pattern contains lookbehind assertions, or \eK, or starts with \eb or \eB, the string that is returned for a partial match includes characters that precede the start of what would be returned for a complete match, because it contains all the characters that were inspected during the partial match. . . .SH "ISSUES WITH MULTI-SEGMENT MATCHING" .rs .sp Certain types of pattern may give problems with multi-segment matching, whichever matching function is used. .P 1. If the pattern contains a test for the beginning of a line, you need to pass the PCRE_NOTBOL option when the subject string for any call does start at the beginning of a line. There is also a PCRE_NOTEOL option, but in practice when doing multi-segment matching you should be using PCRE_PARTIAL_HARD, which includes the effect of PCRE_NOTEOL. .P 2. Lookbehind assertions that have already been obeyed are catered for in the offsets that are returned for a partial match. However a lookbehind assertion later in the pattern could require even earlier characters to be inspected. You can handle this case by using the PCRE_INFO_MAXLOOKBEHIND option of the \fBpcre_fullinfo()\fP or \fBpcre[16|32]_fullinfo()\fP functions to obtain the length of the longest lookbehind in the pattern. This length is given in characters, not bytes. If you always retain at least that many characters before the partially matched string, all should be well. (Of course, near the start of the subject, fewer characters may be present; in that case all characters should be retained.) .P From release 8.33, there is a more accurate way of deciding which characters to retain. Instead of subtracting the length of the longest lookbehind from the earliest inspected character (\fIoffsets[0]\fP), the match start position (\fIoffsets[2]\fP) should be used, and the next match attempt started at the \fIoffsets[2]\fP character by setting the \fIstartoffset\fP argument of \fBpcre_exec()\fP or \fBpcre_dfa_exec()\fP. .P For example, if the pattern "(?<=123)abc" is partially matched against the string "xx123a", the three offset values returned are 2, 6, and 5. This indicates that the matching process that gave a partial match started at offset 5, but the characters "123a" were all inspected. The maximum lookbehind for that pattern is 3, so taking that away from 5 shows that we need only keep "123a", and the next match attempt can be started at offset 3 (that is, at "a") when further characters have been added. When the match start is not the earliest inspected character, \fBpcretest\fP shows it explicitly: .sp re> "(?<=123)abc" data> xx123a\eP\eP Partial match at offset 5: 123a .P 3. Because a partial match must always contain at least one character, what might be considered a partial match of an empty string actually gives a "no match" result. For example: .sp re> /c(?<=abc)x/ data> ab\eP No match .sp If the next segment begins "cx", a match should be found, but this will only happen if characters from the previous segment are retained. For this reason, a "no match" result should be interpreted as "partial match of an empty string" when the pattern contains lookbehinds. .P 4. Matching a subject string that is split into multiple segments may not always produce exactly the same result as matching over one single long string, especially when PCRE_PARTIAL_SOFT is used. The section "Partial Matching and Word Boundaries" above describes an issue that arises if the pattern ends with \eb or \eB. Another kind of difference may occur when there are multiple matching possibilities, because (for PCRE_PARTIAL_SOFT) a partial match result is given only when there are no completed matches. This means that as soon as the shortest match has been found, continuation to a new subject segment is no longer possible. Consider again this \fBpcretest\fP example: .sp re> /dog(sbody)?/ data> dogsb\eP 0: dog data> do\eP\eD Partial match: do data> gsb\eR\eP\eD 0: g data> dogsbody\eD 0: dogsbody 1: dog .sp The first data line passes the string "dogsb" to a standard matching function, setting the PCRE_PARTIAL_SOFT option. Although the string is a partial match for "dogsbody", the result is not PCRE_ERROR_PARTIAL, because the shorter string "dog" is a complete match. Similarly, when the subject is presented to a DFA matching function in several parts ("do" and "gsb" being the first two) the match stops when "dog" has been found, and it is not possible to continue. On the other hand, if "dogsbody" is presented as a single string, a DFA matching function finds both matches. .P Because of these problems, it is best to use PCRE_PARTIAL_HARD when matching multi-segment data. The example above then behaves differently: .sp re> /dog(sbody)?/ data> dogsb\eP\eP Partial match: dogsb data> do\eP\eD Partial match: do data> gsb\eR\eP\eP\eD Partial match: gsb .sp 5. Patterns that contain alternatives at the top level which do not all start with the same pattern item may not work as expected when PCRE_DFA_RESTART is used. For example, consider this pattern: .sp 1234|3789 .sp If the first part of the subject is "ABC123", a partial match of the first alternative is found at offset 3. There is no partial match for the second alternative, because such a match does not start at the same point in the subject string. Attempting to continue with the string "7890" does not yield a match because only those alternatives that match at one point in the subject are remembered. The problem arises because the start of the second alternative matches within the first alternative. There is no problem with anchored patterns or patterns such as: .sp 1234|ABCD .sp where no string can be a partial match for both alternatives. This is not a problem if a standard matching function is used, because the entire match has to be rerun each time: .sp re> /1234|3789/ data> ABC123\eP\eP Partial match: 123 data> 1237890 0: 3789 .sp Of course, instead of using PCRE_DFA_RESTART, the same technique of re-running the entire match can also be used with the DFA matching functions. Another possibility is to work with two buffers. If a partial match at offset \fIn\fP in the first buffer is followed by "no match" when PCRE_DFA_RESTART is used on the second buffer, you can then try a new match starting at offset \fIn+1\fP in the first buffer. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 02 July 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrepattern.3 ================================================ .TH PCREPATTERN 3 "23 October 2016" "PCRE 8.40" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE REGULAR EXPRESSION DETAILS" .rs .sp The syntax and semantics of the regular expressions that are supported by PCRE are described in detail below. There is a quick-reference syntax summary in the .\" HREF \fBpcresyntax\fP .\" page. PCRE tries to match Perl syntax and semantics as closely as it can. PCRE also supports some alternative regular expression syntax (which does not conflict with the Perl syntax) in order to provide some compatibility with regular expressions in Python, .NET, and Oniguruma. .P Perl's regular expressions are described in its own documentation, and regular expressions in general are covered in a number of books, some of which have copious examples. Jeffrey Friedl's "Mastering Regular Expressions", published by O'Reilly, covers regular expressions in great detail. This description of PCRE's regular expressions is intended as reference material. .P This document discusses the patterns that are supported by PCRE when one its main matching functions, \fBpcre_exec()\fP (8-bit) or \fBpcre[16|32]_exec()\fP (16- or 32-bit), is used. PCRE also has alternative matching functions, \fBpcre_dfa_exec()\fP and \fBpcre[16|32_dfa_exec()\fP, which match using a different algorithm that is not Perl-compatible. Some of the features discussed below are not available when DFA matching is used. The advantages and disadvantages of the alternative functions, and how they differ from the normal functions, are discussed in the .\" HREF \fBpcrematching\fP .\" page. . . .SH "SPECIAL START-OF-PATTERN ITEMS" .rs .sp A number of options that can be passed to \fBpcre_compile()\fP can also be set by special items at the start of a pattern. These are not Perl-compatible, but are provided to make these options accessible to pattern writers who are not able to change the program that processes the pattern. Any number of these items may appear, but they must all be together right at the start of the pattern string, and the letters must be in upper case. . . .SS "UTF support" .rs .sp The original operation of PCRE was on strings of one-byte characters. However, there is now also support for UTF-8 strings in the original library, an extra library that supports 16-bit and UTF-16 character strings, and a third library that supports 32-bit and UTF-32 character strings. To use these features, PCRE must be built to include appropriate support. When using UTF strings you must either call the compiling function with the PCRE_UTF8, PCRE_UTF16, or PCRE_UTF32 option, or the pattern must start with one of these special sequences: .sp (*UTF8) (*UTF16) (*UTF32) (*UTF) .sp (*UTF) is a generic sequence that can be used with any of the libraries. Starting a pattern with such a sequence is equivalent to setting the relevant option. How setting a UTF mode affects pattern matching is mentioned in several places below. There is also a summary of features in the .\" HREF \fBpcreunicode\fP .\" page. .P Some applications that allow their users to supply patterns may wish to restrict them to non-UTF data for security reasons. If the PCRE_NEVER_UTF option is set at compile time, (*UTF) etc. are not allowed, and their appearance causes an error. . . .SS "Unicode property support" .rs .sp Another special sequence that may appear at the start of a pattern is (*UCP). This has the same effect as setting the PCRE_UCP option: it causes sequences such as \ed and \ew to use Unicode properties to determine character types, instead of recognizing only characters with codes less than 128 via a lookup table. . . .SS "Disabling auto-possessification" .rs .sp If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as setting the PCRE_NO_AUTO_POSSESS option at compile time. This stops PCRE from making quantifiers possessive when what follows cannot match the repeated item. For example, by default a+b is treated as a++b. For more details, see the .\" HREF \fBpcreapi\fP .\" documentation. . . .SS "Disabling start-up optimizations" .rs .sp If a pattern starts with (*NO_START_OPT), it has the same effect as setting the PCRE_NO_START_OPTIMIZE option either at compile or matching time. This disables several optimizations for quickly reaching "no match" results. For more details, see the .\" HREF \fBpcreapi\fP .\" documentation. . . .\" HTML .SS "Newline conventions" .rs .sp PCRE supports five different conventions for indicating line breaks in strings: a single CR (carriage return) character, a single LF (linefeed) character, the two-character sequence CRLF, any of the three preceding, or any Unicode newline sequence. The .\" HREF \fBpcreapi\fP .\" page has .\" HTML .\" further discussion .\" about newlines, and shows how to set the newline convention in the \fIoptions\fP arguments for the compiling and matching functions. .P It is also possible to specify a newline convention by starting a pattern string with one of the following five sequences: .sp (*CR) carriage return (*LF) linefeed (*CRLF) carriage return, followed by linefeed (*ANYCRLF) any of the three above (*ANY) all Unicode newline sequences .sp These override the default and the options given to the compiling function. For example, on a Unix system where LF is the default newline sequence, the pattern .sp (*CR)a.b .sp changes the convention to CR. That pattern matches "a\enb" because LF is no longer a newline. If more than one of these settings is present, the last one is used. .P The newline convention affects where the circumflex and dollar assertions are true. It also affects the interpretation of the dot metacharacter when PCRE_DOTALL is not set, and the behaviour of \eN. However, it does not affect what the \eR escape sequence matches. By default, this is any Unicode newline sequence, for Perl compatibility. However, this can be changed; see the description of \eR in the section entitled .\" HTML .\" "Newline sequences" .\" below. A change of \eR setting can be combined with a change of newline convention. . . .SS "Setting match and recursion limits" .rs .sp The caller of \fBpcre_exec()\fP can set a limit on the number of times the internal \fBmatch()\fP function is called and on the maximum depth of recursive calls. These facilities are provided to catch runaway matches that are provoked by patterns with huge matching trees (a typical example is a pattern with nested unlimited repeats) and to avoid running out of system stack by too much recursion. When one of these limits is reached, \fBpcre_exec()\fP gives an error return. The limits can also be set by items at the start of the pattern of the form .sp (*LIMIT_MATCH=d) (*LIMIT_RECURSION=d) .sp where d is any number of decimal digits. However, the value of the setting must be less than the value set (or defaulted) by the caller of \fBpcre_exec()\fP for it to have any effect. In other words, the pattern writer can lower the limits set by the programmer, but not raise them. If there is more than one setting of one of these limits, the lower value is used. . . .SH "EBCDIC CHARACTER CODES" .rs .sp PCRE can be compiled to run in an environment that uses EBCDIC as its character code rather than ASCII or Unicode (typically a mainframe system). In the sections below, character code values are ASCII or Unicode; in an EBCDIC environment these characters may have different code values, and there are no code points greater than 255. . . .SH "CHARACTERS AND METACHARACTERS" .rs .sp A regular expression is a pattern that is matched against a subject string from left to right. Most characters stand for themselves in a pattern, and match the corresponding characters in the subject. As a trivial example, the pattern .sp The quick brown fox .sp matches a portion of a subject string that is identical to itself. When caseless matching is specified (the PCRE_CASELESS option), letters are matched independently of case. In a UTF mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF support. .P The power of regular expressions comes from the ability to include alternatives and repetitions in the pattern. These are encoded in the pattern by the use of \fImetacharacters\fP, which do not stand for themselves but instead are interpreted in some special way. .P There are two different sets of metacharacters: those that are recognized anywhere in the pattern except within square brackets, and those that are recognized within square brackets. Outside square brackets, the metacharacters are as follows: .sp \e general escape character with several uses ^ assert start of string (or line, in multiline mode) $ assert end of string (or line, in multiline mode) . match any character except newline (by default) [ start character class definition | start of alternative branch ( start subpattern ) end subpattern ? extends the meaning of ( also 0 or 1 quantifier also quantifier minimizer * 0 or more quantifier + 1 or more quantifier also "possessive quantifier" { start min/max quantifier .sp Part of a pattern that is in square brackets is called a "character class". In a character class the only metacharacters are: .sp \e general escape character ^ negate the class, but only if the first character - indicates character range .\" JOIN [ POSIX character class (only if followed by POSIX syntax) ] terminates the character class .sp The following sections describe the use of each of the metacharacters. . . .SH BACKSLASH .rs .sp The backslash character has several uses. Firstly, if it is followed by a character that is not a number or a letter, it takes away any special meaning that character may have. This use of backslash as an escape character applies both inside and outside character classes. .P For example, if you want to match a * character, you write \e* in the pattern. This escaping action applies whether or not the following character would otherwise be interpreted as a metacharacter, so it is always safe to precede a non-alphanumeric with backslash to specify that it stands for itself. In particular, if you want to match a backslash, you write \e\e. .P In a UTF mode, only ASCII numbers and letters have any special meaning after a backslash. All other characters (in particular, those whose codepoints are greater than 127) are treated as literals. .P If a pattern is compiled with the PCRE_EXTENDED option, most white space in the pattern (other than in a character class), and characters between a # outside a character class and the next newline, inclusive, are ignored. An escaping backslash can be used to include a white space or # character as part of the pattern. .P If you want to remove the special meaning from a sequence of characters, you can do so by putting them between \eQ and \eE. This is different from Perl in that $ and @ are handled as literals in \eQ...\eE sequences in PCRE, whereas in Perl, $ and @ cause variable interpolation. Note the following examples: .sp Pattern PCRE matches Perl matches .sp .\" JOIN \eQabc$xyz\eE abc$xyz abc followed by the contents of $xyz \eQabc\e$xyz\eE abc\e$xyz abc\e$xyz \eQabc\eE\e$\eQxyz\eE abc$xyz abc$xyz .sp The \eQ...\eE sequence is recognized both inside and outside character classes. An isolated \eE that is not preceded by \eQ is ignored. If \eQ is not followed by \eE later in the pattern, the literal interpretation continues to the end of the pattern (that is, \eE is assumed at the end). If the isolated \eQ is inside a character class, this causes an error, because the character class is not terminated. . . .\" HTML .SS "Non-printing characters" .rs .sp A second use of backslash provides a way of encoding non-printing characters in patterns in a visible manner. There is no restriction on the appearance of non-printing characters, apart from the binary zero that terminates a pattern, but when a pattern is being prepared by text editing, it is often easier to use one of the following escape sequences than the binary character it represents. In an ASCII or Unicode environment, these escapes are as follows: .sp \ea alarm, that is, the BEL character (hex 07) \ecx "control-x", where x is any ASCII character \ee escape (hex 1B) \ef form feed (hex 0C) \en linefeed (hex 0A) \er carriage return (hex 0D) \et tab (hex 09) \e0dd character with octal code 0dd \eddd character with octal code ddd, or back reference \eo{ddd..} character with octal code ddd.. \exhh character with hex code hh \ex{hhh..} character with hex code hhh.. (non-JavaScript mode) \euhhhh character with hex code hhhh (JavaScript mode only) .sp The precise effect of \ecx on ASCII characters is as follows: if x is a lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus \ecA to \ecZ become hex 01 to hex 1A (A is 41, Z is 5A), but \ec{ becomes hex 3B ({ is 7B), and \ec; becomes hex 7B (; is 3B). If the data item (byte or 16-bit value) following \ec has a value greater than 127, a compile-time error occurs. This locks out non-ASCII characters in all modes. .P When PCRE is compiled in EBCDIC mode, \ea, \ee, \ef, \en, \er, and \et generate the appropriate EBCDIC code values. The \ec escape is processed as specified for Perl in the \fBperlebcdic\fP document. The only characters that are allowed after \ec are A-Z, a-z, or one of @, [, \e, ], ^, _, or ?. Any other character provokes a compile-time error. The sequence \ec@ encodes character code 0; after \ec the letters (in either case) encode characters 1-26 (hex 01 to hex 1A); [, \e, ], ^, and _ encode characters 27-31 (hex 1B to hex 1F), and \ec? becomes either 255 (hex FF) or 95 (hex 5F). .P Thus, apart from \ec?, these escapes generate the same character code values as they do in an ASCII environment, though the meanings of the values mostly differ. For example, \ecG always generates code value 7, which is BEL in ASCII but DEL in EBCDIC. .P The sequence \ec? generates DEL (127, hex 7F) in an ASCII environment, but because 127 is not a control character in EBCDIC, Perl makes it generate the APC character. Unfortunately, there are several variants of EBCDIC. In most of them the APC character has the value 255 (hex FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If certain other characters have POSIX-BC values, PCRE makes \ec? generate 95; otherwise it generates 255. .P After \e0 up to two further octal digits are read. If there are fewer than two digits, just those that are present are used. Thus the sequence \e0\ex\e015 specifies two binary zeros followed by a CR character (code value 13). Make sure you supply two digits after the initial zero if the pattern character that follows is itself an octal digit. .P The escape \eo must be followed by a sequence of octal digits, enclosed in braces. An error occurs if this is not the case. This escape is a recent addition to Perl; it provides way of specifying character code points as octal numbers greater than 0777, and it also allows octal numbers and back references to be unambiguously specified. .P For greater clarity and unambiguity, it is best to avoid following \e by a digit greater than zero. Instead, use \eo{} or \ex{} to specify character numbers, and \eg{} to specify back references. The following paragraphs describe the old, ambiguous syntax. .P The handling of a backslash followed by a digit other than 0 is complicated, and Perl has changed in recent releases, causing PCRE also to change. Outside a character class, PCRE reads the digit and any following digits as a decimal number. If the number is less than 8, or if there have been at least that many previous capturing left parentheses in the expression, the entire sequence is taken as a \fIback reference\fP. A description of how this works is given .\" HTML .\" later, .\" following the discussion of .\" HTML .\" parenthesized subpatterns. .\" .P Inside a character class, or if the decimal number following \e is greater than 7 and there have not been that many capturing subpatterns, PCRE handles \e8 and \e9 as the literal characters "8" and "9", and otherwise re-reads up to three octal digits following the backslash, using them to generate a data character. Any subsequent digits stand for themselves. For example: .sp \e040 is another way of writing an ASCII space .\" JOIN \e40 is the same, provided there are fewer than 40 previous capturing subpatterns \e7 is always a back reference .\" JOIN \e11 might be a back reference, or another way of writing a tab \e011 is always a tab \e0113 is a tab followed by the character "3" .\" JOIN \e113 might be a back reference, otherwise the character with octal code 113 .\" JOIN \e377 might be a back reference, otherwise the value 255 (decimal) .\" JOIN \e81 is either a back reference, or the two characters "8" and "1" .sp Note that octal values of 100 or greater that are specified using this syntax must not be introduced by a leading zero, because no more than three octal digits are ever read. .P By default, after \ex that is not followed by {, from zero to two hexadecimal digits are read (letters can be in upper or lower case). Any number of hexadecimal digits may appear between \ex{ and }. If a character other than a hexadecimal digit appears between \ex{ and }, or if there is no terminating }, an error occurs. .P If the PCRE_JAVASCRIPT_COMPAT option is set, the interpretation of \ex is as just described only when it is followed by two hexadecimal digits. Otherwise, it matches a literal "x" character. In JavaScript mode, support for code points greater than 256 is provided by \eu, which must be followed by four hexadecimal digits; otherwise it matches a literal "u" character. .P Characters whose value is less than 256 can be defined by either of the two syntaxes for \ex (or by \eu in JavaScript mode). There is no difference in the way they are handled. For example, \exdc is exactly the same as \ex{dc} (or \eu00dc in JavaScript mode). . . .SS "Constraints on character values" .rs .sp Characters that are specified using octal or hexadecimal numbers are limited to certain values, as follows: .sp 8-bit non-UTF mode less than 0x100 8-bit UTF-8 mode less than 0x10ffff and a valid codepoint 16-bit non-UTF mode less than 0x10000 16-bit UTF-16 mode less than 0x10ffff and a valid codepoint 32-bit non-UTF mode less than 0x100000000 32-bit UTF-32 mode less than 0x10ffff and a valid codepoint .sp Invalid Unicode codepoints are the range 0xd800 to 0xdfff (the so-called "surrogate" codepoints), and 0xffef. . . .SS "Escape sequences in character classes" .rs .sp All the sequences that define a single character value can be used both inside and outside character classes. In addition, inside a character class, \eb is interpreted as the backspace character (hex 08). .P \eN is not allowed in a character class. \eB, \eR, and \eX are not special inside a character class. Like other unrecognized escape sequences, they are treated as the literal characters "B", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set. Outside a character class, these sequences have different meanings. . . .SS "Unsupported escape sequences" .rs .sp In Perl, the sequences \el, \eL, \eu, and \eU are recognized by its string handler and used to modify the case of following characters. By default, PCRE does not support these escape sequences. However, if the PCRE_JAVASCRIPT_COMPAT option is set, \eU matches a "U" character, and \eu can be used to define a character by code point, as described in the previous section. . . .SS "Absolute and relative back references" .rs .sp The sequence \eg followed by an unsigned or a negative number, optionally enclosed in braces, is an absolute or relative back reference. A named back reference can be coded as \eg{name}. Back references are discussed .\" HTML .\" later, .\" following the discussion of .\" HTML .\" parenthesized subpatterns. .\" . . .SS "Absolute and relative subroutine calls" .rs .sp For compatibility with Oniguruma, the non-Perl syntax \eg followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative syntax for referencing a subpattern as a "subroutine". Details are discussed .\" HTML .\" later. .\" Note that \eg{...} (Perl syntax) and \eg<...> (Oniguruma syntax) are \fInot\fP synonymous. The former is a back reference; the latter is a .\" HTML .\" subroutine .\" call. . . .\" HTML .SS "Generic character types" .rs .sp Another use of backslash is for specifying generic character types: .sp \ed any decimal digit \eD any character that is not a decimal digit \eh any horizontal white space character \eH any character that is not a horizontal white space character \es any white space character \eS any character that is not a white space character \ev any vertical white space character \eV any character that is not a vertical white space character \ew any "word" character \eW any "non-word" character .sp There is also the single sequence \eN, which matches a non-newline character. This is the same as .\" HTML .\" the "." metacharacter .\" when PCRE_DOTALL is not set. Perl also uses \eN to match characters by name; PCRE does not support this. .P Each pair of lower and upper case escape sequences partitions the complete set of characters into two disjoint sets. Any given character matches one, and only one, of each pair. The sequences can appear both inside and outside character classes. They each match one character of the appropriate type. If the current matching point is at the end of the subject string, all of them fail, because there is no character to match. .P For compatibility with Perl, \es did not used to match the VT character (code 11), which made it different from the the POSIX "space" class. However, Perl added VT at release 5.18, and PCRE followed suit at release 8.34. The default \es characters are now HT (9), LF (10), VT (11), FF (12), CR (13), and space (32), which are defined as white space in the "C" locale. This list may vary if locale-specific matching is taking place. For example, in some locales the "non-breaking space" character (\exA0) is recognized as white space, and in others the VT character is not. .P A "word" character is an underscore or any character that is a letter or digit. By default, the definition of letters and digits is controlled by PCRE's low-valued character tables, and may vary if locale-specific matching is taking place (see .\" HTML .\" "Locale support" .\" in the .\" HREF \fBpcreapi\fP .\" page). For example, in a French locale such as "fr_FR" in Unix-like systems, or "french" in Windows, some character codes greater than 127 are used for accented letters, and these are then matched by \ew. The use of locales with Unicode is discouraged. .P By default, characters whose code points are greater than 127 never match \ed, \es, or \ew, and always match \eD, \eS, and \eW, although this may vary for characters in the range 128-255 when locale-specific matching is happening. These escape sequences retain their original meanings from before Unicode support was available, mainly for efficiency reasons. If PCRE is compiled with Unicode property support, and the PCRE_UCP option is set, the behaviour is changed so that Unicode properties are used to determine character types, as follows: .sp \ed any character that matches \ep{Nd} (decimal digit) \es any character that matches \ep{Z} or \eh or \ev \ew any character that matches \ep{L} or \ep{N}, plus underscore .sp The upper case escapes match the inverse sets of characters. Note that \ed matches only decimal digits, whereas \ew matches any Unicode digit, as well as any Unicode letter, and underscore. Note also that PCRE_UCP affects \eb, and \eB because they are defined in terms of \ew and \eW. Matching these sequences is noticeably slower when PCRE_UCP is set. .P The sequences \eh, \eH, \ev, and \eV are features that were added to Perl at release 5.10. In contrast to the other sequences, which match only ASCII characters by default, these always match certain high-valued code points, whether or not PCRE_UCP is set. The horizontal space characters are: .sp U+0009 Horizontal tab (HT) U+0020 Space U+00A0 Non-break space U+1680 Ogham space mark U+180E Mongolian vowel separator U+2000 En quad U+2001 Em quad U+2002 En space U+2003 Em space U+2004 Three-per-em space U+2005 Four-per-em space U+2006 Six-per-em space U+2007 Figure space U+2008 Punctuation space U+2009 Thin space U+200A Hair space U+202F Narrow no-break space U+205F Medium mathematical space U+3000 Ideographic space .sp The vertical space characters are: .sp U+000A Linefeed (LF) U+000B Vertical tab (VT) U+000C Form feed (FF) U+000D Carriage return (CR) U+0085 Next line (NEL) U+2028 Line separator U+2029 Paragraph separator .sp In 8-bit, non-UTF-8 mode, only the characters with codepoints less than 256 are relevant. . . .\" HTML .SS "Newline sequences" .rs .sp Outside a character class, by default, the escape sequence \eR matches any Unicode newline sequence. In 8-bit non-UTF-8 mode \eR is equivalent to the following: .sp (?>\er\en|\en|\ex0b|\ef|\er|\ex85) .sp This is an example of an "atomic group", details of which are given .\" HTML .\" below. .\" This particular group matches either the two-character sequence CR followed by LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (carriage return, U+000D), or NEL (next line, U+0085). The two-character sequence is treated as a single unit that cannot be split. .P In other modes, two additional characters whose codepoints are greater than 255 are added: LS (line separator, U+2028) and PS (paragraph separator, U+2029). Unicode character property support is not needed for these characters to be recognized. .P It is possible to restrict \eR to match only CR, LF, or CRLF (instead of the complete set of Unicode line endings) by setting the option PCRE_BSR_ANYCRLF either at compile time or when the pattern is matched. (BSR is an abbrevation for "backslash R".) This can be made the default when PCRE is built; if this is the case, the other behaviour can be requested via the PCRE_BSR_UNICODE option. It is also possible to specify these settings by starting a pattern string with one of the following sequences: .sp (*BSR_ANYCRLF) CR, LF, or CRLF only (*BSR_UNICODE) any Unicode newline sequence .sp These override the default and the options given to the compiling function, but they can themselves be overridden by options given to a matching function. Note that these special settings, which are not Perl-compatible, are recognized only at the very start of a pattern, and that they must be in upper case. If more than one of them is present, the last one is used. They can be combined with a change of newline convention; for example, a pattern can start with: .sp (*ANY)(*BSR_ANYCRLF) .sp They can also be combined with the (*UTF8), (*UTF16), (*UTF32), (*UTF) or (*UCP) special sequences. Inside a character class, \eR is treated as an unrecognized escape sequence, and so matches the letter "R" by default, but causes an error if PCRE_EXTRA is set. . . .\" HTML .SS Unicode character properties .rs .sp When PCRE is built with Unicode character property support, three additional escape sequences that match characters with specific properties are available. When in 8-bit non-UTF-8 mode, these sequences are of course limited to testing characters whose codepoints are less than 256, but they do work in this mode. The extra escape sequences are: .sp \ep{\fIxx\fP} a character with the \fIxx\fP property \eP{\fIxx\fP} a character without the \fIxx\fP property \eX a Unicode extended grapheme cluster .sp The property names represented by \fIxx\fP above are limited to the Unicode script names, the general category properties, "Any", which matches any character (including newline), and some special PCRE properties (described in the .\" HTML .\" next section). .\" Other Perl properties such as "InMusicalSymbols" are not currently supported by PCRE. Note that \eP{Any} does not match any characters, so always causes a match failure. .P Sets of Unicode characters are defined as belonging to certain scripts. A character from one of these sets can be matched using a script name. For example: .sp \ep{Greek} \eP{Han} .sp Those that are not part of an identified script are lumped together as "Common". The current list of scripts is: .P Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hieroglyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Shavian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi. .P Each character has exactly one Unicode general category property, specified by a two-letter abbreviation. For compatibility with Perl, negation can be specified by including a circumflex between the opening brace and the property name. For example, \ep{^Lu} is the same as \eP{Lu}. .P If only one letter is specified with \ep or \eP, it includes all the general category properties that start with that letter. In this case, in the absence of negation, the curly brackets in the escape sequence are optional; these two examples have the same effect: .sp \ep{L} \epL .sp The following general category property codes are supported: .sp C Other Cc Control Cf Format Cn Unassigned Co Private use Cs Surrogate .sp L Letter Ll Lower case letter Lm Modifier letter Lo Other letter Lt Title case letter Lu Upper case letter .sp M Mark Mc Spacing mark Me Enclosing mark Mn Non-spacing mark .sp N Number Nd Decimal number Nl Letter number No Other number .sp P Punctuation Pc Connector punctuation Pd Dash punctuation Pe Close punctuation Pf Final punctuation Pi Initial punctuation Po Other punctuation Ps Open punctuation .sp S Symbol Sc Currency symbol Sk Modifier symbol Sm Mathematical symbol So Other symbol .sp Z Separator Zl Line separator Zp Paragraph separator Zs Space separator .sp The special property L& is also supported: it matches a character that has the Lu, Ll, or Lt property, in other words, a letter that is not classified as a modifier or "other". .P The Cs (Surrogate) property applies only to characters in the range U+D800 to U+DFFF. Such characters are not valid in Unicode strings and so cannot be tested by PCRE, unless UTF validity checking has been turned off (see the discussion of PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK and PCRE_NO_UTF32_CHECK in the .\" HREF \fBpcreapi\fP .\" page). Perl does not support the Cs property. .P The long synonyms for property names that Perl supports (such as \ep{Letter}) are not supported by PCRE, nor is it permitted to prefix any of these properties with "Is". .P No character that is in the Unicode table has the Cn (unassigned) property. Instead, this property is assumed for any code point that is not in the Unicode table. .P Specifying caseless matching does not affect these escape sequences. For example, \ep{Lu} always matches only upper case letters. This is different from the behaviour of current versions of Perl. .P Matching characters by Unicode property is not fast, because PCRE has to do a multistage table lookup in order to find a character's property. That is why the traditional escape sequences such as \ed and \ew do not use Unicode properties in PCRE by default, though you can make them do so by setting the PCRE_UCP option or by starting the pattern with (*UCP). . . .SS Extended grapheme clusters .rs .sp The \eX escape matches any number of Unicode characters that form an "extended grapheme cluster", and treats the sequence as an atomic group .\" HTML .\" (see below). .\" Up to and including release 8.31, PCRE matched an earlier, simpler definition that was equivalent to .sp (?>\ePM\epM*) .sp That is, it matched a character without the "mark" property, followed by zero or more characters with the "mark" property. Characters with the "mark" property are typically non-spacing accents that affect the preceding character. .P This simple definition was extended in Unicode to include more complicated kinds of composite character by giving each character a grapheme breaking property, and creating rules that use these properties to define the boundaries of extended grapheme clusters. In releases of PCRE later than 8.31, \eX matches one of these clusters. .P \eX always matches at least one character. Then it decides whether to add additional characters according to the following rules for ending a cluster: .P 1. End at the end of the subject string. .P 2. Do not end between CR and LF; otherwise end after any control character. .P 3. Do not break Hangul (a Korean script) syllable sequences. Hangul characters are of five types: L, V, T, LV, and LVT. An L character may be followed by an L, V, LV, or LVT character; an LV or V character may be followed by a V or T character; an LVT or T character may be follwed only by a T character. .P 4. Do not end before extending characters or spacing marks. Characters with the "mark" property always have the "extend" grapheme breaking property. .P 5. Do not end after prepend characters. .P 6. Otherwise, end the cluster. . . .\" HTML .SS PCRE's additional properties .rs .sp As well as the standard Unicode properties described above, PCRE supports four more that make it possible to convert traditional escape sequences such as \ew and \es to use Unicode properties. PCRE uses these non-standard, non-Perl properties internally when PCRE_UCP is set. However, they may also be used explicitly. These properties are: .sp Xan Any alphanumeric character Xps Any POSIX space character Xsp Any Perl space character Xwd Any Perl "word" character .sp Xan matches characters that have either the L (letter) or the N (number) property. Xps matches the characters tab, linefeed, vertical tab, form feed, or carriage return, and any other character that has the Z (separator) property. Xsp is the same as Xps; it used to exclude vertical tab, for Perl compatibility, but Perl changed, and so PCRE followed at release 8.34. Xwd matches the same characters as Xan, plus underscore. .P There is another non-standard property, Xuc, which matches any character that can be represented by a Universal Character Name in C++ and other programming languages. These are the characters $, @, ` (grave accent), and all characters with Unicode code points greater than or equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that most base (ASCII) characters are excluded. (Universal Character Names are of the form \euHHHH or \eUHHHHHHHH where H is a hexadecimal digit. Note that the Xuc property does not match these sequences but the characters that they represent.) . . .\" HTML .SS "Resetting the match start" .rs .sp The escape sequence \eK causes any previously matched characters not to be included in the final matched sequence. For example, the pattern: .sp foo\eKbar .sp matches "foobar", but reports that it has matched "bar". This feature is similar to a lookbehind assertion .\" HTML .\" (described below). .\" However, in this case, the part of the subject before the real match does not have to be of fixed length, as lookbehind assertions do. The use of \eK does not interfere with the setting of .\" HTML .\" captured substrings. .\" For example, when the pattern .sp (foo)\eKbar .sp matches "foobar", the first substring is still set to "foo". .P Perl documents that the use of \eK within assertions is "not well defined". In PCRE, \eK is acted upon when it occurs inside positive assertions, but is ignored in negative assertions. Note that when a pattern such as (?=ab\eK) matches, the reported start of the match can be greater than the end of the match. . . .\" HTML .SS "Simple assertions" .rs .sp The final use of backslash is for certain simple assertions. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described .\" HTML .\" below. .\" The backslashed assertions are: .sp \eb matches at a word boundary \eB matches when not at a word boundary \eA matches at the start of the subject \eZ matches at the end of the subject also matches before a newline at the end of the subject \ez matches only at the end of the subject \eG matches at the first matching position in the subject .sp Inside a character class, \eb has a different meaning; it matches the backspace character. If any other of these assertions appears in a character class, by default it matches the corresponding literal character (for example, \eB matches the letter B). However, if the PCRE_EXTRA option is set, an "invalid escape sequence" error is generated instead. .P A word boundary is a position in the subject string where the current character and the previous character do not both match \ew or \eW (i.e. one matches \ew and the other matches \eW), or the start or end of the string if the first or last character matches \ew, respectively. In a UTF mode, the meanings of \ew and \eW can be changed by setting the PCRE_UCP option. When this is done, it also affects \eb and \eB. Neither PCRE nor Perl has a separate "start of word" or "end of word" metasequence. However, whatever follows \eb normally determines which it is. For example, the fragment \eba matches "a" at the start of a word. .P The \eA, \eZ, and \ez assertions differ from the traditional circumflex and dollar (described in the next section) in that they only ever match at the very start and end of the subject string, whatever options are set. Thus, they are independent of multiline mode. These three assertions are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options, which affect only the behaviour of the circumflex and dollar metacharacters. However, if the \fIstartoffset\fP argument of \fBpcre_exec()\fP is non-zero, indicating that matching is to start at a point other than the beginning of the subject, \eA can never match. The difference between \eZ and \ez is that \eZ matches before a newline at the end of the string as well as at the very end, whereas \ez matches only at the end. .P The \eG assertion is true only when the current matching position is at the start point of the match, as specified by the \fIstartoffset\fP argument of \fBpcre_exec()\fP. It differs from \eA when the value of \fIstartoffset\fP is non-zero. By calling \fBpcre_exec()\fP multiple times with appropriate arguments, you can mimic Perl's /g option, and it is in this kind of implementation where \eG can be useful. .P Note, however, that PCRE's interpretation of \eG, as the start of the current match, is subtly different from Perl's, which defines it as the end of the previous match. In Perl, these can be different when the previously matched string was empty. Because PCRE does just one match at a time, it cannot reproduce this behaviour. .P If all the alternatives of a pattern begin with \eG, the expression is anchored to the starting match position, and the "anchored" flag is set in the compiled regular expression. . . .SH "CIRCUMFLEX AND DOLLAR" .rs .sp The circumflex and dollar metacharacters are zero-width assertions. That is, they test for a particular condition being true without consuming any characters from the subject string. .P Outside a character class, in the default matching mode, the circumflex character is an assertion that is true only if the current matching point is at the start of the subject string. If the \fIstartoffset\fP argument of \fBpcre_exec()\fP is non-zero, circumflex can never match if the PCRE_MULTILINE option is unset. Inside a character class, circumflex has an entirely different meaning .\" HTML .\" (see below). .\" .P Circumflex need not be the first character of the pattern if a number of alternatives are involved, but it should be the first thing in each alternative in which it appears if the pattern is ever to match that branch. If all possible alternatives start with a circumflex, that is, if the pattern is constrained to match only at the start of the subject, it is said to be an "anchored" pattern. (There are also other constructs that can cause a pattern to be anchored.) .P The dollar character is an assertion that is true only if the current matching point is at the end of the subject string, or immediately before a newline at the end of the string (by default). Note, however, that it does not actually match the newline. Dollar need not be the last character of the pattern if a number of alternatives are involved, but it should be the last item in any branch in which it appears. Dollar has no special meaning in a character class. .P The meaning of dollar can be changed so that it matches only at the very end of the string, by setting the PCRE_DOLLAR_ENDONLY option at compile time. This does not affect the \eZ assertion. .P The meanings of the circumflex and dollar characters are changed if the PCRE_MULTILINE option is set. When this is the case, a circumflex matches immediately after internal newlines as well as at the start of the subject string. It does not match after a newline that ends the string. A dollar matches before any newlines in the string, as well as at the very end, when PCRE_MULTILINE is set. When newline is specified as the two-character sequence CRLF, isolated CR and LF characters do not indicate newlines. .P For example, the pattern /^abc$/ matches the subject string "def\enabc" (where \en represents a newline) in multiline mode, but not otherwise. Consequently, patterns that are anchored in single line mode because all branches start with ^ are not anchored in multiline mode, and a match for circumflex is possible when the \fIstartoffset\fP argument of \fBpcre_exec()\fP is non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. .P Note that the sequences \eA, \eZ, and \ez can be used to match the start and end of the subject in both modes, and if all branches of a pattern start with \eA it is always anchored, whether or not PCRE_MULTILINE is set. . . .\" HTML .SH "FULL STOP (PERIOD, DOT) AND \eN" .rs .sp Outside a character class, a dot in the pattern matches any one character in the subject string except (by default) a character that signifies the end of a line. .P When a line ending is defined as a single character, dot never matches that character; when the two-character sequence CRLF is used, dot does not match CR if it is immediately followed by LF, but otherwise it matches all characters (including isolated CRs and LFs). When any Unicode line endings are being recognized, dot does not match CR or LF or any of the other line ending characters. .P The behaviour of dot with regard to newlines can be changed. If the PCRE_DOTALL option is set, a dot matches any one character, without exception. If the two-character sequence CRLF is present in the subject string, it takes two dots to match it. .P The handling of dot is entirely independent of the handling of circumflex and dollar, the only relationship being that they both involve newlines. Dot has no special meaning in a character class. .P The escape sequence \eN behaves like a dot, except that it is not affected by the PCRE_DOTALL option. In other words, it matches any character except one that signifies the end of a line. Perl also uses \eN to match characters by name; PCRE does not support this. . . .SH "MATCHING A SINGLE DATA UNIT" .rs .sp Outside a character class, the escape sequence \eC matches any one data unit, whether or not a UTF mode is set. In the 8-bit library, one data unit is one byte; in the 16-bit library it is a 16-bit unit; in the 32-bit library it is a 32-bit unit. Unlike a dot, \eC always matches line-ending characters. The feature is provided in Perl in order to match individual bytes in UTF-8 mode, but it is unclear how it can usefully be used. Because \eC breaks up characters into individual data units, matching one unit with \eC in a UTF mode means that the rest of the string may start with a malformed UTF character. This has undefined results, because PCRE assumes that it is dealing with valid UTF strings (and by default it checks this at the start of processing unless the PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK or PCRE_NO_UTF32_CHECK option is used). .P PCRE does not allow \eC to appear in lookbehind assertions .\" HTML .\" (described below) .\" in a UTF mode, because this would make it impossible to calculate the length of the lookbehind. .P In general, the \eC escape sequence is best avoided. However, one way of using it that avoids the problem of malformed UTF characters is to use a lookahead to check the length of the next character, as in this pattern, which could be used with a UTF-8 string (ignore white space and line breaks): .sp (?| (?=[\ex00-\ex7f])(\eC) | (?=[\ex80-\ex{7ff}])(\eC)(\eC) | (?=[\ex{800}-\ex{ffff}])(\eC)(\eC)(\eC) | (?=[\ex{10000}-\ex{1fffff}])(\eC)(\eC)(\eC)(\eC)) .sp A group that starts with (?| resets the capturing parentheses numbers in each alternative (see .\" HTML .\" "Duplicate Subpattern Numbers" .\" below). The assertions at the start of each branch check the next UTF-8 character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The character's individual bytes are then captured by the appropriate number of groups. . . .\" HTML .SH "SQUARE BRACKETS AND CHARACTER CLASSES" .rs .sp An opening square bracket introduces a character class, terminated by a closing square bracket. A closing square bracket on its own is not special by default. However, if the PCRE_JAVASCRIPT_COMPAT option is set, a lone closing square bracket causes a compile-time error. If a closing square bracket is required as a member of the class, it should be the first data character in the class (after an initial circumflex, if present) or escaped with a backslash. .P A character class matches a single character in the subject. In a UTF mode, the character may be more than one data unit long. A matched character must be in the set of characters defined by the class, unless the first character in the class definition is a circumflex, in which case the subject character must not be in the set defined by the class. If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash. .P For example, the character class [aeiou] matches any lower case vowel, while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient notation for specifying the characters that are in the class by enumerating those that are not. A class that starts with a circumflex is not an assertion; it still consumes a character from the subject string, and therefore it fails if the current pointer is at the end of the string. .P In UTF-8 (UTF-16, UTF-32) mode, characters with values greater than 255 (0xffff) can be included in a class as a literal string of data units, or by using the \ex{ escaping mechanism. .P When caseless matching is set, any letters in a class represent both their upper case and lower case versions, so for example, a caseless [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not match "A", whereas a caseful version would. In a UTF mode, PCRE always understands the concept of case for characters whose values are less than 128, so caseless matching is always possible. For characters with higher values, the concept of case is supported if PCRE is compiled with Unicode property support, but not otherwise. If you want to use caseless matching in a UTF mode for characters 128 and above, you must ensure that PCRE is compiled with Unicode property support as well as with UTF support. .P Characters that might indicate line breaks are never treated in any special way when matching character classes, whatever line-ending sequence is in use, and whatever setting of the PCRE_DOTALL and PCRE_MULTILINE options is used. A class such as [^a] always matches one of these characters. .P The minus (hyphen) character can be used to specify a range of characters in a character class. For example, [d-m] matches any letter between d and m, inclusive. If a minus character is required in a class, it must be escaped with a backslash or appear in a position where it cannot be interpreted as indicating a range, typically as the first or last character in the class, or immediately after a range. For example, [b-d-z] matches letters in the range b to d, a hyphen character, or z. .P It is not possible to have the literal character "]" as the end character of a range. A pattern such as [W-]46] is interpreted as a class of two characters ("W" and "-") followed by a literal string "46]", so it would match "W46]" or "-46]". However, if the "]" is escaped with a backslash it is interpreted as the end of range, so [W-\e]46] is interpreted as a class containing a range followed by two other characters. The octal or hexadecimal representation of "]" can also be used to end a range. .P An error is generated if a POSIX character class (see below) or an escape sequence other than one that defines a single character appears at a point where a range ending character is expected. For example, [z-\exff] is valid, but [A-\ed] and [A-[:digit:]] are not. .P Ranges operate in the collating sequence of character values. They can also be used for characters specified numerically, for example [\e000-\e037]. Ranges can include any characters that are valid for the current mode. .P If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, [W-c] is equivalent to [][\e\e^_`wxyzabc], matched caselessly, and in a non-UTF mode, if character tables for a French locale are in use, [\exc8-\excb] matches accented E characters in both cases. In UTF modes, PCRE supports the concept of case for characters with values greater than 128 only when it is compiled with Unicode property support. .P The character escape sequences \ed, \eD, \eh, \eH, \ep, \eP, \es, \eS, \ev, \eV, \ew, and \eW may appear in a character class, and add the characters that they match to the class. For example, [\edABCDEF] matches any hexadecimal digit. In UTF modes, the PCRE_UCP option affects the meanings of \ed, \es, \ew and their upper case partners, just as it does when they appear outside a character class, as described in the section entitled .\" HTML .\" "Generic character types" .\" above. The escape sequence \eb has a different meaning inside a character class; it matches the backspace character. The sequences \eB, \eN, \eR, and \eX are not special inside a character class. Like any other unrecognized escape sequences, they are treated as the literal characters "B", "N", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set. .P A circumflex can conveniently be used with the upper case character types to specify a more restricted set of characters than the matching lower case type. For example, the class [^\eW_] matches any letter or digit, but not underscore, whereas [\ew] includes underscore. A positive character class should be read as "something OR something OR ..." and a negative class as "NOT something AND NOT something AND NOT ...". .P The only metacharacters that are recognized in character classes are backslash, hyphen (only where it can be interpreted as specifying a range), circumflex (only at the start), opening square bracket (only when it can be interpreted as introducing a POSIX class name, or for a special compatibility feature - see the next two sections), and the terminating closing square bracket. However, escaping other non-alphanumeric characters does no harm. . . .SH "POSIX CHARACTER CLASSES" .rs .sp Perl supports the POSIX notation for character classes. This uses names enclosed by [: and :] within the enclosing square brackets. PCRE also supports this notation. For example, .sp [01[:alpha:]%] .sp matches "0", "1", any alphabetic character, or "%". The supported class names are: .sp alnum letters and digits alpha letters ascii character codes 0 - 127 blank space or tab only cntrl control characters digit decimal digits (same as \ed) graph printing characters, excluding space lower lower case letters print printing characters, including space punct printing characters, excluding letters and digits and space space white space (the same as \es from PCRE 8.34) upper upper case letters word "word" characters (same as \ew) xdigit hexadecimal digits .sp The default "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13), and space (32). If locale-specific matching is taking place, the list of space characters may be different; there may be fewer or more of them. "Space" used to be different to \es, which did not include VT, for Perl compatibility. However, Perl changed at release 5.18, and PCRE followed at release 8.34. "Space" and \es now match the same set of characters. .P The name "word" is a Perl extension, and "blank" is a GNU extension from Perl 5.8. Another Perl extension is negation, which is indicated by a ^ character after the colon. For example, .sp [12[:^digit:]] .sp matches "1", "2", or any non-digit. PCRE (and Perl) also recognize the POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not supported, and an error is given if they are encountered. .P By default, characters with values greater than 128 do not match any of the POSIX character classes. However, if the PCRE_UCP option is passed to \fBpcre_compile()\fP, some of the classes are changed so that Unicode character properties are used. This is achieved by replacing certain POSIX classes by other sequences, as follows: .sp [:alnum:] becomes \ep{Xan} [:alpha:] becomes \ep{L} [:blank:] becomes \eh [:digit:] becomes \ep{Nd} [:lower:] becomes \ep{Ll} [:space:] becomes \ep{Xps} [:upper:] becomes \ep{Lu} [:word:] becomes \ep{Xwd} .sp Negated versions, such as [:^alpha:] use \eP instead of \ep. Three other POSIX classes are handled specially in UCP mode: .TP 10 [:graph:] This matches characters that have glyphs that mark the page when printed. In Unicode property terms, it matches all characters with the L, M, N, P, S, or Cf properties, except for: .sp U+061C Arabic Letter Mark U+180E Mongolian Vowel Separator U+2066 - U+2069 Various "isolate"s .sp .TP 10 [:print:] This matches the same characters as [:graph:] plus space characters that are not controls, that is, characters with the Zs property. .TP 10 [:punct:] This matches all characters that have the Unicode P (punctuation) property, plus those characters whose code points are less than 128 that have the S (Symbol) property. .P The other POSIX classes are unchanged, and match only characters with code points less than 128. . . .SH "COMPATIBILITY FEATURE FOR WORD BOUNDARIES" .rs .sp In the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word" and "end of word". PCRE treats these items as follows: .sp [[:<:]] is converted to \eb(?=\ew) [[:>:]] is converted to \eb(?<=\ew) .sp Only these exact character sequences are recognized. A sequence such as [a[:<:]b] provokes error for an unrecognized POSIX class name. This support is not compatible with Perl. It is provided to help migrations from other environments, and is best not used in any new patterns. Note that \eb matches at the start and the end of a word (see .\" HTML .\" "Simple assertions" .\" above), and in a Perl-style pattern the preceding or following character normally shows which is wanted, without the need for the assertions that are used above in order to give exactly the POSIX behaviour. . . .SH "VERTICAL BAR" .rs .sp Vertical bar characters are used to separate alternative patterns. For example, the pattern .sp gilbert|sullivan .sp matches either "gilbert" or "sullivan". Any number of alternatives may appear, and an empty alternative is permitted (matching the empty string). The matching process tries each alternative in turn, from left to right, and the first one that succeeds is used. If the alternatives are within a subpattern .\" HTML .\" (defined below), .\" "succeeds" means matching the rest of the main pattern as well as the alternative in the subpattern. . . .SH "INTERNAL OPTION SETTING" .rs .sp The settings of the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and PCRE_EXTENDED options (which are Perl-compatible) can be changed from within the pattern by a sequence of Perl option letters enclosed between "(?" and ")". The option letters are .sp i for PCRE_CASELESS m for PCRE_MULTILINE s for PCRE_DOTALL x for PCRE_EXTENDED .sp For example, (?im) sets caseless, multiline matching. It is also possible to unset these options by preceding the letter with a hyphen, and a combined setting and unsetting such as (?im-sx), which sets PCRE_CASELESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED, is also permitted. If a letter appears both before and after the hyphen, the option is unset. .P The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA can be changed in the same way as the Perl-compatible options by using the characters J, U and X respectively. .P When one of these option changes occurs at top level (that is, not inside subpattern parentheses), the change applies to the remainder of the pattern that follows. An option change within a subpattern (see below for a description of subpatterns) affects only that part of the subpattern that follows it, so .sp (a(?i)b)c .sp matches abc and aBc and no other strings (assuming PCRE_CASELESS is not used). By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example, .sp (a(?i)b|c) .sp matches "ab", "aB", "c", and "C", even though when matching "C" the first branch is abandoned before the option setting. This is because the effects of option settings happen at compile time. There would be some very weird behaviour otherwise. .P \fBNote:\fP There are other PCRE-specific options that can be set by the application when the compiling or matching functions are called. In some cases the pattern can contain special leading sequences such as (*CRLF) to override what the application has set or what has been defaulted. Details are given in the section entitled .\" HTML .\" "Newline sequences" .\" above. There are also the (*UTF8), (*UTF16),(*UTF32), and (*UCP) leading sequences that can be used to set UTF and Unicode property modes; they are equivalent to setting the PCRE_UTF8, PCRE_UTF16, PCRE_UTF32 and the PCRE_UCP options, respectively. The (*UTF) sequence is a generic version that can be used with any of the libraries. However, the application can set the PCRE_NEVER_UTF option, which locks out the use of the (*UTF) sequences. . . .\" HTML .SH SUBPATTERNS .rs .sp Subpatterns are delimited by parentheses (round brackets), which can be nested. Turning part of a pattern into a subpattern does two things: .sp 1. It localizes a set of alternatives. For example, the pattern .sp cat(aract|erpillar|) .sp matches "cataract", "caterpillar", or "cat". Without the parentheses, it would match "cataract", "erpillar" or an empty string. .sp 2. It sets up the subpattern as a capturing subpattern. This means that, when the whole pattern matches, that portion of the subject string that matched the subpattern is passed back to the caller via the \fIovector\fP argument of the matching function. (This applies only to the traditional matching functions; the DFA matching functions do not support capturing.) .P Opening parentheses are counted from left to right (starting from 1) to obtain numbers for the capturing subpatterns. For example, if the string "the red king" is matched against the pattern .sp the ((red|white) (king|queen)) .sp the captured substrings are "red king", "red", and "king", and are numbered 1, 2, and 3, respectively. .P The fact that plain parentheses fulfil two functions is not always helpful. There are often times when a grouping subpattern is required without a capturing requirement. If an opening parenthesis is followed by a question mark and a colon, the subpattern does not do any capturing, and is not counted when computing the number of any subsequent capturing subpatterns. For example, if the string "the white queen" is matched against the pattern .sp the ((?:red|white) (king|queen)) .sp the captured substrings are "white queen" and "queen", and are numbered 1 and 2. The maximum number of capturing subpatterns is 65535. .P As a convenient shorthand, if any option settings are required at the start of a non-capturing subpattern, the option letters may appear between the "?" and the ":". Thus the two patterns .sp (?i:saturday|sunday) (?:(?i)saturday|sunday) .sp match exactly the same set of strings. Because alternative branches are tried from left to right, and options are not reset until the end of the subpattern is reached, an option setting in one branch does affect subsequent branches, so the above patterns match "SUNDAY" as well as "Saturday". . . .\" HTML .SH "DUPLICATE SUBPATTERN NUMBERS" .rs .sp Perl 5.10 introduced a feature whereby each alternative in a subpattern uses the same numbers for its capturing parentheses. Such a subpattern starts with (?| and is itself a non-capturing subpattern. For example, consider this pattern: .sp (?|(Sat)ur|(Sun))day .sp Because the two alternatives are inside a (?| group, both sets of capturing parentheses are numbered one. Thus, when the pattern matches, you can look at captured substring number one, whichever alternative matched. This construct is useful when you want to capture part, but not all, of one of a number of alternatives. Inside a (?| group, parentheses are numbered as usual, but the number is reset at the start of each branch. The numbers of any capturing parentheses that follow the subpattern start after the highest number used in any branch. The following example is taken from the Perl documentation. The numbers underneath show in which buffer the captured content will be stored. .sp # before ---------------branch-reset----------- after / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x # 1 2 2 3 2 3 4 .sp A back reference to a numbered subpattern uses the most recent value that is set for that number by any subpattern. The following pattern matches "abcabc" or "defdef": .sp /(?|(abc)|(def))\e1/ .sp In contrast, a subroutine call to a numbered subpattern always refers to the first one in the pattern with the given number. The following pattern matches "abcabc" or "defabc": .sp /(?|(abc)|(def))(?1)/ .sp If a .\" HTML .\" condition test .\" for a subpattern's having matched refers to a non-unique number, the test is true if any of the subpatterns of that number have matched. .P An alternative approach to using this "branch reset" feature is to use duplicate named subpatterns, as described in the next section. . . .SH "NAMED SUBPATTERNS" .rs .sp Identifying capturing parentheses by number is simple, but it can be very hard to keep track of the numbers in complicated regular expressions. Furthermore, if an expression is modified, the numbers may change. To help with this difficulty, PCRE supports the naming of subpatterns. This feature was not added to Perl until release 5.10. Python had the feature earlier, and PCRE introduced it at release 4.0, using the Python syntax. PCRE now supports both the Perl and the Python syntax. Perl allows identically numbered subpatterns to have different names, but PCRE does not. .P In PCRE, a subpattern can be named in one of three ways: (?...) or (?'name'...) as in Perl, or (?P...) as in Python. References to capturing parentheses from other parts of the pattern, such as .\" HTML .\" back references, .\" .\" HTML .\" recursion, .\" and .\" HTML .\" conditions, .\" can be made by name as well as by number. .P Names consist of up to 32 alphanumeric characters and underscores, but must start with a non-digit. Named capturing parentheses are still allocated numbers as well as names, exactly as if the names were not present. The PCRE API provides function calls for extracting the name-to-number translation table from a compiled pattern. There is also a convenience function for extracting a captured substring by name. .P By default, a name must be unique within a pattern, but it is possible to relax this constraint by setting the PCRE_DUPNAMES option at compile time. (Duplicate names are also always permitted for subpatterns with the same number, set up as described in the previous section.) Duplicate names can be useful for patterns where only one instance of the named parentheses can match. Suppose you want to match the name of a weekday, either as a 3-letter abbreviation or as the full name, and in both cases you want to extract the abbreviation. This pattern (ignoring the line breaks) does the job: .sp (?Mon|Fri|Sun)(?:day)?| (?Tue)(?:sday)?| (?Wed)(?:nesday)?| (?Thu)(?:rsday)?| (?Sat)(?:urday)? .sp There are five capturing substrings, but only one is ever set after a match. (An alternative way of solving this problem is to use a "branch reset" subpattern, as described in the previous section.) .P The convenience function for extracting the data by name returns the substring for the first (and in this example, the only) subpattern of that name that matched. This saves searching to find which numbered subpattern it was. .P If you make a back reference to a non-unique named subpattern from elsewhere in the pattern, the subpatterns to which the name refers are checked in the order in which they appear in the overall pattern. The first one that is set is used for the reference. For example, this pattern matches both "foofoo" and "barbar" but not "foobar" or "barfoo": .sp (?:(?foo)|(?bar))\ek .sp .P If you make a subroutine call to a non-unique named subpattern, the one that corresponds to the first occurrence of the name is used. In the absence of duplicate numbers (see the previous section) this is the one with the lowest number. .P If you use a named reference in a condition test (see the .\" .\" HTML .\" section about conditions .\" below), either to check whether a subpattern has matched, or to check for recursion, all subpatterns with the same name are tested. If the condition is true for any one of them, the overall condition is true. This is the same behaviour as testing by number. For further details of the interfaces for handling named subpatterns, see the .\" HREF \fBpcreapi\fP .\" documentation. .P \fBWarning:\fP You cannot use different names to distinguish between two subpatterns with the same number because PCRE uses only the numbers when matching. For this reason, an error is given at compile time if different names are given to subpatterns with the same number. However, you can always give the same name to subpatterns with the same number, even when PCRE_DUPNAMES is not set. . . .SH REPETITION .rs .sp Repetition is specified by quantifiers, which can follow any of the following items: .sp a literal data character the dot metacharacter the \eC escape sequence the \eX escape sequence the \eR escape sequence an escape such as \ed or \epL that matches a single character a character class a back reference (see next section) a parenthesized subpattern (including assertions) a subroutine call to a subpattern (recursive or otherwise) .sp The general repetition quantifier specifies a minimum and maximum number of permitted matches, by giving the two numbers in curly brackets (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: .sp z{2,4} .sp matches "zz", "zzz", or "zzzz". A closing brace on its own is not a special character. If the second number is omitted, but the comma is present, there is no upper limit; if the second number and the comma are both omitted, the quantifier specifies an exact number of required matches. Thus .sp [aeiou]{3,} .sp matches at least 3 successive vowels, but may match many more, while .sp \ed{8} .sp matches exactly 8 digits. An opening curly bracket that appears in a position where a quantifier is not allowed, or one that does not match the syntax of a quantifier, is taken as a literal character. For example, {,6} is not a quantifier, but a literal string of four characters. .P In UTF modes, quantifiers apply to characters rather than to individual data units. Thus, for example, \ex{100}{2} matches two characters, each of which is represented by a two-byte sequence in a UTF-8 string. Similarly, \eX{3} matches three Unicode extended grapheme clusters, each of which may be several data units long (and they may be of different lengths). .P The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. This may be useful for subpatterns that are referenced as .\" HTML .\" subroutines .\" from elsewhere in the pattern (but see also the section entitled .\" HTML .\" "Defining subpatterns for use by reference only" .\" below). Items other than subpatterns that have a {0} quantifier are omitted from the compiled pattern. .P For convenience, the three most common quantifiers have single-character abbreviations: .sp * is equivalent to {0,} + is equivalent to {1,} ? is equivalent to {0,1} .sp It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: .sp (a?)* .sp Earlier versions of Perl and PCRE used to give an error at compile time for such patterns. However, because there are cases where this can be useful, such patterns are now accepted, but if any repetition of the subpattern does in fact match no characters, the loop is forcibly broken. .P By default, the quantifiers are "greedy", that is, they match as much as possible (up to the maximum number of permitted times), without causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These appear between /* and */ and within the comment, individual * and / characters may appear. An attempt to match C comments by applying the pattern .sp /\e*.*\e*/ .sp to the string .sp /* first comment */ not comment /* second comment */ .sp fails, because it matches the entire string owing to the greediness of the .* item. .P However, if a quantifier is followed by a question mark, it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern .sp /\e*.*?\e*/ .sp does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in .sp \ed??\ed .sp which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches. .P If the PCRE_UNGREEDY option is set (an option that is not available in Perl), the quantifiers are not greedy by default, but individual ones can be made greedy by following them with a question mark. In other words, it inverts the default behaviour. .P When a parenthesized subpattern is quantified with a minimum repeat count that is greater than 1 or with a limited maximum, more memory is required for the compiled pattern, in proportion to the size of the minimum or maximum. .P If a pattern starts with .* or .{0,} and the PCRE_DOTALL option (equivalent to Perl's /s) is set, thus allowing the dot to match newlines, the pattern is implicitly anchored, because whatever follows will be tried against every character position in the subject string, so there is no point in retrying the overall match at any position after the first. PCRE normally treats such a pattern as though it were preceded by \eA. .P In cases where it is known that the subject string contains no newlines, it is worth setting PCRE_DOTALL in order to obtain this optimization, or alternatively using ^ to indicate anchoring explicitly. .P However, there are some cases where the optimization cannot be used. When .* is inside capturing parentheses that are the subject of a back reference elsewhere in the pattern, a match at the start may fail where a later one succeeds. Consider, for example: .sp (.*)abc\e1 .sp If the subject is "xyz123abc123" the match point is the fourth character. For this reason, such a pattern is not implicitly anchored. .P Another case where implicit anchoring is not applied is when the leading .* is inside an atomic group. Once again, a match at the start may fail where a later one succeeds. Consider this pattern: .sp (?>.*?a)b .sp It matches "ab" in the subject "aab". The use of the backtracking control verbs (*PRUNE) and (*SKIP) also disable this optimization. .P When a capturing subpattern is repeated, the value captured is the substring that matched the final iteration. For example, after .sp (tweedle[dume]{3}\es*)+ .sp has matched "tweedledum tweedledee" the value of the captured substring is "tweedledee". However, if there are nested capturing subpatterns, the corresponding captured values may have been set in previous iterations. For example, after .sp /(a|(b))+/ .sp matches "aba" the value of the second captured substring is "b". . . .\" HTML .SH "ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS" .rs .sp With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy") repetition, failure of what follows normally causes the repeated item to be re-evaluated to see if a different number of repeats allows the rest of the pattern to match. Sometimes it is useful to prevent this, either to change the nature of the match, or to cause it fail earlier than it otherwise might, when the author of the pattern knows there is no point in carrying on. .P Consider, for example, the pattern \ed+foo when applied to the subject line .sp 123456bar .sp After matching all 6 digits and then failing to match "foo", the normal action of the matcher is to try again with only 5 digits matching the \ed+ item, and then with 4, and so on, before ultimately failing. "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides the means for specifying that once a subpattern has matched, it is not to be re-evaluated in this way. .P If we use atomic grouping for the previous example, the matcher gives up immediately on failing to match "foo" the first time. The notation is a kind of special parenthesis, starting with (?> as in this example: .sp (?>\ed+)foo .sp This kind of parenthesis "locks up" the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal. .P An alternative description is that a subpattern of this type matches the string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string. .P Atomic grouping subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both \ed+ and \ed+? are prepared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\ed+) can only match an entire sequence of digits. .P Atomic groups in general can of course contain arbitrarily complicated subpatterns, and can be nested. However, when the subpattern for an atomic group is just a single repeated item, as in the example above, a simpler notation, called a "possessive quantifier" can be used. This consists of an additional + character following a quantifier. Using this notation, the previous example can be rewritten as .sp \ed++foo .sp Note that a possessive quantifier can be used with an entire group, for example: .sp (abc|xyz){2,3}+ .sp Possessive quantifiers are always greedy; the setting of the PCRE_UNGREEDY option is ignored. They are a convenient notation for the simpler forms of atomic group. However, there is no difference in the meaning of a possessive quantifier and the equivalent atomic group, though there may be a performance difference; possessive quantifiers should be slightly faster. .P The possessive quantifier syntax is an extension to the Perl 5.8 syntax. Jeffrey Friedl originated the idea (and the name) in the first edition of his book. Mike McCloskey liked it, so implemented it when he built Sun's Java package, and PCRE copied it from there. It ultimately found its way into Perl at release 5.10. .P PCRE has an optimization that automatically "possessifies" certain simple pattern constructs. For example, the sequence A+B is treated as A++B because there is no point in backtracking into a sequence of A's when B must follow. .P When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of an atomic group is the only way to avoid some failing matches taking a very long time indeed. The pattern .sp (\eD+|<\ed+>)*[!?] .sp matches an unlimited number of substrings that either consist of non-digits, or digits enclosed in <>, followed by either ! or ?. When it matches, it runs quickly. However, if it is applied to .sp aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .sp it takes a long time before reporting failure. This is because the string can be divided between the internal \eD+ repeat and the external * repeat in a large number of ways, and all have to be tried. (The example uses [!?] rather than a single character at the end, because both PCRE and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single character that is required for a match, and fail early if it is not present in the string.) If the pattern is changed so that it uses an atomic group, like this: .sp ((?>\eD+)|<\ed+>)*[!?] .sp sequences of non-digits cannot be broken, and failure happens quickly. . . .\" HTML .SH "BACK REFERENCES" .rs .sp Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing subpattern earlier (that is, to its left) in the pattern, provided there have been that many previous capturing left parentheses. .P However, if the decimal number following the backslash is less than 10, it is always taken as a back reference, and causes an error only if there are not that many capturing left parentheses in the entire pattern. In other words, the parentheses that are referenced need not be to the left of the reference for numbers less than 10. A "forward back reference" of this type can make sense when a repetition is involved and the subpattern to the right has participated in an earlier iteration. .P It is not possible to have a numerical "forward back reference" to a subpattern whose number is 10 or more using this syntax because a sequence such as \e50 is interpreted as a character defined in octal. See the subsection entitled "Non-printing characters" .\" HTML .\" above .\" for further details of the handling of digits following a backslash. There is no such problem when named parentheses are used. A back reference to any subpattern is possible using named parentheses (see below). .P Another way of avoiding the ambiguity inherent in the use of digits following a backslash is to use the \eg escape sequence. This escape must be followed by an unsigned number or a negative number, optionally enclosed in braces. These examples are all identical: .sp (ring), \e1 (ring), \eg1 (ring), \eg{1} .sp An unsigned number specifies an absolute reference without the ambiguity that is present in the older syntax. It is also useful when literal digits follow the reference. A negative number is a relative reference. Consider this example: .sp (abc(def)ghi)\eg{-1} .sp The sequence \eg{-1} is a reference to the most recently started capturing subpattern before \eg, that is, is it equivalent to \e2 in this example. Similarly, \eg{-2} would be equivalent to \e1. The use of relative references can be helpful in long patterns, and also in patterns that are created by joining together fragments that contain references within themselves. .P A back reference matches whatever actually matched the capturing subpattern in the current subject string, rather than anything matching the subpattern itself (see .\" HTML .\" "Subpatterns as subroutines" .\" below for a way of doing that). So the pattern .sp (sens|respons)e and \e1ibility .sp matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If caseful matching is in force at the time of the back reference, the case of letters is relevant. For example, .sp ((?i)rah)\es+\e1 .sp matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original capturing subpattern is matched caselessly. .P There are several different ways of writing back references to named subpatterns. The .NET syntax \ek{name} and the Perl syntax \ek or \ek'name' are supported, as is the Python syntax (?P=name). Perl 5.10's unified back reference syntax, in which \eg can be used for both numeric and named references, is also supported. We could rewrite the above example in any of the following ways: .sp (?(?i)rah)\es+\ek (?'p1'(?i)rah)\es+\ek{p1} (?P(?i)rah)\es+(?P=p1) (?(?i)rah)\es+\eg{p1} .sp A subpattern that is referenced by name may appear in the pattern before or after the reference. .P There may be more than one back reference to the same subpattern. If a subpattern has not actually been used in a particular match, any back references to it always fail by default. For example, the pattern .sp (a|(bc))\e2 .sp always fails if it starts to match "a" rather than "bc". However, if the PCRE_JAVASCRIPT_COMPAT option is set at compile time, a back reference to an unset value matches an empty string. .P Because there may be many capturing parentheses in a pattern, all digits following a backslash are taken as part of a potential back reference number. If the pattern continues with a digit character, some delimiter must be used to terminate the back reference. If the PCRE_EXTENDED option is set, this can be white space. Otherwise, the \eg{ syntax or an empty comment (see .\" HTML .\" "Comments" .\" below) can be used. . .SS "Recursive back references" .rs .sp A back reference that occurs inside the parentheses to which it refers fails when the subpattern is first used, so, for example, (a\e1) never matches. However, such references can be useful inside repeated subpatterns. For example, the pattern .sp (a|b\e1)+ .sp matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration of the subpattern, the back reference matches the character string corresponding to the previous iteration. In order for this to work, the pattern must be such that the first iteration does not need to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero. .P Back references of this type cause the group that they reference to be treated as an .\" HTML .\" atomic group. .\" Once the whole group has been matched, a subsequent matching failure cannot cause backtracking into the middle of the group. . . .\" HTML .SH ASSERTIONS .rs .sp An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters. The simple assertions coded as \eb, \eB, \eA, \eG, \eZ, \ez, ^ and $ are described .\" HTML .\" above. .\" .P More complicated assertions are coded as subpatterns. There are two kinds: those that look ahead of the current position in the subject string, and those that look behind it. An assertion subpattern is matched in the normal way, except that it does not cause the current matching position to be changed. .P Assertion subpatterns are not capturing subpatterns. If such an assertion contains capturing subpatterns within it, these are counted for the purposes of numbering the capturing subpatterns in the whole pattern. However, substring capturing is carried out only for positive assertions. (Perl sometimes, but not always, does do capturing in negative assertions.) .P WARNING: If a positive assertion containing one or more capturing subpatterns succeeds, but failure to match later in the pattern causes backtracking over this assertion, the captures within the assertion are reset only if no higher numbered captures are already set. This is, unfortunately, a fundamental limitation of the current implementation, and as PCRE1 is now in maintenance-only status, it is unlikely ever to change. .P For compatibility with Perl, assertion subpatterns may be repeated; though it makes no sense to assert the same thing several times, the side effect of capturing parentheses may occasionally be useful. In practice, there only three cases: .sp (1) If the quantifier is {0}, the assertion is never obeyed during matching. However, it may contain internal capturing parenthesized groups that are called from elsewhere via the .\" HTML .\" subroutine mechanism. .\" .sp (2) If quantifier is {0,n} where n is greater than zero, it is treated as if it were {0,1}. At run time, the rest of the pattern match is tried with and without the assertion, the order depending on the greediness of the quantifier. .sp (3) If the minimum repetition is greater than zero, the quantifier is ignored. The assertion is obeyed just once when encountered during matching. . . .SS "Lookahead assertions" .rs .sp Lookahead assertions start with (?= for positive assertions and (?! for negative assertions. For example, .sp \ew+(?=;) .sp matches a word followed by a semicolon, but does not include the semicolon in the match, and .sp foo(?!bar) .sp matches any occurrence of "foo" that is not followed by "bar". Note that the apparently similar pattern .sp (?!foo)bar .sp does not find an occurrence of "bar" that is preceded by something other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always true when the next three characters are "bar". A lookbehind assertion is needed to achieve the other effect. .P If you want to force a matching failure at some point in a pattern, the most convenient way to do it is with (?!) because an empty string always matches, so an assertion that requires there not to be an empty string must always fail. The backtracking control verb (*FAIL) or (*F) is a synonym for (?!). . . .\" HTML .SS "Lookbehind assertions" .rs .sp Lookbehind assertions start with (?<= for positive assertions and (? .\" (see above) .\" can be used instead of a lookbehind assertion to get round the fixed-length restriction. .P The implementation of lookbehind assertions is, for each alternative, to temporarily move the current position back by the fixed length and then try to match. If there are insufficient characters before the current position, the assertion fails. .P In a UTF mode, PCRE does not allow the \eC escape (which matches a single data unit even in a UTF mode) to appear in lookbehind assertions, because it makes it impossible to calculate the length of the lookbehind. The \eX and \eR escapes, which can match different numbers of data units, are also not permitted. .P .\" HTML .\" "Subroutine" .\" calls (see below) such as (?2) or (?&X) are permitted in lookbehinds, as long as the subpattern matches a fixed-length string. .\" HTML .\" Recursion, .\" however, is not supported. .P Possessive quantifiers can be used in conjunction with lookbehind assertions to specify efficient matching of fixed-length strings at the end of subject strings. Consider a simple pattern such as .sp abcd$ .sp when applied to a long string that does not match. Because matching proceeds from left to right, PCRE will look for each "a" in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as .sp ^.*abcd$ .sp the initial .* matches the entire string at first, but when this fails (because there is no following "a"), it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for "a" covers the entire string, from right to left, so we are no better off. However, if the pattern is written as .sp ^.*+(?<=abcd) .sp there can be no backtracking for the .*+ item; it can match only the entire string. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the match fails immediately. For long strings, this approach makes a significant difference to the processing time. . . .SS "Using multiple assertions" .rs .sp Several assertions (of any sort) may occur in succession. For example, .sp (?<=\ed{3})(? .SH "CONDITIONAL SUBPATTERNS" .rs .sp It is possible to cause the matching process to obey a subpattern conditionally or to choose between two alternative subpatterns, depending on the result of an assertion, or whether a specific capturing subpattern has already been matched. The two possible forms of conditional subpattern are: .sp (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) .sp If the condition is satisfied, the yes-pattern is used; otherwise the no-pattern (if present) is used. If there are more than two alternatives in the subpattern, a compile-time error occurs. Each of the two alternatives may itself contain nested subpatterns of any form, including conditional subpatterns; the restriction to two alternatives applies only at the level of the condition. This pattern fragment is an example where the alternatives are complex: .sp (?(1) (A|B|C) | (D | (?(2)E|F) | E) ) .sp .P There are four kinds of condition: references to subpatterns, references to recursion, a pseudo-condition called DEFINE, and assertions. . .SS "Checking for a used subpattern by number" .rs .sp If the text between the parentheses consists of a sequence of digits, the condition is true if a capturing subpattern of that number has previously matched. If there is more than one capturing subpattern with the same number (see the earlier .\" .\" HTML .\" section about duplicate subpattern numbers), .\" the condition is true if any of them have matched. An alternative notation is to precede the digits with a plus or minus sign. In this case, the subpattern number is relative rather than absolute. The most recently opened parentheses can be referenced by (?(-1), the next most recent by (?(-2), and so on. Inside loops it can also make sense to refer to subsequent groups. The next parentheses to be opened can be referenced as (?(+1), and so on. (The value zero in any of these forms is not used; it provokes a compile-time error.) .P Consider the following pattern, which contains non-significant white space to make it more readable (assume the PCRE_EXTENDED option) and to divide it into three parts for ease of discussion: .sp ( \e( )? [^()]+ (?(1) \e) ) .sp The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The second part matches one or more characters that are not parentheses. The third part is a conditional subpattern that tests whether or not the first set of parentheses matched. If they did, that is, if subject started with an opening parenthesis, the condition is true, and so the yes-pattern is executed and a closing parenthesis is required. Otherwise, since no-pattern is not present, the subpattern matches nothing. In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses. .P If you were embedding this pattern in a larger one, you could use a relative reference: .sp ...other stuff... ( \e( )? [^()]+ (?(-1) \e) ) ... .sp This makes the fragment independent of the parentheses in the larger pattern. . .SS "Checking for a used subpattern by name" .rs .sp Perl uses the syntax (?()...) or (?('name')...) to test for a used subpattern by name. For compatibility with earlier versions of PCRE, which had this facility before Perl, the syntax (?(name)...) is also recognized. .P Rewriting the above example to use a named subpattern gives this: .sp (? \e( )? [^()]+ (?() \e) ) .sp If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them has matched. . .SS "Checking for pattern recursion" .rs .sp If the condition is the string (R), and there is no subpattern with the name R, the condition is true if a recursive call to the whole pattern or any subpattern has been made. If digits or a name preceded by ampersand follow the letter R, for example: .sp (?(R3)...) or (?(R&name)...) .sp the condition is true if the most recent recursion is into a subpattern whose number or name is given. This condition does not check the entire recursion stack. If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them is the most recent recursion. .P At "top level", all these recursion test conditions are false. .\" HTML .\" The syntax for recursive patterns .\" is described below. . .\" HTML .SS "Defining subpatterns for use by reference only" .rs .sp If the condition is the string (DEFINE), and there is no subpattern with the name DEFINE, the condition is always false. In this case, there may be only one alternative in the subpattern. It is always skipped if control reaches this point in the pattern; the idea of DEFINE is that it can be used to define subroutines that can be referenced from elsewhere. (The use of .\" HTML .\" subroutines .\" is described below.) For example, a pattern to match an IPv4 address such as "192.168.23.245" could be written like this (ignore white space and line breaks): .sp (?(DEFINE) (? 2[0-4]\ed | 25[0-5] | 1\ed\ed | [1-9]?\ed) ) \eb (?&byte) (\e.(?&byte)){3} \eb .sp The first part of the pattern is a DEFINE group inside which a another group named "byte" is defined. This matches an individual component of an IPv4 address (a number less than 256). When matching takes place, this part of the pattern is skipped because DEFINE acts like a false condition. The rest of the pattern uses references to the named group to match the four dot-separated components of an IPv4 address, insisting on a word boundary at each end. . .SS "Assertion conditions" .rs .sp If the condition is not in any of the above formats, it must be an assertion. This may be a positive or negative lookahead or lookbehind assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line: .sp (?(?=[^a-z]*[a-z]) \ed{2}-[a-z]{3}-\ed{2} | \ed{2}-\ed{2}-\ed{2} ) .sp The condition is a positive lookahead assertion that matches an optional sequence of non-letters followed by a letter. In other words, it tests for the presence of at least one letter in the subject. If a letter is found, the subject is matched against the first alternative; otherwise it is matched against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits. . . .\" HTML .SH COMMENTS .rs .sp There are two ways of including comments in patterns that are processed by PCRE. In both cases, the start of the comment must not be in a character class, nor in the middle of any other sequence of related characters such as (?: or a subpattern name or number. The characters that make up a comment play no part in the pattern matching. .P The sequence (?# marks the start of a comment that continues up to the next closing parenthesis. Nested parentheses are not permitted. If the PCRE_EXTENDED option is set, an unescaped # character also introduces a comment, which in this case continues to immediately after the next newline character or character sequence in the pattern. Which characters are interpreted as newlines is controlled by the options passed to a compiling function or by a special sequence at the start of the pattern, as described in the section entitled .\" HTML .\" "Newline conventions" .\" above. Note that the end of this type of comment is a literal newline sequence in the pattern; escape sequences that happen to represent a newline do not count. For example, consider this pattern when PCRE_EXTENDED is set, and the default newline convention is in force: .sp abc #comment \en still comment .sp On encountering the # character, \fBpcre_compile()\fP skips along, looking for a newline in the pattern. The sequence \en is still literal at this stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so. . . .\" HTML .SH "RECURSIVE PATTERNS" .rs .sp Consider the problem of matching a string in parentheses, allowing for unlimited nested parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. .P For some time, Perl has provided a facility that allows regular expressions to recurse (amongst other things). It does this by interpolating Perl code in the expression at run time, and the code can refer to the expression itself. A Perl pattern using code interpolation to solve the parentheses problem can be created like this: .sp $re = qr{\e( (?: (?>[^()]+) | (?p{$re}) )* \e)}x; .sp The (?p{...}) item interpolates Perl code at run time, and in this case refers recursively to the pattern in which it appears. .P Obviously, PCRE cannot support the interpolation of Perl code. Instead, it supports special syntax for recursion of the entire pattern, and also for individual subpattern recursion. After its introduction in PCRE and Python, this kind of recursion was subsequently introduced into Perl at release 5.10. .P A special item that consists of (? followed by a number greater than zero and a closing parenthesis is a recursive subroutine call of the subpattern of the given number, provided that it occurs inside that subpattern. (If not, it is a .\" HTML .\" non-recursive subroutine .\" call, which is described in the next section.) The special item (?R) or (?0) is a recursive call of the entire regular expression. .P This PCRE pattern solves the nested parentheses problem (assume the PCRE_EXTENDED option is set so that white space is ignored): .sp \e( ( [^()]++ | (?R) )* \e) .sp First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (that is, a correctly parenthesized substring). Finally there is a closing parenthesis. Note the use of a possessive quantifier to avoid backtracking into sequences of non-parentheses. .P If this were part of a larger pattern, you would not want to recurse the entire pattern, so instead you could use this: .sp ( \e( ( [^()]++ | (?1) )* \e) ) .sp We have put the pattern into parentheses, and caused the recursion to refer to them instead of the whole pattern. .P In a larger pattern, keeping track of parenthesis numbers can be tricky. This is made easier by the use of relative references. Instead of (?1) in the pattern above you can write (?-2) to refer to the second most recently opened parentheses preceding the recursion. In other words, a negative number counts capturing parentheses leftwards from the point at which it is encountered. .P It is also possible to refer to subsequently opened parentheses, by writing references such as (?+2). However, these cannot be recursive because the reference is not inside the parentheses that are referenced. They are always .\" HTML .\" non-recursive subroutine .\" calls, as described in the next section. .P An alternative approach is to use named parentheses instead. The Perl syntax for this is (?&name); PCRE's earlier syntax (?P>name) is also supported. We could rewrite the above example as follows: .sp (? \e( ( [^()]++ | (?&pn) )* \e) ) .sp If there is more than one subpattern with the same name, the earliest one is used. .P This particular example pattern that we have been looking at contains nested unlimited repeats, and so the use of a possessive quantifier for matching strings of non-parentheses is important when applying the pattern to strings that do not match. For example, when this pattern is applied to .sp (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() .sp it yields "no match" quickly. However, if a possessive quantifier is not used, the match runs for a very long time indeed because there are so many different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported. .P At the end of a match, the values of capturing parentheses are those from the outermost level. If you want to obtain intermediate values, a callout function can be used (see below and the .\" HREF \fBpcrecallout\fP .\" documentation). If the pattern above is matched against .sp (ab(cd)ef) .sp the value for the inner capturing parentheses (numbered 2) is "ef", which is the last value taken on at the top level. If a capturing subpattern is not matched at the top level, its final captured value is unset, even if it was (temporarily) set at a deeper level during the matching process. .P If there are more than 15 capturing parentheses in a pattern, PCRE has to obtain extra memory to store data during a recursion, which it does by using \fBpcre_malloc\fP, freeing it via \fBpcre_free\fP afterwards. If no memory can be obtained, the match fails with the PCRE_ERROR_NOMEMORY error. .P Do not confuse the (?R) item with the condition (R), which tests for recursion. Consider this pattern, which matches text in angle brackets, allowing for arbitrary nesting. Only digits are allowed in nested brackets (that is, when recursing), whereas any characters are permitted at the outer level. .sp < (?: (?(R) \ed++ | [^<>]*+) | (?R)) * > .sp In this pattern, (?(R) is the start of a conditional subpattern, with two different alternatives for the recursive and non-recursive cases. The (?R) item is the actual recursive call. . . .\" HTML .SS "Differences in recursion processing between PCRE and Perl" .rs .sp Recursion processing in PCRE differs from Perl in two important ways. In PCRE (like Python, but unlike Perl), a recursive subpattern call is always treated as an atomic group. That is, once it has matched some of the subject string, it is never re-entered, even if it contains untried alternatives and there is a subsequent matching failure. This can be illustrated by the following pattern, which purports to match a palindromic string that contains an odd number of characters (for example, "a", "aba", "abcba", "abcdcba"): .sp ^(.|(.)(?1)\e2)$ .sp The idea is that it either matches a single character, or two identical characters surrounding a sub-palindrome. In Perl, this pattern works; in PCRE it does not if the pattern is longer than three characters. Consider the subject string "abcba": .P At the top level, the first character is matched, but as it is not at the end of the string, the first alternative fails; the second alternative is taken and the recursion kicks in. The recursive call to subpattern 1 successfully matches the next character ("b"). (Note that the beginning and end of line tests are not part of the recursion). .P Back at the top level, the next character ("c") is compared with what subpattern 2 matched, which was "a". This fails. Because the recursion is treated as an atomic group, there are now no backtracking points, and so the entire match fails. (Perl is able, at this point, to re-enter the recursion and try the second alternative.) However, if the pattern is written with the alternatives in the other order, things are different: .sp ^((.)(?1)\e2|.)$ .sp This time, the recursing alternative is tried first, and continues to recurse until it runs out of characters, at which point the recursion fails. But this time we do have another alternative to try at the higher level. That is the big difference: in the previous case the remaining alternative is at a deeper recursion level, which PCRE cannot use. .P To change the pattern so that it matches all palindromic strings, not just those with an odd number of characters, it is tempting to change the pattern to this: .sp ^((.)(?1)\e2|.?)$ .sp Again, this works in Perl, but not in PCRE, and for the same reason. When a deeper recursion has matched a single character, it cannot be entered again in order to match an empty string. The solution is to separate the two cases, and write out the odd and even cases as alternatives at the higher level: .sp ^(?:((.)(?1)\e2|)|((.)(?3)\e4|.)) .sp If you want to match typical palindromic phrases, the pattern has to ignore all non-word characters, which can be done like this: .sp ^\eW*+(?:((.)\eW*+(?1)\eW*+\e2|)|((.)\eW*+(?3)\eW*+\e4|\eW*+.\eW*+))\eW*+$ .sp If run with the PCRE_CASELESS option, this pattern matches phrases such as "A man, a plan, a canal: Panama!" and it works well in both PCRE and Perl. Note the use of the possessive quantifier *+ to avoid backtracking into sequences of non-word characters. Without this, PCRE takes a great deal longer (ten times or more) to match typical phrases, and Perl takes so long that you think it has gone into a loop. .P \fBWARNING\fP: The palindrome-matching patterns above work only if the subject string does not start with a palindrome that is shorter than the entire string. For example, although "abcba" is correctly matched, if the subject is "ababa", PCRE finds the palindrome "aba" at the start, then fails at top level because the end of the string does not follow. Once again, it cannot jump back into the recursion to try other alternatives, so the entire match fails. .P The second way in which PCRE and Perl differ in their recursion processing is in the handling of captured values. In Perl, when a subpattern is called recursively or as a subpattern (see the next section), it has no access to any values that were captured outside the recursion, whereas in PCRE these values can be referenced. Consider this pattern: .sp ^(.)(\e1|a(?2)) .sp In PCRE, this pattern matches "bab". The first capturing parentheses match "b", then in the second group, when the back reference \e1 fails to match "b", the second alternative matches "a" and then recurses. In the recursion, \e1 does now match "b" and so the whole match succeeds. In Perl, the pattern fails to match because inside the recursive call \e1 cannot access the externally set value. . . .\" HTML .SH "SUBPATTERNS AS SUBROUTINES" .rs .sp If the syntax for a recursive subpattern call (either by number or by name) is used outside the parentheses to which it refers, it operates like a subroutine in a programming language. The called subpattern may be defined before or after the reference. A numbered reference can be absolute or relative, as in these examples: .sp (...(absolute)...)...(?2)... (...(relative)...)...(?-1)... (...(?+1)...(relative)... .sp An earlier example pointed out that the pattern .sp (sens|respons)e and \e1ibility .sp matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If instead the pattern .sp (sens|respons)e and (?1)ibility .sp is used, it does match "sense and responsibility" as well as the other two strings. Another example is given in the discussion of DEFINE above. .P All subroutine calls, whether recursive or not, are always treated as atomic groups. That is, once a subroutine has matched some of the subject string, it is never re-entered, even if it contains untried alternatives and there is a subsequent matching failure. Any capturing parentheses that are set during the subroutine call revert to their previous values afterwards. .P Processing options such as case-independence are fixed when a subpattern is defined, so if it is used as a subroutine, such options cannot be changed for different calls. For example, consider this pattern: .sp (abc)(?i:(?-1)) .sp It matches "abcabc". It does not match "abcABC" because the change of processing option does not affect the called subpattern. . . .\" HTML .SH "ONIGURUMA SUBROUTINE SYNTAX" .rs .sp For compatibility with Oniguruma, the non-Perl syntax \eg followed by a name or a number enclosed either in angle brackets or single quotes, is an alternative syntax for referencing a subpattern as a subroutine, possibly recursively. Here are two of the examples used above, rewritten using this syntax: .sp (? \e( ( (?>[^()]+) | \eg )* \e) ) (sens|respons)e and \eg'1'ibility .sp PCRE supports an extension to Oniguruma: if a number is preceded by a plus or a minus sign it is taken as a relative reference. For example: .sp (abc)(?i:\eg<-1>) .sp Note that \eg{...} (Perl syntax) and \eg<...> (Oniguruma syntax) are \fInot\fP synonymous. The former is a back reference; the latter is a subroutine call. . . .SH CALLOUTS .rs .sp Perl has a feature whereby using the sequence (?{...}) causes arbitrary Perl code to be obeyed in the middle of matching a regular expression. This makes it possible, amongst other things, to extract different substrings that match the same pair of parentheses when there is a repetition. .P PCRE provides a similar feature, but of course it cannot obey arbitrary Perl code. The feature is called "callout". The caller of PCRE provides an external function by putting its entry point in the global variable \fIpcre_callout\fP (8-bit library) or \fIpcre[16|32]_callout\fP (16-bit or 32-bit library). By default, this variable contains NULL, which disables all calling out. .P Within a regular expression, (?C) indicates the points at which the external function is to be called. If you want to identify different callout points, you can put a number less than 256 after the letter C. The default value is zero. For example, this pattern has two callout points: .sp (?C1)abc(?C2)def .sp If the PCRE_AUTO_CALLOUT flag is passed to a compiling function, callouts are automatically installed before each item in the pattern. They are all numbered 255. If there is a conditional group in the pattern whose condition is an assertion, an additional callout is inserted just before the condition. An explicit callout may also be set at this position, as in this example: .sp (?(?C9)(?=a)abc|def) .sp Note that this applies only to assertion conditions, not to other types of condition. .P During matching, when PCRE reaches a callout point, the external function is called. It is provided with the number of the callout, the position in the pattern, and, optionally, one item of data originally supplied by the caller of the matching function. The callout function may cause matching to proceed, to backtrack, or to fail altogether. .P By default, PCRE implements a number of optimizations at compile time and matching time, and one side-effect is that sometimes callouts are skipped. If you need all possible callouts to happen, you need to set options that disable the relevant optimizations. More details, and a complete description of the interface to the callout function, are given in the .\" HREF \fBpcrecallout\fP .\" documentation. . . .\" HTML .SH "BACKTRACKING CONTROL" .rs .sp Perl 5.10 introduced a number of "Special Backtracking Control Verbs", which are still described in the Perl documentation as "experimental and subject to change or removal in a future version of Perl". It goes on to say: "Their usage in production code should be noted to avoid problems during upgrades." The same remarks apply to the PCRE features described in this section. .P The new verbs make use of what was previously invalid syntax: an opening parenthesis followed by an asterisk. They are generally of the form (*VERB) or (*VERB:NAME). Some may take either form, possibly behaving differently depending on whether or not a name is present. A name is any sequence of characters that does not include a closing parenthesis. The maximum length of name is 255 in the 8-bit library and 65535 in the 16-bit and 32-bit libraries. If the name is empty, that is, if the closing parenthesis immediately follows the colon, the effect is as if the colon were not there. Any number of these verbs may occur in a pattern. .P Since these verbs are specifically related to backtracking, most of them can be used only when the pattern is to be matched using one of the traditional matching functions, because these use a backtracking algorithm. With the exception of (*FAIL), which behaves like a failing negative assertion, the backtracking control verbs cause an error if encountered by a DFA matching function. .P The behaviour of these verbs in .\" HTML .\" repeated groups, .\" .\" HTML .\" assertions, .\" and in .\" HTML .\" subpatterns called as subroutines .\" (whether or not recursively) is documented below. . . .\" HTML .SS "Optimizations that affect backtracking verbs" .rs .sp PCRE contains some optimizations that are used to speed up matching by running some checks at the start of each match attempt. For example, it may know the minimum length of matching subject, or that a particular character must be present. When one of these optimizations bypasses the running of a match, any included backtracking verbs will not, of course, be processed. You can suppress the start-of-match optimizations by setting the PCRE_NO_START_OPTIMIZE option when calling \fBpcre_compile()\fP or \fBpcre_exec()\fP, or by starting the pattern with (*NO_START_OPT). There is more discussion of this option in the section entitled .\" HTML .\" "Option bits for \fBpcre_exec()\fP" .\" in the .\" HREF \fBpcreapi\fP .\" documentation. .P Experiments with Perl suggest that it too has similar optimizations, sometimes leading to anomalous results. . . .SS "Verbs that act immediately" .rs .sp The following verbs act as soon as they are encountered. They may not be followed by a name. .sp (*ACCEPT) .sp This verb causes the match to end successfully, skipping the remainder of the pattern. However, when it is inside a subpattern that is called as a subroutine, only that subpattern is ended successfully. Matching then continues at the outer level. If (*ACCEPT) in triggered in a positive assertion, the assertion succeeds; in a negative assertion, the assertion fails. .P If (*ACCEPT) is inside capturing parentheses, the data so far is captured. For example: .sp A((?:A|B(*ACCEPT)|C)D) .sp This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is captured by the outer parentheses. .sp (*FAIL) or (*F) .sp This verb causes a matching failure, forcing backtracking to occur. It is equivalent to (?!) but easier to read. The Perl documentation notes that it is probably useful only when combined with (?{}) or (??{}). Those are, of course, Perl features that are not present in PCRE. The nearest equivalent is the callout feature, as for example in this pattern: .sp a+(?C)(*FAIL) .sp A match with the string "aaaa" always fails, but the callout is taken before each backtrack happens (in this example, 10 times). . . .SS "Recording which path was taken" .rs .sp There is one verb whose main purpose is to track how a match was arrived at, though it also has a secondary use in conjunction with advancing the match starting point (see (*SKIP) below). .sp (*MARK:NAME) or (*:NAME) .sp A name is always required with this verb. There may be as many instances of (*MARK) as you like in a pattern, and their names do not have to be unique. .P When a match succeeds, the name of the last-encountered (*MARK:NAME), (*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to the caller as described in the section entitled .\" HTML .\" "Extra data for \fBpcre_exec()\fP" .\" in the .\" HREF \fBpcreapi\fP .\" documentation. Here is an example of \fBpcretest\fP output, where the /K modifier requests the retrieval and outputting of (*MARK) data: .sp re> /X(*MARK:A)Y|X(*MARK:B)Z/K data> XY 0: XY MK: A XZ 0: XZ MK: B .sp The (*MARK) name is tagged with "MK:" in this output, and in this example it indicates which of the two alternatives matched. This is a more efficient way of obtaining this information than putting each alternative in its own capturing parentheses. .P If a verb with a name is encountered in a positive assertion that is true, the name is recorded and passed back if it is the last-encountered. This does not happen for negative assertions or failing positive assertions. .P After a partial match or a failed match, the last encountered name in the entire match process is returned. For example: .sp re> /X(*MARK:A)Y|X(*MARK:B)Z/K data> XP No match, mark = B .sp Note that in this unanchored example the mark is retained from the match attempt that started at the letter "X" in the subject. Subsequent match attempts starting at "P" and then with an empty string do not get as far as the (*MARK) item, but nevertheless do not reset it. .P If you are interested in (*MARK) values after failed matches, you should probably set the PCRE_NO_START_OPTIMIZE option .\" HTML .\" (see above) .\" to ensure that the match is always attempted. . . .SS "Verbs that act after backtracking" .rs .sp The following verbs do nothing when they are encountered. Matching continues with what follows, but if there is no subsequent match, causing a backtrack to the verb, a failure is forced. That is, backtracking cannot pass to the left of the verb. However, when one of these verbs appears inside an atomic group or an assertion that is true, its effect is confined to that group, because once the group has been matched, there is never any backtracking into it. In this situation, backtracking can "jump back" to the left of the entire atomic group or assertion. (Remember also, as stated above, that this localization also applies in subroutine calls.) .P These verbs differ in exactly what kind of failure occurs when backtracking reaches them. The behaviour described below is what happens when the verb is not in a subroutine or an assertion. Subsequent sections cover these special cases. .sp (*COMMIT) .sp This verb, which may not be followed by a name, causes the whole match to fail outright if there is a later matching failure that causes backtracking to reach it. Even if the pattern is unanchored, no further attempts to find a match by advancing the starting point take place. If (*COMMIT) is the only backtracking verb that is encountered, once it has been passed \fBpcre_exec()\fP is committed to finding a match at the current starting point, or not at all. For example: .sp a+(*COMMIT)b .sp This matches "xxaab" but not "aacaab". It can be thought of as a kind of dynamic anchor, or "I've started, so I must finish." The name of the most recently passed (*MARK) in the path is passed back when (*COMMIT) forces a match failure. .P If there is more than one backtracking verb in a pattern, a different one that follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a match does not always guarantee that a match must be at this starting point. .P Note that (*COMMIT) at the start of a pattern is not the same as an anchor, unless PCRE's start-of-match optimizations are turned off, as shown in this output from \fBpcretest\fP: .sp re> /(*COMMIT)abc/ data> xyzabc 0: abc data> xyzabc\eY No match .sp For this pattern, PCRE knows that any match must start with "a", so the optimization skips along the subject to "a" before applying the pattern to the first set of data. The match attempt then succeeds. In the second set of data, the escape sequence \eY is interpreted by the \fBpcretest\fP program. It causes the PCRE_NO_START_OPTIMIZE option to be set when \fBpcre_exec()\fP is called. This disables the optimization that skips along to the first character. The pattern is now applied starting at "x", and so the (*COMMIT) causes the match to fail without trying any other starting points. .sp (*PRUNE) or (*PRUNE:NAME) .sp This verb causes the match to fail at the current starting position in the subject if there is a later matching failure that causes backtracking to reach it. If the pattern is unanchored, the normal "bumpalong" advance to the next starting character then happens. Backtracking can occur as usual to the left of (*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but if there is no match to the right, backtracking cannot cross (*PRUNE). In simple cases, the use of (*PRUNE) is just an alternative to an atomic group or possessive quantifier, but there are some uses of (*PRUNE) that cannot be expressed in any other way. In an anchored pattern (*PRUNE) has the same effect as (*COMMIT). .P The behaviour of (*PRUNE:NAME) is the not the same as (*MARK:NAME)(*PRUNE). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK). .sp (*SKIP) .sp This verb, when given without a name, is like (*PRUNE), except that if the pattern is unanchored, the "bumpalong" advance is not to the next character, but to the position in the subject where (*SKIP) was encountered. (*SKIP) signifies that whatever text was matched leading up to it cannot be part of a successful match. Consider: .sp a+(*SKIP)b .sp If the subject is "aaaac...", after the first match attempt fails (starting at the first character in the string), the starting point skips on to start the next attempt at "c". Note that a possessive quantifer does not have the same effect as this example; although it would suppress backtracking during the first match attempt, the second attempt would start at the second character instead of skipping on to "c". .sp (*SKIP:NAME) .sp When (*SKIP) has an associated name, its behaviour is modified. When it is triggered, the previous path through the pattern is searched for the most recent (*MARK) that has the same name. If one is found, the "bumpalong" advance is to the subject position that corresponds to that (*MARK) instead of to where (*SKIP) was encountered. If no (*MARK) with a matching name is found, the (*SKIP) is ignored. .P Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores names that are set by (*PRUNE:NAME) or (*THEN:NAME). .sp (*THEN) or (*THEN:NAME) .sp This verb causes a skip to the next innermost alternative when backtracking reaches it. That is, it cancels any further backtracking within the current alternative. Its name comes from the observation that it can be used for a pattern-based if-then-else block: .sp ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ... .sp If the COND1 pattern matches, FOO is tried (and possibly further items after the end of the group if FOO succeeds); on failure, the matcher skips to the second alternative and tries COND2, without backtracking into COND1. If that succeeds and BAR fails, COND3 is tried. If subsequently BAZ fails, there are no more alternatives, so there is a backtrack to whatever came before the entire group. If (*THEN) is not inside an alternation, it acts like (*PRUNE). .P The behaviour of (*THEN:NAME) is the not the same as (*MARK:NAME)(*THEN). It is like (*MARK:NAME) in that the name is remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK). .P A subpattern that does not contain a | character is just a part of the enclosing alternative; it is not a nested alternation with only one alternative. The effect of (*THEN) extends beyond such a subpattern to the enclosing alternative. Consider this pattern, where A, B, etc. are complex pattern fragments that do not contain any | characters at this level: .sp A (B(*THEN)C) | D .sp If A and B are matched, but there is a failure in C, matching does not backtrack into A; instead it moves to the next alternative, that is, D. However, if the subpattern containing (*THEN) is given an alternative, it behaves differently: .sp A (B(*THEN)C | (*FAIL)) | D .sp The effect of (*THEN) is now confined to the inner subpattern. After a failure in C, matching moves to (*FAIL), which causes the whole subpattern to fail because there are no more alternatives to try. In this case, matching does now backtrack into A. .P Note that a conditional subpattern is not considered as having two alternatives, because only one is ever used. In other words, the | character in a conditional subpattern has a different meaning. Ignoring white space, consider: .sp ^.*? (?(?=a) a | b(*THEN)c ) .sp If the subject is "ba", this pattern does not match. Because .*? is ungreedy, it initially matches zero characters. The condition (?=a) then fails, the character "b" is matched, but "c" is not. At this point, matching does not backtrack to .*? as might perhaps be expected from the presence of the | character. The conditional subpattern is part of the single alternative that comprises the whole pattern, and so the match fails. (If there was a backtrack into .*?, allowing it to match "b", the match would succeed.) .P The verbs just described provide four different "strengths" of control when subsequent matching fails. (*THEN) is the weakest, carrying on the match at the next alternative. (*PRUNE) comes next, failing the match at the current starting position, but allowing an advance to the next character (for an unanchored pattern). (*SKIP) is similar, except that the advance may be more than one character. (*COMMIT) is the strongest, causing the entire match to fail. . . .SS "More than one backtracking verb" .rs .sp If more than one backtracking verb is present in a pattern, the one that is backtracked onto first acts. For example, consider this pattern, where A, B, etc. are complex pattern fragments: .sp (A(*COMMIT)B(*THEN)C|ABD) .sp If A matches but B fails, the backtrack to (*COMMIT) causes the entire match to fail. However, if A and B match, but C fails, the backtrack to (*THEN) causes the next alternative (ABD) to be tried. This behaviour is consistent, but is not always the same as Perl's. It means that if two or more backtracking verbs appear in succession, all the the last of them has no effect. Consider this example: .sp ...(*COMMIT)(*PRUNE)... .sp If there is a matching failure to the right, backtracking onto (*PRUNE) causes it to be triggered, and its action is taken. There can never be a backtrack onto (*COMMIT). . . .\" HTML .SS "Backtracking verbs in repeated groups" .rs .sp PCRE differs from Perl in its handling of backtracking verbs in repeated groups. For example, consider: .sp /(a(*COMMIT)b)+ac/ .sp If the subject is "abac", Perl matches, but PCRE fails because the (*COMMIT) in the second repeat of the group acts. . . .\" HTML .SS "Backtracking verbs in assertions" .rs .sp (*FAIL) in an assertion has its normal effect: it forces an immediate backtrack. .P (*ACCEPT) in a positive assertion causes the assertion to succeed without any further processing. In a negative assertion, (*ACCEPT) causes the assertion to fail without any further processing. .P The other backtracking verbs are not treated specially if they appear in a positive assertion. In particular, (*THEN) skips to the next alternative in the innermost enclosing group that has alternations, whether or not this is within the assertion. .P Negative assertions are, however, different, in order to ensure that changing a positive assertion into a negative assertion changes its result. Backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes a negative assertion to be true, without considering any further alternative branches in the assertion. Backtracking into (*THEN) causes it to skip to the next enclosing alternative within the assertion (the normal behaviour), but if the assertion does not have such an alternative, (*THEN) behaves like (*PRUNE). . . .\" HTML .SS "Backtracking verbs in subroutines" .rs .sp These behaviours occur whether or not the subpattern is called recursively. Perl's treatment of subroutines is different in some cases. .P (*FAIL) in a subpattern called as a subroutine has its normal effect: it forces an immediate backtrack. .P (*ACCEPT) in a subpattern called as a subroutine causes the subroutine match to succeed without any further processing. Matching then continues after the subroutine call. .P (*COMMIT), (*SKIP), and (*PRUNE) in a subpattern called as a subroutine cause the subroutine match to fail. .P (*THEN) skips to the next alternative in the innermost enclosing group within the subpattern that has alternatives. If there is no such group within the subpattern, (*THEN) causes the subroutine match to fail. . . .SH "SEE ALSO" .rs .sp \fBpcreapi\fP(3), \fBpcrecallout\fP(3), \fBpcrematching\fP(3), \fBpcresyntax\fP(3), \fBpcre\fP(3), \fBpcre16(3)\fP, \fBpcre32(3)\fP. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 23 October 2016 Copyright (c) 1997-2016 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcreperform.3 ================================================ .TH PCREPERFORM 3 "09 January 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE PERFORMANCE" .rs .sp Two aspects of performance are discussed below: memory usage and processing time. The way you express your pattern as a regular expression can affect both of them. . .SH "COMPILED PATTERN MEMORY USAGE" .rs .sp Patterns are compiled by PCRE into a reasonably efficient interpretive code, so that most simple patterns do not use much memory. However, there is one case where the memory usage of a compiled pattern can be unexpectedly large. If a parenthesized subpattern has a quantifier with a minimum greater than 1 and/or a limited maximum, the whole subpattern is repeated in the compiled code. For example, the pattern .sp (abc|def){2,4} .sp is compiled as if it were .sp (abc|def)(abc|def)((abc|def)(abc|def)?)? .sp (Technical aside: It is done this way so that backtrack points within each of the repetitions can be independently maintained.) .P For regular expressions whose quantifiers use only small numbers, this is not usually a problem. However, if the numbers are large, and particularly if such repetitions are nested, the memory usage can become an embarrassment. For example, the very simple pattern .sp ((ab){1,1000}c){1,3} .sp uses 51K bytes when compiled using the 8-bit library. When PCRE is compiled with its default internal pointer size of two bytes, the size limit on a compiled pattern is 64K data units, and this is reached with the above pattern if the outer repetition is increased from 3 to 4. PCRE can be compiled to use larger internal pointers and thus handle larger compiled patterns, but it is better to try to rewrite your pattern to use less memory if you can. .P One way of reducing the memory usage for such patterns is to make use of PCRE's .\" HTML .\" "subroutine" .\" facility. Re-writing the above pattern as .sp ((ab)(?2){0,999}c)(?1){0,2} .sp reduces the memory requirements to 18K, and indeed it remains under 20K even with the outer repetition increased to 100. However, this pattern is not exactly equivalent, because the "subroutine" calls are treated as .\" HTML .\" atomic groups .\" into which there can be no backtracking if there is a subsequent matching failure. Therefore, PCRE cannot do this kind of rewriting automatically. Furthermore, there is a noticeable loss of speed when executing the modified pattern. Nevertheless, if the atomic grouping is not a problem and the loss of speed is acceptable, this kind of rewriting will allow you to process patterns that PCRE cannot otherwise handle. . . .SH "STACK USAGE AT RUN TIME" .rs .sp When \fBpcre_exec()\fP or \fBpcre[16|32]_exec()\fP is used for matching, certain kinds of pattern can cause it to use large amounts of the process stack. In some environments the default process stack is quite small, and if it runs out the result is often SIGSEGV. This issue is probably the most frequently raised problem with PCRE. Rewriting your pattern can often help. The .\" HREF \fBpcrestack\fP .\" documentation discusses this issue in detail. . . .SH "PROCESSING TIME" .rs .sp Certain items in regular expression patterns are processed more efficiently than others. It is more efficient to use a character class like [aeiou] than a set of single-character alternatives such as (a|e|i|o|u). In general, the simplest construction that provides the required behaviour is usually the most efficient. Jeffrey Friedl's book contains a lot of useful general discussion about optimizing regular expressions for efficient performance. This document contains a few observations about PCRE. .P Using Unicode character properties (the \ep, \eP, and \eX escapes) is slow, because PCRE has to use a multi-stage table lookup whenever it needs a character's property. If you can find an alternative pattern that does not use character properties, it will probably be faster. .P By default, the escape sequences \eb, \ed, \es, and \ew, and the POSIX character classes such as [:alpha:] do not use Unicode properties, partly for backwards compatibility, and partly for performance reasons. However, you can set PCRE_UCP if you want Unicode character properties to be used. This can double the matching time for items such as \ed, when matched with a traditional matching function; the performance loss is less with a DFA matching function, and in both cases there is not much difference for \eb. .P When a pattern begins with .* not in parentheses, or in parentheses that are not the subject of a backreference, and the PCRE_DOTALL option is set, the pattern is implicitly anchored by PCRE, since it can match only at the start of a subject string. However, if PCRE_DOTALL is not set, PCRE cannot make this optimization, because the . metacharacter does not then match a newline, and if the subject string contains newlines, the pattern may match from the character immediately following one of them instead of from the very start. For example, the pattern .sp .*second .sp matches the subject "first\enand second" (where \en stands for a newline character), with the match starting at the seventh character. In order to do this, PCRE has to retry the match starting after every newline in the subject. .P If you are using such a pattern with subject strings that do not contain newlines, the best performance is obtained by setting PCRE_DOTALL, or starting the pattern with ^.* or ^.*? to indicate explicit anchoring. That saves PCRE from having to scan along the subject looking for a newline to restart at. .P Beware of patterns that contain nested indefinite repeats. These can take a long time to run when applied to a string that does not match. Consider the pattern fragment .sp ^(a+)* .sp This can match "aaaa" in 16 different ways, and this number increases very rapidly as the string gets longer. (The * repeat can match 0, 1, 2, 3, or 4 times, and for each of those cases other than 0 or 4, the + repeats can match different numbers of times.) When the remainder of the pattern is such that the entire match is going to fail, PCRE has in principle to try every possible variation, and this can take an extremely long time, even for relatively short strings. .P An optimization catches some of the more simple cases such as .sp (a+)*b .sp where a literal character follows. Before embarking on the standard matching procedure, PCRE checks that there is a "b" later in the subject string, and if there is not, it fails the match immediately. However, when there is no following literal this optimization cannot be used. You can see the difference by comparing the behaviour of .sp (a+)*\ed .sp with the pattern above. The former gives a failure almost instantly when applied to a whole line of "a" characters, whereas the latter takes an appreciable time with strings longer than about 20 characters. .P In many cases, the solution to this kind of performance issue is to use an atomic group or a possessive quantifier. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 25 August 2012 Copyright (c) 1997-2012 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcreposix.3 ================================================ .TH PCREPOSIX 3 "09 January 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions. .SH "SYNOPSIS" .rs .sp .B #include .PP .nf .B int regcomp(regex_t *\fIpreg\fP, const char *\fIpattern\fP, .B " int \fIcflags\fP);" .sp .B int regexec(regex_t *\fIpreg\fP, const char *\fIstring\fP, .B " size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP);" .B " size_t regerror(int \fIerrcode\fP, const regex_t *\fIpreg\fP," .B " char *\fIerrbuf\fP, size_t \fIerrbuf_size\fP);" .sp .B void regfree(regex_t *\fIpreg\fP); .fi . .SH DESCRIPTION .rs .sp This set of functions provides a POSIX-style API for the PCRE regular expression 8-bit library. See the .\" HREF \fBpcreapi\fP .\" documentation for a description of PCRE's native API, which contains much additional functionality. There is no POSIX-style wrapper for PCRE's 16-bit and 32-bit library. .P The functions described here are just wrapper functions that ultimately call the PCRE native API. Their prototypes are defined in the \fBpcreposix.h\fP header file, and on Unix systems the library itself is called \fBpcreposix.a\fP, so can be accessed by adding \fB-lpcreposix\fP to the command for linking an application that uses them. Because the POSIX functions call the native ones, it is also necessary to add \fB-lpcre\fP. .P I have implemented only those POSIX option bits that can be reasonably mapped to PCRE native options. In addition, the option REG_EXTENDED is defined with the value zero. This has no effect, but since programs that are written to the POSIX interface often use it, this makes it easier to slot in PCRE as a replacement library. Other POSIX options are not even defined. .P There are also some other options that are not defined by POSIX. These have been added at the request of users who want to make use of certain PCRE-specific features via the POSIX calling interface. .P When PCRE is called via these functions, it is only the API that is POSIX-like in style. The syntax and semantics of the regular expressions themselves are still those of Perl, subject to the setting of various PCRE options, as described below. "POSIX-like in style" means that the API approximates to the POSIX definition; it is not fully POSIX-compatible, and in multi-byte encoding domains it is probably even less compatible. .P The header for these functions is supplied as \fBpcreposix.h\fP to avoid any potential clash with other POSIX libraries. It can, of course, be renamed or aliased as \fBregex.h\fP, which is the "correct" name. It provides two structure types, \fIregex_t\fP for compiled internal forms, and \fIregmatch_t\fP for returning captured substrings. It also defines some constants whose names start with "REG_"; these are used for setting options and identifying error codes. . . .SH "COMPILING A PATTERN" .rs .sp The function \fBregcomp()\fP is called to compile a pattern into an internal form. The pattern is a C string terminated by a binary zero, and is passed in the argument \fIpattern\fP. The \fIpreg\fP argument is a pointer to a \fBregex_t\fP structure that is used as a base for storing information about the compiled regular expression. .P The argument \fIcflags\fP is either zero, or contains one or more of the bits defined by the following macros: .sp REG_DOTALL .sp The PCRE_DOTALL option is set when the regular expression is passed for compilation to the native function. Note that REG_DOTALL is not part of the POSIX standard. .sp REG_ICASE .sp The PCRE_CASELESS option is set when the regular expression is passed for compilation to the native function. .sp REG_NEWLINE .sp The PCRE_MULTILINE option is set when the regular expression is passed for compilation to the native function. Note that this does \fInot\fP mimic the defined POSIX behaviour for REG_NEWLINE (see the following section). .sp REG_NOSUB .sp The PCRE_NO_AUTO_CAPTURE option is set when the regular expression is passed for compilation to the native function. In addition, when a pattern that is compiled with this flag is passed to \fBregexec()\fP for matching, the \fInmatch\fP and \fIpmatch\fP arguments are ignored, and no captured strings are returned. .sp REG_UCP .sp The PCRE_UCP option is set when the regular expression is passed for compilation to the native function. This causes PCRE to use Unicode properties when matchine \ed, \ew, etc., instead of just recognizing ASCII values. Note that REG_UTF8 is not part of the POSIX standard. .sp REG_UNGREEDY .sp The PCRE_UNGREEDY option is set when the regular expression is passed for compilation to the native function. Note that REG_UNGREEDY is not part of the POSIX standard. .sp REG_UTF8 .sp The PCRE_UTF8 option is set when the regular expression is passed for compilation to the native function. This causes the pattern itself and all data strings used for matching it to be treated as UTF-8 strings. Note that REG_UTF8 is not part of the POSIX standard. .P In the absence of these flags, no options are passed to the native function. This means the the regex is compiled with PCRE default semantics. In particular, the way it handles newline characters in the subject string is the Perl way, not the POSIX way. Note that setting PCRE_MULTILINE has only \fIsome\fP of the effects specified for REG_NEWLINE. It does not affect the way newlines are matched by . (they are not) or by a negative class such as [^a] (they are). .P The yield of \fBregcomp()\fP is zero on success, and non-zero otherwise. The \fIpreg\fP structure is filled in on success, and one member of the structure is public: \fIre_nsub\fP contains the number of capturing subpatterns in the regular expression. Various error codes are defined in the header file. .P NOTE: If the yield of \fBregcomp()\fP is non-zero, you must not attempt to use the contents of the \fIpreg\fP structure. If, for example, you pass it to \fBregexec()\fP, the result is undefined and your program is likely to crash. . . .SH "MATCHING NEWLINE CHARACTERS" .rs .sp This area is not simple, because POSIX and Perl take different views of things. It is not possible to get PCRE to obey POSIX semantics, but then PCRE was never intended to be a POSIX engine. The following table lists the different possibilities for matching newline characters in PCRE: .sp Default Change with .sp . matches newline no PCRE_DOTALL newline matches [^a] yes not changeable $ matches \en at end yes PCRE_DOLLARENDONLY $ matches \en in middle no PCRE_MULTILINE ^ matches \en in middle no PCRE_MULTILINE .sp This is the equivalent table for POSIX: .sp Default Change with .sp . matches newline yes REG_NEWLINE newline matches [^a] yes REG_NEWLINE $ matches \en at end no REG_NEWLINE $ matches \en in middle no REG_NEWLINE ^ matches \en in middle no REG_NEWLINE .sp PCRE's behaviour is the same as Perl's, except that there is no equivalent for PCRE_DOLLAR_ENDONLY in Perl. In both PCRE and Perl, there is no way to stop newline from matching [^a]. .P The default POSIX newline handling can be obtained by setting PCRE_DOTALL and PCRE_DOLLAR_ENDONLY, but there is no way to make PCRE behave exactly as for the REG_NEWLINE action. . . .SH "MATCHING A PATTERN" .rs .sp The function \fBregexec()\fP is called to match a compiled pattern \fIpreg\fP against a given \fIstring\fP, which is by default terminated by a zero byte (but see REG_STARTEND below), subject to the options in \fIeflags\fP. These can be: .sp REG_NOTBOL .sp The PCRE_NOTBOL option is set when calling the underlying PCRE matching function. .sp REG_NOTEMPTY .sp The PCRE_NOTEMPTY option is set when calling the underlying PCRE matching function. Note that REG_NOTEMPTY is not part of the POSIX standard. However, setting this option can give more POSIX-like behaviour in some situations. .sp REG_NOTEOL .sp The PCRE_NOTEOL option is set when calling the underlying PCRE matching function. .sp REG_STARTEND .sp The string is considered to start at \fIstring\fP + \fIpmatch[0].rm_so\fP and to have a terminating NUL located at \fIstring\fP + \fIpmatch[0].rm_eo\fP (there need not actually be a NUL at that location), regardless of the value of \fInmatch\fP. This is a BSD extension, compatible with but not specified by IEEE Standard 1003.2 (POSIX.2), and should be used with caution in software intended to be portable to other systems. Note that a non-zero \fIrm_so\fP does not imply REG_NOTBOL; REG_STARTEND affects only the location of the string, not how it is matched. .P If the pattern was compiled with the REG_NOSUB flag, no data about any matched strings is returned. The \fInmatch\fP and \fIpmatch\fP arguments of \fBregexec()\fP are ignored. .P If the value of \fInmatch\fP is zero, or if the value \fIpmatch\fP is NULL, no data about any matched strings is returned. .P Otherwise,the portion of the string that was matched, and also any captured substrings, are returned via the \fIpmatch\fP argument, which points to an array of \fInmatch\fP structures of type \fIregmatch_t\fP, containing the members \fIrm_so\fP and \fIrm_eo\fP. These contain the offset to the first character of each substring and the offset to the first character after the end of each substring, respectively. The 0th element of the vector relates to the entire portion of \fIstring\fP that was matched; subsequent elements relate to the capturing subpatterns of the regular expression. Unused entries in the array have both structure members set to -1. .P A successful match yields a zero return; various error codes are defined in the header file, of which REG_NOMATCH is the "expected" failure code. . . .SH "ERROR MESSAGES" .rs .sp The \fBregerror()\fP function maps a non-zero errorcode from either \fBregcomp()\fP or \fBregexec()\fP to a printable message. If \fIpreg\fP is not NULL, the error should have arisen from the use of that structure. A message terminated by a binary zero is placed in \fIerrbuf\fP. The length of the message, including the zero, is limited to \fIerrbuf_size\fP. The yield of the function is the size of buffer needed to hold the whole message. . . .SH MEMORY USAGE .rs .sp Compiling a regular expression causes memory to be allocated and associated with the \fIpreg\fP structure. The function \fBregfree()\fP frees all such memory, after which \fIpreg\fP may no longer be used as a compiled expression. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 09 January 2012 Copyright (c) 1997-2012 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcreprecompile.3 ================================================ .TH PCREPRECOMPILE 3 "12 November 2013" "PCRE 8.34" .SH NAME PCRE - Perl-compatible regular expressions .SH "SAVING AND RE-USING PRECOMPILED PCRE PATTERNS" .rs .sp If you are running an application that uses a large number of regular expression patterns, it may be useful to store them in a precompiled form instead of having to compile them every time the application is run. If you are not using any private character tables (see the .\" HREF \fBpcre_maketables()\fP .\" documentation), this is relatively straightforward. If you are using private tables, it is a little bit more complicated. However, if you are using the just-in-time optimization feature, it is not possible to save and reload the JIT data. .P If you save compiled patterns to a file, you can copy them to a different host and run them there. If the two hosts have different endianness (byte order), you should run the \fBpcre[16|32]_pattern_to_host_byte_order()\fP function on the new host before trying to match the pattern. The matching functions return PCRE_ERROR_BADENDIANNESS if they detect a pattern with the wrong endianness. .P Compiling regular expressions with one version of PCRE for use with a different version is not guaranteed to work and may cause crashes, and saving and restoring a compiled pattern loses any JIT optimization data. . . .SH "SAVING A COMPILED PATTERN" .rs .sp The value returned by \fBpcre[16|32]_compile()\fP points to a single block of memory that holds the compiled pattern and associated data. You can find the length of this block in bytes by calling \fBpcre[16|32]_fullinfo()\fP with an argument of PCRE_INFO_SIZE. You can then save the data in any appropriate manner. Here is sample code for the 8-bit library that compiles a pattern and writes it to a file. It assumes that the variable \fIfd\fP refers to a file that is open for output: .sp int erroroffset, rc, size; char *error; pcre *re; .sp re = pcre_compile("my pattern", 0, &error, &erroroffset, NULL); if (re == NULL) { ... handle errors ... } rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); if (rc < 0) { ... handle errors ... } rc = fwrite(re, 1, size, fd); if (rc != size) { ... handle errors ... } .sp In this example, the bytes that comprise the compiled pattern are copied exactly. Note that this is binary data that may contain any of the 256 possible byte values. On systems that make a distinction between binary and non-binary data, be sure that the file is opened for binary output. .P If you want to write more than one pattern to a file, you will have to devise a way of separating them. For binary data, preceding each pattern with its length is probably the most straightforward approach. Another possibility is to write out the data in hexadecimal instead of binary, one pattern to a line. .P Saving compiled patterns in a file is only one possible way of storing them for later use. They could equally well be saved in a database, or in the memory of some daemon process that passes them via sockets to the processes that want them. .P If the pattern has been studied, it is also possible to save the normal study data in a similar way to the compiled pattern itself. However, if the PCRE_STUDY_JIT_COMPILE was used, the just-in-time data that is created cannot be saved because it is too dependent on the current environment. When studying generates additional information, \fBpcre[16|32]_study()\fP returns a pointer to a \fBpcre[16|32]_extra\fP data block. Its format is defined in the .\" HTML .\" section on matching a pattern .\" in the .\" HREF \fBpcreapi\fP .\" documentation. The \fIstudy_data\fP field points to the binary study data, and this is what you must save (not the \fBpcre[16|32]_extra\fP block itself). The length of the study data can be obtained by calling \fBpcre[16|32]_fullinfo()\fP with an argument of PCRE_INFO_STUDYSIZE. Remember to check that \fBpcre[16|32]_study()\fP did return a non-NULL value before trying to save the study data. . . .SH "RE-USING A PRECOMPILED PATTERN" .rs .sp Re-using a precompiled pattern is straightforward. Having reloaded it into main memory, called \fBpcre[16|32]_pattern_to_host_byte_order()\fP if necessary, you pass its pointer to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP in the usual way. .P However, if you passed a pointer to custom character tables when the pattern was compiled (the \fItableptr\fP argument of \fBpcre[16|32]_compile()\fP), you must now pass a similar pointer to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP, because the value saved with the compiled pattern will obviously be nonsense. A field in a \fBpcre[16|32]_extra()\fP block is used to pass this data, as described in the .\" HTML .\" section on matching a pattern .\" in the .\" HREF \fBpcreapi\fP .\" documentation. .P \fBWarning:\fP The tables that \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP use must be the same as those that were used when the pattern was compiled. If this is not the case, the behaviour is undefined. .P If you did not provide custom character tables when the pattern was compiled, the pointer in the compiled pattern is NULL, which causes the matching functions to use PCRE's internal tables. Thus, you do not need to take any special action at run time in this case. .P If you saved study data with the compiled pattern, you need to create your own \fBpcre[16|32]_extra\fP data block and set the \fIstudy_data\fP field to point to the reloaded study data. You must also set the PCRE_EXTRA_STUDY_DATA bit in the \fIflags\fP field to indicate that study data is present. Then pass the \fBpcre[16|32]_extra\fP block to the matching function in the usual way. If the pattern was studied for just-in-time optimization, that data cannot be saved, and so is lost by a save/restore cycle. . . .SH "COMPATIBILITY WITH DIFFERENT PCRE RELEASES" .rs .sp In general, it is safest to recompile all saved patterns when you update to a new PCRE release, though not all updates actually require this. . . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 12 November 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcresample.3 ================================================ .TH PCRESAMPLE 3 "10 January 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE SAMPLE PROGRAM" .rs .sp A simple, complete demonstration program, to get you started with using PCRE, is supplied in the file \fIpcredemo.c\fP in the PCRE distribution. A listing of this program is given in the .\" HREF \fBpcredemo\fP .\" documentation. If you do not have a copy of the PCRE distribution, you can save this listing to re-create \fIpcredemo.c\fP. .P The demonstration program, which uses the original PCRE 8-bit library, compiles the regular expression that is its first argument, and matches it against the subject string in its second argument. No PCRE options are set, and default character tables are used. If matching succeeds, the program outputs the portion of the subject that matched, together with the contents of any captured substrings. .P If the -g option is given on the command line, the program then goes on to check for further matches of the same regular expression in the same subject string. The logic is a little bit tricky because of the possibility of matching an empty string. Comments in the code explain what is going on. .P If PCRE is installed in the standard include and library directories for your operating system, you should be able to compile the demonstration program using this command: .sp gcc -o pcredemo pcredemo.c -lpcre .sp If PCRE is installed elsewhere, you may need to add additional options to the command line. For example, on a Unix-like system that has PCRE installed in \fI/usr/local\fP, you can compile the demonstration program using a command like this: .sp .\" JOINSH gcc -o pcredemo -I/usr/local/include pcredemo.c \e -L/usr/local/lib -lpcre .sp In a Windows environment, if you want to statically link the program against a non-dll \fBpcre.a\fP file, you must uncomment the line that defines PCRE_STATIC before including \fBpcre.h\fP, because otherwise the \fBpcre_malloc()\fP and \fBpcre_free()\fP exported functions will be declared \fB__declspec(dllimport)\fP, with unwanted results. .P Once you have compiled and linked the demonstration program, you can run simple tests like this: .sp ./pcredemo 'cat|dog' 'the cat sat on the mat' ./pcredemo -g 'cat|dog' 'the dog sat on the cat' .sp Note that there is a much more comprehensive test program, called .\" HREF \fBpcretest\fP, .\" which supports many more facilities for testing regular expressions and both PCRE libraries. The .\" HREF \fBpcredemo\fP .\" program is provided as a simple coding example. .P If you try to run .\" HREF \fBpcredemo\fP .\" when PCRE is not installed in the standard library directory, you may get an error like this on some operating systems (e.g. Solaris): .sp ld.so.1: a.out: fatal: libpcre.so.0: open failed: No such file or directory .sp This is caused by the way shared library support works on those systems. You need to add .sp -R/usr/local/lib .sp (for example) to the compile command to get round this problem. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 10 January 2012 Copyright (c) 1997-2012 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcrestack.3 ================================================ .TH PCRESTACK 3 "24 June 2012" "PCRE 8.30" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE DISCUSSION OF STACK USAGE" .rs .sp When you call \fBpcre[16|32]_exec()\fP, it makes use of an internal function called \fBmatch()\fP. This calls itself recursively at branch points in the pattern, in order to remember the state of the match so that it can back up and try a different alternative if the first one fails. As matching proceeds deeper and deeper into the tree of possibilities, the recursion depth increases. The \fBmatch()\fP function is also called in other circumstances, for example, whenever a parenthesized sub-pattern is entered, and in certain cases of repetition. .P Not all calls of \fBmatch()\fP increase the recursion depth; for an item such as a* it may be called several times at the same level, after matching different numbers of a's. Furthermore, in a number of cases where the result of the recursive call would immediately be passed back as the result of the current call (a "tail recursion"), the function is just restarted instead. .P The above comments apply when \fBpcre[16|32]_exec()\fP is run in its normal interpretive manner. If the pattern was studied with the PCRE_STUDY_JIT_COMPILE option, and just-in-time compiling was successful, and the options passed to \fBpcre[16|32]_exec()\fP were not incompatible, the matching process uses the JIT-compiled code instead of the \fBmatch()\fP function. In this case, the memory requirements are handled entirely differently. See the .\" HREF \fBpcrejit\fP .\" documentation for details. .P The \fBpcre[16|32]_dfa_exec()\fP function operates in an entirely different way, and uses recursion only when there is a regular expression recursion or subroutine call in the pattern. This includes the processing of assertion and "once-only" subpatterns, which are handled like subroutine calls. Normally, these are never very deep, and the limit on the complexity of \fBpcre[16|32]_dfa_exec()\fP is controlled by the amount of workspace it is given. However, it is possible to write patterns with runaway infinite recursions; such patterns will cause \fBpcre[16|32]_dfa_exec()\fP to run out of stack. At present, there is no protection against this. .P The comments that follow do NOT apply to \fBpcre[16|32]_dfa_exec()\fP; they are relevant only for \fBpcre[16|32]_exec()\fP without the JIT optimization. . . .SS "Reducing \fBpcre[16|32]_exec()\fP's stack usage" .rs .sp Each time that \fBmatch()\fP is actually called recursively, it uses memory from the process stack. For certain kinds of pattern and data, very large amounts of stack may be needed, despite the recognition of "tail recursion". You can often reduce the amount of recursion, and therefore the amount of stack used, by modifying the pattern that is being matched. Consider, for example, this pattern: .sp ([^<]|<(?!inet))+ .sp It matches from wherever it starts until it encounters " .\" section on extra data for \fBpcre[16|32]_exec()\fP .\" in the .\" HREF \fBpcreapi\fP .\" documentation. .P As a very rough rule of thumb, you should reckon on about 500 bytes per recursion. Thus, if you want to limit your stack usage to 8Mb, you should set the limit at 16000 recursions. A 64Mb stack, on the other hand, can support around 128000 recursions. .P In Unix-like environments, the \fBpcretest\fP test program has a command line option (\fB-S\fP) that can be used to increase the size of its stack. As long as the stack is large enough, another option (\fB-M\fP) can be used to find the smallest limits that allow a particular pattern to match a given subject string. This is done by calling \fBpcre[16|32]_exec()\fP repeatedly with different limits. . . .SS "Obtaining an estimate of stack usage" .rs .sp The actual amount of stack used per recursion can vary quite a lot, depending on the compiler that was used to build PCRE and the optimization or debugging options that were set for it. The rule of thumb value of 500 bytes mentioned above may be larger or smaller than what is actually needed. A better approximation can be obtained by running this command: .sp pcretest -m -C .sp The \fB-C\fP option causes \fBpcretest\fP to output information about the options with which PCRE was compiled. When \fB-m\fP is also given (before \fB-C\fP), information about stack use is given in a line like this: .sp Match recursion uses stack: approximate frame size = 640 bytes .sp The value is approximate because some recursions need a bit more (up to perhaps 16 more bytes). .P If the above command is given when PCRE is compiled to use the heap instead of the stack for recursion, the value that is output is the size of each block that is obtained from the heap. . . .SS "Changing stack size in Unix-like systems" .rs .sp In Unix-like environments, there is not often a problem with the stack unless very long strings are involved, though the default limit on stack size varies from system to system. Values from 8Mb to 64Mb are common. You can find your default limit by running the command: .sp ulimit -s .sp Unfortunately, the effect of running out of stack is often SIGSEGV, though sometimes a more explicit error message is given. You can normally increase the limit on stack size by code such as this: .sp struct rlimit rlim; getrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = 100*1024*1024; setrlimit(RLIMIT_STACK, &rlim); .sp This reads the current limits (soft and hard) using \fBgetrlimit()\fP, then attempts to increase the soft limit to 100Mb using \fBsetrlimit()\fP. You must do this before calling \fBpcre[16|32]_exec()\fP. . . .SS "Changing stack size in Mac OS X" .rs .sp Using \fBsetrlimit()\fP, as described above, should also work on Mac OS X. It is also possible to set a stack size when linking a program. There is a discussion about stack sizes in Mac OS X at this web site: .\" HTML .\" http://developer.apple.com/qa/qa2005/qa1419.html. .\" . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 24 June 2012 Copyright (c) 1997-2012 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcresyntax.3 ================================================ .TH PCRESYNTAX 3 "08 January 2014" "PCRE 8.35" .SH NAME PCRE - Perl-compatible regular expressions .SH "PCRE REGULAR EXPRESSION SYNTAX SUMMARY" .rs .sp The full syntax and semantics of the regular expressions that are supported by PCRE are described in the .\" HREF \fBpcrepattern\fP .\" documentation. This document contains a quick-reference summary of the syntax. . . .SH "QUOTING" .rs .sp \ex where x is non-alphanumeric is a literal x \eQ...\eE treat enclosed characters as literal . . .SH "CHARACTERS" .rs .sp \ea alarm, that is, the BEL character (hex 07) \ecx "control-x", where x is any ASCII character \ee escape (hex 1B) \ef form feed (hex 0C) \en newline (hex 0A) \er carriage return (hex 0D) \et tab (hex 09) \e0dd character with octal code 0dd \eddd character with octal code ddd, or backreference \eo{ddd..} character with octal code ddd.. \exhh character with hex code hh \ex{hhh..} character with hex code hhh.. .sp Note that \e0dd is always an octal code, and that \e8 and \e9 are the literal characters "8" and "9". . . .SH "CHARACTER TYPES" .rs .sp . any character except newline; in dotall mode, any character whatsoever \eC one data unit, even in UTF mode (best avoided) \ed a decimal digit \eD a character that is not a decimal digit \eh a horizontal white space character \eH a character that is not a horizontal white space character \eN a character that is not a newline \ep{\fIxx\fP} a character with the \fIxx\fP property \eP{\fIxx\fP} a character without the \fIxx\fP property \eR a newline sequence \es a white space character \eS a character that is not a white space character \ev a vertical white space character \eV a character that is not a vertical white space character \ew a "word" character \eW a "non-word" character \eX a Unicode extended grapheme cluster .sp By default, \ed, \es, and \ew match only ASCII characters, even in UTF-8 mode or in the 16- bit and 32-bit libraries. However, if locale-specific matching is happening, \es and \ew may also match characters with code points in the range 128-255. If the PCRE_UCP option is set, the behaviour of these escape sequences is changed to use Unicode properties and they match many more characters. . . .SH "GENERAL CATEGORY PROPERTIES FOR \ep and \eP" .rs .sp C Other Cc Control Cf Format Cn Unassigned Co Private use Cs Surrogate .sp L Letter Ll Lower case letter Lm Modifier letter Lo Other letter Lt Title case letter Lu Upper case letter L& Ll, Lu, or Lt .sp M Mark Mc Spacing mark Me Enclosing mark Mn Non-spacing mark .sp N Number Nd Decimal number Nl Letter number No Other number .sp P Punctuation Pc Connector punctuation Pd Dash punctuation Pe Close punctuation Pf Final punctuation Pi Initial punctuation Po Other punctuation Ps Open punctuation .sp S Symbol Sc Currency symbol Sk Modifier symbol Sm Mathematical symbol So Other symbol .sp Z Separator Zl Line separator Zp Paragraph separator Zs Space separator . . .SH "PCRE SPECIAL CATEGORY PROPERTIES FOR \ep and \eP" .rs .sp Xan Alphanumeric: union of properties L and N Xps POSIX space: property Z or tab, NL, VT, FF, CR Xsp Perl space: property Z or tab, NL, VT, FF, CR Xuc Univerally-named character: one that can be represented by a Universal Character Name Xwd Perl word: property Xan or underscore .sp Perl and POSIX space are now the same. Perl added VT to its space character set at release 5.18 and PCRE changed at release 8.34. . . .SH "SCRIPT NAMES FOR \ep AND \eP" .rs .sp Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Carian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cuneiform, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hieroglyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscriptional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Linear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Shavian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi. . . .SH "CHARACTER CLASSES" .rs .sp [...] positive character class [^...] negative character class [x-y] range (can be used for hex characters) [[:xxx:]] positive POSIX named set [[:^xxx:]] negative POSIX named set .sp alnum alphanumeric alpha alphabetic ascii 0-127 blank space or tab cntrl control character digit decimal digit graph printing, excluding space lower lower case letter print printing, including space punct printing, excluding alphanumeric space white space upper upper case letter word same as \ew xdigit hexadecimal digit .sp In PCRE, POSIX character set names recognize only ASCII characters by default, but some of them use Unicode properties if PCRE_UCP is set. You can use \eQ...\eE inside a character class. . . .SH "QUANTIFIERS" .rs .sp ? 0 or 1, greedy ?+ 0 or 1, possessive ?? 0 or 1, lazy * 0 or more, greedy *+ 0 or more, possessive *? 0 or more, lazy + 1 or more, greedy ++ 1 or more, possessive +? 1 or more, lazy {n} exactly n {n,m} at least n, no more than m, greedy {n,m}+ at least n, no more than m, possessive {n,m}? at least n, no more than m, lazy {n,} n or more, greedy {n,}+ n or more, possessive {n,}? n or more, lazy . . .SH "ANCHORS AND SIMPLE ASSERTIONS" .rs .sp \eb word boundary \eB not a word boundary ^ start of subject also after internal newline in multiline mode \eA start of subject $ end of subject also before newline at end of subject also before internal newline in multiline mode \eZ end of subject also before newline at end of subject \ez end of subject \eG first matching position in subject . . .SH "MATCH POINT RESET" .rs .sp \eK reset start of match .sp \eK is honoured in positive assertions, but ignored in negative ones. . . .SH "ALTERNATION" .rs .sp expr|expr|expr... . . .SH "CAPTURING" .rs .sp (...) capturing group (?...) named capturing group (Perl) (?'name'...) named capturing group (Perl) (?P...) named capturing group (Python) (?:...) non-capturing group (?|...) non-capturing group; reset group numbers for capturing groups in each alternative . . .SH "ATOMIC GROUPS" .rs .sp (?>...) atomic, non-capturing group . . . . .SH "COMMENT" .rs .sp (?#....) comment (not nestable) . . .SH "OPTION SETTING" .rs .sp (?i) caseless (?J) allow duplicate names (?m) multiline (?s) single line (dotall) (?U) default ungreedy (lazy) (?x) extended (ignore white space) (?-...) unset option(s) .sp The following are recognized only at the very start of a pattern or after one of the newline or \eR options with similar syntax. More than one of them may appear. .sp (*LIMIT_MATCH=d) set the match limit to d (decimal number) (*LIMIT_RECURSION=d) set the recursion limit to d (decimal number) (*NO_AUTO_POSSESS) no auto-possessification (PCRE_NO_AUTO_POSSESS) (*NO_START_OPT) no start-match optimization (PCRE_NO_START_OPTIMIZE) (*UTF8) set UTF-8 mode: 8-bit library (PCRE_UTF8) (*UTF16) set UTF-16 mode: 16-bit library (PCRE_UTF16) (*UTF32) set UTF-32 mode: 32-bit library (PCRE_UTF32) (*UTF) set appropriate UTF mode for the library in use (*UCP) set PCRE_UCP (use Unicode properties for \ed etc) .sp Note that LIMIT_MATCH and LIMIT_RECURSION can only reduce the value of the limits set by the caller of pcre_exec(), not increase them. . . .SH "NEWLINE CONVENTION" .rs .sp These are recognized only at the very start of the pattern or after option settings with a similar syntax. .sp (*CR) carriage return only (*LF) linefeed only (*CRLF) carriage return followed by linefeed (*ANYCRLF) all three of the above (*ANY) any Unicode newline sequence . . .SH "WHAT \eR MATCHES" .rs .sp These are recognized only at the very start of the pattern or after option setting with a similar syntax. .sp (*BSR_ANYCRLF) CR, LF, or CRLF (*BSR_UNICODE) any Unicode newline sequence . . .SH "LOOKAHEAD AND LOOKBEHIND ASSERTIONS" .rs .sp (?=...) positive look ahead (?!...) negative look ahead (?<=...) positive look behind (? reference by name (Perl) \ek'name' reference by name (Perl) \eg{name} reference by name (Perl) \ek{name} reference by name (.NET) (?P=name) reference by name (Python) . . .SH "SUBROUTINE REFERENCES (POSSIBLY RECURSIVE)" .rs .sp (?R) recurse whole pattern (?n) call subpattern by absolute number (?+n) call subpattern by relative number (?-n) call subpattern by relative number (?&name) call subpattern by name (Perl) (?P>name) call subpattern by name (Python) \eg call subpattern by name (Oniguruma) \eg'name' call subpattern by name (Oniguruma) \eg call subpattern by absolute number (Oniguruma) \eg'n' call subpattern by absolute number (Oniguruma) \eg<+n> call subpattern by relative number (PCRE extension) \eg'+n' call subpattern by relative number (PCRE extension) \eg<-n> call subpattern by relative number (PCRE extension) \eg'-n' call subpattern by relative number (PCRE extension) . . .SH "CONDITIONAL PATTERNS" .rs .sp (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) .sp (?(n)... absolute reference condition (?(+n)... relative reference condition (?(-n)... relative reference condition (?()... named reference condition (Perl) (?('name')... named reference condition (Perl) (?(name)... named reference condition (PCRE) (?(R)... overall recursion condition (?(Rn)... specific group recursion condition (?(R&name)... specific recursion condition (?(DEFINE)... define subpattern for reference (?(assert)... assertion condition . . .SH "BACKTRACKING CONTROL" .rs .sp The following act immediately they are reached: .sp (*ACCEPT) force successful match (*FAIL) force backtrack; synonym (*F) (*MARK:NAME) set name to be passed back; synonym (*:NAME) .sp The following act only when a subsequent match failure causes a backtrack to reach them. They all force a match failure, but they differ in what happens afterwards. Those that advance the start-of-match point do so only if the pattern is not anchored. .sp (*COMMIT) overall failure, no advance of starting point (*PRUNE) advance to next starting character (*PRUNE:NAME) equivalent to (*MARK:NAME)(*PRUNE) (*SKIP) advance to current matching position (*SKIP:NAME) advance to position corresponding to an earlier (*MARK:NAME); if not found, the (*SKIP) is ignored (*THEN) local failure, backtrack to next alternation (*THEN:NAME) equivalent to (*MARK:NAME)(*THEN) . . .SH "CALLOUTS" .rs .sp (?C) callout (?Cn) callout with data n . . .SH "SEE ALSO" .rs .sp \fBpcrepattern\fP(3), \fBpcreapi\fP(3), \fBpcrecallout\fP(3), \fBpcrematching\fP(3), \fBpcre\fP(3). . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 08 January 2014 Copyright (c) 1997-2014 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/pcretest.1 ================================================ .TH PCRETEST 1 "23 February 2017" "PCRE 8.41" .SH NAME pcretest - a program for testing Perl-compatible regular expressions. .SH SYNOPSIS .rs .sp .B pcretest "[options] [input file [output file]]" .sp \fBpcretest\fP was written as a test program for the PCRE regular expression library itself, but it can also be used for experimenting with regular expressions. This document describes the features of the test program; for details of the regular expressions themselves, see the .\" HREF \fBpcrepattern\fP .\" documentation. For details of the PCRE library function calls and their options, see the .\" HREF \fBpcreapi\fP .\" , .\" HREF \fBpcre16\fP and .\" HREF \fBpcre32\fP .\" documentation. .P The input for \fBpcretest\fP is a sequence of regular expression patterns and strings to be matched, as described below. The output shows the result of each match. Options on the command line and the patterns control PCRE options and exactly what is output. .P As PCRE has evolved, it has acquired many different features, and as a result, \fBpcretest\fP now has rather a lot of obscure options for testing every possible feature. Some of these options are specifically designed for use in conjunction with the test script and data files that are distributed as part of PCRE, and are unlikely to be of use otherwise. They are all documented here, but without much justification. . . .SH "INPUT DATA FORMAT" .rs .sp Input to \fBpcretest\fP is processed line by line, either by calling the C library's \fBfgets()\fP function, or via the \fBlibreadline\fP library (see below). In Unix-like environments, \fBfgets()\fP treats any bytes other than newline as data characters. However, in some Windows environments character 26 (hex 1A) causes an immediate end of file, and no further data is read. For maximum portability, therefore, it is safest to use only ASCII characters in \fBpcretest\fP input files. .P The input is processed using using C's string functions, so must not contain binary zeroes, even though in Unix-like environments, \fBfgets()\fP treats any bytes other than newline as data characters. . . .SH "PCRE's 8-BIT, 16-BIT AND 32-BIT LIBRARIES" .rs .sp From release 8.30, two separate PCRE libraries can be built. The original one supports 8-bit character strings, whereas the newer 16-bit library supports character strings encoded in 16-bit units. From release 8.32, a third library can be built, supporting character strings encoded in 32-bit units. The \fBpcretest\fP program can be used to test all three libraries. However, it is itself still an 8-bit program, reading 8-bit input and writing 8-bit output. When testing the 16-bit or 32-bit library, the patterns and data strings are converted to 16- or 32-bit format before being passed to the PCRE library functions. Results are converted to 8-bit for output. .P References to functions and structures of the form \fBpcre[16|32]_xx\fP below mean "\fBpcre_xx\fP when using the 8-bit library, \fBpcre16_xx\fP when using the 16-bit library, or \fBpcre32_xx\fP when using the 32-bit library". . . .SH "COMMAND LINE OPTIONS" .rs .TP 10 \fB-8\fP If both the 8-bit library has been built, this option causes the 8-bit library to be used (which is the default); if the 8-bit library has not been built, this option causes an error. .TP 10 \fB-16\fP If both the 8-bit or the 32-bit, and the 16-bit libraries have been built, this option causes the 16-bit library to be used. If only the 16-bit library has been built, this is the default (so has no effect). If only the 8-bit or the 32-bit library has been built, this option causes an error. .TP 10 \fB-32\fP If both the 8-bit or the 16-bit, and the 32-bit libraries have been built, this option causes the 32-bit library to be used. If only the 32-bit library has been built, this is the default (so has no effect). If only the 8-bit or the 16-bit library has been built, this option causes an error. .TP 10 \fB-b\fP Behave as if each pattern has the \fB/B\fP (show byte code) modifier; the internal form is output after compilation. .TP 10 \fB-C\fP Output the version number of the PCRE library, and all available information about the optional features that are included, and then exit with zero exit code. All other options are ignored. .TP 10 \fB-C\fP \fIoption\fP Output information about a specific build-time option, then exit. This functionality is intended for use in scripts such as \fBRunTest\fP. The following options output the value and set the exit code as indicated: .sp ebcdic-nl the code for LF (= NL) in an EBCDIC environment: 0x15 or 0x25 0 if used in an ASCII environment exit code is always 0 linksize the configured internal link size (2, 3, or 4) exit code is set to the link size newline the default newline setting: CR, LF, CRLF, ANYCRLF, or ANY exit code is always 0 bsr the default setting for what \eR matches: ANYCRLF or ANY exit code is always 0 .sp The following options output 1 for true or 0 for false, and set the exit code to the same value: .sp ebcdic compiled for an EBCDIC environment jit just-in-time support is available pcre16 the 16-bit library was built pcre32 the 32-bit library was built pcre8 the 8-bit library was built ucp Unicode property support is available utf UTF-8 and/or UTF-16 and/or UTF-32 support is available .sp If an unknown option is given, an error message is output; the exit code is 0. .TP 10 \fB-d\fP Behave as if each pattern has the \fB/D\fP (debug) modifier; the internal form and information about the compiled pattern is output after compilation; \fB-d\fP is equivalent to \fB-b -i\fP. .TP 10 \fB-dfa\fP Behave as if each data line contains the \eD escape sequence; this causes the alternative matching function, \fBpcre[16|32]_dfa_exec()\fP, to be used instead of the standard \fBpcre[16|32]_exec()\fP function (more detail is given below). .TP 10 \fB-help\fP Output a brief summary these options and then exit. .TP 10 \fB-i\fP Behave as if each pattern has the \fB/I\fP modifier; information about the compiled pattern is given after compilation. .TP 10 \fB-M\fP Behave as if each data line contains the \eM escape sequence; this causes PCRE to discover the minimum MATCH_LIMIT and MATCH_LIMIT_RECURSION settings by calling \fBpcre[16|32]_exec()\fP repeatedly with different limits. .TP 10 \fB-m\fP Output the size of each compiled pattern after it has been compiled. This is equivalent to adding \fB/M\fP to each regular expression. The size is given in bytes for both libraries. .TP 10 \fB-O\fP Behave as if each pattern has the \fB/O\fP modifier, that is disable auto-possessification for all patterns. .TP 10 \fB-o\fP \fIosize\fP Set the number of elements in the output vector that is used when calling \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP to be \fIosize\fP. The default value is 45, which is enough for 14 capturing subexpressions for \fBpcre[16|32]_exec()\fP or 22 different matches for \fBpcre[16|32]_dfa_exec()\fP. The vector size can be changed for individual matching calls by including \eO in the data line (see below). .TP 10 \fB-p\fP Behave as if each pattern has the \fB/P\fP modifier; the POSIX wrapper API is used to call PCRE. None of the other options has any effect when \fB-p\fP is set. This option can be used only with the 8-bit library. .TP 10 \fB-q\fP Do not output the version number of \fBpcretest\fP at the start of execution. .TP 10 \fB-S\fP \fIsize\fP On Unix-like systems, set the size of the run-time stack to \fIsize\fP megabytes. .TP 10 \fB-s\fP or \fB-s+\fP Behave as if each pattern has the \fB/S\fP modifier; in other words, force each pattern to be studied. If \fB-s+\fP is used, all the JIT compile options are passed to \fBpcre[16|32]_study()\fP, causing just-in-time optimization to be set up if it is available, for both full and partial matching. Specific JIT compile options can be selected by following \fB-s+\fP with a digit in the range 1 to 7, which selects the JIT compile modes as follows: .sp 1 normal match only 2 soft partial match only 3 normal match and soft partial match 4 hard partial match only 6 soft and hard partial match 7 all three modes (default) .sp If \fB-s++\fP is used instead of \fB-s+\fP (with or without a following digit), the text "(JIT)" is added to the first output line after a match or no match when JIT-compiled code was actually used. .sp Note that there are pattern options that can override \fB-s\fP, either specifying no studying at all, or suppressing JIT compilation. .sp If the \fB/I\fP or \fB/D\fP option is present on a pattern (requesting output about the compiled pattern), information about the result of studying is not included when studying is caused only by \fB-s\fP and neither \fB-i\fP nor \fB-d\fP is present on the command line. This behaviour means that the output from tests that are run with and without \fB-s\fP should be identical, except when options that output information about the actual running of a match are set. .sp The \fB-M\fP, \fB-t\fP, and \fB-tm\fP options, which give information about resources used, are likely to produce different output with and without \fB-s\fP. Output may also differ if the \fB/C\fP option is present on an individual pattern. This uses callouts to trace the the matching process, and this may be different between studied and non-studied patterns. If the pattern contains (*MARK) items there may also be differences, for the same reason. The \fB-s\fP command line option can be overridden for specific patterns that should never be studied (see the \fB/S\fP pattern modifier below). .TP 10 \fB-t\fP Run each compile, study, and match many times with a timer, and output the resulting times per compile, study, or match (in milliseconds). Do not set \fB-m\fP with \fB-t\fP, because you will then get the size output a zillion times, and the timing will be distorted. You can control the number of iterations that are used for timing by following \fB-t\fP with a number (as a separate item on the command line). For example, "-t 1000" iterates 1000 times. The default is to iterate 500000 times. .TP 10 \fB-tm\fP This is like \fB-t\fP except that it times only the matching phase, not the compile or study phases. .TP 10 \fB-T\fP \fB-TM\fP These behave like \fB-t\fP and \fB-tm\fP, but in addition, at the end of a run, the total times for all compiles, studies, and matches are output. . . .SH DESCRIPTION .rs .sp If \fBpcretest\fP is given two filename arguments, it reads from the first and writes to the second. If it is given only one filename argument, it reads from that file and writes to stdout. Otherwise, it reads from stdin and writes to stdout, and prompts for each line of input, using "re>" to prompt for regular expressions, and "data>" to prompt for data lines. .P When \fBpcretest\fP is built, a configuration option can specify that it should be linked with the \fBlibreadline\fP library. When this is done, if the input is from a terminal, it is read using the \fBreadline()\fP function. This provides line-editing and history facilities. The output from the \fB-help\fP option states whether or not \fBreadline()\fP will be used. .P The program handles any number of sets of input on a single input file. Each set starts with a regular expression, and continues with any number of data lines to be matched against that pattern. .P Each data line is matched separately and independently. If you want to do multi-line matches, you have to use the \en escape sequence (or \er or \er\en, etc., depending on the newline setting) in a single line of input to encode the newline sequences. There is no limit on the length of data lines; the input buffer is automatically extended if it is too small. .P An empty line signals the end of the data lines, at which point a new regular expression is read. The regular expressions are given enclosed in any non-alphanumeric delimiters other than backslash, for example: .sp /(a|bc)x+yz/ .sp White space before the initial delimiter is ignored. A regular expression may be continued over several input lines, in which case the newline characters are included within it. It is possible to include the delimiter within the pattern by escaping it, for example .sp /abc\e/def/ .sp If you do so, the escape and the delimiter form part of the pattern, but since delimiters are always non-alphanumeric, this does not affect its interpretation. If the terminating delimiter is immediately followed by a backslash, for example, .sp /abc/\e .sp then a backslash is added to the end of the pattern. This is done to provide a way of testing the error condition that arises if a pattern finishes with a backslash, because .sp /abc\e/ .sp is interpreted as the first line of a pattern that starts with "abc/", causing pcretest to read the next line as a continuation of the regular expression. . . .SH "PATTERN MODIFIERS" .rs .sp A pattern may be followed by any number of modifiers, which are mostly single characters, though some of these can be qualified by further characters. Following Perl usage, these are referred to below as, for example, "the \fB/i\fP modifier", even though the delimiter of the pattern need not always be a slash, and no slash is used when writing modifiers. White space may appear between the final pattern delimiter and the first modifier, and between the modifiers themselves. For reference, here is a complete list of modifiers. They fall into several groups that are described in detail in the following sections. .sp \fB/8\fP set UTF mode \fB/9\fP set PCRE_NEVER_UTF (locks out UTF mode) \fB/?\fP disable UTF validity check \fB/+\fP show remainder of subject after match \fB/=\fP show all captures (not just those that are set) .sp \fB/A\fP set PCRE_ANCHORED \fB/B\fP show compiled code \fB/C\fP set PCRE_AUTO_CALLOUT \fB/D\fP same as \fB/B\fP plus \fB/I\fP \fB/E\fP set PCRE_DOLLAR_ENDONLY \fB/F\fP flip byte order in compiled pattern \fB/f\fP set PCRE_FIRSTLINE \fB/G\fP find all matches (shorten string) \fB/g\fP find all matches (use startoffset) \fB/I\fP show information about pattern \fB/i\fP set PCRE_CASELESS \fB/J\fP set PCRE_DUPNAMES \fB/K\fP show backtracking control names \fB/L\fP set locale \fB/M\fP show compiled memory size \fB/m\fP set PCRE_MULTILINE \fB/N\fP set PCRE_NO_AUTO_CAPTURE \fB/O\fP set PCRE_NO_AUTO_POSSESS \fB/P\fP use the POSIX wrapper \fB/Q\fP test external stack check function \fB/S\fP study the pattern after compilation \fB/s\fP set PCRE_DOTALL \fB/T\fP select character tables \fB/U\fP set PCRE_UNGREEDY \fB/W\fP set PCRE_UCP \fB/X\fP set PCRE_EXTRA \fB/x\fP set PCRE_EXTENDED \fB/Y\fP set PCRE_NO_START_OPTIMIZE \fB/Z\fP don't show lengths in \fB/B\fP output .sp \fB/\fP set PCRE_NEWLINE_ANY \fB/\fP set PCRE_NEWLINE_ANYCRLF \fB/\fP set PCRE_NEWLINE_CR \fB/\fP set PCRE_NEWLINE_CRLF \fB/\fP set PCRE_NEWLINE_LF \fB/\fP set PCRE_BSR_ANYCRLF \fB/\fP set PCRE_BSR_UNICODE \fB/\fP set PCRE_JAVASCRIPT_COMPAT .sp . . .SS "Perl-compatible modifiers" .rs .sp The \fB/i\fP, \fB/m\fP, \fB/s\fP, and \fB/x\fP modifiers set the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, or PCRE_EXTENDED options, respectively, when \fBpcre[16|32]_compile()\fP is called. These four modifier letters have the same effect as they do in Perl. For example: .sp /caseless/i .sp . . .SS "Modifiers for other PCRE options" .rs .sp The following table shows additional modifiers for setting PCRE compile-time options that do not correspond to anything in Perl: .sp \fB/8\fP PCRE_UTF8 ) when using the 8-bit \fB/?\fP PCRE_NO_UTF8_CHECK ) library .sp \fB/8\fP PCRE_UTF16 ) when using the 16-bit \fB/?\fP PCRE_NO_UTF16_CHECK ) library .sp \fB/8\fP PCRE_UTF32 ) when using the 32-bit \fB/?\fP PCRE_NO_UTF32_CHECK ) library .sp \fB/9\fP PCRE_NEVER_UTF \fB/A\fP PCRE_ANCHORED \fB/C\fP PCRE_AUTO_CALLOUT \fB/E\fP PCRE_DOLLAR_ENDONLY \fB/f\fP PCRE_FIRSTLINE \fB/J\fP PCRE_DUPNAMES \fB/N\fP PCRE_NO_AUTO_CAPTURE \fB/O\fP PCRE_NO_AUTO_POSSESS \fB/U\fP PCRE_UNGREEDY \fB/W\fP PCRE_UCP \fB/X\fP PCRE_EXTRA \fB/Y\fP PCRE_NO_START_OPTIMIZE \fB/\fP PCRE_NEWLINE_ANY \fB/\fP PCRE_NEWLINE_ANYCRLF \fB/\fP PCRE_NEWLINE_CR \fB/\fP PCRE_NEWLINE_CRLF \fB/\fP PCRE_NEWLINE_LF \fB/\fP PCRE_BSR_ANYCRLF \fB/\fP PCRE_BSR_UNICODE \fB/\fP PCRE_JAVASCRIPT_COMPAT .sp The modifiers that are enclosed in angle brackets are literal strings as shown, including the angle brackets, but the letters within can be in either case. This example sets multiline matching with CRLF as the line ending sequence: .sp /^abc/m .sp As well as turning on the PCRE_UTF8/16/32 option, the \fB/8\fP modifier causes all non-printing characters in output strings to be printed using the \ex{hh...} notation. Otherwise, those less than 0x100 are output in hex without the curly brackets. .P Full details of the PCRE options are given in the .\" HREF \fBpcreapi\fP .\" documentation. . . .SS "Finding all matches in a string" .rs .sp Searching for all possible matches within each subject string can be requested by the \fB/g\fP or \fB/G\fP modifier. After finding a match, PCRE is called again to search the remainder of the subject string. The difference between \fB/g\fP and \fB/G\fP is that the former uses the \fIstartoffset\fP argument to \fBpcre[16|32]_exec()\fP to start searching at a new point within the entire string (which is in effect what Perl does), whereas the latter passes over a shortened substring. This makes a difference to the matching process if the pattern begins with a lookbehind assertion (including \eb or \eB). .P If any call to \fBpcre[16|32]_exec()\fP in a \fB/g\fP or \fB/G\fP sequence matches an empty string, the next call is done with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set in order to search for another, non-empty, match at the same point. If this second match fails, the start offset is advanced, and the normal match is retried. This imitates the way Perl handles such cases when using the \fB/g\fP modifier or the \fBsplit()\fP function. Normally, the start offset is advanced by one character, but if the newline convention recognizes CRLF as a newline, and the current character is CR followed by LF, an advance of two is used. . . .SS "Other modifiers" .rs .sp There are yet more modifiers for controlling the way \fBpcretest\fP operates. .P The \fB/+\fP modifier requests that as well as outputting the substring that matched the entire pattern, \fBpcretest\fP should in addition output the remainder of the subject string. This is useful for tests where the subject contains multiple copies of the same substring. If the \fB+\fP modifier appears twice, the same action is taken for captured substrings. In each case the remainder is output on the following line with a plus character following the capture number. Note that this modifier must not immediately follow the /S modifier because /S+ and /S++ have other meanings. .P The \fB/=\fP modifier requests that the values of all potential captured parentheses be output after a match. By default, only those up to the highest one actually used in the match are output (corresponding to the return code from \fBpcre[16|32]_exec()\fP). Values in the offsets vector corresponding to higher numbers should be set to -1, and these are output as "". This modifier gives a way of checking that this is happening. .P The \fB/B\fP modifier is a debugging feature. It requests that \fBpcretest\fP output a representation of the compiled code after compilation. Normally this information contains length and offset values; however, if \fB/Z\fP is also present, this data is replaced by spaces. This is a special feature for use in the automatic test scripts; it ensures that the same output is generated for different internal link sizes. .P The \fB/D\fP modifier is a PCRE debugging feature, and is equivalent to \fB/BI\fP, that is, both the \fB/B\fP and the \fB/I\fP modifiers. .P The \fB/F\fP modifier causes \fBpcretest\fP to flip the byte order of the 2-byte and 4-byte fields in the compiled pattern. This facility is for testing the feature in PCRE that allows it to execute patterns that were compiled on a host with a different endianness. This feature is not available when the POSIX interface to PCRE is being used, that is, when the \fB/P\fP pattern modifier is specified. See also the section about saving and reloading compiled patterns below. .P The \fB/I\fP modifier requests that \fBpcretest\fP output information about the compiled pattern (whether it is anchored, has a fixed first character, and so on). It does this by calling \fBpcre[16|32]_fullinfo()\fP after compiling a pattern. If the pattern is studied, the results of that are also output. In this output, the word "char" means a non-UTF character, that is, the value of a single data item (8-bit, 16-bit, or 32-bit, depending on the library that is being tested). .P The \fB/K\fP modifier requests \fBpcretest\fP to show names from backtracking control verbs that are returned from calls to \fBpcre[16|32]_exec()\fP. It causes \fBpcretest\fP to create a \fBpcre[16|32]_extra\fP block if one has not already been created by a call to \fBpcre[16|32]_study()\fP, and to set the PCRE_EXTRA_MARK flag and the \fBmark\fP field within it, every time that \fBpcre[16|32]_exec()\fP is called. If the variable that the \fBmark\fP field points to is non-NULL for a match, non-match, or partial match, \fBpcretest\fP prints the string to which it points. For a match, this is shown on a line by itself, tagged with "MK:". For a non-match it is added to the message. .P The \fB/L\fP modifier must be followed directly by the name of a locale, for example, .sp /pattern/Lfr_FR .sp For this reason, it must be the last modifier. The given locale is set, \fBpcre[16|32]_maketables()\fP is called to build a set of character tables for the locale, and this is then passed to \fBpcre[16|32]_compile()\fP when compiling the regular expression. Without an \fB/L\fP (or \fB/T\fP) modifier, NULL is passed as the tables pointer; that is, \fB/L\fP applies only to the expression on which it appears. .P The \fB/M\fP modifier causes the size in bytes of the memory block used to hold the compiled pattern to be output. This does not include the size of the \fBpcre[16|32]\fP block; it is just the actual compiled data. If the pattern is successfully studied with the PCRE_STUDY_JIT_COMPILE option, the size of the JIT compiled code is also output. .P The \fB/Q\fP modifier is used to test the use of \fBpcre_stack_guard\fP. It must be followed by '0' or '1', specifying the return code to be given from an external function that is passed to PCRE and used for stack checking during compilation (see the .\" HREF \fBpcreapi\fP .\" documentation for details). .P The \fB/S\fP modifier causes \fBpcre[16|32]_study()\fP to be called after the expression has been compiled, and the results used when the expression is matched. There are a number of qualifying characters that may follow \fB/S\fP. They may appear in any order. .P If \fB/S\fP is followed by an exclamation mark, \fBpcre[16|32]_study()\fP is called with the PCRE_STUDY_EXTRA_NEEDED option, causing it always to return a \fBpcre_extra\fP block, even when studying discovers no useful information. .P If \fB/S\fP is followed by a second S character, it suppresses studying, even if it was requested externally by the \fB-s\fP command line option. This makes it possible to specify that certain patterns are always studied, and others are never studied, independently of \fB-s\fP. This feature is used in the test files in a few cases where the output is different when the pattern is studied. .P If the \fB/S\fP modifier is followed by a + character, the call to \fBpcre[16|32]_study()\fP is made with all the JIT study options, requesting just-in-time optimization support if it is available, for both normal and partial matching. If you want to restrict the JIT compiling modes, you can follow \fB/S+\fP with a digit in the range 1 to 7: .sp 1 normal match only 2 soft partial match only 3 normal match and soft partial match 4 hard partial match only 6 soft and hard partial match 7 all three modes (default) .sp If \fB/S++\fP is used instead of \fB/S+\fP (with or without a following digit), the text "(JIT)" is added to the first output line after a match or no match when JIT-compiled code was actually used. .P Note that there is also an independent \fB/+\fP modifier; it must not be given immediately after \fB/S\fP or \fB/S+\fP because this will be misinterpreted. .P If JIT studying is successful, the compiled JIT code will automatically be used when \fBpcre[16|32]_exec()\fP is run, except when incompatible run-time options are specified. For more details, see the .\" HREF \fBpcrejit\fP .\" documentation. See also the \fB\eJ\fP escape sequence below for a way of setting the size of the JIT stack. .P Finally, if \fB/S\fP is followed by a minus character, JIT compilation is suppressed, even if it was requested externally by the \fB-s\fP command line option. This makes it possible to specify that JIT is never to be used for certain patterns. .P The \fB/T\fP modifier must be followed by a single digit. It causes a specific set of built-in character tables to be passed to \fBpcre[16|32]_compile()\fP. It is used in the standard PCRE tests to check behaviour with different character tables. The digit specifies the tables as follows: .sp 0 the default ASCII tables, as distributed in pcre_chartables.c.dist 1 a set of tables defining ISO 8859 characters .sp In table 1, some characters whose codes are greater than 128 are identified as letters, digits, spaces, etc. . . .SS "Using the POSIX wrapper API" .rs .sp The \fB/P\fP modifier causes \fBpcretest\fP to call PCRE via the POSIX wrapper API rather than its native API. This supports only the 8-bit library. When \fB/P\fP is set, the following modifiers set options for the \fBregcomp()\fP function: .sp /i REG_ICASE /m REG_NEWLINE /N REG_NOSUB /s REG_DOTALL ) /U REG_UNGREEDY ) These options are not part of /W REG_UCP ) the POSIX standard /8 REG_UTF8 ) .sp The \fB/+\fP modifier works as described above. All other modifiers are ignored. . . .SS "Locking out certain modifiers" .rs .sp PCRE can be compiled with or without support for certain features such as UTF-8/16/32 or Unicode properties. Accordingly, the standard tests are split up into a number of different files that are selected for running depending on which features are available. When updating the tests, it is all too easy to put a new test into the wrong file by mistake; for example, to put a test that requires UTF support into a file that is used when it is not available. To help detect such mistakes as early as possible, there is a facility for locking out specific modifiers. If an input line for \fBpcretest\fP starts with the string "< forbid " the following sequence of characters is taken as a list of forbidden modifiers. For example, in the test files that must not use UTF or Unicode property support, this line appears: .sp < forbid 8W .sp This locks out the /8 and /W modifiers. An immediate error is given if they are subsequently encountered. If the character string contains < but not >, all the multi-character modifiers that begin with < are locked out. Otherwise, such modifiers must be explicitly listed, for example: .sp < forbid .sp There must be a single space between < and "forbid" for this feature to be recognised. If there is not, the line is interpreted either as a request to re-load a pre-compiled pattern (see "SAVING AND RELOADING COMPILED PATTERNS" below) or, if there is a another < character, as a pattern that uses < as its delimiter. . . .SH "DATA LINES" .rs .sp Before each data line is passed to \fBpcre[16|32]_exec()\fP, leading and trailing white space is removed, and it is then scanned for \e escapes. Some of these are pretty esoteric features, intended for checking out some of the more complicated features of PCRE. If you are just testing "ordinary" regular expressions, you probably don't need any of these. The following escapes are recognized: .sp \ea alarm (BEL, \ex07) \eb backspace (\ex08) \ee escape (\ex27) \ef form feed (\ex0c) \en newline (\ex0a) .\" JOIN \eqdd set the PCRE_MATCH_LIMIT limit to dd (any number of digits) \er carriage return (\ex0d) \et tab (\ex09) \ev vertical tab (\ex0b) \ennn octal character (up to 3 octal digits); always a byte unless > 255 in UTF-8 or 16-bit or 32-bit mode \eo{dd...} octal character (any number of octal digits} \exhh hexadecimal byte (up to 2 hex digits) \ex{hh...} hexadecimal character (any number of hex digits) .\" JOIN \eA pass the PCRE_ANCHORED option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \eB pass the PCRE_NOTBOL option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \eCdd call pcre[16|32]_copy_substring() for substring dd after a successful match (number less than 32) .\" JOIN \eCname call pcre[16|32]_copy_named_substring() for substring "name" after a successful match (name termin- ated by next non alphanumeric character) .\" JOIN \eC+ show the current captured substrings at callout time \eC- do not supply a callout function .\" JOIN \eC!n return 1 instead of 0 when callout number n is reached .\" JOIN \eC!n!m return 1 instead of 0 when callout number n is reached for the nth time .\" JOIN \eC*n pass the number n (may be negative) as callout data; this is used as the callout return value \eD use the \fBpcre[16|32]_dfa_exec()\fP match function \eF only shortest match for \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \eGdd call pcre[16|32]_get_substring() for substring dd after a successful match (number less than 32) .\" JOIN \eGname call pcre[16|32]_get_named_substring() for substring "name" after a successful match (name termin- ated by next non-alphanumeric character) .\" JOIN \eJdd set up a JIT stack of dd kilobytes maximum (any number of digits) .\" JOIN \eL call pcre[16|32]_get_substringlist() after a successful match .\" JOIN \eM discover the minimum MATCH_LIMIT and MATCH_LIMIT_RECURSION settings .\" JOIN \eN pass the PCRE_NOTEMPTY option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP; if used twice, pass the PCRE_NOTEMPTY_ATSTART option .\" JOIN \eOdd set the size of the output vector passed to \fBpcre[16|32]_exec()\fP to dd (any number of digits) .\" JOIN \eP pass the PCRE_PARTIAL_SOFT option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP; if used twice, pass the PCRE_PARTIAL_HARD option .\" JOIN \eQdd set the PCRE_MATCH_LIMIT_RECURSION limit to dd (any number of digits) \eR pass the PCRE_DFA_RESTART option to \fBpcre[16|32]_dfa_exec()\fP \eS output details of memory get/free calls during matching .\" JOIN \eY pass the PCRE_NO_START_OPTIMIZE option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \eZ pass the PCRE_NOTEOL option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e? pass the PCRE_NO_UTF[8|16|32]_CHECK option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e>dd start the match at offset dd (optional "-"; then any number of digits); this sets the \fIstartoffset\fP argument for \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e pass the PCRE_NEWLINE_CR option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e pass the PCRE_NEWLINE_LF option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e pass the PCRE_NEWLINE_CRLF option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e pass the PCRE_NEWLINE_ANYCRLF option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .\" JOIN \e pass the PCRE_NEWLINE_ANY option to \fBpcre[16|32]_exec()\fP or \fBpcre[16|32]_dfa_exec()\fP .sp The use of \ex{hh...} is not dependent on the use of the \fB/8\fP modifier on the pattern. It is recognized always. There may be any number of hexadecimal digits inside the braces; invalid values provoke error messages. .P Note that \exhh specifies one byte rather than one character in UTF-8 mode; this makes it possible to construct invalid UTF-8 sequences for testing purposes. On the other hand, \ex{hh} is interpreted as a UTF-8 character in UTF-8 mode, generating more than one byte if the value is greater than 127. When testing the 8-bit library not in UTF-8 mode, \ex{hh} generates one byte for values less than 256, and causes an error for greater values. .P In UTF-16 mode, all 4-digit \ex{hhhh} values are accepted. This makes it possible to construct invalid UTF-16 sequences for testing purposes. .P In UTF-32 mode, all 4- to 8-digit \ex{...} values are accepted. This makes it possible to construct invalid UTF-32 sequences for testing purposes. .P The escapes that specify line ending sequences are literal strings, exactly as shown. No more than one newline setting should be present in any data line. .P A backslash followed by anything else just escapes the anything else. If the very last character is a backslash, it is ignored. This gives a way of passing an empty line as data, since a real empty line terminates the data input. .P The \fB\eJ\fP escape provides a way of setting the maximum stack size that is used by the just-in-time optimization code. It is ignored if JIT optimization is not being used. Providing a stack that is larger than the default 32K is necessary only for very complicated patterns. .P If \eM is present, \fBpcretest\fP calls \fBpcre[16|32]_exec()\fP several times, with different values in the \fImatch_limit\fP and \fImatch_limit_recursion\fP fields of the \fBpcre[16|32]_extra\fP data structure, until it finds the minimum numbers for each parameter that allow \fBpcre[16|32]_exec()\fP to complete without error. Because this is testing a specific feature of the normal interpretive \fBpcre[16|32]_exec()\fP execution, the use of any JIT optimization that might have been set up by the \fB/S+\fP qualifier of \fB-s+\fP option is disabled. .P The \fImatch_limit\fP number is a measure of the amount of backtracking that takes place, and checking it out can be instructive. For most simple matches, the number is quite small, but for patterns with very large numbers of matching possibilities, it can become large very quickly with increasing length of subject string. The \fImatch_limit_recursion\fP number is a measure of how much stack (or, if PCRE is compiled with NO_RECURSE, how much heap) memory is needed to complete the match attempt. .P When \eO is used, the value specified may be higher or lower than the size set by the \fB-O\fP command line option (or defaulted to 45); \eO applies only to the call of \fBpcre[16|32]_exec()\fP for the line in which it appears. .P If the \fB/P\fP modifier was present on the pattern, causing the POSIX wrapper API to be used, the only option-setting sequences that have any effect are \eB, \eN, and \eZ, causing REG_NOTBOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to \fBregexec()\fP. . . .SH "THE ALTERNATIVE MATCHING FUNCTION" .rs .sp By default, \fBpcretest\fP uses the standard PCRE matching function, \fBpcre[16|32]_exec()\fP to match each data line. PCRE also supports an alternative matching function, \fBpcre[16|32]_dfa_test()\fP, which operates in a different way, and has some restrictions. The differences between the two functions are described in the .\" HREF \fBpcrematching\fP .\" documentation. .P If a data line contains the \eD escape sequence, or if the command line contains the \fB-dfa\fP option, the alternative matching function is used. This function finds all possible matches at a given point. If, however, the \eF escape sequence is present in the data line, it stops after the first match is found. This is always the shortest possible match. . . .SH "DEFAULT OUTPUT FROM PCRETEST" .rs .sp This section describes the output when the normal matching function, \fBpcre[16|32]_exec()\fP, is being used. .P When a match succeeds, \fBpcretest\fP outputs the list of captured substrings that \fBpcre[16|32]_exec()\fP returns, starting with number 0 for the string that matched the whole pattern. Otherwise, it outputs "No match" when the return is PCRE_ERROR_NOMATCH, and "Partial match:" followed by the partially matching substring when \fBpcre[16|32]_exec()\fP returns PCRE_ERROR_PARTIAL. (Note that this is the entire substring that was inspected during the partial match; it may include characters before the actual match start if a lookbehind assertion, \eK, \eb, or \eB was involved.) For any other return, \fBpcretest\fP outputs the PCRE negative error number and a short descriptive phrase. If the error is a failed UTF string check, the offset of the start of the failing character and the reason code are also output, provided that the size of the output vector is at least two. Here is an example of an interactive \fBpcretest\fP run. .sp $ pcretest PCRE version 8.13 2011-04-30 .sp re> /^abc(\ed+)/ data> abc123 0: abc123 1: 123 data> xyz No match .sp Unset capturing substrings that are not followed by one that is set are not returned by \fBpcre[16|32]_exec()\fP, and are not shown by \fBpcretest\fP. In the following example, there are two capturing substrings, but when the first data line is matched, the second, unset substring is not shown. An "internal" unset substring is shown as "", as for the second data line. .sp re> /(a)|(b)/ data> a 0: a 1: a data> b 0: b 1: 2: b .sp If the strings contain any non-printing characters, they are output as \exhh escapes if the value is less than 256 and UTF mode is not set. Otherwise they are output as \ex{hh...} escapes. See below for the definition of non-printing characters. If the pattern has the \fB/+\fP modifier, the output for substring 0 is followed by the the rest of the subject string, identified by "0+" like this: .sp re> /cat/+ data> cataract 0: cat 0+ aract .sp If the pattern has the \fB/g\fP or \fB/G\fP modifier, the results of successive matching attempts are output in sequence, like this: .sp re> /\eBi(\ew\ew)/g data> Mississippi 0: iss 1: ss 0: iss 1: ss 0: ipp 1: pp .sp "No match" is output only if the first match attempt fails. Here is an example of a failure message (the offset 4 that is specified by \e>4 is past the end of the subject string): .sp re> /xyz/ data> xyz\e>4 Error -24 (bad offset value) .P If any of the sequences \fB\eC\fP, \fB\eG\fP, or \fB\eL\fP are present in a data line that is successfully matched, the substrings extracted by the convenience functions are output with C, G, or L after the string number instead of a colon. This is in addition to the normal full list. The string length (that is, the return from the extraction function) is given in parentheses after each string for \fB\eC\fP and \fB\eG\fP. .P Note that whereas patterns can be continued over several lines (a plain ">" prompt is used for continuations), data lines may not. However newlines can be included in data by means of the \en escape (or \er, \er\en, etc., depending on the newline sequence setting). . . . .SH "OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION" .rs .sp When the alternative matching function, \fBpcre[16|32]_dfa_exec()\fP, is used (by means of the \eD escape sequence or the \fB-dfa\fP command line option), the output consists of a list of all the matches that start at the first point in the subject where there is at least one match. For example: .sp re> /(tang|tangerine|tan)/ data> yellow tangerine\eD 0: tangerine 1: tang 2: tan .sp (Using the normal matching function on this data finds only "tang".) The longest matching string is always given first (and numbered zero). After a PCRE_ERROR_PARTIAL return, the output is "Partial match:", followed by the partially matching substring. (Note that this is the entire substring that was inspected during the partial match; it may include characters before the actual match start if a lookbehind assertion, \eK, \eb, or \eB was involved.) .P If \fB/g\fP is present on the pattern, the search for further matches resumes at the end of the longest match. For example: .sp re> /(tang|tangerine|tan)/g data> yellow tangerine and tangy sultana\eD 0: tangerine 1: tang 2: tan 0: tang 1: tan 0: tan .sp Since the matching function does not support substring capture, the escape sequences that are concerned with captured substrings are not relevant. . . .SH "RESTARTING AFTER A PARTIAL MATCH" .rs .sp When the alternative matching function has given the PCRE_ERROR_PARTIAL return, indicating that the subject partially matched the pattern, you can restart the match with additional subject data by means of the \eR escape sequence. For example: .sp re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/ data> 23ja\eP\eD Partial match: 23ja data> n05\eR\eD 0: n05 .sp For further information about partial matching, see the .\" HREF \fBpcrepartial\fP .\" documentation. . . .SH CALLOUTS .rs .sp If the pattern contains any callout requests, \fBpcretest\fP's callout function is called during matching. This works with both matching functions. By default, the called function displays the callout number, the start and current positions in the text at the callout time, and the next pattern item to be tested. For example: .sp --->pqrabcdef 0 ^ ^ \ed .sp This output indicates that callout number 0 occurred for a match attempt starting at the fourth character of the subject string, when the pointer was at the seventh character of the data, and when the next pattern item was \ed. Just one circumflex is output if the start and current positions are the same. .P Callouts numbered 255 are assumed to be automatic callouts, inserted as a result of the \fB/C\fP pattern modifier. In this case, instead of showing the callout number, the offset in the pattern, preceded by a plus, is output. For example: .sp re> /\ed?[A-E]\e*/C data> E* --->E* +0 ^ \ed? +3 ^ [A-E] +8 ^^ \e* +10 ^ ^ 0: E* .sp If a pattern contains (*MARK) items, an additional line is output whenever a change of latest mark is passed to the callout function. For example: .sp re> /a(*MARK:X)bc/C data> abc --->abc +0 ^ a +1 ^^ (*MARK:X) +10 ^^ b Latest Mark: X +11 ^ ^ c +12 ^ ^ 0: abc .sp The mark changes between matching "a" and "b", but stays the same for the rest of the match, so nothing more is output. If, as a result of backtracking, the mark reverts to being unset, the text "" is output. .P The callout function in \fBpcretest\fP returns zero (carry on matching) by default, but you can use a \eC item in a data line (as described above) to change this and other parameters of the callout. .P Inserting callouts can be helpful when using \fBpcretest\fP to check complicated regular expressions. For further information about callouts, see the .\" HREF \fBpcrecallout\fP .\" documentation. . . . .SH "NON-PRINTING CHARACTERS" .rs .sp When \fBpcretest\fP is outputting text in the compiled version of a pattern, bytes other than 32-126 are always treated as non-printing characters are are therefore shown as hex escapes. .P When \fBpcretest\fP is outputting text that is a matched part of a subject string, it behaves in the same way, unless a different locale has been set for the pattern (using the \fB/L\fP modifier). In this case, the \fBisprint()\fP function to distinguish printing and non-printing characters. . . . .SH "SAVING AND RELOADING COMPILED PATTERNS" .rs .sp The facilities described in this section are not available when the POSIX interface to PCRE is being used, that is, when the \fB/P\fP pattern modifier is specified. .P When the POSIX interface is not in use, you can cause \fBpcretest\fP to write a compiled pattern to a file, by following the modifiers with > and a file name. For example: .sp /pattern/im >/some/file .sp See the .\" HREF \fBpcreprecompile\fP .\" documentation for a discussion about saving and re-using compiled patterns. Note that if the pattern was successfully studied with JIT optimization, the JIT data cannot be saved. .P The data that is written is binary. The first eight bytes are the length of the compiled pattern data followed by the length of the optional study data, each written as four bytes in big-endian order (most significant byte first). If there is no study data (either the pattern was not studied, or studying did not return any data), the second length is zero. The lengths are followed by an exact copy of the compiled pattern. If there is additional study data, this (excluding any JIT data) follows immediately after the compiled pattern. After writing the file, \fBpcretest\fP expects to read a new pattern. .P A saved pattern can be reloaded into \fBpcretest\fP by specifying < and a file name instead of a pattern. There must be no space between < and the file name, which must not contain a < character, as otherwise \fBpcretest\fP will interpret the line as a pattern delimited by < characters. For example: .sp re> " to prompt for regular expressions, and "data>" to prompt for data lines. When pcretest is built, a configuration option can specify that it should be linked with the libreadline library. When this is done, if the input is from a terminal, it is read using the readline() function. This provides line-editing and history facilities. The output from the -help option states whether or not readline() will be used. The program handles any number of sets of input on a single input file. Each set starts with a regular expression, and continues with any num- ber of data lines to be matched against that pattern. Each data line is matched separately and independently. If you want to do multi-line matches, you have to use the \n escape sequence (or \r or \r\n, etc., depending on the newline setting) in a single line of input to encode the newline sequences. There is no limit on the length of data lines; the input buffer is automatically extended if it is too small. An empty line signals the end of the data lines, at which point a new regular expression is read. The regular expressions are given enclosed in any non-alphanumeric delimiters other than backslash, for example: /(a|bc)x+yz/ White space before the initial delimiter is ignored. A regular expres- sion may be continued over several input lines, in which case the new- line characters are included within it. It is possible to include the delimiter within the pattern by escaping it, for example /abc\/def/ If you do so, the escape and the delimiter form part of the pattern, but since delimiters are always non-alphanumeric, this does not affect its interpretation. If the terminating delimiter is immediately fol- lowed by a backslash, for example, /abc/\ then a backslash is added to the end of the pattern. This is done to provide a way of testing the error condition that arises if a pattern finishes with a backslash, because /abc\/ is interpreted as the first line of a pattern that starts with "abc/", causing pcretest to read the next line as a continuation of the regular expression. PATTERN MODIFIERS A pattern may be followed by any number of modifiers, which are mostly single characters, though some of these can be qualified by further characters. Following Perl usage, these are referred to below as, for example, "the /i modifier", even though the delimiter of the pattern need not always be a slash, and no slash is used when writing modi- fiers. White space may appear between the final pattern delimiter and the first modifier, and between the modifiers themselves. For refer- ence, here is a complete list of modifiers. They fall into several groups that are described in detail in the following sections. /8 set UTF mode /9 set PCRE_NEVER_UTF (locks out UTF mode) /? disable UTF validity check /+ show remainder of subject after match /= show all captures (not just those that are set) /A set PCRE_ANCHORED /B show compiled code /C set PCRE_AUTO_CALLOUT /D same as /B plus /I /E set PCRE_DOLLAR_ENDONLY /F flip byte order in compiled pattern /f set PCRE_FIRSTLINE /G find all matches (shorten string) /g find all matches (use startoffset) /I show information about pattern /i set PCRE_CASELESS /J set PCRE_DUPNAMES /K show backtracking control names /L set locale /M show compiled memory size /m set PCRE_MULTILINE /N set PCRE_NO_AUTO_CAPTURE /O set PCRE_NO_AUTO_POSSESS /P use the POSIX wrapper /Q test external stack check function /S study the pattern after compilation /s set PCRE_DOTALL /T select character tables /U set PCRE_UNGREEDY /W set PCRE_UCP /X set PCRE_EXTRA /x set PCRE_EXTENDED /Y set PCRE_NO_START_OPTIMIZE /Z don't show lengths in /B output / set PCRE_NEWLINE_ANY / set PCRE_NEWLINE_ANYCRLF / set PCRE_NEWLINE_CR / set PCRE_NEWLINE_CRLF / set PCRE_NEWLINE_LF / set PCRE_BSR_ANYCRLF / set PCRE_BSR_UNICODE / set PCRE_JAVASCRIPT_COMPAT Perl-compatible modifiers The /i, /m, /s, and /x modifiers set the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, or PCRE_EXTENDED options, respectively, when pcre[16|32]_compile() is called. These four modifier letters have the same effect as they do in Perl. For example: /caseless/i Modifiers for other PCRE options The following table shows additional modifiers for setting PCRE com- pile-time options that do not correspond to anything in Perl: /8 PCRE_UTF8 ) when using the 8-bit /? PCRE_NO_UTF8_CHECK ) library /8 PCRE_UTF16 ) when using the 16-bit /? PCRE_NO_UTF16_CHECK ) library /8 PCRE_UTF32 ) when using the 32-bit /? PCRE_NO_UTF32_CHECK ) library /9 PCRE_NEVER_UTF /A PCRE_ANCHORED /C PCRE_AUTO_CALLOUT /E PCRE_DOLLAR_ENDONLY /f PCRE_FIRSTLINE /J PCRE_DUPNAMES /N PCRE_NO_AUTO_CAPTURE /O PCRE_NO_AUTO_POSSESS /U PCRE_UNGREEDY /W PCRE_UCP /X PCRE_EXTRA /Y PCRE_NO_START_OPTIMIZE / PCRE_NEWLINE_ANY / PCRE_NEWLINE_ANYCRLF / PCRE_NEWLINE_CR / PCRE_NEWLINE_CRLF / PCRE_NEWLINE_LF / PCRE_BSR_ANYCRLF / PCRE_BSR_UNICODE / PCRE_JAVASCRIPT_COMPAT The modifiers that are enclosed in angle brackets are literal strings as shown, including the angle brackets, but the letters within can be in either case. This example sets multiline matching with CRLF as the line ending sequence: /^abc/m As well as turning on the PCRE_UTF8/16/32 option, the /8 modifier causes all non-printing characters in output strings to be printed using the \x{hh...} notation. Otherwise, those less than 0x100 are out- put in hex without the curly brackets. Full details of the PCRE options are given in the pcreapi documenta- tion. Finding all matches in a string Searching for all possible matches within each subject string can be requested by the /g or /G modifier. After finding a match, PCRE is called again to search the remainder of the subject string. The differ- ence between /g and /G is that the former uses the startoffset argument to pcre[16|32]_exec() to start searching at a new point within the entire string (which is in effect what Perl does), whereas the latter passes over a shortened substring. This makes a difference to the matching process if the pattern begins with a lookbehind assertion (including \b or \B). If any call to pcre[16|32]_exec() in a /g or /G sequence matches an empty string, the next call is done with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set in order to search for another, non-empty, match at the same point. If this second match fails, the start offset is advanced, and the normal match is retried. This imitates the way Perl handles such cases when using the /g modifier or the split() func- tion. Normally, the start offset is advanced by one character, but if the newline convention recognizes CRLF as a newline, and the current character is CR followed by LF, an advance of two is used. Other modifiers There are yet more modifiers for controlling the way pcretest operates. The /+ modifier requests that as well as outputting the substring that matched the entire pattern, pcretest should in addition output the remainder of the subject string. This is useful for tests where the subject contains multiple copies of the same substring. If the + modi- fier appears twice, the same action is taken for captured substrings. In each case the remainder is output on the following line with a plus character following the capture number. Note that this modifier must not immediately follow the /S modifier because /S+ and /S++ have other meanings. The /= modifier requests that the values of all potential captured parentheses be output after a match. By default, only those up to the highest one actually used in the match are output (corresponding to the return code from pcre[16|32]_exec()). Values in the offsets vector cor- responding to higher numbers should be set to -1, and these are output as "". This modifier gives a way of checking that this is hap- pening. The /B modifier is a debugging feature. It requests that pcretest out- put a representation of the compiled code after compilation. Normally this information contains length and offset values; however, if /Z is also present, this data is replaced by spaces. This is a special fea- ture for use in the automatic test scripts; it ensures that the same output is generated for different internal link sizes. The /D modifier is a PCRE debugging feature, and is equivalent to /BI, that is, both the /B and the /I modifiers. The /F modifier causes pcretest to flip the byte order of the 2-byte and 4-byte fields in the compiled pattern. This facility is for testing the feature in PCRE that allows it to execute patterns that were com- piled on a host with a different endianness. This feature is not avail- able when the POSIX interface to PCRE is being used, that is, when the /P pattern modifier is specified. See also the section about saving and reloading compiled patterns below. The /I modifier requests that pcretest output information about the compiled pattern (whether it is anchored, has a fixed first character, and so on). It does this by calling pcre[16|32]_fullinfo() after com- piling a pattern. If the pattern is studied, the results of that are also output. In this output, the word "char" means a non-UTF character, that is, the value of a single data item (8-bit, 16-bit, or 32-bit, depending on the library that is being tested). The /K modifier requests pcretest to show names from backtracking con- trol verbs that are returned from calls to pcre[16|32]_exec(). It causes pcretest to create a pcre[16|32]_extra block if one has not already been created by a call to pcre[16|32]_study(), and to set the PCRE_EXTRA_MARK flag and the mark field within it, every time that pcre[16|32]_exec() is called. If the variable that the mark field points to is non-NULL for a match, non-match, or partial match, pcretest prints the string to which it points. For a match, this is shown on a line by itself, tagged with "MK:". For a non-match it is added to the message. The /L modifier must be followed directly by the name of a locale, for example, /pattern/Lfr_FR For this reason, it must be the last modifier. The given locale is set, pcre[16|32]_maketables() is called to build a set of character tables for the locale, and this is then passed to pcre[16|32]_compile() when compiling the regular expression. Without an /L (or /T) modifier, NULL is passed as the tables pointer; that is, /L applies only to the expression on which it appears. The /M modifier causes the size in bytes of the memory block used to hold the compiled pattern to be output. This does not include the size of the pcre[16|32] block; it is just the actual compiled data. If the pattern is successfully studied with the PCRE_STUDY_JIT_COMPILE option, the size of the JIT compiled code is also output. The /Q modifier is used to test the use of pcre_stack_guard. It must be followed by '0' or '1', specifying the return code to be given from an external function that is passed to PCRE and used for stack checking during compilation (see the pcreapi documentation for details). The /S modifier causes pcre[16|32]_study() to be called after the expression has been compiled, and the results used when the expression is matched. There are a number of qualifying characters that may follow /S. They may appear in any order. If /S is followed by an exclamation mark, pcre[16|32]_study() is called with the PCRE_STUDY_EXTRA_NEEDED option, causing it always to return a pcre_extra block, even when studying discovers no useful information. If /S is followed by a second S character, it suppresses studying, even if it was requested externally by the -s command line option. This makes it possible to specify that certain patterns are always studied, and others are never studied, independently of -s. This feature is used in the test files in a few cases where the output is different when the pattern is studied. If the /S modifier is followed by a + character, the call to pcre[16|32]_study() is made with all the JIT study options, requesting just-in-time optimization support if it is available, for both normal and partial matching. If you want to restrict the JIT compiling modes, you can follow /S+ with a digit in the range 1 to 7: 1 normal match only 2 soft partial match only 3 normal match and soft partial match 4 hard partial match only 6 soft and hard partial match 7 all three modes (default) If /S++ is used instead of /S+ (with or without a following digit), the text "(JIT)" is added to the first output line after a match or no match when JIT-compiled code was actually used. Note that there is also an independent /+ modifier; it must not be given immediately after /S or /S+ because this will be misinterpreted. If JIT studying is successful, the compiled JIT code will automatically be used when pcre[16|32]_exec() is run, except when incompatible run- time options are specified. For more details, see the pcrejit documen- tation. See also the \J escape sequence below for a way of setting the size of the JIT stack. Finally, if /S is followed by a minus character, JIT compilation is suppressed, even if it was requested externally by the -s command line option. This makes it possible to specify that JIT is never to be used for certain patterns. The /T modifier must be followed by a single digit. It causes a spe- cific set of built-in character tables to be passed to pcre[16|32]_com- pile(). It is used in the standard PCRE tests to check behaviour with different character tables. The digit specifies the tables as follows: 0 the default ASCII tables, as distributed in pcre_chartables.c.dist 1 a set of tables defining ISO 8859 characters In table 1, some characters whose codes are greater than 128 are iden- tified as letters, digits, spaces, etc. Using the POSIX wrapper API The /P modifier causes pcretest to call PCRE via the POSIX wrapper API rather than its native API. This supports only the 8-bit library. When /P is set, the following modifiers set options for the regcomp() func- tion: /i REG_ICASE /m REG_NEWLINE /N REG_NOSUB /s REG_DOTALL ) /U REG_UNGREEDY ) These options are not part of /W REG_UCP ) the POSIX standard /8 REG_UTF8 ) The /+ modifier works as described above. All other modifiers are ignored. Locking out certain modifiers PCRE can be compiled with or without support for certain features such as UTF-8/16/32 or Unicode properties. Accordingly, the standard tests are split up into a number of different files that are selected for running depending on which features are available. When updating the tests, it is all too easy to put a new test into the wrong file by mis- take; for example, to put a test that requires UTF support into a file that is used when it is not available. To help detect such mistakes as early as possible, there is a facility for locking out specific modi- fiers. If an input line for pcretest starts with the string "< forbid " the following sequence of characters is taken as a list of forbidden modifiers. For example, in the test files that must not use UTF or Uni- code property support, this line appears: < forbid 8W This locks out the /8 and /W modifiers. An immediate error is given if they are subsequently encountered. If the character string contains < but not >, all the multi-character modifiers that begin with < are locked out. Otherwise, such modifiers must be explicitly listed, for example: < forbid There must be a single space between < and "forbid" for this feature to be recognised. If there is not, the line is interpreted either as a request to re-load a pre-compiled pattern (see "SAVING AND RELOADING COMPILED PATTERNS" below) or, if there is a another < character, as a pattern that uses < as its delimiter. DATA LINES Before each data line is passed to pcre[16|32]_exec(), leading and trailing white space is removed, and it is then scanned for \ escapes. Some of these are pretty esoteric features, intended for checking out some of the more complicated features of PCRE. If you are just testing "ordinary" regular expressions, you probably don't need any of these. The following escapes are recognized: \a alarm (BEL, \x07) \b backspace (\x08) \e escape (\x27) \f form feed (\x0c) \n newline (\x0a) \qdd set the PCRE_MATCH_LIMIT limit to dd (any number of digits) \r carriage return (\x0d) \t tab (\x09) \v vertical tab (\x0b) \nnn octal character (up to 3 octal digits); always a byte unless > 255 in UTF-8 or 16-bit or 32-bit mode \o{dd...} octal character (any number of octal digits} \xhh hexadecimal byte (up to 2 hex digits) \x{hh...} hexadecimal character (any number of hex digits) \A pass the PCRE_ANCHORED option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \B pass the PCRE_NOTBOL option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \Cdd call pcre[16|32]_copy_substring() for substring dd after a successful match (number less than 32) \Cname call pcre[16|32]_copy_named_substring() for substring "name" after a successful match (name termin- ated by next non alphanumeric character) \C+ show the current captured substrings at callout time \C- do not supply a callout function \C!n return 1 instead of 0 when callout number n is reached \C!n!m return 1 instead of 0 when callout number n is reached for the nth time \C*n pass the number n (may be negative) as callout data; this is used as the callout return value \D use the pcre[16|32]_dfa_exec() match function \F only shortest match for pcre[16|32]_dfa_exec() \Gdd call pcre[16|32]_get_substring() for substring dd after a successful match (number less than 32) \Gname call pcre[16|32]_get_named_substring() for substring "name" after a successful match (name termin- ated by next non-alphanumeric character) \Jdd set up a JIT stack of dd kilobytes maximum (any number of digits) \L call pcre[16|32]_get_substringlist() after a successful match \M discover the minimum MATCH_LIMIT and MATCH_LIMIT_RECURSION settings \N pass the PCRE_NOTEMPTY option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec(); if used twice, pass the PCRE_NOTEMPTY_ATSTART option \Odd set the size of the output vector passed to pcre[16|32]_exec() to dd (any number of digits) \P pass the PCRE_PARTIAL_SOFT option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec(); if used twice, pass the PCRE_PARTIAL_HARD option \Qdd set the PCRE_MATCH_LIMIT_RECURSION limit to dd (any number of digits) \R pass the PCRE_DFA_RESTART option to pcre[16|32]_dfa_exec() \S output details of memory get/free calls during matching \Y pass the PCRE_NO_START_OPTIMIZE option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \Z pass the PCRE_NOTEOL option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \? pass the PCRE_NO_UTF[8|16|32]_CHECK option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \>dd start the match at offset dd (optional "-"; then any number of digits); this sets the startoffset argument for pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \ pass the PCRE_NEWLINE_CR option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \ pass the PCRE_NEWLINE_LF option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \ pass the PCRE_NEWLINE_CRLF option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \ pass the PCRE_NEWLINE_ANYCRLF option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() \ pass the PCRE_NEWLINE_ANY option to pcre[16|32]_exec() or pcre[16|32]_dfa_exec() The use of \x{hh...} is not dependent on the use of the /8 modifier on the pattern. It is recognized always. There may be any number of hexa- decimal digits inside the braces; invalid values provoke error mes- sages. Note that \xhh specifies one byte rather than one character in UTF-8 mode; this makes it possible to construct invalid UTF-8 sequences for testing purposes. On the other hand, \x{hh} is interpreted as a UTF-8 character in UTF-8 mode, generating more than one byte if the value is greater than 127. When testing the 8-bit library not in UTF-8 mode, \x{hh} generates one byte for values less than 256, and causes an error for greater values. In UTF-16 mode, all 4-digit \x{hhhh} values are accepted. This makes it possible to construct invalid UTF-16 sequences for testing purposes. In UTF-32 mode, all 4- to 8-digit \x{...} values are accepted. This makes it possible to construct invalid UTF-32 sequences for testing purposes. The escapes that specify line ending sequences are literal strings, exactly as shown. No more than one newline setting should be present in any data line. A backslash followed by anything else just escapes the anything else. If the very last character is a backslash, it is ignored. This gives a way of passing an empty line as data, since a real empty line termi- nates the data input. The \J escape provides a way of setting the maximum stack size that is used by the just-in-time optimization code. It is ignored if JIT opti- mization is not being used. Providing a stack that is larger than the default 32K is necessary only for very complicated patterns. If \M is present, pcretest calls pcre[16|32]_exec() several times, with different values in the match_limit and match_limit_recursion fields of the pcre[16|32]_extra data structure, until it finds the minimum num- bers for each parameter that allow pcre[16|32]_exec() to complete with- out error. Because this is testing a specific feature of the normal interpretive pcre[16|32]_exec() execution, the use of any JIT optimiza- tion that might have been set up by the /S+ qualifier of -s+ option is disabled. The match_limit number is a measure of the amount of backtracking that takes place, and checking it out can be instructive. For most simple matches, the number is quite small, but for patterns with very large numbers of matching possibilities, it can become large very quickly with increasing length of subject string. The match_limit_recursion number is a measure of how much stack (or, if PCRE is compiled with NO_RECURSE, how much heap) memory is needed to complete the match attempt. When \O is used, the value specified may be higher or lower than the size set by the -O command line option (or defaulted to 45); \O applies only to the call of pcre[16|32]_exec() for the line in which it appears. If the /P modifier was present on the pattern, causing the POSIX wrap- per API to be used, the only option-setting sequences that have any effect are \B, \N, and \Z, causing REG_NOTBOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to regexec(). THE ALTERNATIVE MATCHING FUNCTION By default, pcretest uses the standard PCRE matching function, pcre[16|32]_exec() to match each data line. PCRE also supports an alternative matching function, pcre[16|32]_dfa_test(), which operates in a different way, and has some restrictions. The differences between the two functions are described in the pcrematching documentation. If a data line contains the \D escape sequence, or if the command line contains the -dfa option, the alternative matching function is used. This function finds all possible matches at a given point. If, however, the \F escape sequence is present in the data line, it stops after the first match is found. This is always the shortest possible match. DEFAULT OUTPUT FROM PCRETEST This section describes the output when the normal matching function, pcre[16|32]_exec(), is being used. When a match succeeds, pcretest outputs the list of captured substrings that pcre[16|32]_exec() returns, starting with number 0 for the string that matched the whole pattern. Otherwise, it outputs "No match" when the return is PCRE_ERROR_NOMATCH, and "Partial match:" followed by the partially matching substring when pcre[16|32]_exec() returns PCRE_ERROR_PARTIAL. (Note that this is the entire substring that was inspected during the partial match; it may include characters before the actual match start if a lookbehind assertion, \K, \b, or \B was involved.) For any other return, pcretest outputs the PCRE negative error number and a short descriptive phrase. If the error is a failed UTF string check, the offset of the start of the failing character and the reason code are also output, provided that the size of the output vector is at least two. Here is an example of an interactive pcretest run. $ pcretest PCRE version 8.13 2011-04-30 re> /^abc(\d+)/ data> abc123 0: abc123 1: 123 data> xyz No match Unset capturing substrings that are not followed by one that is set are not returned by pcre[16|32]_exec(), and are not shown by pcretest. In the following example, there are two capturing substrings, but when the first data line is matched, the second, unset substring is not shown. An "internal" unset substring is shown as "", as for the second data line. re> /(a)|(b)/ data> a 0: a 1: a data> b 0: b 1: 2: b If the strings contain any non-printing characters, they are output as \xhh escapes if the value is less than 256 and UTF mode is not set. Otherwise they are output as \x{hh...} escapes. See below for the defi- nition of non-printing characters. If the pattern has the /+ modifier, the output for substring 0 is followed by the the rest of the subject string, identified by "0+" like this: re> /cat/+ data> cataract 0: cat 0+ aract If the pattern has the /g or /G modifier, the results of successive matching attempts are output in sequence, like this: re> /\Bi(\w\w)/g data> Mississippi 0: iss 1: ss 0: iss 1: ss 0: ipp 1: pp "No match" is output only if the first match attempt fails. Here is an example of a failure message (the offset 4 that is specified by \>4 is past the end of the subject string): re> /xyz/ data> xyz\>4 Error -24 (bad offset value) If any of the sequences \C, \G, or \L are present in a data line that is successfully matched, the substrings extracted by the convenience functions are output with C, G, or L after the string number instead of a colon. This is in addition to the normal full list. The string length (that is, the return from the extraction function) is given in paren- theses after each string for \C and \G. Note that whereas patterns can be continued over several lines (a plain ">" prompt is used for continuations), data lines may not. However new- lines can be included in data by means of the \n escape (or \r, \r\n, etc., depending on the newline sequence setting). OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION When the alternative matching function, pcre[16|32]_dfa_exec(), is used (by means of the \D escape sequence or the -dfa command line option), the output consists of a list of all the matches that start at the first point in the subject where there is at least one match. For exam- ple: re> /(tang|tangerine|tan)/ data> yellow tangerine\D 0: tangerine 1: tang 2: tan (Using the normal matching function on this data finds only "tang".) The longest matching string is always given first (and numbered zero). After a PCRE_ERROR_PARTIAL return, the output is "Partial match:", fol- lowed by the partially matching substring. (Note that this is the entire substring that was inspected during the partial match; it may include characters before the actual match start if a lookbehind asser- tion, \K, \b, or \B was involved.) If /g is present on the pattern, the search for further matches resumes at the end of the longest match. For example: re> /(tang|tangerine|tan)/g data> yellow tangerine and tangy sultana\D 0: tangerine 1: tang 2: tan 0: tang 1: tan 0: tan Since the matching function does not support substring capture, the escape sequences that are concerned with captured substrings are not relevant. RESTARTING AFTER A PARTIAL MATCH When the alternative matching function has given the PCRE_ERROR_PARTIAL return, indicating that the subject partially matched the pattern, you can restart the match with additional subject data by means of the \R escape sequence. For example: re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/ data> 23ja\P\D Partial match: 23ja data> n05\R\D 0: n05 For further information about partial matching, see the pcrepartial documentation. CALLOUTS If the pattern contains any callout requests, pcretest's callout func- tion is called during matching. This works with both matching func- tions. By default, the called function displays the callout number, the start and current positions in the text at the callout time, and the next pattern item to be tested. For example: --->pqrabcdef 0 ^ ^ \d This output indicates that callout number 0 occurred for a match attempt starting at the fourth character of the subject string, when the pointer was at the seventh character of the data, and when the next pattern item was \d. Just one circumflex is output if the start and current positions are the same. Callouts numbered 255 are assumed to be automatic callouts, inserted as a result of the /C pattern modifier. In this case, instead of showing the callout number, the offset in the pattern, preceded by a plus, is output. For example: re> /\d?[A-E]\*/C data> E* --->E* +0 ^ \d? +3 ^ [A-E] +8 ^^ \* +10 ^ ^ 0: E* If a pattern contains (*MARK) items, an additional line is output when- ever a change of latest mark is passed to the callout function. For example: re> /a(*MARK:X)bc/C data> abc --->abc +0 ^ a +1 ^^ (*MARK:X) +10 ^^ b Latest Mark: X +11 ^ ^ c +12 ^ ^ 0: abc The mark changes between matching "a" and "b", but stays the same for the rest of the match, so nothing more is output. If, as a result of backtracking, the mark reverts to being unset, the text "" is output. The callout function in pcretest returns zero (carry on matching) by default, but you can use a \C item in a data line (as described above) to change this and other parameters of the callout. Inserting callouts can be helpful when using pcretest to check compli- cated regular expressions. For further information about callouts, see the pcrecallout documentation. NON-PRINTING CHARACTERS When pcretest is outputting text in the compiled version of a pattern, bytes other than 32-126 are always treated as non-printing characters are are therefore shown as hex escapes. When pcretest is outputting text that is a matched part of a subject string, it behaves in the same way, unless a different locale has been set for the pattern (using the /L modifier). In this case, the isprint() function to distinguish printing and non-printing characters. SAVING AND RELOADING COMPILED PATTERNS The facilities described in this section are not available when the POSIX interface to PCRE is being used, that is, when the /P pattern modifier is specified. When the POSIX interface is not in use, you can cause pcretest to write a compiled pattern to a file, by following the modifiers with > and a file name. For example: /pattern/im >/some/file See the pcreprecompile documentation for a discussion about saving and re-using compiled patterns. Note that if the pattern was successfully studied with JIT optimization, the JIT data cannot be saved. The data that is written is binary. The first eight bytes are the length of the compiled pattern data followed by the length of the optional study data, each written as four bytes in big-endian order (most significant byte first). If there is no study data (either the pattern was not studied, or studying did not return any data), the sec- ond length is zero. The lengths are followed by an exact copy of the compiled pattern. If there is additional study data, this (excluding any JIT data) follows immediately after the compiled pattern. After writing the file, pcretest expects to read a new pattern. A saved pattern can be reloaded into pcretest by specifying < and a file name instead of a pattern. There must be no space between < and the file name, which must not contain a < character, as otherwise pcretest will interpret the line as a pattern delimited by < charac- ters. For example: re> .SS "Validity of UTF-8 strings" .rs .sp When you set the PCRE_UTF8 flag, the byte strings passed as patterns and subjects are (by default) checked for validity on entry to the relevant functions. The entire string is checked before any other processing takes place. From release 7.3 of PCRE, the check is according the rules of RFC 3629, which are themselves derived from the Unicode specification. Earlier releases of PCRE followed the rules of RFC 2279, which allows the full range of 31-bit values (0 to 0x7FFFFFFF). The current check allows only values in the range U+0 to U+10FFFF, excluding the surrogate area. (From release 8.33 the so-called "non-character" code points are no longer excluded because Unicode corrigendum #9 makes it clear that they should not be.) .P Characters in the "Surrogate Area" of Unicode are reserved for use by UTF-16, where they are used in pairs to encode codepoints with values greater than 0xFFFF. The code points that are encoded by UTF-16 pairs are available independently in the UTF-8 and UTF-32 encodings. (In other words, the whole surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and UTF-32.) .P If an invalid UTF-8 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first byte of the failing character. The run-time functions \fBpcre_exec()\fP and \fBpcre_dfa_exec()\fP also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this. .P In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve performance, for example in the case of a long subject string that is being scanned repeatedly. If you set the PCRE_NO_UTF8_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-8 codes. In this case, it does not diagnose an invalid UTF-8 string. .P Note that passing PCRE_NO_UTF8_CHECK to \fBpcre_compile()\fP just disables the check for the pattern; it does not also apply to subject strings. If you want to disable the check for a subject string you must pass this option to \fBpcre_exec()\fP or \fBpcre_dfa_exec()\fP. .P If you pass an invalid UTF-8 string when PCRE_NO_UTF8_CHECK is set, the result is undefined and your program may crash. . . .\" HTML .SS "Validity of UTF-16 strings" .rs .sp When you set the PCRE_UTF16 flag, the strings of 16-bit data units that are passed as patterns and subjects are (by default) checked for validity on entry to the relevant functions. Values other than those in the surrogate range U+D800 to U+DFFF are independent code points. Values in the surrogate range must be used in pairs in the correct manner. .P If an invalid UTF-16 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first data unit of the failing character. The run-time functions \fBpcre16_exec()\fP and \fBpcre16_dfa_exec()\fP also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this. .P In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve performance. If you set the PCRE_NO_UTF16_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-16 sequences. In this case, it does not diagnose an invalid UTF-16 string. However, if an invalid string is passed, the result is undefined. . . .\" HTML .SS "Validity of UTF-32 strings" .rs .sp When you set the PCRE_UTF32 flag, the strings of 32-bit data units that are passed as patterns and subjects are (by default) checked for validity on entry to the relevant functions. This check allows only values in the range U+0 to U+10FFFF, excluding the surrogate area U+D800 to U+DFFF. .P If an invalid UTF-32 string is passed to PCRE, an error return is given. At compile time, the only additional information is the offset to the first data unit of the failing character. The run-time functions \fBpcre32_exec()\fP and \fBpcre32_dfa_exec()\fP also pass back this information, as well as a more detailed reason code if the caller has provided memory in which to do this. .P In some situations, you may already know that your strings are valid, and therefore want to skip these checks in order to improve performance. If you set the PCRE_NO_UTF32_CHECK flag at compile time or at run time, PCRE assumes that the pattern or subject it is given (respectively) contains only valid UTF-32 sequences. In this case, it does not diagnose an invalid UTF-32 string. However, if an invalid string is passed, the result is undefined. . . .SS "General comments about UTF modes" .rs .sp 1. Codepoints less than 256 can be specified in patterns by either braced or unbraced hexadecimal escape sequences (for example, \ex{b3} or \exb3). Larger values have to use braced sequences. .P 2. Octal numbers up to \e777 are recognized, and in UTF-8 mode they match two-byte characters for values greater than \e177. .P 3. Repeat quantifiers apply to complete UTF characters, not to individual data units, for example: \ex{100}{3}. .P 4. The dot metacharacter matches one UTF character instead of a single data unit. .P 5. The escape sequence \eC can be used to match a single byte in UTF-8 mode, or a single 16-bit data unit in UTF-16 mode, or a single 32-bit data unit in UTF-32 mode, but its use can lead to some strange effects because it breaks up multi-unit characters (see the description of \eC in the .\" HREF \fBpcrepattern\fP .\" documentation). The use of \eC is not supported in the alternative matching function \fBpcre[16|32]_dfa_exec()\fP, nor is it supported in UTF mode by the JIT optimization of \fBpcre[16|32]_exec()\fP. If JIT optimization is requested for a UTF pattern that contains \eC, it will not succeed, and so the matching will be carried out by the normal interpretive function. .P 6. The character escapes \eb, \eB, \ed, \eD, \es, \eS, \ew, and \eW correctly test characters of any code value, but, by default, the characters that PCRE recognizes as digits, spaces, or word characters remain the same set as in non-UTF mode, all with values less than 256. This remains true even when PCRE is built to include Unicode property support, because to do otherwise would slow down PCRE in many common cases. Note in particular that this applies to \eb and \eB, because they are defined in terms of \ew and \eW. If you really want to test for a wider sense of, say, "digit", you can use explicit Unicode property tests such as \ep{Nd}. Alternatively, if you set the PCRE_UCP option, the way that the character escapes work is changed so that Unicode properties are used to determine which characters match. There are more details in the section on .\" HTML .\" generic character types .\" in the .\" HREF \fBpcrepattern\fP .\" documentation. .P 7. Similarly, characters that match the POSIX named character classes are all low-valued characters, unless the PCRE_UCP option is set. .P 8. However, the horizontal and vertical white space matching escapes (\eh, \eH, \ev, and \eV) do match all the appropriate Unicode characters, whether or not PCRE_UCP is set. .P 9. Case-insensitive matching applies only to characters whose values are less than 128, unless PCRE is built with Unicode property support. A few Unicode characters such as Greek sigma have more than two codepoints that are case-equivalent. Up to and including PCRE release 8.31, only one-to-one case mappings were supported, but later releases (with Unicode property support) do treat as case-equivalent all versions of characters such as Greek sigma. . . .SH AUTHOR .rs .sp .nf Philip Hazel University Computing Service Cambridge CB2 3QH, England. .fi . . .SH REVISION .rs .sp .nf Last updated: 27 February 2013 Copyright (c) 1997-2013 University of Cambridge. .fi ================================================ FILE: src/pcre/doc/perltest.txt ================================================ The perltest program -------------------- The perltest.pl script tests Perl's regular expressions; it has the same specification as pcretest, and so can be given identical input, except that input patterns can be followed only by Perl's lower case modifiers and certain other pcretest modifiers that are either handled or ignored: /+ recognized and handled by perltest /++ the second + is ignored /8 recognized and handled by perltest /J ignored /K ignored /W ignored /S ignored /SS ignored /Y ignored The pcretest \Y escape in data lines is removed before matching. The data lines are processed as Perl double-quoted strings, so if they contain " $ or @ characters, these have to be escaped. For this reason, all such characters in the Perl-compatible testinput1 file are escaped so that they can be used for perltest as well as for pcretest. The special upper case pattern modifiers such as /A that pcretest recognizes, and its special data line escapes, are not used in the Perl-compatible test file. The output should be identical, apart from the initial identifying banner. The perltest.pl script can also test UTF-8 features. It recognizes the special modifier /8 that pcretest uses to invoke UTF-8 functionality. The testinput4 and testinput6 files can be fed to perltest to run compatible UTF-8 tests. However, it is necessary to add "use utf8; require Encode" to the script to make this work correctly. I have not managed to find a way to handle this automatically. The other testinput files are not suitable for feeding to perltest.pl, since they make use of the special upper case modifiers and escapes that pcretest uses to test certain features of PCRE. Some of these files also contain malformed regular expressions, in order to check that PCRE diagnoses them correctly. Philip Hazel January 2012 ================================================ FILE: src/pcre/install-sh ================================================ #!/bin/sh # install - install a program, script, or datafile scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # Note that $RANDOM variable is not portable (e.g. dash); Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p' feature. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/pcre/libpcre.pc.in ================================================ # Package Information for pkg-config prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libpcre Description: PCRE - Perl compatible regular expressions C library with 8 bit character support Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpcre Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ ================================================ FILE: src/pcre/libpcre16.pc.in ================================================ # Package Information for pkg-config prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libpcre16 Description: PCRE - Perl compatible regular expressions C library with 16 bit character support Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpcre16 Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ ================================================ FILE: src/pcre/libpcre32.pc.in ================================================ # Package Information for pkg-config prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libpcre32 Description: PCRE - Perl compatible regular expressions C library with 32 bit character support Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpcre32 Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@ Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ ================================================ FILE: src/pcre/libpcrecpp.pc.in ================================================ # Package Information for pkg-config prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libpcrecpp Description: PCRECPP - C++ wrapper for PCRE Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpcre -lpcrecpp Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ ================================================ FILE: src/pcre/libpcreposix.pc.in ================================================ # Package Information for pkg-config prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libpcreposix Description: PCREPosix - Posix compatible interface to libpcre Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lpcreposix Cflags: -I${includedir} @PCRE_STATIC_CFLAG@ Requires.private: libpcre ================================================ FILE: src/pcre/ltmain.sh ================================================ #! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2018-07-24.06 # libtool (GNU libtool) 2.4.6.42-b88ce # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2018 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.6.42-b88ce package_revision=2.4.6.42 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2018-07-24.06; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2004-2018 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 3 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # func_unset VAR # -------------- # Portably unset VAR. # In some shells, an 'unset VAR' statement leaves a non-zero return # status if VAR is already unset, which might be problematic if the # statement is used at the end of a function (thus poisoning its return # value) or when 'set -e' is active (causing even a spurious abort of # the script in this case). func_unset () { { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; } } # Make sure CDPATH doesn't cause `cd` commands to output the target dir. func_unset CDPATH # Make sure ${,E,F}GREP behave sanely. func_unset GREP_OPTIONS ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin" rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin" GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1+=\\ \$func_quote_arg_result" }' else func_append_quoted () { $debug_cmd func_quote_arg pretty "$2" eval "$1=\$$1\\ \$func_quote_arg_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_portable EVAL ARG # ---------------------------- # Internal function to portably implement func_quote_arg. Note that we still # keep attention to performance here so we as much as possible try to avoid # calling sed binary (so far O(N) complexity as long as func_append is O(1)). func_quote_portable () { $debug_cmd func_quote_portable_result=$2 # one-time-loop (easy break) while true do if $1; then func_quote_portable_result=`$ECHO "$2" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` break fi # Quote for eval. case $func_quote_portable_result in *[\\\`\"\$]*) case $func_quote_portable_result in *[\[\*\?]*) func_quote_portable_result=`$ECHO "$func_quote_portable_result" \ | $SED "$sed_quote_subst"` break ;; esac func_quote_portable_old_IFS=$IFS for _G_char in '\' '`' '"' '$' do # STATE($1) PREV($2) SEPARATOR($3) set start "" "" func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy IFS=$_G_char for _G_part in $func_quote_portable_result do case $1 in quote) func_append func_quote_portable_result "$3$2" set quote "$_G_part" "\\$_G_char" ;; start) set first "" "" func_quote_portable_result= ;; first) set quote "$_G_part" "" ;; esac done done IFS=$func_quote_portable_old_IFS ;; *) ;; esac break done func_quote_portable_unquoted_result=$func_quote_portable_result case $func_quote_portable_result in # double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # many bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_portable_result=\"$func_quote_portable_result\" ;; esac } # func_quotefast_eval ARG # ----------------------- # Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG', # but optimized for speed. Result is stored in $func_quotefast_eval. if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then printf -v _GL_test_printf_tilde %q '~' if test '\~' = "$_GL_test_printf_tilde"; then func_quotefast_eval () { printf -v func_quotefast_eval_result %q "$1" } else # Broken older Bash implementations. Make those faster too if possible. func_quotefast_eval () { case $1 in '~'*) func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result ;; *) printf -v func_quotefast_eval_result %q "$1" ;; esac } fi else func_quotefast_eval () { func_quote_portable false "$1" func_quotefast_eval_result=$func_quote_portable_result } fi # func_quote_arg MODEs ARG # ------------------------ # Quote one ARG to be evaled later. MODEs argument may contain zero or more # specifiers listed below separated by ',' character. This function returns two # values: # i) func_quote_arg_result # double-quoted (when needed), suitable for a subsequent eval # ii) func_quote_arg_unquoted_result # has all characters that are still active within double # quotes backslashified. Available only if 'unquoted' is specified. # # Available modes: # ---------------- # 'eval' (default) # - escape shell special characters # 'expand' # - the same as 'eval'; but do not quote variable references # 'pretty' # - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might # be used later in func_quote to get output like: 'echo "a b"' instead # of 'echo a\ b'. This is slower than default on some shells. # 'unquoted' # - produce also $func_quote_arg_unquoted_result which does not contain # wrapping double-quotes. # # Examples for 'func_quote_arg pretty,unquoted string': # # string | *_result | *_unquoted_result # ------------+-----------------------+------------------- # " | \" | \" # a b | "a b" | a b # "a b" | "\"a b\"" | \"a b\" # * | "*" | * # z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\" # # Examples for 'func_quote_arg pretty,unquoted,expand string': # # string | *_result | *_unquoted_result # --------------+---------------------+-------------------- # z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\" func_quote_arg () { _G_quote_expand=false case ,$1, in *,expand,*) _G_quote_expand=: ;; esac case ,$1, in *,pretty,*|*,expand,*|*,unquoted,*) func_quote_portable $_G_quote_expand "$2" func_quote_arg_result=$func_quote_portable_result func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result ;; *) # Faster quote-for-eval for some shells. func_quotefast_eval "$2" func_quote_arg_result=$func_quotefast_eval_result ;; esac } # func_quote MODEs ARGs... # ------------------------ # Quote all ARGs to be evaled later and join them into single command. See # func_quote_arg's description for more info. func_quote () { $debug_cmd _G_func_quote_mode=$1 ; shift func_quote_result= while test 0 -lt $#; do func_quote_arg "$_G_func_quote_mode" "$1" if test -n "$func_quote_result"; then func_append func_quote_result " $func_quote_arg_result" else func_append func_quote_result "$func_quote_arg_result" fi shift done } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_arg pretty,expand "$_G_cmd" eval "func_notquiet $func_quote_arg_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_arg expand,pretty "$_G_cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # This is free software. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Copyright (C) 2010-2018 Bootstrap Authors # # This file is dual licensed under the terms of the MIT license # , and GPL version 3 or later # . You must apply one of # these licenses when using or redistributing this software or any of # the files within it. See the URLs above, or the file `LICENSE` # included in the Bootstrap distribution for the full license texts. # Please report bugs or propose patches to: # # Set a version string for this script. scriptversion=2018-07-24.06; # UTC ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# Copyright'. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug in processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # in the main code. A hook is just a list of function names that can be # run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of hook functions to be called by # FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_propagate_result FUNC_NAME_A FUNC_NAME_B # --------------------------------------------- # If the *_result variable of FUNC_NAME_A _is set_, assign its value to # *_result variable of FUNC_NAME_B. func_propagate_result () { $debug_cmd func_propagate_result_result=: if eval "test \"\${${1}_result+set}\" = set" then eval "${2}_result=\$${1}_result" else func_propagate_result_result=false fi } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It's assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook functions." ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do func_unset "${_G_hook}_result" eval $_G_hook '${1+"$@"}' func_propagate_result $_G_hook func_run_hooks if $func_propagate_result_result; then eval set dummy "$func_run_hooks_result"; shift fi done } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list from your hook function. You may remove # or edit any options that you action, and then pass back the remaining # unprocessed options in '_result', escaped # suitably for 'eval'. # # The '_result' variable is automatically unset # before your hook gets called; for best performance, only set the # *_result variable when necessary (i.e. don't call the 'func_quote' # function unnecessarily because it can be an expensive operation on some # machines). # # Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # No change in '$@' (ignored completely by this hook). Leave # # my_options_prep_result variable intact. # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # args_changed=false # # # Note that, for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: # args_changed=: # ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # args_changed=: # ;; # *) # Make sure the first unrecognised option "$_G_opt" # # is added back to "$@" in case we need it later, # # if $args_changed was set to 'true'. # set dummy "$_G_opt" ${1+"$@"}; shift; break ;; # esac # done # # # Only call 'func_quote' here if we processed at least one argument. # if $args_changed; then # func_quote eval ${1+"$@"} # my_silent_option_result=$func_quote_result # fi # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # } # func_add_hook func_validate_options my_option_validation # # You'll also need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options_finish [ARG]... # ---------------------------- # Finishing the option parse loop (call 'func_options' hooks ATM). func_options_finish () { $debug_cmd func_run_hooks func_options ${1+"$@"} func_propagate_result func_run_hooks func_options_finish } # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd _G_options_quoted=false for my_func in options_prep parse_options validate_options options_finish do func_unset func_${my_func}_result func_unset func_run_hooks_result eval func_$my_func '${1+"$@"}' func_propagate_result func_$my_func func_options if $func_propagate_result_result; then eval set dummy "$func_options_result"; shift _G_options_quoted=: fi done $_G_options_quoted || { # As we (func_options) are top-level options-parser function and # nobody quoted "$@" for us yet, we need to do it explicitly for # caller. func_quote eval ${1+"$@"} func_options_result=$func_quote_result } } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propagate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} func_propagate_result func_run_hooks func_options_prep } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd _G_parse_options_requote=false # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} func_propagate_result func_run_hooks func_parse_options if $func_propagate_result_result; then eval set dummy "$func_parse_options_result"; shift # Even though we may have changed "$@", we passed the "$@" array # down into the hook and it quoted it for us (because we are in # this if-branch). No need to quote it again. _G_parse_options_requote=false fi # Break out of the loop if we already parsed every option. test $# -gt 0 || break # We expect that one of the options parsed in this function matches # and thus we remove _G_opt from "$@" and need to re-quote. _G_match_parse_options=: _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" >&2 $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) if test $# = 0 && func_missing_arg $_G_opt; then _G_parse_options_requote=: break fi case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) _G_parse_options_requote=: ; break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift _G_match_parse_options=false break ;; esac if $_G_match_parse_options; then _G_parse_options_requote=: fi done if $_G_parse_options_requote; then # save modified positional parameters for caller func_quote eval ${1+"$@"} func_parse_options_result=$func_quote_result fi } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} func_propagate_result func_run_hooks func_validate_options # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables # after splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} if test "x$func_split_equals_lhs" = "x$1"; then func_split_equals_rhs= fi }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. # The version message is extracted from the calling file's header # comments, with leading '# ' stripped: # 1. First display the progname and version # 2. Followed by the header comment line matching /^# Written by / # 3. Then a blank line followed by the first following line matching # /^# Copyright / # 4. Immediately followed by any lines between the previous matches, # except lines preceding the intervening completely blank line. # For example, see the header comments of this file. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /^# Written by /!b s|^# ||; p; n :fwd2blnk /./ { n b fwd2blnk } p; n :holdwrnt s|^# || s|^# *$|| /^Copyright /!{ /./H n b holdwrnt } s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| G s|\(\n\)\n*|\1|g p; q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6.42-b88ce' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname (GNU libtool) 2.4.6.42-b88ce automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= _G_rc_lt_options_prep=: # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; *) _G_rc_lt_options_prep=false ;; esac if $_G_rc_lt_options_prep; then # Pass back the list of options. func_quote eval ${1+"$@"} libtool_options_prep_result=$func_quote_result fi } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd _G_rc_lt_parse_options=false # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_match_lt_parse_options=: _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"} ; shift _G_match_lt_parse_options=false break ;; esac $_G_match_lt_parse_options && _G_rc_lt_parse_options=: done if $_G_rc_lt_parse_options; then # save modified positional parameters for caller func_quote eval ${1+"$@"} libtool_parse_options_result=$func_quote_result fi } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote eval ${1+"$@"} libtool_validate_options_result=$func_quote_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_arg pretty "$libobj" test "X$libobj" != "X$func_quote_arg_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_arg pretty "$srcfile" qsrcfile=$func_quote_arg_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_arg pretty "$nonopt" install_prog="$func_quote_arg_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_arg pretty "$arg" func_append install_prog "$func_quote_arg_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_arg pretty "$arg" func_append install_prog " $func_quote_arg_result" if test -n "$arg2"; then func_quote_arg pretty "$arg2" fi func_append install_shared_prog " $func_quote_arg_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_arg pretty "$install_override_mode" func_append install_shared_prog " -m $func_quote_arg_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_arg expand,pretty "$relink_command" eval "func_echo $func_quote_arg_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" func_quote_arg pretty "$ECHO" qECHO=$func_quote_arg_result $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=$qECHO fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_arg pretty,unquoted "$arg" qarg=$func_quote_arg_unquoted_result func_append libtool_args " $func_quote_arg_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $func_quote_arg_result" func_append compiler_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_arg pretty "$flag" func_append arg " $wl$func_quote_arg_result" func_append compiler_flags " $wl$func_quote_arg_result" func_append linker_flags " $func_quote_arg_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer # -fuse-ld=* Linker select flags for GCC -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*|-fuse-ld=*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_arg pretty "$arg" arg=$func_quote_arg_result fi ;; # Some other compiler flag. -* | +*) func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_arg pretty "$arg" arg=$func_quote_arg_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_arg expand,pretty "$cmd" eval "func_echo $func_quote_arg_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty "$var_value" relink_command="$var=$func_quote_arg_result; export $var; $relink_command" fi done func_quote eval cd "`pwd`" func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)" relink_command=$func_quote_arg_unquoted_result fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_arg pretty,unquoted "$var_value" relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command" fi done # Quote the link command for shipping. func_quote eval cd "`pwd`" relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" func_quote_arg pretty,unquoted "$relink_command" relink_command=$func_quote_arg_unquoted_result if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: ================================================ FILE: src/pcre/m4/ax_pthread.m4 ================================================ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 18 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) AC_MSG_RESULT($ax_pthread_ok) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case ${host_os} in solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($ax_pthread_ok) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $attr; return attr /* ; */])], [attr_name=$attr; break], []) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case ${host_os} in aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; osf* | hpux*) flag="-D_REENTRANT";; solaris*) if test "$GCC" = "yes"; then flag="-D_REENTRANT" else flag="-mt -D_REENTRANT" fi ;; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], ax_cv_PTHREAD_PRIO_INHERIT, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD ================================================ FILE: src/pcre/m4/libtool.m4 ================================================ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2018 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC and # ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} _LT_DECL([], [AR], [1], [The archiver]) # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS _LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)]) # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. _LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -z "$STRIP"; then AC_MSG_RESULT([no]) else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl* | *,icl*) # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC and ICC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl* | ,icl* | no,icl*) # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS ================================================ FILE: src/pcre/m4/ltoptions.m4 ================================================ # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2018 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) ================================================ FILE: src/pcre/m4/ltsugar.m4 ================================================ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2018 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) ================================================ FILE: src/pcre/m4/ltversion.m4 ================================================ # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2018 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4221 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6.42-b88ce]) m4_define([LT_PACKAGE_REVISION], [2.4.6.42]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6.42-b88ce' macro_revision='2.4.6.42' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) ================================================ FILE: src/pcre/m4/lt~obsolete.m4 ================================================ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2018 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) ================================================ FILE: src/pcre/m4/pcre_visibility.m4 ================================================ # visibility.m4 serial 4 (gettext-0.18.2) dnl Copyright (C) 2005, 2008, 2010-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Tests whether the compiler supports the command-line option dnl -fvisibility=hidden and the function and variable attributes dnl __attribute__((__visibility__("hidden"))) and dnl __attribute__((__visibility__("default"))). dnl Does *not* test for __visibility__("protected") - which has tricky dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on dnl MacOS X. dnl Does *not* test for __visibility__("internal") - which has processor dnl dependent semantics. dnl Does *not* test for #pragma GCC visibility push(hidden) - which is dnl "really only recommended for legacy code". dnl Set the variable CFLAG_VISIBILITY. dnl Defines and sets the variable HAVE_VISIBILITY. dnl Modified to fit with PCRE build environment by Cristian Rodríguez. AC_DEFUN([PCRE_VISIBILITY], [ AC_REQUIRE([AC_PROG_CC]) VISIBILITY_CFLAGS= VISIBILITY_CXXFLAGS= HAVE_VISIBILITY=0 if test -n "$GCC"; then dnl First, check whether -Werror can be added to the command line, or dnl whether it leads to an error because of some other option that the dnl user has put into $CC $CFLAGS $CPPFLAGS. AC_MSG_CHECKING([whether the -Werror option is usable]) AC_CACHE_VAL([pcre_cv_cc_vis_werror], [ pcre_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[]], [[]])], [pcre_cv_cc_vis_werror=yes], [pcre_cv_cc_vis_werror=no]) CFLAGS="$pcre_save_CFLAGS"]) AC_MSG_RESULT([$pcre_cv_cc_vis_werror]) dnl Now check whether visibility declarations are supported. AC_MSG_CHECKING([for simple visibility declarations]) AC_CACHE_VAL([pcre_cv_cc_visibility], [ pcre_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fvisibility=hidden" dnl We use the option -Werror and a function dummyfunc, because on some dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning dnl "visibility attribute not supported in this configuration; ignored" dnl at the first function definition in every compilation unit, and we dnl don't want to use the option in this case. if test $pcre_cv_cc_vis_werror = yes; then CFLAGS="$CFLAGS -Werror" fi AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[extern __attribute__((__visibility__("hidden"))) int hiddenvar; extern __attribute__((__visibility__("default"))) int exportedvar; extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); extern __attribute__((__visibility__("default"))) int exportedfunc (void); void dummyfunc (void) {} ]], [[]])], [pcre_cv_cc_visibility=yes], [pcre_cv_cc_visibility=no]) CFLAGS="$pcre_save_CFLAGS"]) AC_MSG_RESULT([$pcre_cv_cc_visibility]) if test $pcre_cv_cc_visibility = yes; then VISIBILITY_CFLAGS="-fvisibility=hidden" VISIBILITY_CXXFLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" HAVE_VISIBILITY=1 AC_DEFINE(PCRE_EXP_DECL, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible]) AC_DEFINE(PCRE_EXP_DEFN, [__attribute__ ((visibility ("default")))], [to make a symbol visible]) AC_DEFINE(PCRE_EXP_DATA_DEFN, [__attribute__ ((visibility ("default")))], [to make a symbol visible]) AC_DEFINE(PCREPOSIX_EXP_DECL, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible]) AC_DEFINE(PCREPOSIX_EXP_DEFN, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible]) AC_DEFINE(PCRECPP_EXP_DECL, [extern __attribute__ ((visibility ("default")))], [to make a symbol visible]) AC_DEFINE(PCRECPP_EXP_DEFN, [__attribute__ ((visibility ("default")))], [to make a symbol visible]) fi fi AC_SUBST([VISIBILITY_CFLAGS]) AC_SUBST([VISIBILITY_CXXFLAGS]) AC_SUBST([HAVE_VISIBILITY]) AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], [Define to 1 if the compiler supports simple visibility declarations.]) ]) ================================================ FILE: src/pcre/makevp.bat ================================================ :: AH 20-12-06 modified for new PCRE-7.0 and VP/BCC :: PH 19-03-07 renamed !compile.txt and !linklib.txt as makevp-compile.txt and :: makevp-linklib.txt :: PH 26-03-07 re-renamed !compile.txt and !linklib.txt as makevp-c.txt and :: makevp-l.txt :: PH 29-03-07 hopefully the final rename to makevp_c and makevp_l :: AH 27.08.08 updated for new PCRE-7.7 :: required PCRE.H and CONFIG.H will be generated if not existing @echo off echo. echo Compiling PCRE with BORLAND C++ for VIRTUAL PASCAL echo. REM This file was contributed by Alexander Tokarev for building PCRE for use REM with Virtual Pascal. It has not been tested with the latest PCRE release. REM This file has been modified and extended to compile with newer PCRE releases REM by Stefan Weber (Angels Holocaust). REM CHANGE THIS FOR YOUR BORLAND C++ COMPILER PATH SET BORLAND=f:\bcc REM location of the TASM binaries, if compiling with the -B BCC switch SET TASM=f:\tasm SET PATH=%PATH%;%BORLAND%\bin;%TASM%\bin SET PCRE_VER=77 SET COMPILE_DEFAULTS=-DHAVE_CONFIG_H -DPCRE_STATIC -I%BORLAND%\include del pcre%PCRE_VER%.lib >nul 2>nul :: sh configure :: check for needed header files if not exist pcre.h copy pcre.h.generic pcre.h if not exist config.h copy config.h.generic config.h bcc32 -DDFTABLES %COMPILE_DEFAULTS% -L%BORLAND%\lib dftables.c IF ERRORLEVEL 1 GOTO ERROR :: dftables > chartables.c dftables pcre_chartables.c REM compile and link the PCRE library into lib: option -B for ASM compile works too bcc32 -a4 -c -RT- -y- -v- -u- -R- -Q- -X -d -fp -ff -P- -O2 -Oc -Ov -3 -w-8004 -w-8064 -w-8065 -w-8012 -UDFTABLES -DVPCOMPAT %COMPILE_DEFAULTS% @makevp_c.txt IF ERRORLEVEL 1 GOTO ERROR tlib %BORLAND%\lib\cw32.lib *calloc *del *strncmp *memcpy *memmove *memset *memcmp *strlen IF ERRORLEVEL 1 GOTO ERROR tlib pcre%PCRE_VER%.lib @makevp_l.txt +calloc.obj +del.obj +strncmp.obj +memcpy.obj +memmove.obj +memset.obj +memcmp.obj +strlen.obj IF ERRORLEVEL 1 GOTO ERROR del *.obj *.tds *.bak >nul 2>nul echo --- echo Now the library should be complete. Please check all messages above. echo Don't care for warnings, it's OK. goto END :ERROR echo --- echo Error while compiling PCRE. Aborting... pause goto END :END ================================================ FILE: src/pcre/makevp_c.txt ================================================ pcre_byte_order.c pcre_chartables.c pcre_compile.c pcre_config.c pcre_dfa_exec.c pcre_exec.c pcre_fullinfo.c pcre_get.c pcre_globals.c pcre_jit_compile.c pcre_maketables.c pcre_newline.c pcre_ord2utf8.c pcre_refcount.c pcre_string_utils.c pcre_study.c pcre_tables.c pcre_ucd.c pcre_valid_utf8.c pcre_version.c pcre_xclass.c ================================================ FILE: src/pcre/makevp_l.txt ================================================ +pcre_byte_order.obj & +pcre_chartables.obj & +pcre_compile.obj & +pcre_config.obj & +pcre_dfa_exec.obj & +pcre_exec.obj & +pcre_fullinfo.obj & +pcre_get.obj & +pcre_globals.obj & +pcre_jit_compile.obj & +pcre_maketables.obj & +pcre_newline.obj & +pcre_ord2utf8.obj & +pcre_refcount.obj & +pcre_string_utils.obj & +pcre_study.obj & +pcre_tables.obj & +pcre_ucd.obj & +pcre_valid_utf8.obj & +pcre_version.obj & +pcre_xclass.obj ================================================ FILE: src/pcre/missing ================================================ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2018 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/pcre/pcre-config.in ================================================ #!/bin/sh prefix=@prefix@ exec_prefix=@exec_prefix@ exec_prefix_set=no cflags="[--cflags]" if test @enable_cpp@ = yes ; then libs="[--libs-cpp]" else libs= fi if test @enable_pcre16@ = yes ; then libs="[--libs16] $libs" fi if test @enable_pcre32@ = yes ; then libs="[--libs32] $libs" fi if test @enable_pcre8@ = yes ; then libs="[--libs] [--libs-posix] $libs" cflags="$cflags [--cflags-posix]" fi usage="Usage: pcre-config [--prefix] [--exec-prefix] [--version] $libs $cflags" if test $# -eq 0; then echo "${usage}" 1>&2 exit 1 fi libR= case `uname -s` in *SunOS*) libR=" -R@libdir@" ;; *BSD*) libR=" -Wl,-R@libdir@" ;; esac libS= if test @libdir@ != /usr/lib ; then libS=-L@libdir@ fi while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --prefix=*) prefix=$optarg if test $exec_prefix_set = no ; then exec_prefix=$optarg fi ;; --prefix) echo $prefix ;; --exec-prefix=*) exec_prefix=$optarg exec_prefix_set=yes ;; --exec-prefix) echo $exec_prefix ;; --version) echo @PACKAGE_VERSION@ ;; --cflags) if test @includedir@ != /usr/include ; then includes=-I@includedir@ fi echo $includes @PCRE_STATIC_CFLAG@ ;; --cflags-posix) if test @enable_pcre8@ = yes ; then if test @includedir@ != /usr/include ; then includes=-I@includedir@ fi echo $includes @PCRE_STATIC_CFLAG@ else echo "${usage}" 1>&2 fi ;; --libs-posix) if test @enable_pcre8@ = yes ; then echo $libS$libR -lpcreposix -lpcre else echo "${usage}" 1>&2 fi ;; --libs) if test @enable_pcre8@ = yes ; then echo $libS$libR -lpcre else echo "${usage}" 1>&2 fi ;; --libs16) if test @enable_pcre16@ = yes ; then echo $libS$libR -lpcre16 else echo "${usage}" 1>&2 fi ;; --libs32) if test @enable_pcre32@ = yes ; then echo $libS$libR -lpcre32 else echo "${usage}" 1>&2 fi ;; --libs-cpp) if test @enable_cpp@ = yes ; then echo $libS$libR -lpcrecpp -lpcre else echo "${usage}" 1>&2 fi ;; *) echo "${usage}" 1>&2 exit 1 ;; esac shift done ================================================ FILE: src/pcre/pcre.h.generic ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is the public header file for the PCRE library, to be #included by applications that call the PCRE functions. Copyright (c) 1997-2014 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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 _PCRE_H #define _PCRE_H /* The current PCRE version information. */ #define PCRE_MAJOR 8 #define PCRE_MINOR 43 #define PCRE_PRERELEASE #define PCRE_DATE 2019-02-23 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate export setting is defined in pcre_internal.h, which includes this file. So we don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ #if defined(_WIN32) && !defined(PCRE_STATIC) # ifndef PCRE_EXP_DECL # define PCRE_EXP_DECL extern __declspec(dllimport) # endif # ifdef __cplusplus # ifndef PCRECPP_EXP_DECL # define PCRECPP_EXP_DECL extern __declspec(dllimport) # endif # ifndef PCRECPP_EXP_DEFN # define PCRECPP_EXP_DEFN __declspec(dllimport) # endif # endif #endif /* By default, we use the standard "extern" declarations. */ #ifndef PCRE_EXP_DECL # ifdef __cplusplus # define PCRE_EXP_DECL extern "C" # else # define PCRE_EXP_DECL extern # endif #endif #ifdef __cplusplus # ifndef PCRECPP_EXP_DECL # define PCRECPP_EXP_DECL extern # endif # ifndef PCRECPP_EXP_DEFN # define PCRECPP_EXP_DEFN # endif #endif /* Have to include stdlib.h in order to ensure that size_t is defined; it is needed here for malloc. */ #include /* Allow for C++ users */ #ifdef __cplusplus extern "C" { #endif /* Public options. Some are compile-time only, some are run-time only, and some are both. Most of the compile-time options are saved with the compiled regex so that they can be inspected during studying (and therefore JIT compiling). Note that pcre_study() has its own set of options. Originally, all the options defined here used distinct bits. However, almost all the bits in a 32-bit word are now used, so in order to conserve them, option bits that were previously only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may also be used for compile-time options that affect only compiling and are not relevant for studying or JIT compiling. Some options for pcre_compile() change its behaviour but do not affect the behaviour of the execution functions. Other options are passed through to the execution functions and affect their behaviour, with or without affecting the behaviour of pcre_compile(). Options that can be passed to pcre_compile() are tagged Cx below, with these variants: C1 Affects compile only C2 Does not affect compile; affects exec, dfa_exec C3 Affects compile, exec, dfa_exec C4 Affects compile, exec, dfa_exec, study C5 Affects compile, exec, study Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with E and D, respectively. They take precedence over C3, C4, and C5 settings passed from pcre_compile(). Those that are compatible with JIT execution are flagged with J. */ #define PCRE_CASELESS 0x00000001 /* C1 */ #define PCRE_MULTILINE 0x00000002 /* C1 */ #define PCRE_DOTALL 0x00000004 /* C1 */ #define PCRE_EXTENDED 0x00000008 /* C1 */ #define PCRE_ANCHORED 0x00000010 /* C4 E D */ #define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */ #define PCRE_EXTRA 0x00000040 /* C1 */ #define PCRE_NOTBOL 0x00000080 /* E D J */ #define PCRE_NOTEOL 0x00000100 /* E D J */ #define PCRE_UNGREEDY 0x00000200 /* C1 */ #define PCRE_NOTEMPTY 0x00000400 /* E D J */ #define PCRE_UTF8 0x00000800 /* C4 ) */ #define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */ #define PCRE_UTF32 0x00000800 /* C4 ) */ #define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */ #define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */ #define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */ #define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */ #define PCRE_PARTIAL 0x00008000 /* E D J ) */ /* This pair use the same bit. */ #define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */ #define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */ /* This pair use the same bit. */ #define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */ #define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */ #define PCRE_FIRSTLINE 0x00040000 /* C3 */ #define PCRE_DUPNAMES 0x00080000 /* C1 */ #define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */ #define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */ #define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */ #define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */ #define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */ #define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */ #define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */ #define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */ #define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */ #define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */ #define PCRE_PARTIAL_HARD 0x08000000 /* E D J */ #define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */ #define PCRE_UCP 0x20000000 /* C3 */ /* Exec-time and get/set-time error codes */ #define PCRE_ERROR_NOMATCH (-1) #define PCRE_ERROR_NULL (-2) #define PCRE_ERROR_BADOPTION (-3) #define PCRE_ERROR_BADMAGIC (-4) #define PCRE_ERROR_UNKNOWN_OPCODE (-5) #define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */ #define PCRE_ERROR_NOMEMORY (-6) #define PCRE_ERROR_NOSUBSTRING (-7) #define PCRE_ERROR_MATCHLIMIT (-8) #define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ #define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_PARTIAL (-12) #define PCRE_ERROR_BADPARTIAL (-13) #define PCRE_ERROR_INTERNAL (-14) #define PCRE_ERROR_BADCOUNT (-15) #define PCRE_ERROR_DFA_UITEM (-16) #define PCRE_ERROR_DFA_UCOND (-17) #define PCRE_ERROR_DFA_UMLIMIT (-18) #define PCRE_ERROR_DFA_WSSIZE (-19) #define PCRE_ERROR_DFA_RECURSE (-20) #define PCRE_ERROR_RECURSIONLIMIT (-21) #define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */ #define PCRE_ERROR_BADNEWLINE (-23) #define PCRE_ERROR_BADOFFSET (-24) #define PCRE_ERROR_SHORTUTF8 (-25) #define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */ #define PCRE_ERROR_RECURSELOOP (-26) #define PCRE_ERROR_JIT_STACKLIMIT (-27) #define PCRE_ERROR_BADMODE (-28) #define PCRE_ERROR_BADENDIANNESS (-29) #define PCRE_ERROR_DFA_BADRESTART (-30) #define PCRE_ERROR_JIT_BADOPTION (-31) #define PCRE_ERROR_BADLENGTH (-32) #define PCRE_ERROR_UNSET (-33) /* Specific error codes for UTF-8 validity checks */ #define PCRE_UTF8_ERR0 0 #define PCRE_UTF8_ERR1 1 #define PCRE_UTF8_ERR2 2 #define PCRE_UTF8_ERR3 3 #define PCRE_UTF8_ERR4 4 #define PCRE_UTF8_ERR5 5 #define PCRE_UTF8_ERR6 6 #define PCRE_UTF8_ERR7 7 #define PCRE_UTF8_ERR8 8 #define PCRE_UTF8_ERR9 9 #define PCRE_UTF8_ERR10 10 #define PCRE_UTF8_ERR11 11 #define PCRE_UTF8_ERR12 12 #define PCRE_UTF8_ERR13 13 #define PCRE_UTF8_ERR14 14 #define PCRE_UTF8_ERR15 15 #define PCRE_UTF8_ERR16 16 #define PCRE_UTF8_ERR17 17 #define PCRE_UTF8_ERR18 18 #define PCRE_UTF8_ERR19 19 #define PCRE_UTF8_ERR20 20 #define PCRE_UTF8_ERR21 21 #define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */ /* Specific error codes for UTF-16 validity checks */ #define PCRE_UTF16_ERR0 0 #define PCRE_UTF16_ERR1 1 #define PCRE_UTF16_ERR2 2 #define PCRE_UTF16_ERR3 3 #define PCRE_UTF16_ERR4 4 /* Unused (was non-character) */ /* Specific error codes for UTF-32 validity checks */ #define PCRE_UTF32_ERR0 0 #define PCRE_UTF32_ERR1 1 #define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */ #define PCRE_UTF32_ERR3 3 /* Request types for pcre_fullinfo() */ #define PCRE_INFO_OPTIONS 0 #define PCRE_INFO_SIZE 1 #define PCRE_INFO_CAPTURECOUNT 2 #define PCRE_INFO_BACKREFMAX 3 #define PCRE_INFO_FIRSTBYTE 4 #define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ #define PCRE_INFO_FIRSTTABLE 5 #define PCRE_INFO_LASTLITERAL 6 #define PCRE_INFO_NAMEENTRYSIZE 7 #define PCRE_INFO_NAMECOUNT 8 #define PCRE_INFO_NAMETABLE 9 #define PCRE_INFO_STUDYSIZE 10 #define PCRE_INFO_DEFAULT_TABLES 11 #define PCRE_INFO_OKPARTIAL 12 #define PCRE_INFO_JCHANGED 13 #define PCRE_INFO_HASCRORLF 14 #define PCRE_INFO_MINLENGTH 15 #define PCRE_INFO_JIT 16 #define PCRE_INFO_JITSIZE 17 #define PCRE_INFO_MAXLOOKBEHIND 18 #define PCRE_INFO_FIRSTCHARACTER 19 #define PCRE_INFO_FIRSTCHARACTERFLAGS 20 #define PCRE_INFO_REQUIREDCHAR 21 #define PCRE_INFO_REQUIREDCHARFLAGS 22 #define PCRE_INFO_MATCHLIMIT 23 #define PCRE_INFO_RECURSIONLIMIT 24 #define PCRE_INFO_MATCH_EMPTY 25 /* Request types for pcre_config(). Do not re-arrange, in order to remain compatible. */ #define PCRE_CONFIG_UTF8 0 #define PCRE_CONFIG_NEWLINE 1 #define PCRE_CONFIG_LINK_SIZE 2 #define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 #define PCRE_CONFIG_MATCH_LIMIT 4 #define PCRE_CONFIG_STACKRECURSE 5 #define PCRE_CONFIG_UNICODE_PROPERTIES 6 #define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7 #define PCRE_CONFIG_BSR 8 #define PCRE_CONFIG_JIT 9 #define PCRE_CONFIG_UTF16 10 #define PCRE_CONFIG_JITTARGET 11 #define PCRE_CONFIG_UTF32 12 #define PCRE_CONFIG_PARENS_LIMIT 13 /* Request types for pcre_study(). Do not re-arrange, in order to remain compatible. */ #define PCRE_STUDY_JIT_COMPILE 0x0001 #define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002 #define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004 #define PCRE_STUDY_EXTRA_NEEDED 0x0008 /* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine these bits, just add new ones on the end, in order to remain compatible. */ #define PCRE_EXTRA_STUDY_DATA 0x0001 #define PCRE_EXTRA_MATCH_LIMIT 0x0002 #define PCRE_EXTRA_CALLOUT_DATA 0x0004 #define PCRE_EXTRA_TABLES 0x0008 #define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010 #define PCRE_EXTRA_MARK 0x0020 #define PCRE_EXTRA_EXECUTABLE_JIT 0x0040 /* Types */ struct real_pcre8_or_16; /* declaration; the definition is private */ typedef struct real_pcre8_or_16 pcre; struct real_pcre8_or_16; /* declaration; the definition is private */ typedef struct real_pcre8_or_16 pcre16; struct real_pcre32; /* declaration; the definition is private */ typedef struct real_pcre32 pcre32; struct real_pcre_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre_jit_stack pcre_jit_stack; struct real_pcre16_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre16_jit_stack pcre16_jit_stack; struct real_pcre32_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre32_jit_stack pcre32_jit_stack; /* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain a 16 bit wide signed data type. Otherwise it can be a dummy data type since pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */ #ifndef PCRE_UCHAR16 #define PCRE_UCHAR16 unsigned short #endif #ifndef PCRE_SPTR16 #define PCRE_SPTR16 const PCRE_UCHAR16 * #endif /* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain a 32 bit wide signed data type. Otherwise it can be a dummy data type since pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */ #ifndef PCRE_UCHAR32 #define PCRE_UCHAR32 unsigned int #endif #ifndef PCRE_SPTR32 #define PCRE_SPTR32 const PCRE_UCHAR32 * #endif /* When PCRE is compiled as a C++ library, the subject pointer type can be replaced with a custom type. For conventional use, the public interface is a const char *. */ #ifndef PCRE_SPTR #define PCRE_SPTR const char * #endif /* The structure for passing additional data to pcre_exec(). This is defined in such as way as to be extensible. Always add new fields at the end, in order to remain compatible. */ typedef struct pcre_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ unsigned char **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre_extra; /* Same structure as above, but with 16 bit char pointers. */ typedef struct pcre16_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre16_extra; /* Same structure as above, but with 32 bit char pointers. */ typedef struct pcre32_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ PCRE_UCHAR32 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre32_extra; /* The structure for passing out data via the pcre_callout_function. We use a structure so that new fields can be added on the end in future versions, without changing the API of the function, thereby allowing old clients to work without modification. */ typedef struct pcre_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const unsigned char *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre_callout_block; /* Same structure as above, but with 16 bit char pointers. */ typedef struct pcre16_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR16 subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre16_callout_block; /* Same structure as above, but with 32 bit char pointers. */ typedef struct pcre32_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR32 subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre32_callout_block; /* Indirection for store get and free functions. These can be set to alternative malloc/free functions if required. Special ones are used in the non-recursive case for "frames". There is also an optional callout function that is triggered by the (?) regex item. For Virtual Pascal, these definitions have to take another form. */ #ifndef VPCOMPAT PCRE_EXP_DECL void *(*pcre_malloc)(size_t); PCRE_EXP_DECL void (*pcre_free)(void *); PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre_stack_free)(void *); PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *); PCRE_EXP_DECL int (*pcre_stack_guard)(void); PCRE_EXP_DECL void *(*pcre16_malloc)(size_t); PCRE_EXP_DECL void (*pcre16_free)(void *); PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre16_stack_free)(void *); PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *); PCRE_EXP_DECL int (*pcre16_stack_guard)(void); PCRE_EXP_DECL void *(*pcre32_malloc)(size_t); PCRE_EXP_DECL void (*pcre32_free)(void *); PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre32_stack_free)(void *); PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *); PCRE_EXP_DECL int (*pcre32_stack_guard)(void); #else /* VPCOMPAT */ PCRE_EXP_DECL void *pcre_malloc(size_t); PCRE_EXP_DECL void pcre_free(void *); PCRE_EXP_DECL void *pcre_stack_malloc(size_t); PCRE_EXP_DECL void pcre_stack_free(void *); PCRE_EXP_DECL int pcre_callout(pcre_callout_block *); PCRE_EXP_DECL int pcre_stack_guard(void); PCRE_EXP_DECL void *pcre16_malloc(size_t); PCRE_EXP_DECL void pcre16_free(void *); PCRE_EXP_DECL void *pcre16_stack_malloc(size_t); PCRE_EXP_DECL void pcre16_stack_free(void *); PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *); PCRE_EXP_DECL int pcre16_stack_guard(void); PCRE_EXP_DECL void *pcre32_malloc(size_t); PCRE_EXP_DECL void pcre32_free(void *); PCRE_EXP_DECL void *pcre32_stack_malloc(size_t); PCRE_EXP_DECL void pcre32_stack_free(void *); PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *); PCRE_EXP_DECL int pcre32_stack_guard(void); #endif /* VPCOMPAT */ /* User defined callback which provides a stack just before the match starts. */ typedef pcre_jit_stack *(*pcre_jit_callback)(void *); typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *); typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *); /* Exported PCRE functions */ PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL int pcre_config(int, void *); PCRE_EXP_DECL int pcre16_config(int, void *); PCRE_EXP_DECL int pcre32_config(int, void *); PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, int *, int, const char *, char *, int); PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32, int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int); PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, char *, int); PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int, PCRE_UCHAR32 *, int); PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int); PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int); PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int); PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int, pcre_jit_stack *); PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int, pcre16_jit_stack *); PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int, pcre32_jit_stack *); PCRE_EXP_DECL void pcre_free_substring(const char *); PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16); PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32); PCRE_EXP_DECL void pcre_free_substring_list(const char **); PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *); PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *); PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int, void *); PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int, void *); PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, int *, int, const char *, const char **); PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16, int *, int, PCRE_SPTR16, PCRE_SPTR16 *); PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32, int *, int, PCRE_SPTR32, PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32); PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, char **, char **); PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16, PCRE_UCHAR16 **, PCRE_UCHAR16 **); PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32, PCRE_UCHAR32 **, PCRE_UCHAR32 **); PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, const char **); PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, PCRE_SPTR16 *); PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int, PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, const char ***); PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int, PCRE_SPTR16 **); PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int, PCRE_SPTR32 **); PCRE_EXP_DECL const unsigned char *pcre_maketables(void); PCRE_EXP_DECL const unsigned char *pcre16_maketables(void); PCRE_EXP_DECL const unsigned char *pcre32_maketables(void); PCRE_EXP_DECL int pcre_refcount(pcre *, int); PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int); PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int); PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **); PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **); PCRE_EXP_DECL void pcre_free_study(pcre_extra *); PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *); PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *); PCRE_EXP_DECL const char *pcre_version(void); PCRE_EXP_DECL const char *pcre16_version(void); PCRE_EXP_DECL const char *pcre32_version(void); /* Utility functions for byte order swaps. */ PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, const unsigned char *); PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, PCRE_SPTR16, int, int *, int); PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *, PCRE_SPTR32, int, int *, int); /* JIT compiler related functions. */ PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int); PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *); PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *); PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *); PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, pcre_jit_callback, void *); PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *, pcre16_jit_callback, void *); PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *, pcre32_jit_callback, void *); PCRE_EXP_DECL void pcre_jit_free_unused_memory(void); PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void); PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* End of pcre.h */ ================================================ FILE: src/pcre/pcre.h.in ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This is the public header file for the PCRE library, to be #included by applications that call the PCRE functions. Copyright (c) 1997-2014 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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 _PCRE_H #define _PCRE_H /* The current PCRE version information. */ #define PCRE_MAJOR @PCRE_MAJOR@ #define PCRE_MINOR @PCRE_MINOR@ #define PCRE_PRERELEASE @PCRE_PRERELEASE@ #define PCRE_DATE @PCRE_DATE@ /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate export setting is defined in pcre_internal.h, which includes this file. So we don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ #if defined(_WIN32) && !defined(PCRE_STATIC) # ifndef PCRE_EXP_DECL # define PCRE_EXP_DECL extern __declspec(dllimport) # endif # ifdef __cplusplus # ifndef PCRECPP_EXP_DECL # define PCRECPP_EXP_DECL extern __declspec(dllimport) # endif # ifndef PCRECPP_EXP_DEFN # define PCRECPP_EXP_DEFN __declspec(dllimport) # endif # endif #endif /* By default, we use the standard "extern" declarations. */ #ifndef PCRE_EXP_DECL # ifdef __cplusplus # define PCRE_EXP_DECL extern "C" # else # define PCRE_EXP_DECL extern # endif #endif #ifdef __cplusplus # ifndef PCRECPP_EXP_DECL # define PCRECPP_EXP_DECL extern # endif # ifndef PCRECPP_EXP_DEFN # define PCRECPP_EXP_DEFN # endif #endif /* Have to include stdlib.h in order to ensure that size_t is defined; it is needed here for malloc. */ #include /* Allow for C++ users */ #ifdef __cplusplus extern "C" { #endif /* Public options. Some are compile-time only, some are run-time only, and some are both. Most of the compile-time options are saved with the compiled regex so that they can be inspected during studying (and therefore JIT compiling). Note that pcre_study() has its own set of options. Originally, all the options defined here used distinct bits. However, almost all the bits in a 32-bit word are now used, so in order to conserve them, option bits that were previously only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may also be used for compile-time options that affect only compiling and are not relevant for studying or JIT compiling. Some options for pcre_compile() change its behaviour but do not affect the behaviour of the execution functions. Other options are passed through to the execution functions and affect their behaviour, with or without affecting the behaviour of pcre_compile(). Options that can be passed to pcre_compile() are tagged Cx below, with these variants: C1 Affects compile only C2 Does not affect compile; affects exec, dfa_exec C3 Affects compile, exec, dfa_exec C4 Affects compile, exec, dfa_exec, study C5 Affects compile, exec, study Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with E and D, respectively. They take precedence over C3, C4, and C5 settings passed from pcre_compile(). Those that are compatible with JIT execution are flagged with J. */ #define PCRE_CASELESS 0x00000001 /* C1 */ #define PCRE_MULTILINE 0x00000002 /* C1 */ #define PCRE_DOTALL 0x00000004 /* C1 */ #define PCRE_EXTENDED 0x00000008 /* C1 */ #define PCRE_ANCHORED 0x00000010 /* C4 E D */ #define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */ #define PCRE_EXTRA 0x00000040 /* C1 */ #define PCRE_NOTBOL 0x00000080 /* E D J */ #define PCRE_NOTEOL 0x00000100 /* E D J */ #define PCRE_UNGREEDY 0x00000200 /* C1 */ #define PCRE_NOTEMPTY 0x00000400 /* E D J */ #define PCRE_UTF8 0x00000800 /* C4 ) */ #define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */ #define PCRE_UTF32 0x00000800 /* C4 ) */ #define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */ #define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */ #define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */ #define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */ #define PCRE_PARTIAL 0x00008000 /* E D J ) */ /* This pair use the same bit. */ #define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */ #define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */ /* This pair use the same bit. */ #define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */ #define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */ #define PCRE_FIRSTLINE 0x00040000 /* C3 */ #define PCRE_DUPNAMES 0x00080000 /* C1 */ #define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */ #define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */ #define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */ #define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */ #define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */ #define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */ #define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */ #define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */ #define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */ #define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */ #define PCRE_PARTIAL_HARD 0x08000000 /* E D J */ #define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */ #define PCRE_UCP 0x20000000 /* C3 */ /* Exec-time and get/set-time error codes */ #define PCRE_ERROR_NOMATCH (-1) #define PCRE_ERROR_NULL (-2) #define PCRE_ERROR_BADOPTION (-3) #define PCRE_ERROR_BADMAGIC (-4) #define PCRE_ERROR_UNKNOWN_OPCODE (-5) #define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */ #define PCRE_ERROR_NOMEMORY (-6) #define PCRE_ERROR_NOSUBSTRING (-7) #define PCRE_ERROR_MATCHLIMIT (-8) #define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ #define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_PARTIAL (-12) #define PCRE_ERROR_BADPARTIAL (-13) #define PCRE_ERROR_INTERNAL (-14) #define PCRE_ERROR_BADCOUNT (-15) #define PCRE_ERROR_DFA_UITEM (-16) #define PCRE_ERROR_DFA_UCOND (-17) #define PCRE_ERROR_DFA_UMLIMIT (-18) #define PCRE_ERROR_DFA_WSSIZE (-19) #define PCRE_ERROR_DFA_RECURSE (-20) #define PCRE_ERROR_RECURSIONLIMIT (-21) #define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */ #define PCRE_ERROR_BADNEWLINE (-23) #define PCRE_ERROR_BADOFFSET (-24) #define PCRE_ERROR_SHORTUTF8 (-25) #define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */ #define PCRE_ERROR_RECURSELOOP (-26) #define PCRE_ERROR_JIT_STACKLIMIT (-27) #define PCRE_ERROR_BADMODE (-28) #define PCRE_ERROR_BADENDIANNESS (-29) #define PCRE_ERROR_DFA_BADRESTART (-30) #define PCRE_ERROR_JIT_BADOPTION (-31) #define PCRE_ERROR_BADLENGTH (-32) #define PCRE_ERROR_UNSET (-33) /* Specific error codes for UTF-8 validity checks */ #define PCRE_UTF8_ERR0 0 #define PCRE_UTF8_ERR1 1 #define PCRE_UTF8_ERR2 2 #define PCRE_UTF8_ERR3 3 #define PCRE_UTF8_ERR4 4 #define PCRE_UTF8_ERR5 5 #define PCRE_UTF8_ERR6 6 #define PCRE_UTF8_ERR7 7 #define PCRE_UTF8_ERR8 8 #define PCRE_UTF8_ERR9 9 #define PCRE_UTF8_ERR10 10 #define PCRE_UTF8_ERR11 11 #define PCRE_UTF8_ERR12 12 #define PCRE_UTF8_ERR13 13 #define PCRE_UTF8_ERR14 14 #define PCRE_UTF8_ERR15 15 #define PCRE_UTF8_ERR16 16 #define PCRE_UTF8_ERR17 17 #define PCRE_UTF8_ERR18 18 #define PCRE_UTF8_ERR19 19 #define PCRE_UTF8_ERR20 20 #define PCRE_UTF8_ERR21 21 #define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */ /* Specific error codes for UTF-16 validity checks */ #define PCRE_UTF16_ERR0 0 #define PCRE_UTF16_ERR1 1 #define PCRE_UTF16_ERR2 2 #define PCRE_UTF16_ERR3 3 #define PCRE_UTF16_ERR4 4 /* Unused (was non-character) */ /* Specific error codes for UTF-32 validity checks */ #define PCRE_UTF32_ERR0 0 #define PCRE_UTF32_ERR1 1 #define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */ #define PCRE_UTF32_ERR3 3 /* Request types for pcre_fullinfo() */ #define PCRE_INFO_OPTIONS 0 #define PCRE_INFO_SIZE 1 #define PCRE_INFO_CAPTURECOUNT 2 #define PCRE_INFO_BACKREFMAX 3 #define PCRE_INFO_FIRSTBYTE 4 #define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ #define PCRE_INFO_FIRSTTABLE 5 #define PCRE_INFO_LASTLITERAL 6 #define PCRE_INFO_NAMEENTRYSIZE 7 #define PCRE_INFO_NAMECOUNT 8 #define PCRE_INFO_NAMETABLE 9 #define PCRE_INFO_STUDYSIZE 10 #define PCRE_INFO_DEFAULT_TABLES 11 #define PCRE_INFO_OKPARTIAL 12 #define PCRE_INFO_JCHANGED 13 #define PCRE_INFO_HASCRORLF 14 #define PCRE_INFO_MINLENGTH 15 #define PCRE_INFO_JIT 16 #define PCRE_INFO_JITSIZE 17 #define PCRE_INFO_MAXLOOKBEHIND 18 #define PCRE_INFO_FIRSTCHARACTER 19 #define PCRE_INFO_FIRSTCHARACTERFLAGS 20 #define PCRE_INFO_REQUIREDCHAR 21 #define PCRE_INFO_REQUIREDCHARFLAGS 22 #define PCRE_INFO_MATCHLIMIT 23 #define PCRE_INFO_RECURSIONLIMIT 24 #define PCRE_INFO_MATCH_EMPTY 25 /* Request types for pcre_config(). Do not re-arrange, in order to remain compatible. */ #define PCRE_CONFIG_UTF8 0 #define PCRE_CONFIG_NEWLINE 1 #define PCRE_CONFIG_LINK_SIZE 2 #define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 #define PCRE_CONFIG_MATCH_LIMIT 4 #define PCRE_CONFIG_STACKRECURSE 5 #define PCRE_CONFIG_UNICODE_PROPERTIES 6 #define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7 #define PCRE_CONFIG_BSR 8 #define PCRE_CONFIG_JIT 9 #define PCRE_CONFIG_UTF16 10 #define PCRE_CONFIG_JITTARGET 11 #define PCRE_CONFIG_UTF32 12 #define PCRE_CONFIG_PARENS_LIMIT 13 /* Request types for pcre_study(). Do not re-arrange, in order to remain compatible. */ #define PCRE_STUDY_JIT_COMPILE 0x0001 #define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002 #define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004 #define PCRE_STUDY_EXTRA_NEEDED 0x0008 /* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine these bits, just add new ones on the end, in order to remain compatible. */ #define PCRE_EXTRA_STUDY_DATA 0x0001 #define PCRE_EXTRA_MATCH_LIMIT 0x0002 #define PCRE_EXTRA_CALLOUT_DATA 0x0004 #define PCRE_EXTRA_TABLES 0x0008 #define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010 #define PCRE_EXTRA_MARK 0x0020 #define PCRE_EXTRA_EXECUTABLE_JIT 0x0040 /* Types */ struct real_pcre8_or_16; /* declaration; the definition is private */ typedef struct real_pcre8_or_16 pcre; struct real_pcre8_or_16; /* declaration; the definition is private */ typedef struct real_pcre8_or_16 pcre16; struct real_pcre32; /* declaration; the definition is private */ typedef struct real_pcre32 pcre32; struct real_pcre_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre_jit_stack pcre_jit_stack; struct real_pcre16_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre16_jit_stack pcre16_jit_stack; struct real_pcre32_jit_stack; /* declaration; the definition is private */ typedef struct real_pcre32_jit_stack pcre32_jit_stack; /* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain a 16 bit wide signed data type. Otherwise it can be a dummy data type since pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */ #ifndef PCRE_UCHAR16 #define PCRE_UCHAR16 unsigned short #endif #ifndef PCRE_SPTR16 #define PCRE_SPTR16 const PCRE_UCHAR16 * #endif /* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain a 32 bit wide signed data type. Otherwise it can be a dummy data type since pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */ #ifndef PCRE_UCHAR32 #define PCRE_UCHAR32 unsigned int #endif #ifndef PCRE_SPTR32 #define PCRE_SPTR32 const PCRE_UCHAR32 * #endif /* When PCRE is compiled as a C++ library, the subject pointer type can be replaced with a custom type. For conventional use, the public interface is a const char *. */ #ifndef PCRE_SPTR #define PCRE_SPTR const char * #endif /* The structure for passing additional data to pcre_exec(). This is defined in such as way as to be extensible. Always add new fields at the end, in order to remain compatible. */ typedef struct pcre_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ unsigned char **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre_extra; /* Same structure as above, but with 16 bit char pointers. */ typedef struct pcre16_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre16_extra; /* Same structure as above, but with 32 bit char pointers. */ typedef struct pcre32_extra { unsigned long int flags; /* Bits for which fields are set */ void *study_data; /* Opaque data from pcre_study() */ unsigned long int match_limit; /* Maximum number of calls to match() */ void *callout_data; /* Data passed back in callouts */ const unsigned char *tables; /* Pointer to character tables */ unsigned long int match_limit_recursion; /* Max recursive calls to match() */ PCRE_UCHAR32 **mark; /* For passing back a mark pointer */ void *executable_jit; /* Contains a pointer to a compiled jit code */ } pcre32_extra; /* The structure for passing out data via the pcre_callout_function. We use a structure so that new fields can be added on the end in future versions, without changing the API of the function, thereby allowing old clients to work without modification. */ typedef struct pcre_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const unsigned char *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre_callout_block; /* Same structure as above, but with 16 bit char pointers. */ typedef struct pcre16_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR16 subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre16_callout_block; /* Same structure as above, but with 32 bit char pointers. */ typedef struct pcre32_callout_block { int version; /* Identifies version of block */ /* ------------------------ Version 0 ------------------------------- */ int callout_number; /* Number compiled into pattern */ int *offset_vector; /* The offset vector */ PCRE_SPTR32 subject; /* The subject being matched */ int subject_length; /* The length of the subject */ int start_match; /* Offset to start of this match attempt */ int current_position; /* Where we currently are in the subject */ int capture_top; /* Max current capture */ int capture_last; /* Most recently closed capture */ void *callout_data; /* Data passed in with the call */ /* ------------------- Added for Version 1 -------------------------- */ int pattern_position; /* Offset to next item in the pattern */ int next_item_length; /* Length of next item in the pattern */ /* ------------------- Added for Version 2 -------------------------- */ const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */ /* ------------------------------------------------------------------ */ } pcre32_callout_block; /* Indirection for store get and free functions. These can be set to alternative malloc/free functions if required. Special ones are used in the non-recursive case for "frames". There is also an optional callout function that is triggered by the (?) regex item. For Virtual Pascal, these definitions have to take another form. */ #ifndef VPCOMPAT PCRE_EXP_DECL void *(*pcre_malloc)(size_t); PCRE_EXP_DECL void (*pcre_free)(void *); PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre_stack_free)(void *); PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *); PCRE_EXP_DECL int (*pcre_stack_guard)(void); PCRE_EXP_DECL void *(*pcre16_malloc)(size_t); PCRE_EXP_DECL void (*pcre16_free)(void *); PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre16_stack_free)(void *); PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *); PCRE_EXP_DECL int (*pcre16_stack_guard)(void); PCRE_EXP_DECL void *(*pcre32_malloc)(size_t); PCRE_EXP_DECL void (*pcre32_free)(void *); PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t); PCRE_EXP_DECL void (*pcre32_stack_free)(void *); PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *); PCRE_EXP_DECL int (*pcre32_stack_guard)(void); #else /* VPCOMPAT */ PCRE_EXP_DECL void *pcre_malloc(size_t); PCRE_EXP_DECL void pcre_free(void *); PCRE_EXP_DECL void *pcre_stack_malloc(size_t); PCRE_EXP_DECL void pcre_stack_free(void *); PCRE_EXP_DECL int pcre_callout(pcre_callout_block *); PCRE_EXP_DECL int pcre_stack_guard(void); PCRE_EXP_DECL void *pcre16_malloc(size_t); PCRE_EXP_DECL void pcre16_free(void *); PCRE_EXP_DECL void *pcre16_stack_malloc(size_t); PCRE_EXP_DECL void pcre16_stack_free(void *); PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *); PCRE_EXP_DECL int pcre16_stack_guard(void); PCRE_EXP_DECL void *pcre32_malloc(size_t); PCRE_EXP_DECL void pcre32_free(void *); PCRE_EXP_DECL void *pcre32_stack_malloc(size_t); PCRE_EXP_DECL void pcre32_stack_free(void *); PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *); PCRE_EXP_DECL int pcre32_stack_guard(void); #endif /* VPCOMPAT */ /* User defined callback which provides a stack just before the match starts. */ typedef pcre_jit_stack *(*pcre_jit_callback)(void *); typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *); typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *); /* Exported PCRE functions */ PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **, int *, const unsigned char *); PCRE_EXP_DECL int pcre_config(int, void *); PCRE_EXP_DECL int pcre16_config(int, void *); PCRE_EXP_DECL int pcre32_config(int, void *); PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, int *, int, const char *, char *, int); PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32, int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int); PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, char *, int); PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, PCRE_UCHAR16 *, int); PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int, PCRE_UCHAR32 *, int); PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, const char *, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int , int *, int); PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int); PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int); PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int); PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *, PCRE_SPTR, int, int, int, int *, int, pcre_jit_stack *); PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *, PCRE_SPTR16, int, int, int, int *, int, pcre16_jit_stack *); PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *, PCRE_SPTR32, int, int, int, int *, int, pcre32_jit_stack *); PCRE_EXP_DECL void pcre_free_substring(const char *); PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16); PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32); PCRE_EXP_DECL void pcre_free_substring_list(const char **); PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *); PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, void *); PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int, void *); PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int, void *); PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, int *, int, const char *, const char **); PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16, int *, int, PCRE_SPTR16, PCRE_SPTR16 *); PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32, int *, int, PCRE_SPTR32, PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32); PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, char **, char **); PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16, PCRE_UCHAR16 **, PCRE_UCHAR16 **); PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32, PCRE_UCHAR32 **, PCRE_UCHAR32 **); PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, const char **); PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, PCRE_SPTR16 *); PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int, PCRE_SPTR32 *); PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, const char ***); PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int, PCRE_SPTR16 **); PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int, PCRE_SPTR32 **); PCRE_EXP_DECL const unsigned char *pcre_maketables(void); PCRE_EXP_DECL const unsigned char *pcre16_maketables(void); PCRE_EXP_DECL const unsigned char *pcre32_maketables(void); PCRE_EXP_DECL int pcre_refcount(pcre *, int); PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int); PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int); PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **); PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **); PCRE_EXP_DECL void pcre_free_study(pcre_extra *); PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *); PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *); PCRE_EXP_DECL const char *pcre_version(void); PCRE_EXP_DECL const char *pcre16_version(void); PCRE_EXP_DECL const char *pcre32_version(void); /* Utility functions for byte order swaps. */ PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, const unsigned char *); PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *, const unsigned char *); PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, PCRE_SPTR16, int, int *, int); PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *, PCRE_SPTR32, int, int *, int); /* JIT compiler related functions. */ PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int); PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *); PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *); PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *); PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, pcre_jit_callback, void *); PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *, pcre16_jit_callback, void *); PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *, pcre32_jit_callback, void *); PCRE_EXP_DECL void pcre_jit_free_unused_memory(void); PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void); PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* End of pcre.h */ ================================================ FILE: src/pcre/pcre16_byte_order.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_byte_order.c" /* End of pcre16_byte_order.c */ ================================================ FILE: src/pcre/pcre16_chartables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_chartables.c" /* End of pcre16_chartables.c */ ================================================ FILE: src/pcre/pcre16_compile.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_compile.c" /* End of pcre16_compile.c */ ================================================ FILE: src/pcre/pcre16_config.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_config.c" /* End of pcre16_config.c */ ================================================ FILE: src/pcre/pcre16_dfa_exec.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_dfa_exec.c" /* End of pcre16_dfa_exec.c */ ================================================ FILE: src/pcre/pcre16_exec.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_exec.c" /* End of pcre16_exec.c */ ================================================ FILE: src/pcre/pcre16_fullinfo.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_fullinfo.c" /* End of pcre16_fullinfo.c */ ================================================ FILE: src/pcre/pcre16_get.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_get.c" /* End of pcre16_get.c */ ================================================ FILE: src/pcre/pcre16_globals.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_globals.c" /* End of pcre16_globals.c */ ================================================ FILE: src/pcre/pcre16_jit_compile.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_jit_compile.c" /* End of pcre16_jit_compile.c */ ================================================ FILE: src/pcre/pcre16_maketables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_maketables.c" /* End of pcre16_maketables.c */ ================================================ FILE: src/pcre/pcre16_newline.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_newline.c" /* End of pcre16_newline.c */ ================================================ FILE: src/pcre/pcre16_ord2utf16.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This file contains a private PCRE function that converts an ordinal character value into a UTF16 string. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_internal.h" /************************************************* * Convert character value to UTF-16 * *************************************************/ /* This function takes an integer value in the range 0 - 0x10ffff and encodes it as a UTF-16 character in 1 to 2 pcre_uchars. Arguments: cvalue the character value buffer pointer to buffer for result - at least 2 pcre_uchars long Returns: number of characters placed in the buffer */ unsigned int PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer) { #ifdef SUPPORT_UTF if (cvalue <= 0xffff) { *buffer = (pcre_uchar)cvalue; return 1; } cvalue -= 0x10000; *buffer++ = 0xd800 | (cvalue >> 10); *buffer = 0xdc00 | (cvalue & 0x3ff); return 2; #else /* SUPPORT_UTF */ (void)(cvalue); /* Keep compiler happy; this function won't ever be */ (void)(buffer); /* called when SUPPORT_UTF is not defined. */ return 0; #endif /* SUPPORT_UTF */ } /* End of pcre16_ord2utf16.c */ ================================================ FILE: src/pcre/pcre16_printint.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_printint.c" /* End of pcre16_printint.c */ ================================================ FILE: src/pcre/pcre16_refcount.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_refcount.c" /* End of pcre16_refcount.c */ ================================================ FILE: src/pcre/pcre16_string_utils.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_string_utils.c" /* End of pcre16_string_utils.c */ ================================================ FILE: src/pcre/pcre16_study.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_study.c" /* End of pcre16_study.c */ ================================================ FILE: src/pcre/pcre16_tables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_tables.c" /* End of pcre16_tables.c */ ================================================ FILE: src/pcre/pcre16_ucd.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_ucd.c" /* End of pcre16_ucd.c */ ================================================ FILE: src/pcre/pcre16_utf16_utils.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains a function for converting any UTF-16 character strings to host byte order. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_internal.h" /************************************************* * Convert any UTF-16 string to host byte order * *************************************************/ /* This function takes an UTF-16 string and converts it to host byte order. The length can be explicitly set, or automatically detected for zero terminated strings. BOMs can be kept or discarded during the conversion. Conversion can be done in place (output == input). Arguments: output the output buffer, its size must be greater or equal than the input string input any UTF-16 string length the number of 16-bit units in the input string can be less than zero for zero terminated strings host_byte_order A non-zero value means the input is in host byte order, which can be dynamically changed by BOMs later. Initially it contains the starting byte order and returns with the last byte order so it can be used for stream processing. It can be NULL, which set the host byte order mode by default. keep_boms for a non-zero value, the BOM (0xfeff) characters are copied as well Returns: the number of 16-bit units placed into the output buffer, including the zero-terminator */ int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input, int length, int *host_byte_order, int keep_boms) { #ifdef SUPPORT_UTF /* This function converts any UTF-16 string to host byte order and optionally removes any Byte Order Marks (BOMS). Returns with the remainig length. */ int host_bo = host_byte_order != NULL ? *host_byte_order : 1; pcre_uchar *optr = (pcre_uchar *)output; const pcre_uchar *iptr = (const pcre_uchar *)input; const pcre_uchar *end; /* The c variable must be unsigned. */ register pcre_uchar c; if (length < 0) length = STRLEN_UC(iptr) + 1; end = iptr + length; while (iptr < end) { c = *iptr++; if (c == 0xfeff || c == 0xfffe) { /* Detecting the byte order of the machine is unnecessary, it is enough to know that the UTF-16 string has the same byte order or not. */ host_bo = c == 0xfeff; if (keep_boms != 0) *optr++ = 0xfeff; else length--; } else *optr++ = host_bo ? c : ((c >> 8) | (c << 8)); /* Flip bytes if needed. */ } if (host_byte_order != NULL) *host_byte_order = host_bo; #else /* Not SUPPORT_UTF */ (void)(output); /* Keep picky compilers happy */ (void)(input); (void)(keep_boms); (void)(host_byte_order); #endif /* SUPPORT_UTF */ return length; } /* End of pcre16_utf16_utils.c */ ================================================ FILE: src/pcre/pcre16_valid_utf16.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2013 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains an internal function for validating UTF-16 character strings. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_internal.h" /************************************************* * Validate a UTF-16 string * *************************************************/ /* This function is called (optionally) at the start of compile or match, to check that a supposed UTF-16 string is actually valid. The early check means that subsequent code can assume it is dealing with a valid string. The check can be turned off for maximum performance, but the consequences of supplying an invalid string are then undefined. From release 8.21 more information about the details of the error are passed back in the returned value: PCRE_UTF16_ERR0 No error PCRE_UTF16_ERR1 Missing low surrogate at the end of the string PCRE_UTF16_ERR2 Invalid low surrogate PCRE_UTF16_ERR3 Isolated low surrogate PCRE_UTF16_ERR4 Unused (was non-character) Arguments: string points to the string length length of string, or -1 if the string is zero-terminated errp pointer to an error position offset variable Returns: = 0 if the string is a valid UTF-16 string > 0 otherwise, setting the offset of the bad character */ int PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset) { #ifdef SUPPORT_UTF register PCRE_PUCHAR p; register pcre_uint32 c; if (length < 0) { for (p = string; *p != 0; p++); length = p - string; } for (p = string; length-- > 0; p++) { c = *p; if ((c & 0xf800) != 0xd800) { /* Normal UTF-16 code point. Neither high nor low surrogate. */ } else if ((c & 0x0400) == 0) { /* High surrogate. Must be a followed by a low surrogate. */ if (length == 0) { *erroroffset = p - string; return PCRE_UTF16_ERR1; } p++; length--; if ((*p & 0xfc00) != 0xdc00) { *erroroffset = p - string; return PCRE_UTF16_ERR2; } } else { /* Isolated low surrogate. Always an error. */ *erroroffset = p - string; return PCRE_UTF16_ERR3; } } #else /* SUPPORT_UTF */ (void)(string); /* Keep picky compilers happy */ (void)(length); (void)(erroroffset); #endif /* SUPPORT_UTF */ return PCRE_UTF16_ERR0; /* This indicates success */ } /* End of pcre16_valid_utf16.c */ ================================================ FILE: src/pcre/pcre16_version.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_version.c" /* End of pcre16_version.c */ ================================================ FILE: src/pcre/pcre16_xclass.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 16 bit character support. */ #define COMPILE_PCRE16 #include "pcre_xclass.c" /* End of pcre16_xclass.c */ ================================================ FILE: src/pcre/pcre32_byte_order.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_byte_order.c" /* End of pcre32_byte_order.c */ ================================================ FILE: src/pcre/pcre32_chartables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_chartables.c" /* End of pcre32_chartables.c */ ================================================ FILE: src/pcre/pcre32_compile.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_compile.c" /* End of pcre32_compile.c */ ================================================ FILE: src/pcre/pcre32_config.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_config.c" /* End of pcre32_config.c */ ================================================ FILE: src/pcre/pcre32_dfa_exec.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_dfa_exec.c" /* End of pcre32_dfa_exec.c */ ================================================ FILE: src/pcre/pcre32_exec.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_exec.c" /* End of pcre32_exec.c */ ================================================ FILE: src/pcre/pcre32_fullinfo.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_fullinfo.c" /* End of pcre32_fullinfo.c */ ================================================ FILE: src/pcre/pcre32_get.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_get.c" /* End of pcre32_get.c */ ================================================ FILE: src/pcre/pcre32_globals.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_globals.c" /* End of pcre32_globals.c */ ================================================ FILE: src/pcre/pcre32_jit_compile.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_jit_compile.c" /* End of pcre32_jit_compile.c */ ================================================ FILE: src/pcre/pcre32_maketables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_maketables.c" /* End of pcre32_maketables.c */ ================================================ FILE: src/pcre/pcre32_newline.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_newline.c" /* End of pcre32_newline.c */ ================================================ FILE: src/pcre/pcre32_ord2utf32.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This file contains a private PCRE function that converts an ordinal character value into a UTF32 string. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_internal.h" /************************************************* * Convert character value to UTF-32 * *************************************************/ /* This function takes an integer value in the range 0 - 0x10ffff and encodes it as a UTF-32 character in 1 pcre_uchars. Arguments: cvalue the character value buffer pointer to buffer for result - at least 1 pcre_uchars long Returns: number of characters placed in the buffer */ unsigned int PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer) { #ifdef SUPPORT_UTF *buffer = (pcre_uchar)cvalue; return 1; #else /* SUPPORT_UTF */ (void)(cvalue); /* Keep compiler happy; this function won't ever be */ (void)(buffer); /* called when SUPPORT_UTF is not defined. */ return 0; #endif /* SUPPORT_UTF */ } /* End of pcre32_ord2utf32.c */ ================================================ FILE: src/pcre/pcre32_printint.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_printint.c" /* End of pcre32_printint.c */ ================================================ FILE: src/pcre/pcre32_refcount.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_refcount.c" /* End of pcre32_refcount.c */ ================================================ FILE: src/pcre/pcre32_string_utils.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_string_utils.c" /* End of pcre32_string_utils.c */ ================================================ FILE: src/pcre/pcre32_study.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_study.c" /* End of pcre32_study.c */ ================================================ FILE: src/pcre/pcre32_tables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_tables.c" /* End of pcre32_tables.c */ ================================================ FILE: src/pcre/pcre32_ucd.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_ucd.c" /* End of pcre32_ucd.c */ ================================================ FILE: src/pcre/pcre32_utf32_utils.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains a function for converting any UTF-32 character strings to host byte order. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_internal.h" #ifdef SUPPORT_UTF static pcre_uint32 swap_uint32(pcre_uint32 value) { return ((value & 0x000000ff) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | (value >> 24); } #endif /************************************************* * Convert any UTF-32 string to host byte order * *************************************************/ /* This function takes an UTF-32 string and converts it to host byte order. The length can be explicitly set, or automatically detected for zero terminated strings. BOMs can be kept or discarded during the conversion. Conversion can be done in place (output == input). Arguments: output the output buffer, its size must be greater or equal than the input string input any UTF-32 string length the number of 32-bit units in the input string can be less than zero for zero terminated strings host_byte_order A non-zero value means the input is in host byte order, which can be dynamically changed by BOMs later. Initially it contains the starting byte order and returns with the last byte order so it can be used for stream processing. It can be NULL, which set the host byte order mode by default. keep_boms for a non-zero value, the BOM (0xfeff) characters are copied as well Returns: the number of 32-bit units placed into the output buffer, including the zero-terminator */ int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *output, PCRE_SPTR32 input, int length, int *host_byte_order, int keep_boms) { #ifdef SUPPORT_UTF /* This function converts any UTF-32 string to host byte order and optionally removes any Byte Order Marks (BOMS). Returns with the remainig length. */ int host_bo = host_byte_order != NULL ? *host_byte_order : 1; pcre_uchar *optr = (pcre_uchar *)output; const pcre_uchar *iptr = (const pcre_uchar *)input; const pcre_uchar *end; /* The c variable must be unsigned. */ register pcre_uchar c; if (length < 0) end = iptr + STRLEN_UC(iptr) + 1; else end = iptr + length; while (iptr < end) { c = *iptr++; if (c == 0x0000feffu || c == 0xfffe0000u) { /* Detecting the byte order of the machine is unnecessary, it is enough to know that the UTF-32 string has the same byte order or not. */ host_bo = c == 0x0000feffu; if (keep_boms != 0) *optr++ = 0x0000feffu; } else *optr++ = host_bo ? c : swap_uint32(c); } if (host_byte_order != NULL) *host_byte_order = host_bo; #else /* SUPPORT_UTF */ (void)(output); /* Keep picky compilers happy */ (void)(input); (void)(keep_boms); (void)(host_byte_order); #endif /* SUPPORT_UTF */ return length; } /* End of pcre32_utf32_utils.c */ ================================================ FILE: src/pcre/pcre32_valid_utf32.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2013 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains an internal function for validating UTF-32 character strings. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_internal.h" /************************************************* * Validate a UTF-32 string * *************************************************/ /* This function is called (optionally) at the start of compile or match, to check that a supposed UTF-32 string is actually valid. The early check means that subsequent code can assume it is dealing with a valid string. The check can be turned off for maximum performance, but the consequences of supplying an invalid string are then undefined. More information about the details of the error are passed back in the returned value: PCRE_UTF32_ERR0 No error PCRE_UTF32_ERR1 Surrogate character PCRE_UTF32_ERR2 Unused (was non-character) PCRE_UTF32_ERR3 Character > 0x10ffff Arguments: string points to the string length length of string, or -1 if the string is zero-terminated errp pointer to an error position offset variable Returns: = 0 if the string is a valid UTF-32 string > 0 otherwise, setting the offset of the bad character */ int PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset) { #ifdef SUPPORT_UTF register PCRE_PUCHAR p; register pcre_uchar c; if (length < 0) { for (p = string; *p != 0; p++); length = p - string; } for (p = string; length-- > 0; p++) { c = *p; if ((c & 0xfffff800u) != 0xd800u) { /* Normal UTF-32 code point. Neither high nor low surrogate. */ if (c > 0x10ffffu) { *erroroffset = p - string; return PCRE_UTF32_ERR3; } } else { /* A surrogate */ *erroroffset = p - string; return PCRE_UTF32_ERR1; } } #else /* SUPPORT_UTF */ (void)(string); /* Keep picky compilers happy */ (void)(length); (void)(erroroffset); #endif /* SUPPORT_UTF */ return PCRE_UTF32_ERR0; /* This indicates success */ } /* End of pcre32_valid_utf32.c */ ================================================ FILE: src/pcre/pcre32_version.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_version.c" /* End of pcre32_version.c */ ================================================ FILE: src/pcre/pcre32_xclass.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Generate code with 32 bit character support. */ #define COMPILE_PCRE32 #include "pcre_xclass.c" /* End of pcre32_xclass.c */ ================================================ FILE: src/pcre/pcre_byte_order.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2014 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains an internal function that tests a compiled pattern to see if it was compiled with the opposite endianness. If so, it uses an auxiliary local function to flip the appropriate bytes. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Swap byte functions * *************************************************/ /* The following functions swap the bytes of a pcre_uint16 and pcre_uint32 value. Arguments: value any number Returns: the byte swapped value */ static pcre_uint32 swap_uint32(pcre_uint32 value) { return ((value & 0x000000ff) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | (value >> 24); } static pcre_uint16 swap_uint16(pcre_uint16 value) { return (value >> 8) | (value << 8); } /************************************************* * Test for a byte-flipped compiled regex * *************************************************/ /* This function swaps the bytes of a compiled pattern usually loaded form the disk. It also sets the tables pointer, which is likely an invalid pointer after reload. Arguments: argument_re points to the compiled expression extra_data points to extra data or is NULL tables points to the character tables or NULL Returns: 0 if the swap is successful, negative on error */ #if defined COMPILE_PCRE8 PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re, pcre_extra *extra_data, const unsigned char *tables) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re, pcre16_extra *extra_data, const unsigned char *tables) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *argument_re, pcre32_extra *extra_data, const unsigned char *tables) #endif { REAL_PCRE *re = (REAL_PCRE *)argument_re; pcre_study_data *study; #ifndef COMPILE_PCRE8 pcre_uchar *ptr; int length; #if defined SUPPORT_UTF && defined COMPILE_PCRE16 BOOL utf; BOOL utf16_char; #endif /* SUPPORT_UTF && COMPILE_PCRE16 */ #endif /* !COMPILE_PCRE8 */ if (re == NULL) return PCRE_ERROR_NULL; if (re->magic_number == MAGIC_NUMBER) { if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; re->tables = tables; return 0; } if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; if ((swap_uint32(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; re->magic_number = MAGIC_NUMBER; re->size = swap_uint32(re->size); re->options = swap_uint32(re->options); re->flags = swap_uint32(re->flags); re->limit_match = swap_uint32(re->limit_match); re->limit_recursion = swap_uint32(re->limit_recursion); #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 re->first_char = swap_uint16(re->first_char); re->req_char = swap_uint16(re->req_char); #elif defined COMPILE_PCRE32 re->first_char = swap_uint32(re->first_char); re->req_char = swap_uint32(re->req_char); #endif re->max_lookbehind = swap_uint16(re->max_lookbehind); re->top_bracket = swap_uint16(re->top_bracket); re->top_backref = swap_uint16(re->top_backref); re->name_table_offset = swap_uint16(re->name_table_offset); re->name_entry_size = swap_uint16(re->name_entry_size); re->name_count = swap_uint16(re->name_count); re->ref_count = swap_uint16(re->ref_count); re->tables = tables; if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) { study = (pcre_study_data *)extra_data->study_data; study->size = swap_uint32(study->size); study->flags = swap_uint32(study->flags); study->minlength = swap_uint32(study->minlength); } #ifndef COMPILE_PCRE8 ptr = (pcre_uchar *)re + re->name_table_offset; length = re->name_count * re->name_entry_size; #if defined SUPPORT_UTF && defined COMPILE_PCRE16 utf = (re->options & PCRE_UTF16) != 0; utf16_char = FALSE; #endif /* SUPPORT_UTF && COMPILE_PCRE16 */ while(TRUE) { /* Swap previous characters. */ while (length-- > 0) { #if defined COMPILE_PCRE16 *ptr = swap_uint16(*ptr); #elif defined COMPILE_PCRE32 *ptr = swap_uint32(*ptr); #endif ptr++; } #if defined SUPPORT_UTF && defined COMPILE_PCRE16 if (utf16_char) { if (HAS_EXTRALEN(ptr[-1])) { /* We know that there is only one extra character in UTF-16. */ *ptr = swap_uint16(*ptr); ptr++; } } utf16_char = FALSE; #endif /* SUPPORT_UTF */ /* Get next opcode. */ length = 0; #if defined COMPILE_PCRE16 *ptr = swap_uint16(*ptr); #elif defined COMPILE_PCRE32 *ptr = swap_uint32(*ptr); #endif switch (*ptr) { case OP_END: return 0; #if defined SUPPORT_UTF && defined COMPILE_PCRE16 case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_UPTO: case OP_MINUPTO: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_UPTOI: case OP_MINUPTOI: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: if (utf) utf16_char = TRUE; #endif /* Fall through. */ default: length = PRIV(OP_lengths)[*ptr] - 1; break; case OP_CLASS: case OP_NCLASS: /* Skip the character bit map. */ ptr += 32/sizeof(pcre_uchar); length = 0; break; case OP_XCLASS: /* Reverse the size of the XCLASS instance. */ ptr++; #if defined COMPILE_PCRE16 *ptr = swap_uint16(*ptr); #elif defined COMPILE_PCRE32 *ptr = swap_uint32(*ptr); #endif #ifndef COMPILE_PCRE32 if (LINK_SIZE > 1) { /* LINK_SIZE can be 1 or 2 in 16 bit mode. */ ptr++; *ptr = swap_uint16(*ptr); } #endif ptr++; length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1); #if defined COMPILE_PCRE16 *ptr = swap_uint16(*ptr); #elif defined COMPILE_PCRE32 *ptr = swap_uint32(*ptr); #endif if ((*ptr & XCL_MAP) != 0) { /* Skip the character bit map. */ ptr += 32/sizeof(pcre_uchar); length -= 32/sizeof(pcre_uchar); } break; } ptr++; } /* Control should never reach here in 16/32 bit mode. */ #else /* In 8-bit mode, the pattern does not need to be processed. */ return 0; #endif /* !COMPILE_PCRE8 */ } /* End of pcre_byte_order.c */ ================================================ FILE: src/pcre/pcre_chartables.c.dist ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* This file contains character tables that are used when no external tables are passed to PCRE by the application that calls it. The tables are used only for characters whose code values are less than 256. This is a default version of the tables that assumes ASCII encoding. A program called dftables (which is distributed with PCRE) can be used to build alternative versions of this file. This is necessary if you are running in an EBCDIC environment, or if you want to default to a different encoding, for example ISO-8859-1. When dftables is run, it creates these tables in the current locale. If PCRE is configured with --enable-rebuild-chartables, this happens automatically. The following #includes are present because without them gcc 4.x may remove the array definition from the final binary if PCRE is built into a static library and dead code stripping is activated. This leads to link errors. Pulling in the header ensures that the array gets flagged as "someone outside this compilation unit might reference this" and so it will always be supplied to the linker. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" const pcre_uint8 PRIV(default_tables)[] = { /* This table is a lower casing table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table is a case flipping table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table contains bit maps for various character classes. Each map is 32 bytes long and the bits run from the least significant end of each byte. The classes that have their own maps are: space, xdigit, digit, upper, lower, word, graph, print, punct, and cntrl. Other classes are built from combinations. */ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* This table identifies various classes of character by individual bits: 0x01 white space character 0x02 letter 0x04 decimal digit 0x08 hexadecimal digit 0x10 alphanumeric or '_' 0x80 regular expression metacharacter or binary zero */ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ /* End of pcre_chartables.c */ ================================================ FILE: src/pcre/pcre_compile.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2018 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_compile(), along with supporting internal functions that are not used by other modules. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define NLBLOCK cd /* Block containing newline information */ #define PSSTART start_pattern /* Field containing pattern start */ #define PSEND end_pattern /* Field containing pattern end */ #include "pcre_internal.h" /* When PCRE_DEBUG is defined, we need the pcre(16|32)_printint() function, which is also used by pcretest. PCRE_DEBUG is not defined when building a production library. We do not need to select pcre16_printint.c specially, because the COMPILE_PCREx macro will already be appropriately set. */ #ifdef PCRE_DEBUG /* pcre_printint.c should not include any headers */ #define PCRE_INCLUDED #include "pcre_printint.c" #undef PCRE_INCLUDED #endif /* Macro for setting individual bits in class bitmaps. */ #define SETBIT(a,b) a[(b)/8] |= (1 << ((b)&7)) /* Maximum length value to check against when making sure that the integer that holds the compiled pattern length does not overflow. We make it a bit less than INT_MAX to allow for adding in group terminating bytes, so that we don't have to check them every time. */ #define OFLOW_MAX (INT_MAX - 20) /* Definitions to allow mutual recursion */ static int add_list_to_class(pcre_uint8 *, pcre_uchar **, int, compile_data *, const pcre_uint32 *, unsigned int); static BOOL compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int, pcre_uint32 *, pcre_int32 *, pcre_uint32 *, pcre_int32 *, branch_chain *, compile_data *, int *); /************************************************* * Code parameters and static tables * *************************************************/ /* This value specifies the size of stack workspace that is used during the first pre-compile phase that determines how much memory is required. The regex is partly compiled into this space, but the compiled parts are discarded as soon as they can be, so that hopefully there will never be an overrun. The code does, however, check for an overrun. The largest amount I've seen used is 218, so this number is very generous. The same workspace is used during the second, actual compile phase for remembering forward references to groups so that they can be filled in at the end. Each entry in this list occupies LINK_SIZE bytes, so even when LINK_SIZE is 4 there is plenty of room for most patterns. However, the memory can get filled up by repetitions of forward references, for example patterns like /(?1){0,1999}(b)/, and one user did hit the limit. The code has been changed so that the workspace is expanded using malloc() in this situation. The value below is therefore a minimum, and we put a maximum on it for safety. The minimum is now also defined in terms of LINK_SIZE so that the use of malloc() kicks in at the same number of forward references in all cases. */ #define COMPILE_WORK_SIZE (2048*LINK_SIZE) #define COMPILE_WORK_SIZE_MAX (100*COMPILE_WORK_SIZE) /* This value determines the size of the initial vector that is used for remembering named groups during the pre-compile. It is allocated on the stack, but if it is too small, it is expanded using malloc(), in a similar way to the workspace. The value is the number of slots in the list. */ #define NAMED_GROUP_LIST_SIZE 20 /* The overrun tests check for a slightly smaller size so that they detect the overrun before it actually does run off the end of the data block. */ #define WORK_SIZE_SAFETY_MARGIN (100) /* Private flags added to firstchar and reqchar. */ #define REQ_CASELESS (1 << 0) /* Indicates caselessness */ #define REQ_VARY (1 << 1) /* Reqchar followed non-literal item */ /* Negative values for the firstchar and reqchar flags */ #define REQ_UNSET (-2) #define REQ_NONE (-1) /* Repeated character flags. */ #define UTF_LENGTH 0x10000000l /* The char contains its length. */ /* Table for handling escaped characters in the range '0'-'z'. Positive returns are simple data values; negative values are for special things like \d and so on. Zero means further processing is needed (for things like \x), or the escape is invalid. */ #ifndef EBCDIC /* This is the "normal" table for ASCII systems or for EBCDIC systems running in UTF-8 mode. */ static const short int escapes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CHAR_COLON, CHAR_SEMICOLON, CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK, CHAR_COMMERCIAL_AT, -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G, -ESC_H, 0, 0, -ESC_K, 0, 0, -ESC_N, 0, -ESC_P, -ESC_Q, -ESC_R, -ESC_S, 0, 0, -ESC_V, -ESC_W, -ESC_X, 0, -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, CHAR_GRAVE_ACCENT, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, -ESC_h, 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p, 0, ESC_r, -ESC_s, ESC_tee, 0, -ESC_v, -ESC_w, 0, 0, -ESC_z }; #else /* This is the "abnormal" table for EBCDIC systems without UTF-8 support. */ static const short int escapes[] = { /* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', /* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, /* 58 */ 0, 0, '!', '$', '*', ')', ';', '~', /* 60 */ '-', '/', 0, 0, 0, 0, 0, 0, /* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', /* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, /* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p, /* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, /* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0, /* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, /* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* B8 */ 0, 0, 0, 0, 0, ']', '=', '-', /* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G, /* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0, /* D0 */ '}', 0, -ESC_K, 0, 0,-ESC_N, 0, -ESC_P, /* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0, /* E0 */ '\\', 0, -ESC_S, 0, 0,-ESC_V, -ESC_W, -ESC_X, /* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0, /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 }; /* We also need a table of characters that may follow \c in an EBCDIC environment for characters 0-31. */ static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; #endif /* Table of special "verbs" like (*PRUNE). This is a short table, so it is searched linearly. Put all the names into a single string, in order to reduce the number of relocations when a shared library is dynamically linked. The string is built from string macros so that it works in UTF-8 mode on EBCDIC platforms. */ typedef struct verbitem { int len; /* Length of verb name */ int op; /* Op when no arg, or -1 if arg mandatory */ int op_arg; /* Op when arg present, or -1 if not allowed */ } verbitem; static const char verbnames[] = "\0" /* Empty name is a shorthand for MARK */ STRING_MARK0 STRING_ACCEPT0 STRING_COMMIT0 STRING_F0 STRING_FAIL0 STRING_PRUNE0 STRING_SKIP0 STRING_THEN; static const verbitem verbs[] = { { 0, -1, OP_MARK }, { 4, -1, OP_MARK }, { 6, OP_ACCEPT, -1 }, { 6, OP_COMMIT, -1 }, { 1, OP_FAIL, -1 }, { 4, OP_FAIL, -1 }, { 5, OP_PRUNE, OP_PRUNE_ARG }, { 4, OP_SKIP, OP_SKIP_ARG }, { 4, OP_THEN, OP_THEN_ARG } }; static const int verbcount = sizeof(verbs)/sizeof(verbitem); /* Substitutes for [[:<:]] and [[:>:]], which mean start and end of word in another regex library. */ static const pcre_uchar sub_start_of_word[] = { CHAR_BACKSLASH, CHAR_b, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_EQUALS_SIGN, CHAR_BACKSLASH, CHAR_w, CHAR_RIGHT_PARENTHESIS, '\0' }; static const pcre_uchar sub_end_of_word[] = { CHAR_BACKSLASH, CHAR_b, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK, CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, CHAR_BACKSLASH, CHAR_w, CHAR_RIGHT_PARENTHESIS, '\0' }; /* Tables of names of POSIX character classes and their lengths. The names are now all in a single string, to reduce the number of relocations when a shared library is dynamically loaded. The list of lengths is terminated by a zero length entry. The first three must be alpha, lower, upper, as this is assumed for handling case independence. The indices for graph, print, and punct are needed, so identify them. */ static const char posix_names[] = STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0 STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0 STRING_graph0 STRING_print0 STRING_punct0 STRING_space0 STRING_word0 STRING_xdigit; static const pcre_uint8 posix_name_lengths[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; #define PC_GRAPH 8 #define PC_PRINT 9 #define PC_PUNCT 10 /* Table of class bit maps for each POSIX class. Each class is formed from a base map, with an optional addition or removal of another map. Then, for some classes, there is some additional tweaking: for [:blank:] the vertical space characters are removed, and for [:alpha:] and [:alnum:] the underscore character is removed. The triples in the table consist of the base map offset, second map offset or -1 if no second map, and a non-negative value for map addition or a negative value for map subtraction (if there are two maps). The absolute value of the third field has these meanings: 0 => no tweaking, 1 => remove vertical space characters, 2 => remove underscore. */ static const int posix_class_maps[] = { cbit_word, cbit_digit, -2, /* alpha */ cbit_lower, -1, 0, /* lower */ cbit_upper, -1, 0, /* upper */ cbit_word, -1, 2, /* alnum - word without underscore */ cbit_print, cbit_cntrl, 0, /* ascii */ cbit_space, -1, 1, /* blank - a GNU extension */ cbit_cntrl, -1, 0, /* cntrl */ cbit_digit, -1, 0, /* digit */ cbit_graph, -1, 0, /* graph */ cbit_print, -1, 0, /* print */ cbit_punct, -1, 0, /* punct */ cbit_space, -1, 0, /* space */ cbit_word, -1, 0, /* word - a Perl extension */ cbit_xdigit,-1, 0 /* xdigit */ }; /* Table of substitutes for \d etc when PCRE_UCP is set. They are replaced by Unicode property escapes. */ #ifdef SUPPORT_UCP static const pcre_uchar string_PNd[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_pNd[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_PXsp[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_pXsp[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_PXwd[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_pXwd[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar *substitutes[] = { string_PNd, /* \D */ string_pNd, /* \d */ string_PXsp, /* \S */ /* Xsp is Perl space, but from 8.34, Perl */ string_pXsp, /* \s */ /* space and POSIX space are the same. */ string_PXwd, /* \W */ string_pXwd /* \w */ }; /* The POSIX class substitutes must be in the order of the POSIX class names, defined above, and there are both positive and negative cases. NULL means no general substitute of a Unicode property escape (\p or \P). However, for some POSIX classes (e.g. graph, print, punct) a special property code is compiled directly. */ static const pcre_uchar string_pL[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_pLl[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_pLu[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_pXan[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_h[] = { CHAR_BACKSLASH, CHAR_h, '\0' }; static const pcre_uchar string_pXps[] = { CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_PL[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_PLl[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_PLu[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_PXan[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar string_H[] = { CHAR_BACKSLASH, CHAR_H, '\0' }; static const pcre_uchar string_PXps[] = { CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' }; static const pcre_uchar *posix_substitutes[] = { string_pL, /* alpha */ string_pLl, /* lower */ string_pLu, /* upper */ string_pXan, /* alnum */ NULL, /* ascii */ string_h, /* blank */ NULL, /* cntrl */ string_pNd, /* digit */ NULL, /* graph */ NULL, /* print */ NULL, /* punct */ string_pXps, /* space */ /* Xps is POSIX space, but from 8.34 */ string_pXwd, /* word */ /* Perl and POSIX space are the same */ NULL, /* xdigit */ /* Negated cases */ string_PL, /* ^alpha */ string_PLl, /* ^lower */ string_PLu, /* ^upper */ string_PXan, /* ^alnum */ NULL, /* ^ascii */ string_H, /* ^blank */ NULL, /* ^cntrl */ string_PNd, /* ^digit */ NULL, /* ^graph */ NULL, /* ^print */ NULL, /* ^punct */ string_PXps, /* ^space */ /* Xps is POSIX space, but from 8.34 */ string_PXwd, /* ^word */ /* Perl and POSIX space are the same */ NULL /* ^xdigit */ }; #define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(pcre_uchar *)) #endif #define STRING(a) # a #define XSTRING(s) STRING(s) /* The texts of compile-time error messages. These are "char *" because they are passed to the outside world. Do not ever re-use any error number, because they are documented. Always add a new error instead. Messages marked DEAD below are no longer used. This used to be a table of strings, but in order to reduce the number of relocations needed when a shared library is loaded dynamically, it is now one long string. We cannot use a table of offsets, because the lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we simply count through to the one we want - this isn't a performance issue because these strings are used only when there is a compilation error. Each substring ends with \0 to insert a null character. This includes the final substring, so that the whole string ends with \0\0, which can be detected when counting through. */ static const char error_texts[] = "no error\0" "\\ at end of pattern\0" "\\c at end of pattern\0" "unrecognized character follows \\\0" "numbers out of order in {} quantifier\0" /* 5 */ "number too big in {} quantifier\0" "missing terminating ] for character class\0" "invalid escape sequence in character class\0" "range out of order in character class\0" "nothing to repeat\0" /* 10 */ "internal error: invalid forward reference offset\0" "internal error: unexpected repeat\0" "unrecognized character after (? or (?-\0" "POSIX named classes are supported only within a class\0" "missing )\0" /* 15 */ "reference to non-existent subpattern\0" "erroffset passed as NULL\0" "unknown option bit(s) set\0" "missing ) after comment\0" "parentheses nested too deeply\0" /** DEAD **/ /* 20 */ "regular expression is too large\0" "failed to get memory\0" "unmatched parentheses\0" "internal error: code overflow\0" "unrecognized character after (?<\0" /* 25 */ "lookbehind assertion is not fixed length\0" "malformed number or name after (?(\0" "conditional group contains more than two branches\0" "assertion expected after (?( or (?(?C)\0" "(?R or (?[+-]digits must be followed by )\0" /* 30 */ "unknown POSIX class name\0" "POSIX collating elements are not supported\0" "this version of PCRE is compiled without UTF support\0" "spare error\0" /** DEAD **/ "character value in \\x{} or \\o{} is too large\0" /* 35 */ "invalid condition (?(0)\0" "\\C not allowed in lookbehind assertion\0" "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0" "number after (?C is > 255\0" "closing ) for (?C expected\0" /* 40 */ "recursive call could loop indefinitely\0" "unrecognized character after (?P\0" "syntax error in subpattern name (missing terminator)\0" "two named subpatterns have the same name\0" "invalid UTF-8 string\0" /* 45 */ "support for \\P, \\p, and \\X has not been compiled\0" "malformed \\P or \\p sequence\0" "unknown property name after \\P or \\p\0" "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0" "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0" /* 50 */ "repeated subpattern is too long\0" /** DEAD **/ "octal value is greater than \\377 in 8-bit non-UTF-8 mode\0" "internal error: overran compiling workspace\0" "internal error: previously-checked referenced subpattern not found\0" "DEFINE group contains more than one branch\0" /* 55 */ "repeating a DEFINE group is not allowed\0" /** DEAD **/ "inconsistent NEWLINE options\0" "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0" "a numbered reference must not be zero\0" "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0" /* 60 */ "(*VERB) not recognized or malformed\0" "number is too big\0" "subpattern name expected\0" "digit expected after (?+\0" "] is an invalid data character in JavaScript compatibility mode\0" /* 65 */ "different names for subpatterns of the same number are not allowed\0" "(*MARK) must have an argument\0" "this version of PCRE is not compiled with Unicode property support\0" #ifndef EBCDIC "\\c must be followed by an ASCII character\0" #else "\\c must be followed by a letter or one of [\\]^_?\0" #endif "\\k is not followed by a braced, angle-bracketed, or quoted name\0" /* 70 */ "internal error: unknown opcode in find_fixedlength()\0" "\\N is not supported in a class\0" "too many forward references\0" "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0" "invalid UTF-16 string\0" /* 75 */ "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0" "character value in \\u.... sequence is too large\0" "invalid UTF-32 string\0" "setting UTF is disabled by the application\0" "non-hex character in \\x{} (closing brace missing?)\0" /* 80 */ "non-octal character in \\o{} (closing brace missing?)\0" "missing opening brace after \\o\0" "parentheses are too deeply nested\0" "invalid range in character class\0" "group name must start with a non-digit\0" /* 85 */ "parentheses are too deeply nested (stack check)\0" "digits missing in \\x{} or \\o{}\0" "regular expression is too complicated\0" ; /* Table to identify digits and hex digits. This is used when compiling patterns. Note that the tables in chartables are dependent on the locale, and may mark arbitrary characters as digits - but the PCRE compiling code expects to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have a private table here. It costs 256 bytes, but it is a lot faster than doing character value tests (at least in some simple cases I timed), and in some applications one wants PCRE to compile efficiently as well as match efficiently. For convenience, we use the same bit definitions as in chartables: 0x04 decimal digit 0x08 hexadecimal digit Then we can use ctype_digit and ctype_xdigit in the code. */ /* Using a simple comparison for decimal numbers rather than a memory read is much faster, and the resulting code is simpler (the compiler turns it into a subtraction and unsigned comparison). */ #define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9) #ifndef EBCDIC /* This is the "normal" case, for ASCII systems, and EBCDIC systems running in UTF-8 mode. */ static const pcre_uint8 digitab[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ #else /* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */ static const pcre_uint8 digitab[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- 95 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */ 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ static const pcre_uint8 ebcdic_chartab[] = { /* chartable partial dup */ 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */ 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */ 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */ 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- 95 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */ 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */ 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ #endif /* This table is used to check whether auto-possessification is possible between adjacent character-type opcodes. The left-hand (repeated) opcode is used to select the row, and the right-hand opcode is use to select the column. A value of 1 means that auto-possessification is OK. For example, the second value in the first row means that \D+\d can be turned into \D++\d. The Unicode property types (\P and \p) have to be present to fill out the table because of what their opcode values are, but the table values should always be zero because property types are handled separately in the code. The last four columns apply to items that cannot be repeated, so there is no need to have rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */ #define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1) #define APTCOLS (LAST_AUTOTAB_RIGHT_OP - FIRST_AUTOTAB_OP + 1) static const pcre_uint8 autoposstab[APTROWS][APTCOLS] = { /* \D \d \S \s \W \w . .+ \C \P \p \R \H \h \V \v \X \Z \z $ $M */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \D */ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \d */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \S */ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \s */ { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \W */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \w */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* . */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* .+ */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \C */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \P */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \p */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \R */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \H */ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \h */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \V */ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* \v */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } /* \X */ }; /* This table is used to check whether auto-possessification is possible between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP). The left-hand (repeated) opcode is used to select the row, and the right-hand opcode is used to select the column. The values are as follows: 0 Always return FALSE (never auto-possessify) 1 Character groups are distinct (possessify if both are OP_PROP) 2 Check character categories in the same group (general or particular) 3 TRUE if the two opcodes are not the same (PROP vs NOTPROP) 4 Check left general category vs right particular category 5 Check right general category vs left particular category 6 Left alphanum vs right general category 7 Left space vs right general category 8 Left word vs right general category 9 Right alphanum vs left general category 10 Right space vs left general category 11 Right word vs left general category 12 Left alphanum vs right particular category 13 Left space vs right particular category 14 Left word vs right particular category 15 Right alphanum vs left particular category 16 Right space vs left particular category 17 Right word vs left particular category */ static const pcre_uint8 propposstab[PT_TABSIZE][PT_TABSIZE] = { /* ANY LAMP GC PC SC ALNUM SPACE PXSPACE WORD CLIST UCNC */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */ { 0, 3, 0, 0, 0, 3, 1, 1, 0, 0, 0 }, /* PT_LAMP */ { 0, 0, 2, 4, 0, 9, 10, 10, 11, 0, 0 }, /* PT_GC */ { 0, 0, 5, 2, 0, 15, 16, 16, 17, 0, 0 }, /* PT_PC */ { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, /* PT_SC */ { 0, 3, 6, 12, 0, 3, 1, 1, 0, 0, 0 }, /* PT_ALNUM */ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_SPACE */ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_PXSPACE */ { 0, 0, 8, 14, 0, 0, 1, 1, 3, 0, 0 }, /* PT_WORD */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 } /* PT_UCNC */ }; /* This table is used to check whether auto-possessification is possible between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP) when one specifies a general category and the other specifies a particular category. The row is selected by the general category and the column by the particular category. The value is 1 if the particular category is not part of the general category. */ static const pcre_uint8 catposstab[7][30] = { /* Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs */ { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* C */ { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* L */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* M */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* N */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, /* P */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, /* S */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 } /* Z */ }; /* This table is used when checking ALNUM, (PX)SPACE, SPACE, and WORD against a general or particular category. The properties in each row are those that apply to the character set in question. Duplication means that a little unnecessary work is done when checking, but this keeps things much simpler because they can all use the same code. For more details see the comment where this table is used. Note: SPACE and PXSPACE used to be different because Perl excluded VT from "space", but from Perl 5.18 it's included, so both categories are treated the same here. */ static const pcre_uint8 posspropstab[3][4] = { { ucp_L, ucp_N, ucp_N, ucp_Nl }, /* ALNUM, 3rd and 4th values redundant */ { ucp_Z, ucp_Z, ucp_C, ucp_Cc }, /* SPACE and PXSPACE, 2nd value redundant */ { ucp_L, ucp_N, ucp_P, ucp_Po } /* WORD */ }; /* This table is used when converting repeating opcodes into possessified versions as a result of an explicit possessive quantifier such as ++. A zero value means there is no possessified version - in those cases the item in question must be wrapped in ONCE brackets. The table is truncated at OP_CALLOUT because all relevant opcodes are less than that. */ static const pcre_uint8 opcode_possessify[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */ 0, /* NOTI */ OP_POSSTAR, 0, /* STAR, MINSTAR */ OP_POSPLUS, 0, /* PLUS, MINPLUS */ OP_POSQUERY, 0, /* QUERY, MINQUERY */ OP_POSUPTO, 0, /* UPTO, MINUPTO */ 0, /* EXACT */ 0, 0, 0, 0, /* POS{STAR,PLUS,QUERY,UPTO} */ OP_POSSTARI, 0, /* STARI, MINSTARI */ OP_POSPLUSI, 0, /* PLUSI, MINPLUSI */ OP_POSQUERYI, 0, /* QUERYI, MINQUERYI */ OP_POSUPTOI, 0, /* UPTOI, MINUPTOI */ 0, /* EXACTI */ 0, 0, 0, 0, /* POS{STARI,PLUSI,QUERYI,UPTOI} */ OP_NOTPOSSTAR, 0, /* NOTSTAR, NOTMINSTAR */ OP_NOTPOSPLUS, 0, /* NOTPLUS, NOTMINPLUS */ OP_NOTPOSQUERY, 0, /* NOTQUERY, NOTMINQUERY */ OP_NOTPOSUPTO, 0, /* NOTUPTO, NOTMINUPTO */ 0, /* NOTEXACT */ 0, 0, 0, 0, /* NOTPOS{STAR,PLUS,QUERY,UPTO} */ OP_NOTPOSSTARI, 0, /* NOTSTARI, NOTMINSTARI */ OP_NOTPOSPLUSI, 0, /* NOTPLUSI, NOTMINPLUSI */ OP_NOTPOSQUERYI, 0, /* NOTQUERYI, NOTMINQUERYI */ OP_NOTPOSUPTOI, 0, /* NOTUPTOI, NOTMINUPTOI */ 0, /* NOTEXACTI */ 0, 0, 0, 0, /* NOTPOS{STARI,PLUSI,QUERYI,UPTOI} */ OP_TYPEPOSSTAR, 0, /* TYPESTAR, TYPEMINSTAR */ OP_TYPEPOSPLUS, 0, /* TYPEPLUS, TYPEMINPLUS */ OP_TYPEPOSQUERY, 0, /* TYPEQUERY, TYPEMINQUERY */ OP_TYPEPOSUPTO, 0, /* TYPEUPTO, TYPEMINUPTO */ 0, /* TYPEEXACT */ 0, 0, 0, 0, /* TYPEPOS{STAR,PLUS,QUERY,UPTO} */ OP_CRPOSSTAR, 0, /* CRSTAR, CRMINSTAR */ OP_CRPOSPLUS, 0, /* CRPLUS, CRMINPLUS */ OP_CRPOSQUERY, 0, /* CRQUERY, CRMINQUERY */ OP_CRPOSRANGE, 0, /* CRRANGE, CRMINRANGE */ 0, 0, 0, 0, /* CRPOS{STAR,PLUS,QUERY,RANGE} */ 0, 0, 0, /* CLASS, NCLASS, XCLASS */ 0, 0, /* REF, REFI */ 0, 0, /* DNREF, DNREFI */ 0, 0 /* RECURSE, CALLOUT */ }; /************************************************* * Find an error text * *************************************************/ /* The error texts are now all in one long string, to save on relocations. As some of the text is of unknown length, we can't use a table of offsets. Instead, just count through the strings. This is not a performance issue because it happens only when there has been a compilation error. Argument: the error number Returns: pointer to the error string */ static const char * find_error_text(int n) { const char *s = error_texts; for (; n > 0; n--) { while (*s++ != CHAR_NULL) {}; if (*s == CHAR_NULL) return "Error text not found (please report)"; } return s; } /************************************************* * Expand the workspace * *************************************************/ /* This function is called during the second compiling phase, if the number of forward references fills the existing workspace, which is originally a block on the stack. A larger block is obtained from malloc() unless the ultimate limit has been reached or the increase will be rather small. Argument: pointer to the compile data block Returns: 0 if all went well, else an error number */ static int expand_workspace(compile_data *cd) { pcre_uchar *newspace; int newsize = cd->workspace_size * 2; if (newsize > COMPILE_WORK_SIZE_MAX) newsize = COMPILE_WORK_SIZE_MAX; if (cd->workspace_size >= COMPILE_WORK_SIZE_MAX || newsize - cd->workspace_size < WORK_SIZE_SAFETY_MARGIN) return ERR72; newspace = (PUBL(malloc))(IN_UCHARS(newsize)); if (newspace == NULL) return ERR21; memcpy(newspace, cd->start_workspace, cd->workspace_size * sizeof(pcre_uchar)); cd->hwm = (pcre_uchar *)newspace + (cd->hwm - cd->start_workspace); if (cd->workspace_size > COMPILE_WORK_SIZE) (PUBL(free))((void *)cd->start_workspace); cd->start_workspace = newspace; cd->workspace_size = newsize; return 0; } /************************************************* * Check for counted repeat * *************************************************/ /* This function is called when a '{' is encountered in a place where it might start a quantifier. It looks ahead to see if it really is a quantifier or not. It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} where the ddds are digits. Arguments: p pointer to the first char after '{' Returns: TRUE or FALSE */ static BOOL is_counted_repeat(const pcre_uchar *p) { if (!IS_DIGIT(*p)) return FALSE; p++; while (IS_DIGIT(*p)) p++; if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; if (*p++ != CHAR_COMMA) return FALSE; if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; if (!IS_DIGIT(*p)) return FALSE; p++; while (IS_DIGIT(*p)) p++; return (*p == CHAR_RIGHT_CURLY_BRACKET); } /************************************************* * Handle escapes * *************************************************/ /* This function is called when a \ has been encountered. It either returns a positive value for a simple escape such as \n, or 0 for a data character which will be placed in chptr. A backreference to group n is returned as negative n. When UTF-8 is enabled, a positive value greater than 255 may be returned in chptr. On entry, ptr is pointing at the \. On exit, it is on the final character of the escape sequence. Arguments: ptrptr points to the pattern position pointer chptr points to a returned data character errorcodeptr points to the errorcode variable bracount number of previous extracting brackets options the options bits isclass TRUE if inside a character class Returns: zero => a data character positive => a special escape sequence negative => a back reference on error, errorcodeptr is set */ static int check_escape(const pcre_uchar **ptrptr, pcre_uint32 *chptr, int *errorcodeptr, int bracount, int options, BOOL isclass) { /* PCRE_UTF16 has the same value as PCRE_UTF8. */ BOOL utf = (options & PCRE_UTF8) != 0; const pcre_uchar *ptr = *ptrptr + 1; pcre_uint32 c; int escape = 0; int i; GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */ ptr--; /* Set pointer back to the last byte */ /* If backslash is at the end of the pattern, it's an error. */ if (c == CHAR_NULL) *errorcodeptr = ERR1; /* Non-alphanumerics are literals. For digits or letters, do an initial lookup in a table. A non-zero result is something that can be returned immediately. Otherwise further processing may be required. */ #ifndef EBCDIC /* ASCII/UTF-8 coding */ /* Not alphanumeric */ else if (c < CHAR_0 || c > CHAR_z) {} else if ((i = escapes[c - CHAR_0]) != 0) { if (i > 0) c = (pcre_uint32)i; else escape = -i; } #else /* EBCDIC coding */ /* Not alphanumeric */ else if (c < CHAR_a || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {} else if ((i = escapes[c - 0x48]) != 0) { if (i > 0) c = (pcre_uint32)i; else escape = -i; } #endif /* Escapes that need further processing, or are illegal. */ else { const pcre_uchar *oldptr; BOOL braced, negated, overflow; int s; switch (c) { /* A number of Perl escapes are not handled by PCRE. We give an explicit error. */ case CHAR_l: case CHAR_L: *errorcodeptr = ERR37; break; case CHAR_u: if ((options & PCRE_JAVASCRIPT_COMPAT) != 0) { /* In JavaScript, \u must be followed by four hexadecimal numbers. Otherwise it is a lowercase u letter. */ if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0 && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0 && MAX_255(ptr[3]) && (digitab[ptr[3]] & ctype_xdigit) != 0 && MAX_255(ptr[4]) && (digitab[ptr[4]] & ctype_xdigit) != 0) { c = 0; for (i = 0; i < 4; ++i) { register pcre_uint32 cc = *(++ptr); #ifndef EBCDIC /* ASCII/UTF-8 coding */ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); #else /* EBCDIC coding */ if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); #endif } #if defined COMPILE_PCRE8 if (c > (utf ? 0x10ffffU : 0xffU)) #elif defined COMPILE_PCRE16 if (c > (utf ? 0x10ffffU : 0xffffU)) #elif defined COMPILE_PCRE32 if (utf && c > 0x10ffffU) #endif { *errorcodeptr = ERR76; } else if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; } } else *errorcodeptr = ERR37; break; case CHAR_U: /* In JavaScript, \U is an uppercase U letter. */ if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) *errorcodeptr = ERR37; break; /* In a character class, \g is just a literal "g". Outside a character class, \g must be followed by one of a number of specific things: (1) A number, either plain or braced. If positive, it is an absolute backreference. If negative, it is a relative backreference. This is a Perl 5.10 feature. (2) Perl 5.10 also supports \g{name} as a reference to a named group. This is part of Perl's movement towards a unified syntax for back references. As this is synonymous with \k{name}, we fudge it up by pretending it really was \k. (3) For Oniguruma compatibility we also support \g followed by a name or a number either in angle brackets or in single quotes. However, these are (possibly recursive) subroutine calls, _not_ backreferences. Just return the ESC_g code (cf \k). */ case CHAR_g: if (isclass) break; if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE) { escape = ESC_g; break; } /* Handle the Perl-compatible cases */ if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) { const pcre_uchar *p; for (p = ptr+2; *p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET; p++) if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break; if (*p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET) { escape = ESC_k; break; } braced = TRUE; ptr++; } else braced = FALSE; if (ptr[1] == CHAR_MINUS) { negated = TRUE; ptr++; } else negated = FALSE; /* The integer range is limited by the machine's int representation. */ s = 0; overflow = FALSE; while (IS_DIGIT(ptr[1])) { if (s > INT_MAX / 10 - 1) /* Integer overflow */ { overflow = TRUE; break; } s = s * 10 + (int)(*(++ptr) - CHAR_0); } if (overflow) /* Integer overflow */ { while (IS_DIGIT(ptr[1])) ptr++; *errorcodeptr = ERR61; break; } if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET) { *errorcodeptr = ERR57; break; } if (s == 0) { *errorcodeptr = ERR58; break; } if (negated) { if (s > bracount) { *errorcodeptr = ERR15; break; } s = bracount - (s - 1); } escape = -s; break; /* The handling of escape sequences consisting of a string of digits starting with one that is not zero is not straightforward. Perl has changed over the years. Nowadays \g{} for backreferences and \o{} for octal are recommended to avoid the ambiguities in the old syntax. Outside a character class, the digits are read as a decimal number. If the number is less than 8 (used to be 10), or if there are that many previous extracting left brackets, then it is a back reference. Otherwise, up to three octal digits are read to form an escaped byte. Thus \123 is likely to be octal 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal value is greater than 377, the least significant 8 bits are taken. \8 and \9 are treated as the literal characters 8 and 9. Inside a character class, \ followed by a digit is always either a literal 8 or 9 or an octal number. */ case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: if (!isclass) { oldptr = ptr; /* The integer range is limited by the machine's int representation. */ s = (int)(c -CHAR_0); overflow = FALSE; while (IS_DIGIT(ptr[1])) { if (s > INT_MAX / 10 - 1) /* Integer overflow */ { overflow = TRUE; break; } s = s * 10 + (int)(*(++ptr) - CHAR_0); } if (overflow) /* Integer overflow */ { while (IS_DIGIT(ptr[1])) ptr++; *errorcodeptr = ERR61; break; } if (s < 8 || s <= bracount) /* Check for back reference */ { escape = -s; break; } ptr = oldptr; /* Put the pointer back and fall through */ } /* Handle a digit following \ when the number is not a back reference. If the first digit is 8 or 9, Perl used to generate a binary zero byte and then treat the digit as a following literal. At least by Perl 5.18 this changed so as not to insert the binary zero. */ if ((c = *ptr) >= CHAR_8) break; /* Fall through with a digit less than 8 */ /* \0 always starts an octal number, but we may drop through to here with a larger first octal digit. The original code used just to take the least significant 8 bits of octal numbers (I think this is what early Perls used to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode, but no more than 3 octal digits. */ case CHAR_0: c -= CHAR_0; while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7) c = c * 8 + *(++ptr) - CHAR_0; #ifdef COMPILE_PCRE8 if (!utf && c > 0xff) *errorcodeptr = ERR51; #endif break; /* \o is a relatively new Perl feature, supporting a more general way of specifying character codes in octal. The only supported form is \o{ddd}. */ case CHAR_o: if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR81; else if (ptr[2] == CHAR_RIGHT_CURLY_BRACKET) *errorcodeptr = ERR86; else { ptr += 2; c = 0; overflow = FALSE; while (*ptr >= CHAR_0 && *ptr <= CHAR_7) { register pcre_uint32 cc = *ptr++; if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ #ifdef COMPILE_PCRE32 if (c >= 0x20000000l) { overflow = TRUE; break; } #endif c = (c << 3) + cc - CHAR_0 ; #if defined COMPILE_PCRE8 if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; } #elif defined COMPILE_PCRE16 if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; } #elif defined COMPILE_PCRE32 if (utf && c > 0x10ffffU) { overflow = TRUE; break; } #endif } if (overflow) { while (*ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++; *errorcodeptr = ERR34; } else if (*ptr == CHAR_RIGHT_CURLY_BRACKET) { if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; } else *errorcodeptr = ERR80; } break; /* \x is complicated. In JavaScript, \x must be followed by two hexadecimal numbers. Otherwise it is a lowercase x letter. */ case CHAR_x: if ((options & PCRE_JAVASCRIPT_COMPAT) != 0) { if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0 && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0) { c = 0; for (i = 0; i < 2; ++i) { register pcre_uint32 cc = *(++ptr); #ifndef EBCDIC /* ASCII/UTF-8 coding */ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); #else /* EBCDIC coding */ if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); #endif } } } /* End JavaScript handling */ /* Handle \x in Perl's style. \x{ddd} is a character number which can be greater than 0xff in utf or non-8bit mode, but only if the ddd are hex digits. If not, { used to be treated as a data character. However, Perl seems to read hex digits up to the first non-such, and ignore the rest, so that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE now gives an error. */ else { if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) { ptr += 2; if (*ptr == CHAR_RIGHT_CURLY_BRACKET) { *errorcodeptr = ERR86; break; } c = 0; overflow = FALSE; while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0) { register pcre_uint32 cc = *ptr++; if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ #ifdef COMPILE_PCRE32 if (c >= 0x10000000l) { overflow = TRUE; break; } #endif #ifndef EBCDIC /* ASCII/UTF-8 coding */ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); #else /* EBCDIC coding */ if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); #endif #if defined COMPILE_PCRE8 if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; } #elif defined COMPILE_PCRE16 if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; } #elif defined COMPILE_PCRE32 if (utf && c > 0x10ffffU) { overflow = TRUE; break; } #endif } if (overflow) { while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0) ptr++; *errorcodeptr = ERR34; } else if (*ptr == CHAR_RIGHT_CURLY_BRACKET) { if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; } /* If the sequence of hex digits does not end with '}', give an error. We used just to recognize this construct and fall through to the normal \x handling, but nowadays Perl gives an error, which seems much more sensible, so we do too. */ else *errorcodeptr = ERR79; } /* End of \x{} processing */ /* Read a single-byte hex-defined char (up to two hex digits after \x) */ else { c = 0; while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0) { pcre_uint32 cc; /* Some compilers don't like */ cc = *(++ptr); /* ++ in initializers */ #ifndef EBCDIC /* ASCII/UTF-8 coding */ if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ c = c * 16 + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); #else /* EBCDIC coding */ if (cc <= CHAR_z) cc += 64; /* Convert to upper case */ c = c * 16 + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); #endif } } /* End of \xdd handling */ } /* End of Perl-style \x handling */ break; /* For \c, a following letter is upper-cased; then the 0x40 bit is flipped. An error is given if the byte following \c is not an ASCII character. This coding is ASCII-specific, but then the whole concept of \cx is ASCII-specific. (However, an EBCDIC equivalent has now been added.) */ case CHAR_c: c = *(++ptr); if (c == CHAR_NULL) { *errorcodeptr = ERR2; break; } #ifndef EBCDIC /* ASCII/UTF-8 coding */ if (c > 127) /* Excludes all non-ASCII in either mode */ { *errorcodeptr = ERR68; break; } if (c >= CHAR_a && c <= CHAR_z) c -= 32; c ^= 0x40; #else /* EBCDIC coding */ if (c >= CHAR_a && c <= CHAR_z) c += 64; if (c == CHAR_QUESTION_MARK) c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff; else { for (i = 0; i < 32; i++) { if (c == ebcdic_escape_c[i]) break; } if (i < 32) c = i; else *errorcodeptr = ERR68; } #endif break; /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any other alphanumeric following \ is an error if PCRE_EXTRA was set; otherwise, for Perl compatibility, it is a literal. This code looks a bit odd, but there used to be some cases other than the default, and there may be again in future, so I haven't "optimized" it. */ default: if ((options & PCRE_EXTRA) != 0) switch(c) { default: *errorcodeptr = ERR3; break; } break; } } /* Perl supports \N{name} for character names, as well as plain \N for "not newline". PCRE does not support \N{name}. However, it does support quantification such as \N{2,3}. */ if (escape == ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET && !is_counted_repeat(ptr+2)) *errorcodeptr = ERR37; /* If PCRE_UCP is set, we change the values for \d etc. */ if ((options & PCRE_UCP) != 0 && escape >= ESC_D && escape <= ESC_w) escape += (ESC_DU - ESC_D); /* Set the pointer to the final character before returning. */ *ptrptr = ptr; *chptr = c; return escape; } #ifdef SUPPORT_UCP /************************************************* * Handle \P and \p * *************************************************/ /* This function is called after \P or \p has been encountered, provided that PCRE is compiled with support for Unicode properties. On entry, ptrptr is pointing at the P or p. On exit, it is pointing at the final character of the escape sequence. Argument: ptrptr points to the pattern position pointer negptr points to a boolean that is set TRUE for negation else FALSE ptypeptr points to an unsigned int that is set to the type value pdataptr points to an unsigned int that is set to the detailed property value errorcodeptr points to the error code variable Returns: TRUE if the type value was found, or FALSE for an invalid type */ static BOOL get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, unsigned int *ptypeptr, unsigned int *pdataptr, int *errorcodeptr) { pcre_uchar c; int i, bot, top; const pcre_uchar *ptr = *ptrptr; pcre_uchar name[32]; c = *(++ptr); if (c == CHAR_NULL) goto ERROR_RETURN; *negptr = FALSE; /* \P or \p can be followed by a name in {}, optionally preceded by ^ for negation. */ if (c == CHAR_LEFT_CURLY_BRACKET) { if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT) { *negptr = TRUE; ptr++; } for (i = 0; i < (int)(sizeof(name) / sizeof(pcre_uchar)) - 1; i++) { c = *(++ptr); if (c == CHAR_NULL) goto ERROR_RETURN; if (c == CHAR_RIGHT_CURLY_BRACKET) break; name[i] = c; } if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN; name[i] = 0; } /* Otherwise there is just one following character */ else { name[0] = c; name[1] = 0; } *ptrptr = ptr; /* Search for a recognized property name using binary chop */ bot = 0; top = PRIV(utt_size); while (bot < top) { int r; i = (bot + top) >> 1; r = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset); if (r == 0) { *ptypeptr = PRIV(utt)[i].type; *pdataptr = PRIV(utt)[i].value; return TRUE; } if (r > 0) bot = i + 1; else top = i; } *errorcodeptr = ERR47; *ptrptr = ptr; return FALSE; ERROR_RETURN: *errorcodeptr = ERR46; *ptrptr = ptr; return FALSE; } #endif /************************************************* * Read repeat counts * *************************************************/ /* Read an item of the form {n,m} and return the values. This is called only after is_counted_repeat() has confirmed that a repeat-count quantifier exists, so the syntax is guaranteed to be correct, but we need to check the values. Arguments: p pointer to first char after '{' minp pointer to int for min maxp pointer to int for max returned as -1 if no max errorcodeptr points to error code variable Returns: pointer to '}' on success; current ptr on error, with errorcodeptr set non-zero */ static const pcre_uchar * read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr) { int min = 0; int max = -1; while (IS_DIGIT(*p)) { min = min * 10 + (int)(*p++ - CHAR_0); if (min > 65535) { *errorcodeptr = ERR5; return p; } } if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else { if (*(++p) != CHAR_RIGHT_CURLY_BRACKET) { max = 0; while(IS_DIGIT(*p)) { max = max * 10 + (int)(*p++ - CHAR_0); if (max > 65535) { *errorcodeptr = ERR5; return p; } } if (max < min) { *errorcodeptr = ERR4; return p; } } } *minp = min; *maxp = max; return p; } /************************************************* * Find first significant op code * *************************************************/ /* This is called by several functions that scan a compiled expression looking for a fixed first character, or an anchoring op code etc. It skips over things that do not influence this. For some calls, it makes sense to skip negative forward and all backward assertions, and also the \b assertion; for others it does not. Arguments: code pointer to the start of the group skipassert TRUE if certain assertions are to be skipped Returns: pointer to the first significant opcode */ static const pcre_uchar* first_significant_code(const pcre_uchar *code, BOOL skipassert) { for (;;) { switch ((int)*code) { case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: if (!skipassert) return code; do code += GET(code, 1); while (*code == OP_ALT); code += PRIV(OP_lengths)[*code]; break; case OP_WORD_BOUNDARY: case OP_NOT_WORD_BOUNDARY: if (!skipassert) return code; /* Fall through */ case OP_CALLOUT: case OP_CREF: case OP_DNCREF: case OP_RREF: case OP_DNRREF: case OP_DEF: code += PRIV(OP_lengths)[*code]; break; default: return code; } } /* Control never reaches here */ } /************************************************* * Find the fixed length of a branch * *************************************************/ /* Scan a branch and compute the fixed length of subject that will match it, if the length is fixed. This is needed for dealing with backward assertions. In UTF8 mode, the result is in characters rather than bytes. The branch is temporarily terminated with OP_END when this function is called. This function is called when a backward assertion is encountered, so that if it fails, the error message can point to the correct place in the pattern. However, we cannot do this when the assertion contains subroutine calls, because they can be forward references. We solve this by remembering this case and doing the check at the end; a flag specifies which mode we are running in. Arguments: code points to the start of the pattern (the bracket) utf TRUE in UTF-8 / UTF-16 / UTF-32 mode atend TRUE if called when the pattern is complete cd the "compile data" structure recurses chain of recurse_check to catch mutual recursion Returns: the fixed length, or -1 if there is no fixed length, or -2 if \C was encountered (in UTF-8 mode only) or -3 if an OP_RECURSE item was encountered and atend is FALSE or -4 if an unknown opcode was encountered (internal error) */ static int find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd, recurse_check *recurses) { int length = -1; recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = code + 1 + LINK_SIZE; /* Scan along the opcodes for this branch. If we get to the end of the branch, check the length against that of the other branches. */ for (;;) { int d; pcre_uchar *ce, *cs; register pcre_uchar op = *cc; switch (op) { /* We only need to continue for OP_CBRA (normal capturing bracket) and OP_BRA (normal non-capturing bracket) because the other variants of these opcodes are all concerned with unlimited repeated groups, which of course are not of fixed length. */ case OP_CBRA: case OP_BRA: case OP_ONCE: case OP_ONCE_NC: case OP_COND: d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd, recurses); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); cc += 1 + LINK_SIZE; break; /* Reached end of a branch; if it's a ket it is the end of a nested call. If it's ALT it is an alternation in a nested call. An ACCEPT is effectively an ALT. If it is END it's the end of the outer call. All can be handled by the same code. Note that we must not include the OP_KETRxxx opcodes here, because they all imply an unlimited repeat. */ case OP_ALT: case OP_KET: case OP_END: case OP_ACCEPT: case OP_ASSERT_ACCEPT: if (length < 0) length = branchlength; else if (length != branchlength) return -1; if (*cc != OP_ALT) return length; cc += 1 + LINK_SIZE; branchlength = 0; break; /* A true recursion implies not fixed length, but a subroutine call may be OK. If the subroutine is a forward reference, we can't deal with it until the end of the pattern, so return -3. */ case OP_RECURSE: if (!atend) return -3; cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */ do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */ if (cc > cs && cc < ce) return -1; /* Recursion */ else /* Check for mutual recursion */ { recurse_check *r = recurses; for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; if (r != NULL) return -1; /* Mutual recursion */ } this_recurse.prev = recurses; this_recurse.group = cs; d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd, &this_recurse); if (d < 0) return d; branchlength += d; cc += 1 + LINK_SIZE; break; /* Skip over assertive subpatterns */ case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += GET(cc, 1); while (*cc == OP_ALT); cc += 1 + LINK_SIZE; break; /* Skip over things that don't match chars */ case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: cc += cc[1] + PRIV(OP_lengths)[*cc]; break; case OP_CALLOUT: case OP_CIRC: case OP_CIRCM: case OP_CLOSE: case OP_COMMIT: case OP_CREF: case OP_DEF: case OP_DNCREF: case OP_DNRREF: case OP_DOLL: case OP_DOLLM: case OP_EOD: case OP_EODN: case OP_FAIL: case OP_NOT_WORD_BOUNDARY: case OP_PRUNE: case OP_REVERSE: case OP_RREF: case OP_SET_SOM: case OP_SKIP: case OP_SOD: case OP_SOM: case OP_THEN: case OP_WORD_BOUNDARY: cc += PRIV(OP_lengths)[*cc]; break; /* Handle literal characters */ case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: branchlength++; cc += 2; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; /* Handle exact repetitions. The count is already in characters, but we need to skip over a multibyte character in UTF8 mode. */ case OP_EXACT: case OP_EXACTI: case OP_NOTEXACT: case OP_NOTEXACTI: branchlength += (int)GET2(cc,1); cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; case OP_TYPEEXACT: branchlength += GET2(cc,1); if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2; cc += 1 + IMM2_SIZE + 1; break; /* Handle single-char matchers */ case OP_PROP: case OP_NOTPROP: cc += 2; /* Fall through */ case OP_HSPACE: case OP_VSPACE: case OP_NOT_HSPACE: case OP_NOT_VSPACE: case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: case OP_ALLANY: branchlength++; cc++; break; /* The single-byte matcher isn't allowed. This only happens in UTF-8 mode; otherwise \C is coded as OP_ALLANY. */ case OP_ANYBYTE: return -2; /* Check a class for variable quantification */ case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case OP_XCLASS: /* The original code caused an unsigned overflow in 64 bit systems, so now we use a conditional statement. */ if (op == OP_XCLASS) cc += GET(cc, 1); else cc += PRIV(OP_lengths)[OP_CLASS]; #else cc += PRIV(OP_lengths)[OP_CLASS]; #endif switch (*cc) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: return -1; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1; branchlength += (int)GET2(cc,1); cc += 1 + 2 * IMM2_SIZE; break; default: branchlength++; } break; /* Anything else is variable length */ case OP_ANYNL: case OP_BRAMINZERO: case OP_BRAPOS: case OP_BRAPOSZERO: case OP_BRAZERO: case OP_CBRAPOS: case OP_EXTUNI: case OP_KETRMAX: case OP_KETRMIN: case OP_KETRPOS: case OP_MINPLUS: case OP_MINPLUSI: case OP_MINQUERY: case OP_MINQUERYI: case OP_MINSTAR: case OP_MINSTARI: case OP_MINUPTO: case OP_MINUPTOI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_NOTSTAR: case OP_NOTSTARI: case OP_NOTUPTO: case OP_NOTUPTOI: case OP_PLUS: case OP_PLUSI: case OP_POSPLUS: case OP_POSPLUSI: case OP_POSQUERY: case OP_POSQUERYI: case OP_POSSTAR: case OP_POSSTARI: case OP_POSUPTO: case OP_POSUPTOI: case OP_QUERY: case OP_QUERYI: case OP_REF: case OP_REFI: case OP_DNREF: case OP_DNREFI: case OP_SBRA: case OP_SBRAPOS: case OP_SCBRA: case OP_SCBRAPOS: case OP_SCOND: case OP_SKIPZERO: case OP_STAR: case OP_STARI: case OP_TYPEMINPLUS: case OP_TYPEMINQUERY: case OP_TYPEMINSTAR: case OP_TYPEMINUPTO: case OP_TYPEPLUS: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSSTAR: case OP_TYPEPOSUPTO: case OP_TYPEQUERY: case OP_TYPESTAR: case OP_TYPEUPTO: case OP_UPTO: case OP_UPTOI: return -1; /* Catch unrecognized opcodes so that when new ones are added they are not forgotten, as has happened in the past. */ default: return -4; } } /* Control never gets here */ } /************************************************* * Scan compiled regex for specific bracket * *************************************************/ /* This little function scans through a compiled pattern until it finds a capturing bracket with the given number, or, if the number is negative, an instance of OP_REVERSE for a lookbehind. The function is global in the C sense so that it can be called from pcre_study() when finding the minimum matching length. Arguments: code points to start of expression utf TRUE in UTF-8 / UTF-16 / UTF-32 mode number the required bracket number or negative to find a lookbehind Returns: pointer to the opcode for the bracket, or NULL if not found */ const pcre_uchar * PRIV(find_bracket)(const pcre_uchar *code, BOOL utf, int number) { for (;;) { register pcre_uchar c = *code; if (c == OP_END) return NULL; /* XCLASS is used for classes that cannot be represented just by a bit map. This includes negated single high-valued characters. The length in the table is zero; the actual length is stored in the compiled code. */ if (c == OP_XCLASS) code += GET(code, 1); /* Handle recursion */ else if (c == OP_REVERSE) { if (number < 0) return (pcre_uchar *)code; code += PRIV(OP_lengths)[c]; } /* Handle capturing bracket */ else if (c == OP_CBRA || c == OP_SCBRA || c == OP_CBRAPOS || c == OP_SCBRAPOS) { int n = (int)GET2(code, 1+LINK_SIZE); if (n == number) return (pcre_uchar *)code; code += PRIV(OP_lengths)[c]; } /* Otherwise, we can get the item's length from the table, except that for repeated character types, we have to test for \p and \P, which have an extra two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we must add in its length. */ else { switch(c) { case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; break; case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEEXACT: case OP_TYPEPOSUPTO: if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; break; case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: code += code[1]; break; } /* Add in the fixed length from the table */ code += PRIV(OP_lengths)[c]; /* In UTF-8 mode, opcodes that are followed by a character may be followed by a multi-byte character. The length in the table is a minimum, so we have to arrange to skip the extra bytes. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) switch(c) { case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_EXACT: case OP_EXACTI: case OP_NOTEXACT: case OP_NOTEXACTI: case OP_UPTO: case OP_UPTOI: case OP_NOTUPTO: case OP_NOTUPTOI: case OP_MINUPTO: case OP_MINUPTOI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: case OP_POSUPTO: case OP_POSUPTOI: case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: case OP_STAR: case OP_STARI: case OP_NOTSTAR: case OP_NOTSTARI: case OP_MINSTAR: case OP_MINSTARI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_POSSTAR: case OP_POSSTARI: case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: case OP_PLUS: case OP_PLUSI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_MINPLUS: case OP_MINPLUSI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_POSPLUS: case OP_POSPLUSI: case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: case OP_QUERY: case OP_QUERYI: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_MINQUERY: case OP_MINQUERYI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: case OP_POSQUERY: case OP_POSQUERYI: case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); break; } #else (void)(utf); /* Keep compiler happy by referencing function argument */ #endif } } } /************************************************* * Scan compiled regex for recursion reference * *************************************************/ /* This little function scans through a compiled pattern until it finds an instance of OP_RECURSE. Arguments: code points to start of expression utf TRUE in UTF-8 / UTF-16 / UTF-32 mode Returns: pointer to the opcode for OP_RECURSE, or NULL if not found */ static const pcre_uchar * find_recurse(const pcre_uchar *code, BOOL utf) { for (;;) { register pcre_uchar c = *code; if (c == OP_END) return NULL; if (c == OP_RECURSE) return code; /* XCLASS is used for classes that cannot be represented just by a bit map. This includes negated single high-valued characters. The length in the table is zero; the actual length is stored in the compiled code. */ if (c == OP_XCLASS) code += GET(code, 1); /* Otherwise, we can get the item's length from the table, except that for repeated character types, we have to test for \p and \P, which have an extra two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we must add in its length. */ else { switch(c) { case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; break; case OP_TYPEPOSUPTO: case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEEXACT: if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; break; case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: code += code[1]; break; } /* Add in the fixed length from the table */ code += PRIV(OP_lengths)[c]; /* In UTF-8 mode, opcodes that are followed by a character may be followed by a multi-byte character. The length in the table is a minimum, so we have to arrange to skip the extra bytes. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) switch(c) { case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_EXACT: case OP_EXACTI: case OP_NOTEXACT: case OP_NOTEXACTI: case OP_UPTO: case OP_UPTOI: case OP_NOTUPTO: case OP_NOTUPTOI: case OP_MINUPTO: case OP_MINUPTOI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: case OP_POSUPTO: case OP_POSUPTOI: case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: case OP_STAR: case OP_STARI: case OP_NOTSTAR: case OP_NOTSTARI: case OP_MINSTAR: case OP_MINSTARI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_POSSTAR: case OP_POSSTARI: case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: case OP_PLUS: case OP_PLUSI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_MINPLUS: case OP_MINPLUSI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_POSPLUS: case OP_POSPLUSI: case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: case OP_QUERY: case OP_QUERYI: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_MINQUERY: case OP_MINQUERYI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: case OP_POSQUERY: case OP_POSQUERYI: case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); break; } #else (void)(utf); /* Keep compiler happy by referencing function argument */ #endif } } } /************************************************* * Scan compiled branch for non-emptiness * *************************************************/ /* This function scans through a branch of a compiled pattern to see whether it can match the empty string or not. It is called from could_be_empty() below and from compile_branch() when checking for an unlimited repeat of a group that can match nothing. Note that first_significant_code() skips over backward and negative forward assertions when its final argument is TRUE. If we hit an unclosed bracket, we return "empty" - this means we've struck an inner bracket whose current branch will already have been scanned. Arguments: code points to start of search endcode points to where to stop utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode cd contains pointers to tables etc. recurses chain of recurse_check to catch mutual recursion Returns: TRUE if what is matched could be empty */ static BOOL could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode, BOOL utf, compile_data *cd, recurse_check *recurses) { register pcre_uchar c; recurse_check this_recurse; for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); code < endcode; code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE)) { const pcre_uchar *ccode; c = *code; /* Skip over forward assertions; the other assertions are skipped by first_significant_code() with a TRUE final argument. */ if (c == OP_ASSERT) { do code += GET(code, 1); while (*code == OP_ALT); c = *code; continue; } /* For a recursion/subroutine call, if its end has been reached, which implies a backward reference subroutine call, we can scan it. If it's a forward reference subroutine call, we can't. To detect forward reference we have to scan up the list that is kept in the workspace. This function is called only when doing the real compile, not during the pre-compile that measures the size of the compiled pattern. */ if (c == OP_RECURSE) { const pcre_uchar *scode = cd->start_code + GET(code, 1); const pcre_uchar *endgroup = scode; BOOL empty_branch; /* Test for forward reference or uncompleted reference. This is disabled when called to scan a completed pattern by setting cd->start_workspace to NULL. */ if (cd->start_workspace != NULL) { const pcre_uchar *tcode; for (tcode = cd->start_workspace; tcode < cd->hwm; tcode += LINK_SIZE) if ((int)GET(tcode, 0) == (int)(code + 1 - cd->start_code)) return TRUE; if (GET(scode, 1) == 0) return TRUE; /* Unclosed */ } /* If the reference is to a completed group, we need to detect whether this is a recursive call, as otherwise there will be an infinite loop. If it is a recursion, just skip over it. Simple recursions are easily detected. For mutual recursions we keep a chain on the stack. */ do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT); if (code >= scode && code <= endgroup) continue; /* Simple recursion */ else { recurse_check *r = recurses; for (r = recurses; r != NULL; r = r->prev) if (r->group == scode) break; if (r != NULL) continue; /* Mutual recursion */ } /* Completed reference; scan the referenced group, remembering it on the stack chain to detect mutual recursions. */ empty_branch = FALSE; this_recurse.prev = recurses; this_recurse.group = scode; do { if (could_be_empty_branch(scode, endcode, utf, cd, &this_recurse)) { empty_branch = TRUE; break; } scode += GET(scode, 1); } while (*scode == OP_ALT); if (!empty_branch) return FALSE; /* All branches are non-empty */ continue; } /* Groups with zero repeats can of course be empty; skip them. */ if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO || c == OP_BRAPOSZERO) { code += PRIV(OP_lengths)[c]; do code += GET(code, 1); while (*code == OP_ALT); c = *code; continue; } /* A nested group that is already marked as "could be empty" can just be skipped. */ if (c == OP_SBRA || c == OP_SBRAPOS || c == OP_SCBRA || c == OP_SCBRAPOS) { do code += GET(code, 1); while (*code == OP_ALT); c = *code; continue; } /* For other groups, scan the branches. */ if (c == OP_BRA || c == OP_BRAPOS || c == OP_CBRA || c == OP_CBRAPOS || c == OP_ONCE || c == OP_ONCE_NC || c == OP_COND || c == OP_SCOND) { BOOL empty_branch; if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ /* If a conditional group has only one branch, there is a second, implied, empty branch, so just skip over the conditional, because it could be empty. Otherwise, scan the individual branches of the group. */ if (c == OP_COND && code[GET(code, 1)] != OP_ALT) code += GET(code, 1); else { empty_branch = FALSE; do { if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, recurses)) empty_branch = TRUE; code += GET(code, 1); } while (*code == OP_ALT); if (!empty_branch) return FALSE; /* All branches are non-empty */ } c = *code; continue; } /* Handle the other opcodes */ switch (c) { /* Check for quantifiers after a class. XCLASS is used for classes that cannot be represented just by a bit map. This includes negated single high-valued characters. The length in PRIV(OP_lengths)[] is zero; the actual length is stored in the compiled code, so we must update "code" here. */ #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: ccode = code += GET(code, 1); goto CHECK_CLASS_REPEAT; #endif case OP_CLASS: case OP_NCLASS: ccode = code + PRIV(OP_lengths)[OP_CLASS]; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 CHECK_CLASS_REPEAT: #endif switch (*ccode) { case OP_CRSTAR: /* These could be empty; continue */ case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSQUERY: break; default: /* Non-repeat => class must match */ case OP_CRPLUS: /* These repeats aren't empty */ case OP_CRMINPLUS: case OP_CRPOSPLUS: return FALSE; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ break; } break; /* Opcodes that must match a character */ case OP_ANY: case OP_ALLANY: case OP_ANYBYTE: case OP_PROP: case OP_NOTPROP: case OP_ANYNL: case OP_NOT_HSPACE: case OP_HSPACE: case OP_NOT_VSPACE: case OP_VSPACE: case OP_EXTUNI: case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_PLUS: case OP_PLUSI: case OP_MINPLUS: case OP_MINPLUSI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_POSPLUS: case OP_POSPLUSI: case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: case OP_EXACT: case OP_EXACTI: case OP_NOTEXACT: case OP_NOTEXACTI: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEPOSPLUS: case OP_TYPEEXACT: return FALSE; /* These are going to continue, as they may be empty, but we have to fudge the length for the \p and \P cases. */ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPOSSTAR: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSQUERY: if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; break; /* Same for these */ case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO: if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; break; /* End of branch */ case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_KETRPOS: case OP_ALT: return TRUE; /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO, MINUPTO, and POSUPTO and their caseless and negative versions may be followed by a multibyte character. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 case OP_STAR: case OP_STARI: case OP_NOTSTAR: case OP_NOTSTARI: case OP_MINSTAR: case OP_MINSTARI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_POSSTAR: case OP_POSSTARI: case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: case OP_QUERY: case OP_QUERYI: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_MINQUERY: case OP_MINQUERYI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: case OP_POSQUERY: case OP_POSQUERYI: case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]); break; case OP_UPTO: case OP_UPTOI: case OP_NOTUPTO: case OP_NOTUPTOI: case OP_MINUPTO: case OP_MINUPTOI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: case OP_POSUPTO: case OP_POSUPTOI: case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]); break; #endif /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument string. */ case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: code += code[1]; break; /* None of the remaining opcodes are required to match a character. */ default: break; } } return TRUE; } /************************************************* * Scan compiled regex for non-emptiness * *************************************************/ /* This function is called to check for left recursive calls. We want to check the current branch of the current pattern to see if it could match the empty string. If it could, we must look outwards for branches at other levels, stopping when we pass beyond the bracket which is the subject of the recursion. This function is called only during the real compile, not during the pre-compile. Arguments: code points to start of the recursion endcode points to where to stop (current RECURSE item) bcptr points to the chain of current (unclosed) branch starts utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode cd pointers to tables etc Returns: TRUE if what is matched could be empty */ static BOOL could_be_empty(const pcre_uchar *code, const pcre_uchar *endcode, branch_chain *bcptr, BOOL utf, compile_data *cd) { while (bcptr != NULL && bcptr->current_branch >= code) { if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd, NULL)) return FALSE; bcptr = bcptr->outer; } return TRUE; } /************************************************* * Base opcode of repeated opcodes * *************************************************/ /* Returns the base opcode for repeated single character type opcodes. If the opcode is not a repeated character type, it returns with the original value. Arguments: c opcode Returns: base opcode for the type */ static pcre_uchar get_repeat_base(pcre_uchar c) { return (c > OP_TYPEPOSUPTO)? c : (c >= OP_TYPESTAR)? OP_TYPESTAR : (c >= OP_NOTSTARI)? OP_NOTSTARI : (c >= OP_NOTSTAR)? OP_NOTSTAR : (c >= OP_STARI)? OP_STARI : OP_STAR; } #ifdef SUPPORT_UCP /************************************************* * Check a character and a property * *************************************************/ /* This function is called by check_auto_possessive() when a property item is adjacent to a fixed character. Arguments: c the character ptype the property type pdata the data for the type negated TRUE if it's a negated property (\P or \p{^) Returns: TRUE if auto-possessifying is OK */ static BOOL check_char_prop(pcre_uint32 c, unsigned int ptype, unsigned int pdata, BOOL negated) { const pcre_uint32 *p; const ucd_record *prop = GET_UCD(c); switch(ptype) { case PT_LAMP: return (prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt) == negated; case PT_GC: return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated; case PT_PC: return (pdata == prop->chartype) == negated; case PT_SC: return (pdata == prop->script) == negated; /* These are specials */ case PT_ALNUM: return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: return negated; default: return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated; } break; /* Control never reaches here */ case PT_WORD: return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE) == negated; case PT_CLIST: p = PRIV(ucd_caseless_sets) + prop->caseset; for (;;) { if (c < *p) return !negated; if (c == *p++) return negated; } break; /* Control never reaches here */ } return FALSE; } #endif /* SUPPORT_UCP */ /************************************************* * Fill the character property list * *************************************************/ /* Checks whether the code points to an opcode that can take part in auto- possessification, and if so, fills a list with its properties. Arguments: code points to start of expression utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode fcc points to case-flipping table list points to output list list[0] will be filled with the opcode list[1] will be non-zero if this opcode can match an empty character string list[2..7] depends on the opcode Returns: points to the start of the next opcode if *code is accepted NULL if *code is not accepted */ static const pcre_uchar * get_chr_property_list(const pcre_uchar *code, BOOL utf, const pcre_uint8 *fcc, pcre_uint32 *list) { pcre_uchar c = *code; pcre_uchar base; const pcre_uchar *end; pcre_uint32 chr; #ifdef SUPPORT_UCP pcre_uint32 *clist_dest; const pcre_uint32 *clist_src; #else utf = utf; /* Suppress "unused parameter" compiler warning */ #endif list[0] = c; list[1] = FALSE; code++; if (c >= OP_STAR && c <= OP_TYPEPOSUPTO) { base = get_repeat_base(c); c -= (base - OP_STAR); if (c == OP_UPTO || c == OP_MINUPTO || c == OP_EXACT || c == OP_POSUPTO) code += IMM2_SIZE; list[1] = (c != OP_PLUS && c != OP_MINPLUS && c != OP_EXACT && c != OP_POSPLUS); switch(base) { case OP_STAR: list[0] = OP_CHAR; break; case OP_STARI: list[0] = OP_CHARI; break; case OP_NOTSTAR: list[0] = OP_NOT; break; case OP_NOTSTARI: list[0] = OP_NOTI; break; case OP_TYPESTAR: list[0] = *code; code++; break; } c = list[0]; } switch(c) { case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: case OP_ALLANY: case OP_ANYNL: case OP_NOT_HSPACE: case OP_HSPACE: case OP_NOT_VSPACE: case OP_VSPACE: case OP_EXTUNI: case OP_EODN: case OP_EOD: case OP_DOLL: case OP_DOLLM: return code; case OP_CHAR: case OP_NOT: GETCHARINCTEST(chr, code); list[2] = chr; list[3] = NOTACHAR; return code; case OP_CHARI: case OP_NOTI: list[0] = (c == OP_CHARI) ? OP_CHAR : OP_NOT; GETCHARINCTEST(chr, code); list[2] = chr; #ifdef SUPPORT_UCP if (chr < 128 || (chr < 256 && !utf)) list[3] = fcc[chr]; else list[3] = UCD_OTHERCASE(chr); #elif defined SUPPORT_UTF || !defined COMPILE_PCRE8 list[3] = (chr < 256) ? fcc[chr] : chr; #else list[3] = fcc[chr]; #endif /* The othercase might be the same value. */ if (chr == list[3]) list[3] = NOTACHAR; else list[4] = NOTACHAR; return code; #ifdef SUPPORT_UCP case OP_PROP: case OP_NOTPROP: if (code[0] != PT_CLIST) { list[2] = code[0]; list[3] = code[1]; return code + 2; } /* Convert only if we have enough space. */ clist_src = PRIV(ucd_caseless_sets) + code[1]; clist_dest = list + 2; code += 2; do { if (clist_dest >= list + 8) { /* Early return if there is not enough space. This should never happen, since all clists are shorter than 5 character now. */ list[2] = code[0]; list[3] = code[1]; return code; } *clist_dest++ = *clist_src; } while(*clist_src++ != NOTACHAR); /* All characters are stored. The terminating NOTACHAR is copied form the clist itself. */ list[0] = (c == OP_PROP) ? OP_CHAR : OP_NOT; return code; #endif case OP_NCLASS: case OP_CLASS: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: if (c == OP_XCLASS) end = code + GET(code, 0) - 1; else #endif end = code + 32 / sizeof(pcre_uchar); switch(*end) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSQUERY: list[1] = TRUE; end++; break; case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRPOSPLUS: end++; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: list[1] = (GET2(end, 1) == 0); end += 1 + 2 * IMM2_SIZE; break; } list[2] = (pcre_uint32)(end - code); return end; } return NULL; /* Opcode not accepted */ } /************************************************* * Scan further character sets for match * *************************************************/ /* Checks whether the base and the current opcode have a common character, in which case the base cannot be possessified. Arguments: code points to the byte code utf TRUE in UTF-8 / UTF-16 / UTF-32 mode cd static compile data base_list the data list of the base opcode Returns: TRUE if the auto-possessification is possible */ static BOOL compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd, const pcre_uint32 *base_list, const pcre_uchar *base_end, int *rec_limit) { pcre_uchar c; pcre_uint32 list[8]; const pcre_uint32 *chr_ptr; const pcre_uint32 *ochr_ptr; const pcre_uint32 *list_ptr; const pcre_uchar *next_code; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 const pcre_uchar *xclass_flags; #endif const pcre_uint8 *class_bitset; const pcre_uint8 *set1, *set2, *set_end; pcre_uint32 chr; BOOL accepted, invert_bits; BOOL entered_a_group = FALSE; if (*rec_limit == 0) return FALSE; --(*rec_limit); /* Note: the base_list[1] contains whether the current opcode has greedy (represented by a non-zero value) quantifier. This is a different from other character type lists, which stores here that the character iterator matches to an empty string (also represented by a non-zero value). */ for(;;) { /* All operations move the code pointer forward. Therefore infinite recursions are not possible. */ c = *code; /* Skip over callouts */ if (c == OP_CALLOUT) { code += PRIV(OP_lengths)[c]; continue; } if (c == OP_ALT) { do code += GET(code, 1); while (*code == OP_ALT); c = *code; } switch(c) { case OP_END: case OP_KETRPOS: /* TRUE only in greedy case. The non-greedy case could be replaced by an OP_EXACT, but it is probably not worth it. (And note that OP_EXACT uses more memory, which we cannot get at this stage.) */ return base_list[1] != 0; case OP_KET: /* If the bracket is capturing, and referenced by an OP_RECURSE, or it is an atomic sub-pattern (assert, once, etc.) the non-greedy case cannot be converted to a possessive form. */ if (base_list[1] == 0) return FALSE; switch(*(code - GET(code, 1))) { case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_ONCE_NC: /* Atomic sub-patterns and assertions can always auto-possessify their last iterator. However, if the group was entered as a result of checking a previous iterator, this is not possible. */ return !entered_a_group; } code += PRIV(OP_lengths)[c]; continue; case OP_ONCE: case OP_ONCE_NC: case OP_BRA: case OP_CBRA: next_code = code + GET(code, 1); code += PRIV(OP_lengths)[c]; while (*next_code == OP_ALT) { if (!compare_opcodes(code, utf, cd, base_list, base_end, rec_limit)) return FALSE; code = next_code + 1 + LINK_SIZE; next_code += GET(next_code, 1); } entered_a_group = TRUE; continue; case OP_BRAZERO: case OP_BRAMINZERO: next_code = code + 1; if (*next_code != OP_BRA && *next_code != OP_CBRA && *next_code != OP_ONCE && *next_code != OP_ONCE_NC) return FALSE; do next_code += GET(next_code, 1); while (*next_code == OP_ALT); /* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */ next_code += 1 + LINK_SIZE; if (!compare_opcodes(next_code, utf, cd, base_list, base_end, rec_limit)) return FALSE; code += PRIV(OP_lengths)[c]; continue; default: break; } /* Check for a supported opcode, and load its properties. */ code = get_chr_property_list(code, utf, cd->fcc, list); if (code == NULL) return FALSE; /* Unsupported */ /* If either opcode is a small character list, set pointers for comparing characters from that list with another list, or with a property. */ if (base_list[0] == OP_CHAR) { chr_ptr = base_list + 2; list_ptr = list; } else if (list[0] == OP_CHAR) { chr_ptr = list + 2; list_ptr = base_list; } /* Character bitsets can also be compared to certain opcodes. */ else if (base_list[0] == OP_CLASS || list[0] == OP_CLASS #ifdef COMPILE_PCRE8 /* In 8 bit, non-UTF mode, OP_CLASS and OP_NCLASS are the same. */ || (!utf && (base_list[0] == OP_NCLASS || list[0] == OP_NCLASS)) #endif ) { #ifdef COMPILE_PCRE8 if (base_list[0] == OP_CLASS || (!utf && base_list[0] == OP_NCLASS)) #else if (base_list[0] == OP_CLASS) #endif { set1 = (pcre_uint8 *)(base_end - base_list[2]); list_ptr = list; } else { set1 = (pcre_uint8 *)(code - list[2]); list_ptr = base_list; } invert_bits = FALSE; switch(list_ptr[0]) { case OP_CLASS: case OP_NCLASS: set2 = (pcre_uint8 *) ((list_ptr == list ? code : base_end) - list_ptr[2]); break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE; if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE; if ((*xclass_flags & XCL_MAP) == 0) { /* No bits are set for characters < 256. */ if (list[1] == 0) return (*xclass_flags & XCL_NOT) == 0; /* Might be an empty repeat. */ continue; } set2 = (pcre_uint8 *)(xclass_flags + 1); break; #endif case OP_NOT_DIGIT: invert_bits = TRUE; /* Fall through */ case OP_DIGIT: set2 = (pcre_uint8 *)(cd->cbits + cbit_digit); break; case OP_NOT_WHITESPACE: invert_bits = TRUE; /* Fall through */ case OP_WHITESPACE: set2 = (pcre_uint8 *)(cd->cbits + cbit_space); break; case OP_NOT_WORDCHAR: invert_bits = TRUE; /* Fall through */ case OP_WORDCHAR: set2 = (pcre_uint8 *)(cd->cbits + cbit_word); break; default: return FALSE; } /* Because the sets are unaligned, we need to perform byte comparison here. */ set_end = set1 + 32; if (invert_bits) { do { if ((*set1++ & ~(*set2++)) != 0) return FALSE; } while (set1 < set_end); } else { do { if ((*set1++ & *set2++) != 0) return FALSE; } while (set1 < set_end); } if (list[1] == 0) return TRUE; /* Might be an empty repeat. */ continue; } /* Some property combinations also acceptable. Unicode property opcodes are processed specially; the rest can be handled with a lookup table. */ else { pcre_uint32 leftop, rightop; leftop = base_list[0]; rightop = list[0]; #ifdef SUPPORT_UCP accepted = FALSE; /* Always set in non-unicode case. */ if (leftop == OP_PROP || leftop == OP_NOTPROP) { if (rightop == OP_EOD) accepted = TRUE; else if (rightop == OP_PROP || rightop == OP_NOTPROP) { int n; const pcre_uint8 *p; BOOL same = leftop == rightop; BOOL lisprop = leftop == OP_PROP; BOOL risprop = rightop == OP_PROP; BOOL bothprop = lisprop && risprop; /* There's a table that specifies how each combination is to be processed: 0 Always return FALSE (never auto-possessify) 1 Character groups are distinct (possessify if both are OP_PROP) 2 Check character categories in the same group (general or particular) 3 Return TRUE if the two opcodes are not the same ... see comments below */ n = propposstab[base_list[2]][list[2]]; switch(n) { case 0: break; case 1: accepted = bothprop; break; case 2: accepted = (base_list[3] == list[3]) != same; break; case 3: accepted = !same; break; case 4: /* Left general category, right particular category */ accepted = risprop && catposstab[base_list[3]][list[3]] == same; break; case 5: /* Right general category, left particular category */ accepted = lisprop && catposstab[list[3]][base_list[3]] == same; break; /* This code is logically tricky. Think hard before fiddling with it. The posspropstab table has four entries per row. Each row relates to one of PCRE's special properties such as ALNUM or SPACE or WORD. Only WORD actually needs all four entries, but using repeats for the others means they can all use the same code below. The first two entries in each row are Unicode general categories, and apply always, because all the characters they include are part of the PCRE character set. The third and fourth entries are a general and a particular category, respectively, that include one or more relevant characters. One or the other is used, depending on whether the check is for a general or a particular category. However, in both cases the category contains more characters than the specials that are defined for the property being tested against. Therefore, it cannot be used in a NOTPROP case. Example: the row for WORD contains ucp_L, ucp_N, ucp_P, ucp_Po. Underscore is covered by ucp_P or ucp_Po. */ case 6: /* Left alphanum vs right general category */ case 7: /* Left space vs right general category */ case 8: /* Left word vs right general category */ p = posspropstab[n-6]; accepted = risprop && lisprop == (list[3] != p[0] && list[3] != p[1] && (list[3] != p[2] || !lisprop)); break; case 9: /* Right alphanum vs left general category */ case 10: /* Right space vs left general category */ case 11: /* Right word vs left general category */ p = posspropstab[n-9]; accepted = lisprop && risprop == (base_list[3] != p[0] && base_list[3] != p[1] && (base_list[3] != p[2] || !risprop)); break; case 12: /* Left alphanum vs right particular category */ case 13: /* Left space vs right particular category */ case 14: /* Left word vs right particular category */ p = posspropstab[n-12]; accepted = risprop && lisprop == (catposstab[p[0]][list[3]] && catposstab[p[1]][list[3]] && (list[3] != p[3] || !lisprop)); break; case 15: /* Right alphanum vs left particular category */ case 16: /* Right space vs left particular category */ case 17: /* Right word vs left particular category */ p = posspropstab[n-15]; accepted = lisprop && risprop == (catposstab[p[0]][base_list[3]] && catposstab[p[1]][base_list[3]] && (base_list[3] != p[3] || !risprop)); break; } } } else #endif /* SUPPORT_UCP */ accepted = leftop >= FIRST_AUTOTAB_OP && leftop <= LAST_AUTOTAB_LEFT_OP && rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP && autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP]; if (!accepted) return FALSE; if (list[1] == 0) return TRUE; /* Might be an empty repeat. */ continue; } /* Control reaches here only if one of the items is a small character list. All characters are checked against the other side. */ do { chr = *chr_ptr; switch(list_ptr[0]) { case OP_CHAR: ochr_ptr = list_ptr + 2; do { if (chr == *ochr_ptr) return FALSE; ochr_ptr++; } while(*ochr_ptr != NOTACHAR); break; case OP_NOT: ochr_ptr = list_ptr + 2; do { if (chr == *ochr_ptr) break; ochr_ptr++; } while(*ochr_ptr != NOTACHAR); if (*ochr_ptr == NOTACHAR) return FALSE; /* Not found */ break; /* Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */ case OP_DIGIT: if (chr < 256 && (cd->ctypes[chr] & ctype_digit) != 0) return FALSE; break; case OP_NOT_DIGIT: if (chr > 255 || (cd->ctypes[chr] & ctype_digit) == 0) return FALSE; break; case OP_WHITESPACE: if (chr < 256 && (cd->ctypes[chr] & ctype_space) != 0) return FALSE; break; case OP_NOT_WHITESPACE: if (chr > 255 || (cd->ctypes[chr] & ctype_space) == 0) return FALSE; break; case OP_WORDCHAR: if (chr < 255 && (cd->ctypes[chr] & ctype_word) != 0) return FALSE; break; case OP_NOT_WORDCHAR: if (chr > 255 || (cd->ctypes[chr] & ctype_word) == 0) return FALSE; break; case OP_HSPACE: switch(chr) { HSPACE_CASES: return FALSE; default: break; } break; case OP_NOT_HSPACE: switch(chr) { HSPACE_CASES: break; default: return FALSE; } break; case OP_ANYNL: case OP_VSPACE: switch(chr) { VSPACE_CASES: return FALSE; default: break; } break; case OP_NOT_VSPACE: switch(chr) { VSPACE_CASES: break; default: return FALSE; } break; case OP_DOLL: case OP_EODN: switch (chr) { case CHAR_CR: case CHAR_LF: case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ return FALSE; } break; case OP_EOD: /* Can always possessify before \z */ break; #ifdef SUPPORT_UCP case OP_PROP: case OP_NOTPROP: if (!check_char_prop(chr, list_ptr[2], list_ptr[3], list_ptr[0] == OP_NOTPROP)) return FALSE; break; #endif case OP_NCLASS: if (chr > 255) return FALSE; /* Fall through */ case OP_CLASS: if (chr > 255) break; class_bitset = (pcre_uint8 *) ((list_ptr == list ? code : base_end) - list_ptr[2]); if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE; break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE, utf)) return FALSE; break; #endif default: return FALSE; } chr_ptr++; } while(*chr_ptr != NOTACHAR); /* At least one character must be matched from this opcode. */ if (list[1] == 0) return TRUE; } /* Control never reaches here. There used to be a fail-save return FALSE; here, but some compilers complain about an unreachable statement. */ } /************************************************* * Scan compiled regex for auto-possession * *************************************************/ /* Replaces single character iterations with their possessive alternatives if appropriate. This function modifies the compiled opcode! Arguments: code points to start of the byte code utf TRUE in UTF-8 / UTF-16 / UTF-32 mode cd static compile data Returns: nothing */ static void auto_possessify(pcre_uchar *code, BOOL utf, const compile_data *cd) { register pcre_uchar c; const pcre_uchar *end; pcre_uchar *repeat_opcode; pcre_uint32 list[8]; int rec_limit; for (;;) { c = *code; /* When a pattern with bad UTF-8 encoding is compiled with NO_UTF_CHECK, it may compile without complaining, but may get into a loop here if the code pointer points to a bad value. This is, of course a documentated possibility, when NO_UTF_CHECK is set, so it isn't a bug, but we can detect this case and just give up on this optimization. */ if (c >= OP_TABLE_LENGTH) return; if (c >= OP_STAR && c <= OP_TYPEPOSUPTO) { c -= get_repeat_base(c) - OP_STAR; end = (c <= OP_MINUPTO) ? get_chr_property_list(code, utf, cd->fcc, list) : NULL; list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO; rec_limit = 1000; if (end != NULL && compare_opcodes(end, utf, cd, list, end, &rec_limit)) { switch(c) { case OP_STAR: *code += OP_POSSTAR - OP_STAR; break; case OP_MINSTAR: *code += OP_POSSTAR - OP_MINSTAR; break; case OP_PLUS: *code += OP_POSPLUS - OP_PLUS; break; case OP_MINPLUS: *code += OP_POSPLUS - OP_MINPLUS; break; case OP_QUERY: *code += OP_POSQUERY - OP_QUERY; break; case OP_MINQUERY: *code += OP_POSQUERY - OP_MINQUERY; break; case OP_UPTO: *code += OP_POSUPTO - OP_UPTO; break; case OP_MINUPTO: *code += OP_POSUPTO - OP_MINUPTO; break; } } c = *code; } else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS) { #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 if (c == OP_XCLASS) repeat_opcode = code + GET(code, 1); else #endif repeat_opcode = code + 1 + (32 / sizeof(pcre_uchar)); c = *repeat_opcode; if (c >= OP_CRSTAR && c <= OP_CRMINRANGE) { /* end must not be NULL. */ end = get_chr_property_list(code, utf, cd->fcc, list); list[1] = (c & 1) == 0; rec_limit = 1000; if (compare_opcodes(end, utf, cd, list, end, &rec_limit)) { switch (c) { case OP_CRSTAR: case OP_CRMINSTAR: *repeat_opcode = OP_CRPOSSTAR; break; case OP_CRPLUS: case OP_CRMINPLUS: *repeat_opcode = OP_CRPOSPLUS; break; case OP_CRQUERY: case OP_CRMINQUERY: *repeat_opcode = OP_CRPOSQUERY; break; case OP_CRRANGE: case OP_CRMINRANGE: *repeat_opcode = OP_CRPOSRANGE; break; } } } c = *code; } switch(c) { case OP_END: return; case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; break; case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEEXACT: case OP_TYPEPOSUPTO: if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: code += GET(code, 1); break; #endif case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: code += code[1]; break; } /* Add in the fixed length from the table */ code += PRIV(OP_lengths)[c]; /* In UTF-8 mode, opcodes that are followed by a character may be followed by a multi-byte character. The length in the table is a minimum, so we have to arrange to skip the extra bytes. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) switch(c) { case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_UPTO: case OP_MINUPTO: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_UPTOI: case OP_MINUPTOI: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); break; } #else (void)(utf); /* Keep compiler happy by referencing function argument */ #endif } } /************************************************* * Check for POSIX class syntax * *************************************************/ /* This function is called when the sequence "[:" or "[." or "[=" is encountered in a character class. It checks whether this is followed by a sequence of characters terminated by a matching ":]" or ".]" or "=]". If we reach an unescaped ']' without the special preceding character, return FALSE. Originally, this function only recognized a sequence of letters between the terminators, but it seems that Perl recognizes any sequence of characters, though of course unknown POSIX names are subsequently rejected. Perl gives an "Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE didn't consider this to be a POSIX class. Likewise for [:1234:]. The problem in trying to be exactly like Perl is in the handling of escapes. We have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code below handles the special cases \\ and \], but does not try to do any other escape processing. This makes it different from Perl for cases such as [:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize "l\ower". This is a lesser evil than not diagnosing bad classes when Perl does, I think. A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. It seems that the appearance of a nested POSIX class supersedes an apparent external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or a digit. In Perl, unescaped square brackets may also appear as part of class names. For example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for [:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not seem right at all. PCRE does not allow closing square brackets in POSIX class names. Arguments: ptr pointer to the initial [ endptr where to return the end pointer Returns: TRUE or FALSE */ static BOOL check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr) { pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */ terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ for (++ptr; *ptr != CHAR_NULL; ptr++) { if (*ptr == CHAR_BACKSLASH && (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || ptr[1] == CHAR_BACKSLASH)) ptr++; else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) || *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { *endptr = ptr; return TRUE; } } return FALSE; } /************************************************* * Check POSIX class name * *************************************************/ /* This function is called to check the name given in a POSIX-style class entry such as [:alnum:]. Arguments: ptr points to the first letter len the length of the name Returns: a value representing the name, or -1 if unknown */ static int check_posix_name(const pcre_uchar *ptr, int len) { const char *pn = posix_names; register int yield = 0; while (posix_name_lengths[yield] != 0) { if (len == posix_name_lengths[yield] && STRNCMP_UC_C8(ptr, pn, (unsigned int)len) == 0) return yield; pn += posix_name_lengths[yield] + 1; yield++; } return -1; } /************************************************* * Adjust OP_RECURSE items in repeated group * *************************************************/ /* OP_RECURSE items contain an offset from the start of the regex to the group that is referenced. This means that groups can be replicated for fixed repetition simply by copying (because the recursion is allowed to refer to earlier groups that are outside the current group). However, when a group is optional (i.e. the minimum quantifier is zero), OP_BRAZERO or OP_SKIPZERO is inserted before it, after it has been compiled. This means that any OP_RECURSE items within it that refer to the group itself or any contained groups have to have their offsets adjusted. That one of the jobs of this function. Before it is called, the partially compiled regex must be temporarily terminated with OP_END. This function has been extended to cope with forward references for recursions and subroutine calls. It must check the list of such references for the group we are dealing with. If it finds that one of the recursions in the current group is on this list, it does not adjust the value in the reference (which is a group number). After the group has been scanned, all the offsets in the forward reference list for the group are adjusted. Arguments: group points to the start of the group adjust the amount by which the group is to be moved utf TRUE in UTF-8 / UTF-16 / UTF-32 mode cd contains pointers to tables etc. save_hwm_offset the hwm forward reference offset at the start of the group Returns: nothing */ static void adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, size_t save_hwm_offset) { int offset; pcre_uchar *hc; pcre_uchar *ptr = group; while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) { for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; hc += LINK_SIZE) { offset = (int)GET(hc, 0); if (cd->start_code + offset == ptr + 1) break; } /* If we have not found this recursion on the forward reference list, adjust the recursion's offset if it's after the start of this group. */ if (hc >= cd->hwm) { offset = (int)GET(ptr, 1); if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust); } ptr += 1 + LINK_SIZE; } /* Now adjust all forward reference offsets for the group. */ for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; hc += LINK_SIZE) { offset = (int)GET(hc, 0); PUT(hc, 0, offset + adjust); } } /************************************************* * Insert an automatic callout point * *************************************************/ /* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert callout points before each pattern item. Arguments: code current code pointer ptr current pattern pointer cd pointers to tables etc Returns: new code pointer */ static pcre_uchar * auto_callout(pcre_uchar *code, const pcre_uchar *ptr, compile_data *cd) { *code++ = OP_CALLOUT; *code++ = 255; PUT(code, 0, (int)(ptr - cd->start_pattern)); /* Pattern offset */ PUT(code, LINK_SIZE, 0); /* Default length */ return code + 2 * LINK_SIZE; } /************************************************* * Complete a callout item * *************************************************/ /* A callout item contains the length of the next item in the pattern, which we can't fill in till after we have reached the relevant point. This is used for both automatic and manual callouts. Arguments: previous_callout points to previous callout item ptr current pattern pointer cd pointers to tables etc Returns: nothing */ static void complete_callout(pcre_uchar *previous_callout, const pcre_uchar *ptr, compile_data *cd) { int length = (int)(ptr - cd->start_pattern - GET(previous_callout, 2)); PUT(previous_callout, 2 + LINK_SIZE, length); } #ifdef SUPPORT_UCP /************************************************* * Get othercase range * *************************************************/ /* This function is passed the start and end of a class range, in UTF-8 mode with UCP support. It searches up the characters, looking for ranges of characters in the "other" case. Each call returns the next one, updating the start address. A character with multiple other cases is returned on its own with a special return value. Arguments: cptr points to starting character value; updated d end value ocptr where to put start of othercase range odptr where to put end of othercase range Yield: -1 when no more 0 when a range is returned >0 the CASESET offset for char with multiple other cases in this case, ocptr contains the original */ static int get_othercase_range(pcre_uint32 *cptr, pcre_uint32 d, pcre_uint32 *ocptr, pcre_uint32 *odptr) { pcre_uint32 c, othercase, next; unsigned int co; /* Find the first character that has an other case. If it has multiple other cases, return its case offset value. */ for (c = *cptr; c <= d; c++) { if ((co = UCD_CASESET(c)) != 0) { *ocptr = c++; /* Character that has the set */ *cptr = c; /* Rest of input range */ return (int)co; } if ((othercase = UCD_OTHERCASE(c)) != c) break; } if (c > d) return -1; /* Reached end of range */ /* Found a character that has a single other case. Search for the end of the range, which is either the end of the input range, or a character that has zero or more than one other cases. */ *ocptr = othercase; next = othercase + 1; for (++c; c <= d; c++) { if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break; next++; } *odptr = next - 1; /* End of othercase range */ *cptr = c; /* Rest of input range */ return 0; } #endif /* SUPPORT_UCP */ /************************************************* * Add a character or range to a class * *************************************************/ /* This function packages up the logic of adding a character or range of characters to a class. The character values in the arguments will be within the valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is mutually recursive with the function immediately below. Arguments: classbits the bit map for characters < 256 uchardptr points to the pointer for extra data options the options word cd contains pointers to tables etc. start start of range character end end of range character Returns: the number of < 256 characters added the pointer to extra data is updated */ static int add_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options, compile_data *cd, pcre_uint32 start, pcre_uint32 end) { pcre_uint32 c; pcre_uint32 classbits_end = (end <= 0xff ? end : 0xff); int n8 = 0; /* If caseless matching is required, scan the range and process alternate cases. In Unicode, there are 8-bit characters that have alternate cases that are greater than 255 and vice-versa. Sometimes we can just extend the original range. */ if ((options & PCRE_CASELESS) != 0) { #ifdef SUPPORT_UCP if ((options & PCRE_UTF8) != 0) { int rc; pcre_uint32 oc, od; options &= ~PCRE_CASELESS; /* Remove for recursive calls */ c = start; while ((rc = get_othercase_range(&c, end, &oc, &od)) >= 0) { /* Handle a single character that has more than one other case. */ if (rc > 0) n8 += add_list_to_class(classbits, uchardptr, options, cd, PRIV(ucd_caseless_sets) + rc, oc); /* Do nothing if the other case range is within the original range. */ else if (oc >= start && od <= end) continue; /* Extend the original range if there is overlap, noting that if oc < c, we can't have od > end because a subrange is always shorter than the basic range. Otherwise, use a recursive call to add the additional range. */ else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */ else if (od > end && oc <= end + 1) { end = od; /* Extend upwards */ if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff); } else n8 += add_to_class(classbits, uchardptr, options, cd, oc, od); } } else #endif /* SUPPORT_UCP */ /* Not UTF-mode, or no UCP */ for (c = start; c <= classbits_end; c++) { SETBIT(classbits, cd->fcc[c]); n8++; } } /* Now handle the original range. Adjust the final value according to the bit length - this means that the same lists of (e.g.) horizontal spaces can be used in all cases. */ #if defined COMPILE_PCRE8 #ifdef SUPPORT_UTF if ((options & PCRE_UTF8) == 0) #endif if (end > 0xff) end = 0xff; #elif defined COMPILE_PCRE16 #ifdef SUPPORT_UTF if ((options & PCRE_UTF16) == 0) #endif if (end > 0xffff) end = 0xffff; #endif /* COMPILE_PCRE[8|16] */ /* Use the bitmap for characters < 256. Otherwise use extra data.*/ for (c = start; c <= classbits_end; c++) { /* Regardless of start, c will always be <= 255. */ SETBIT(classbits, c); n8++; } #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 if (start <= 0xff) start = 0xff + 1; if (end >= start) { pcre_uchar *uchardata = *uchardptr; #ifdef SUPPORT_UTF if ((options & PCRE_UTF8) != 0) /* All UTFs use the same flag bit */ { if (start < end) { *uchardata++ = XCL_RANGE; uchardata += PRIV(ord2utf)(start, uchardata); uchardata += PRIV(ord2utf)(end, uchardata); } else if (start == end) { *uchardata++ = XCL_SINGLE; uchardata += PRIV(ord2utf)(start, uchardata); } } else #endif /* SUPPORT_UTF */ /* Without UTF support, character values are constrained by the bit length, and can only be > 256 for 16-bit and 32-bit libraries. */ #ifdef COMPILE_PCRE8 {} #else if (start < end) { *uchardata++ = XCL_RANGE; *uchardata++ = start; *uchardata++ = end; } else if (start == end) { *uchardata++ = XCL_SINGLE; *uchardata++ = start; } #endif *uchardptr = uchardata; /* Updata extra data pointer */ } #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ return n8; /* Number of 8-bit characters */ } /************************************************* * Add a list of characters to a class * *************************************************/ /* This function is used for adding a list of case-equivalent characters to a class, and also for adding a list of horizontal or vertical whitespace. If the list is in order (which it should be), ranges of characters are detected and handled appropriately. This function is mutually recursive with the function above. Arguments: classbits the bit map for characters < 256 uchardptr points to the pointer for extra data options the options word cd contains pointers to tables etc. p points to row of 32-bit values, terminated by NOTACHAR except character to omit; this is used when adding lists of case-equivalent characters to avoid including the one we already know about Returns: the number of < 256 characters added the pointer to extra data is updated */ static int add_list_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options, compile_data *cd, const pcre_uint32 *p, unsigned int except) { int n8 = 0; while (p[0] < NOTACHAR) { int n = 0; if (p[0] != except) { while(p[n+1] == p[0] + n + 1) n++; n8 += add_to_class(classbits, uchardptr, options, cd, p[0], p[n]); } p += n + 1; } return n8; } /************************************************* * Add characters not in a list to a class * *************************************************/ /* This function is used for adding the complement of a list of horizontal or vertical whitespace to a class. The list must be in order. Arguments: classbits the bit map for characters < 256 uchardptr points to the pointer for extra data options the options word cd contains pointers to tables etc. p points to row of 32-bit values, terminated by NOTACHAR Returns: the number of < 256 characters added the pointer to extra data is updated */ static int add_not_list_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options, compile_data *cd, const pcre_uint32 *p) { BOOL utf = (options & PCRE_UTF8) != 0; int n8 = 0; if (p[0] > 0) n8 += add_to_class(classbits, uchardptr, options, cd, 0, p[0] - 1); while (p[0] < NOTACHAR) { while (p[1] == p[0] + 1) p++; n8 += add_to_class(classbits, uchardptr, options, cd, p[0] + 1, (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1); p++; } return n8; } /************************************************* * Compile one branch * *************************************************/ /* Scan the pattern, compiling it into the a vector. If the options are changed during the branch, the pointer is used to change the external options bits. This function is used during the pre-compile phase when we are trying to find out the amount of memory needed, as well as during the real compile phase. The value of lengthptr distinguishes the two phases. Arguments: optionsptr pointer to the option bits codeptr points to the pointer to the current code point ptrptr points to the current pattern pointer errorcodeptr points to error code variable firstcharptr place to put the first required character firstcharflagsptr place to put the first character flags, or a negative number reqcharptr place to put the last required character reqcharflagsptr place to put the last required character flags, or a negative number bcptr points to current branch chain cond_depth conditional nesting depth cd contains pointers to tables etc. lengthptr NULL during the real compile phase points to length accumulator during pre-compile phase Returns: TRUE on success FALSE, with *errorcodeptr set non-zero on error */ static BOOL compile_branch(int *optionsptr, pcre_uchar **codeptr, const pcre_uchar **ptrptr, int *errorcodeptr, pcre_uint32 *firstcharptr, pcre_int32 *firstcharflagsptr, pcre_uint32 *reqcharptr, pcre_int32 *reqcharflagsptr, branch_chain *bcptr, int cond_depth, compile_data *cd, int *lengthptr) { int repeat_type, op_type; int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ int bravalue = 0; int greedy_default, greedy_non_default; pcre_uint32 firstchar, reqchar; pcre_int32 firstcharflags, reqcharflags; pcre_uint32 zeroreqchar, zerofirstchar; pcre_int32 zeroreqcharflags, zerofirstcharflags; pcre_int32 req_caseopt, reqvary, tempreqvary; int options = *optionsptr; /* May change dynamically */ int after_manual_callout = 0; int length_prevgroup = 0; register pcre_uint32 c; int escape; register pcre_uchar *code = *codeptr; pcre_uchar *last_code = code; pcre_uchar *orig_code = code; pcre_uchar *tempcode; BOOL inescq = FALSE; BOOL groupsetfirstchar = FALSE; const pcre_uchar *ptr = *ptrptr; const pcre_uchar *tempptr; const pcre_uchar *nestptr = NULL; pcre_uchar *previous = NULL; pcre_uchar *previous_callout = NULL; size_t item_hwm_offset = 0; pcre_uint8 classbits[32]; /* We can fish out the UTF-8 setting once and for all into a BOOL, but we must not do this for other options (e.g. PCRE_EXTENDED) because they may change dynamically as we process the pattern. */ #ifdef SUPPORT_UTF /* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */ BOOL utf = (options & PCRE_UTF8) != 0; #ifndef COMPILE_PCRE32 pcre_uchar utf_chars[6]; #endif #else BOOL utf = FALSE; #endif /* Helper variables for OP_XCLASS opcode (for characters > 255). We define class_uchardata always so that it can be passed to add_to_class() always, though it will not be used in non-UTF 8-bit cases. This avoids having to supply alternative calls for the different cases. */ pcre_uchar *class_uchardata; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 BOOL xclass; pcre_uchar *class_uchardata_base; #endif #ifdef PCRE_DEBUG if (lengthptr != NULL) DPRINTF((">> start branch\n")); #endif /* Set up the default and non-default settings for greediness */ greedy_default = ((options & PCRE_UNGREEDY) != 0); greedy_non_default = greedy_default ^ 1; /* Initialize no first byte, no required byte. REQ_UNSET means "no char matching encountered yet". It gets changed to REQ_NONE if we hit something that matches a non-fixed char first char; reqchar just remains unset if we never find one. When we hit a repeat whose minimum is zero, we may have to adjust these values to take the zero repeat into account. This is implemented by setting them to zerofirstbyte and zeroreqchar when such a repeat is encountered. The individual item types that can be repeated set these backoff variables appropriately. */ firstchar = reqchar = zerofirstchar = zeroreqchar = 0; firstcharflags = reqcharflags = zerofirstcharflags = zeroreqcharflags = REQ_UNSET; /* The variable req_caseopt contains either the REQ_CASELESS value or zero, according to the current setting of the caseless flag. The REQ_CASELESS leaves the lower 28 bit empty. It is added into the firstchar or reqchar variables to record the case status of the value. This is used only for ASCII characters. */ req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS:0; /* Switch on next character until the end of the branch */ for (;; ptr++) { BOOL negate_class; BOOL should_flip_negation; BOOL possessive_quantifier; BOOL is_quantifier; BOOL is_recurse; BOOL reset_bracount; int class_has_8bitchar; int class_one_char; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 BOOL xclass_has_prop; #endif int newoptions; int recno; int refsign; int skipbytes; pcre_uint32 subreqchar, subfirstchar; pcre_int32 subreqcharflags, subfirstcharflags; int terminator; unsigned int mclength; unsigned int tempbracount; pcre_uint32 ec; pcre_uchar mcbuffer[8]; /* Come here to restart the loop without advancing the pointer. */ REDO_LOOP: /* Get next character in the pattern */ c = *ptr; /* If we are at the end of a nested substitution, revert to the outer level string. Nesting only happens one level deep. */ if (c == CHAR_NULL && nestptr != NULL) { ptr = nestptr; nestptr = NULL; c = *ptr; } /* If we are in the pre-compile phase, accumulate the length used for the previous cycle of this loop. */ if (lengthptr != NULL) { #ifdef PCRE_DEBUG if (code > cd->hwm) cd->hwm = code; /* High water info */ #endif if (code > cd->start_workspace + cd->workspace_size - WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */ { *errorcodeptr = (code >= cd->start_workspace + cd->workspace_size)? ERR52 : ERR87; goto FAILED; } /* There is at least one situation where code goes backwards: this is the case of a zero quantifier after a class (e.g. [ab]{0}). At compile time, the class is simply eliminated. However, it is created first, so we have to allow memory for it. Therefore, don't ever reduce the length at this point. */ if (code < last_code) code = last_code; /* Paranoid check for integer overflow */ if (OFLOW_MAX - *lengthptr < code - last_code) { *errorcodeptr = ERR20; goto FAILED; } *lengthptr += (int)(code - last_code); DPRINTF(("length=%d added %d c=%c (0x%x)\n", *lengthptr, (int)(code - last_code), c, c)); /* If "previous" is set and it is not at the start of the work space, move it back to there, in order to avoid filling up the work space. Otherwise, if "previous" is NULL, reset the current code pointer to the start. */ if (previous != NULL) { if (previous > orig_code) { memmove(orig_code, previous, IN_UCHARS(code - previous)); code -= previous - orig_code; previous = orig_code; } } else code = orig_code; /* Remember where this code item starts so we can pick up the length next time round. */ last_code = code; } /* In the real compile phase, just check the workspace used by the forward reference list. */ else if (cd->hwm > cd->start_workspace + cd->workspace_size) { *errorcodeptr = ERR52; goto FAILED; } /* If in \Q...\E, check for the end; if not, we have a literal. Otherwise an isolated \E is ignored. */ if (c != CHAR_NULL) { if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) { inescq = FALSE; ptr++; continue; } else if (inescq) { if (previous_callout != NULL) { if (lengthptr == NULL) /* Don't attempt in pre-compile phase */ complete_callout(previous_callout, ptr, cd); previous_callout = NULL; } if ((options & PCRE_AUTO_CALLOUT) != 0) { previous_callout = code; code = auto_callout(code, ptr, cd); } goto NORMAL_CHAR; } /* Check for the start of a \Q...\E sequence. We must do this here rather than later in case it is immediately followed by \E, which turns it into a "do nothing" sequence. */ if (c == CHAR_BACKSLASH && ptr[1] == CHAR_Q) { inescq = TRUE; ptr++; continue; } } /* In extended mode, skip white space and comments. */ if ((options & PCRE_EXTENDED) != 0) { const pcre_uchar *wscptr = ptr; while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr); if (c == CHAR_NUMBER_SIGN) { ptr++; while (*ptr != CHAR_NULL) { if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */ { /* IS_NEWLINE sets cd->nllen. */ ptr += cd->nllen; break; } ptr++; #ifdef SUPPORT_UTF if (utf) FORWARDCHAR(ptr); #endif } } /* If we skipped any characters, restart the loop. Otherwise, we didn't see a comment. */ if (ptr > wscptr) goto REDO_LOOP; } /* Skip over (?# comments. We need to do this here because we want to know if the next thing is a quantifier, and these comments may come between an item and its quantifier. */ if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK && ptr[2] == CHAR_NUMBER_SIGN) { ptr += 3; while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; if (*ptr == CHAR_NULL) { *errorcodeptr = ERR18; goto FAILED; } continue; } /* See if the next thing is a quantifier. */ is_quantifier = c == CHAR_ASTERISK || c == CHAR_PLUS || c == CHAR_QUESTION_MARK || (c == CHAR_LEFT_CURLY_BRACKET && is_counted_repeat(ptr+1)); /* Fill in length of a previous callout, except when the next thing is a quantifier or when processing a property substitution string in UCP mode. */ if (!is_quantifier && previous_callout != NULL && nestptr == NULL && after_manual_callout-- <= 0) { if (lengthptr == NULL) /* Don't attempt in pre-compile phase */ complete_callout(previous_callout, ptr, cd); previous_callout = NULL; } /* Create auto callout, except for quantifiers, or while processing property strings that are substituted for \w etc in UCP mode. */ if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier && nestptr == NULL) { previous_callout = code; code = auto_callout(code, ptr, cd); } /* Process the next pattern item. */ switch(c) { /* ===================================================================*/ case CHAR_NULL: /* The branch terminates at string end */ case CHAR_VERTICAL_LINE: /* or | or ) */ case CHAR_RIGHT_PARENTHESIS: *firstcharptr = firstchar; *firstcharflagsptr = firstcharflags; *reqcharptr = reqchar; *reqcharflagsptr = reqcharflags; *codeptr = code; *ptrptr = ptr; if (lengthptr != NULL) { if (OFLOW_MAX - *lengthptr < code - last_code) { *errorcodeptr = ERR20; goto FAILED; } *lengthptr += (int)(code - last_code); /* To include callout length */ DPRINTF((">> end branch\n")); } return TRUE; /* ===================================================================*/ /* Handle single-character metacharacters. In multiline mode, ^ disables the setting of any following char as a first character. */ case CHAR_CIRCUMFLEX_ACCENT: previous = NULL; if ((options & PCRE_MULTILINE) != 0) { if (firstcharflags == REQ_UNSET) zerofirstcharflags = firstcharflags = REQ_NONE; *code++ = OP_CIRCM; } else *code++ = OP_CIRC; break; case CHAR_DOLLAR_SIGN: previous = NULL; *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL; break; /* There can never be a first char if '.' is first, whatever happens about repeats. The value of reqchar doesn't change either. */ case CHAR_DOT: if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; break; /* ===================================================================*/ /* Character classes. If the included characters are all < 256, we build a 32-byte bitmap of the permitted characters, except in the special case where there is only one such character. For negated classes, we build the map as usual, then invert it at the end. However, we use a different opcode so that data characters > 255 can be handled correctly. If the class contains characters outside the 0-255 range, a different opcode is compiled. It may optionally have a bit map for characters < 256, but those above are are explicitly listed afterwards. A flag byte tells whether the bitmap is present, and whether this is a negated class or not. In JavaScript compatibility mode, an isolated ']' causes an error. In default (Perl) mode, it is treated as a data character. */ case CHAR_RIGHT_SQUARE_BRACKET: if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0) { *errorcodeptr = ERR64; goto FAILED; } goto NORMAL_CHAR; /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is used for "start of word" and "end of word". As these are otherwise illegal sequences, we don't break anything by recognizing them. They are replaced by \b(?=\w) and \b(?<=\w) respectively. Sequences like [a[:<:]] are erroneous and are handled by the normal code below. */ case CHAR_LEFT_SQUARE_BRACKET: if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0) { nestptr = ptr + 7; ptr = sub_start_of_word; goto REDO_LOOP; } if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0) { nestptr = ptr + 7; ptr = sub_end_of_word; goto REDO_LOOP; } /* Handle a real character class. */ previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; /* PCRE supports POSIX class stuff inside a class. Perl gives an error if they are encountered at the top level, so we'll do that too. */ if ((ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr)) { *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR13 : ERR31; goto FAILED; } /* If the first character is '^', set the negation flag and skip it. Also, if the first few characters (either before or after ^) are \Q\E or \E we skip them too. This makes for compatibility with Perl. */ negate_class = FALSE; for (;;) { c = *(++ptr); if (c == CHAR_BACKSLASH) { if (ptr[1] == CHAR_E) ptr++; else if (STRNCMP_UC_C8(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0) ptr += 3; else break; } else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT) negate_class = TRUE; else break; } /* Empty classes are allowed in JavaScript compatibility mode. Otherwise, an initial ']' is taken as a data character -- the code below handles that. In JS mode, [] must always fail, so generate OP_FAIL, whereas [^] must match any character, so generate OP_ALLANY. */ if (c == CHAR_RIGHT_SQUARE_BRACKET && (cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0) { *code++ = negate_class? OP_ALLANY : OP_FAIL; if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; break; } /* If a class contains a negative special such as \S, we need to flip the negation flag at the end, so that support for characters > 255 works correctly (they are all included in the class). */ should_flip_negation = FALSE; /* Extended class (xclass) will be used when characters > 255 might match. */ #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 xclass = FALSE; class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */ class_uchardata_base = class_uchardata; /* Save the start */ #endif /* For optimization purposes, we track some properties of the class: class_has_8bitchar will be non-zero if the class contains at least one < 256 character; class_one_char will be 1 if the class contains just one character; xclass_has_prop will be TRUE if unicode property checks are present in the class. */ class_has_8bitchar = 0; class_one_char = 0; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 xclass_has_prop = FALSE; #endif /* Initialize the 32-char bit map to all zeros. We build the map in a temporary bit of memory, in case the class contains fewer than two 8-bit characters because in that case the compiled code doesn't use the bit map. */ memset(classbits, 0, 32 * sizeof(pcre_uint8)); /* Process characters until ] is reached. By writing this as a "do" it means that an initial ] is taken as a data character. At the start of the loop, c contains the first byte of the character. */ if (c != CHAR_NULL) do { const pcre_uchar *oldptr; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(c)) { /* Braces are required because the */ GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ } #endif #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 /* In the pre-compile phase, accumulate the length of any extra data and reset the pointer. This is so that very large classes that contain a zillion > 255 characters no longer overwrite the work space (which is on the stack). We have to remember that there was XCLASS data, however. */ if (class_uchardata > class_uchardata_base) xclass = TRUE; if (lengthptr != NULL && class_uchardata > class_uchardata_base) { *lengthptr += (int)(class_uchardata - class_uchardata_base); class_uchardata = class_uchardata_base; } #endif /* Inside \Q...\E everything is literal except \E */ if (inescq) { if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) /* If we are at \E */ { inescq = FALSE; /* Reset literal state */ ptr++; /* Skip the 'E' */ continue; /* Carry on with next */ } goto CHECK_RANGE; /* Could be range if \E follows */ } /* Handle POSIX class names. Perl allows a negation extension of the form [:^name:]. A square bracket that doesn't match the syntax is treated as a literal. We also recognize the POSIX constructions [.ch.] and [=ch=] ("collating elements") and fault them, as Perl 5.6 and 5.8 do. */ if (c == CHAR_LEFT_SQUARE_BRACKET && (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr)) { BOOL local_negate = FALSE; int posix_class, taboffset, tabopt; register const pcre_uint8 *cbits = cd->cbits; pcre_uint8 pbits[32]; if (ptr[1] != CHAR_COLON) { *errorcodeptr = ERR31; goto FAILED; } ptr += 2; if (*ptr == CHAR_CIRCUMFLEX_ACCENT) { local_negate = TRUE; should_flip_negation = TRUE; /* Note negative special */ ptr++; } posix_class = check_posix_name(ptr, (int)(tempptr - ptr)); if (posix_class < 0) { *errorcodeptr = ERR30; goto FAILED; } /* If matching is caseless, upper and lower are converted to alpha. This relies on the fact that the class table starts with alpha, lower, upper as the first 3 entries. */ if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) posix_class = 0; /* When PCRE_UCP is set, some of the POSIX classes are converted to different escape sequences that use Unicode properties \p or \P. Others that are not available via \p or \P generate XCL_PROP/XCL_NOTPROP directly. */ #ifdef SUPPORT_UCP if ((options & PCRE_UCP) != 0) { unsigned int ptype = 0; int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0); /* The posix_substitutes table specifies which POSIX classes can be converted to \p or \P items. */ if (posix_substitutes[pc] != NULL) { nestptr = tempptr + 1; ptr = posix_substitutes[pc] - 1; continue; } /* There are three other classes that generate special property calls that are recognized only in an XCLASS. */ else switch(posix_class) { case PC_GRAPH: ptype = PT_PXGRAPH; /* Fall through */ case PC_PRINT: if (ptype == 0) ptype = PT_PXPRINT; /* Fall through */ case PC_PUNCT: if (ptype == 0) ptype = PT_PXPUNCT; *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP; *class_uchardata++ = ptype; *class_uchardata++ = 0; xclass_has_prop = TRUE; ptr = tempptr + 1; continue; /* For the other POSIX classes (ascii, cntrl, xdigit) we are going to fall through to the non-UCP case and build a bit map for characters with code points less than 256. If we are in a negated POSIX class, characters with code points greater than 255 must either all match or all not match. In the special case where we have not yet generated any xclass data, and this is the final item in the overall class, we need do nothing: later on, the opcode OP_NCLASS will be used to indicate that characters greater than 255 are acceptable. If we have already seen an xclass item or one may follow (we have to assume that it might if this is not the end of the class), explicitly list all wide codepoints, which will then either not match or match, depending on whether the class is or is not negated. */ default: if (local_negate && (xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET)) { *class_uchardata++ = XCL_RANGE; class_uchardata += PRIV(ord2utf)(0x100, class_uchardata); class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); } break; } } #endif /* In the non-UCP case, or when UCP makes no difference, we build the bit map for the POSIX class in a chunk of local store because we may be adding and subtracting from it, and we don't want to subtract bits that may be in the main map already. At the end we or the result into the bit map that is being built. */ posix_class *= 3; /* Copy in the first table (always present) */ memcpy(pbits, cbits + posix_class_maps[posix_class], 32 * sizeof(pcre_uint8)); /* If there is a second table, add or remove it as required. */ taboffset = posix_class_maps[posix_class + 1]; tabopt = posix_class_maps[posix_class + 2]; if (taboffset >= 0) { if (tabopt >= 0) for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset]; else for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset]; } /* Now see if we need to remove any special characters. An option value of 1 removes vertical space and 2 removes underscore. */ if (tabopt < 0) tabopt = -tabopt; if (tabopt == 1) pbits[1] &= ~0x3c; else if (tabopt == 2) pbits[11] &= 0x7f; /* Add the POSIX table or its complement into the main table that is being built and we are done. */ if (local_negate) for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c]; else for (c = 0; c < 32; c++) classbits[c] |= pbits[c]; ptr = tempptr + 1; /* Every class contains at least one < 256 character. */ class_has_8bitchar = 1; /* Every class contains at least two characters. */ class_one_char = 2; continue; /* End of POSIX syntax handling */ } /* Backslash may introduce a single character, or it may introduce one of the specials, which just set a flag. The sequence \b is a special case. Inside a class (and only there) it is treated as backspace. We assume that other escapes have more than one character in them, so speculatively set both class_has_8bitchar and class_one_char bigger than one. Unrecognized escapes fall through and are either treated as literal characters (by default), or are faulted if PCRE_EXTRA is set. */ if (c == CHAR_BACKSLASH) { escape = check_escape(&ptr, &ec, errorcodeptr, cd->bracount, options, TRUE); if (*errorcodeptr != 0) goto FAILED; if (escape == 0) c = ec; else if (escape == ESC_b) c = CHAR_BS; /* \b is backspace in a class */ else if (escape == ESC_N) /* \N is not supported in a class */ { *errorcodeptr = ERR71; goto FAILED; } else if (escape == ESC_Q) /* Handle start of quoted string */ { if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) { ptr += 2; /* avoid empty string */ } else inescq = TRUE; continue; } else if (escape == ESC_E) continue; /* Ignore orphan \E */ else { register const pcre_uint8 *cbits = cd->cbits; /* Every class contains at least two < 256 characters. */ class_has_8bitchar++; /* Every class contains at least two characters. */ class_one_char += 2; switch (escape) { #ifdef SUPPORT_UCP case ESC_du: /* These are the values given for \d etc */ case ESC_DU: /* when PCRE_UCP is set. We replace the */ case ESC_wu: /* escape sequence with an appropriate \p */ case ESC_WU: /* or \P to test Unicode properties instead */ case ESC_su: /* of the default ASCII testing. */ case ESC_SU: nestptr = ptr; ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */ class_has_8bitchar--; /* Undo! */ continue; #endif case ESC_d: for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit]; continue; case ESC_D: should_flip_negation = TRUE; for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit]; continue; case ESC_w: for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word]; continue; case ESC_W: should_flip_negation = TRUE; for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word]; continue; /* Perl 5.004 onwards omitted VT from \s, but restored it at Perl 5.18. Before PCRE 8.34, we had to preserve the VT bit if it was previously set by something earlier in the character class. Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so we could just adjust the appropriate bit. From PCRE 8.34 we no longer treat \s and \S specially. */ case ESC_s: for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space]; continue; case ESC_S: should_flip_negation = TRUE; for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space]; continue; /* The rest apply in both UCP and non-UCP cases. */ case ESC_h: (void)add_list_to_class(classbits, &class_uchardata, options, cd, PRIV(hspace_list), NOTACHAR); continue; case ESC_H: (void)add_not_list_to_class(classbits, &class_uchardata, options, cd, PRIV(hspace_list)); continue; case ESC_v: (void)add_list_to_class(classbits, &class_uchardata, options, cd, PRIV(vspace_list), NOTACHAR); continue; case ESC_V: (void)add_not_list_to_class(classbits, &class_uchardata, options, cd, PRIV(vspace_list)); continue; case ESC_p: case ESC_P: #ifdef SUPPORT_UCP { BOOL negated; unsigned int ptype = 0, pdata = 0; if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) goto FAILED; *class_uchardata++ = ((escape == ESC_p) != negated)? XCL_PROP : XCL_NOTPROP; *class_uchardata++ = ptype; *class_uchardata++ = pdata; xclass_has_prop = TRUE; class_has_8bitchar--; /* Undo! */ continue; } #else *errorcodeptr = ERR45; goto FAILED; #endif /* Unrecognized escapes are faulted if PCRE is running in its strict mode. By default, for compatibility with Perl, they are treated as literals. */ default: if ((options & PCRE_EXTRA) != 0) { *errorcodeptr = ERR7; goto FAILED; } class_has_8bitchar--; /* Undo the speculative increase. */ class_one_char -= 2; /* Undo the speculative increase. */ c = *ptr; /* Get the final character and fall through */ break; } } /* Fall through if the escape just defined a single character (c >= 0). This may be greater than 256. */ escape = 0; } /* End of backslash handling */ /* A character may be followed by '-' to form a range. However, Perl does not permit ']' to be the end of the range. A '-' character at the end is treated as a literal. Perl ignores orphaned \E sequences entirely. The code for handling \Q and \E is messy. */ CHECK_RANGE: while (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) { inescq = FALSE; ptr += 2; } oldptr = ptr; /* Remember if \r or \n were explicitly used */ if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; /* Check for range */ if (!inescq && ptr[1] == CHAR_MINUS) { pcre_uint32 d; ptr += 2; while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2; /* If we hit \Q (not followed by \E) at this point, go into escaped mode. */ while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_Q) { ptr += 2; if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) { ptr += 2; continue; } inescq = TRUE; break; } /* Minus (hyphen) at the end of a class is treated as a literal, so put back the pointer and jump to handle the character that preceded it. */ if (*ptr == CHAR_NULL || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET)) { ptr = oldptr; goto CLASS_SINGLE_CHARACTER; } /* Otherwise, we have a potential range; pick up the next character */ #ifdef SUPPORT_UTF if (utf) { /* Braces are required because the */ GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ } else #endif d = *ptr; /* Not UTF-8 mode */ /* The second part of a range can be a single-character escape sequence, but not any of the other escapes. Perl treats a hyphen as a literal in such circumstances. However, in Perl's warning mode, a warning is given, so PCRE now faults it as it is almost certainly a mistake on the user's part. */ if (!inescq) { if (d == CHAR_BACKSLASH) { int descape; descape = check_escape(&ptr, &d, errorcodeptr, cd->bracount, options, TRUE); if (*errorcodeptr != 0) goto FAILED; /* 0 means a character was put into d; \b is backspace; any other special causes an error. */ if (descape != 0) { if (descape == ESC_b) d = CHAR_BS; else { *errorcodeptr = ERR83; goto FAILED; } } } /* A hyphen followed by a POSIX class is treated in the same way. */ else if (d == CHAR_LEFT_SQUARE_BRACKET && (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr)) { *errorcodeptr = ERR83; goto FAILED; } } /* Check that the two values are in the correct order. Optimize one-character ranges. */ if (d < c) { *errorcodeptr = ERR8; goto FAILED; } if (d == c) goto CLASS_SINGLE_CHARACTER; /* A few lines below */ /* We have found a character range, so single character optimizations cannot be done anymore. Any value greater than 1 indicates that there is more than one character. */ class_one_char = 2; /* Remember an explicit \r or \n, and add the range to the class. */ if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; class_has_8bitchar += add_to_class(classbits, &class_uchardata, options, cd, c, d); continue; /* Go get the next char in the class */ } /* Handle a single character - we can get here for a normal non-escape char, or after \ that introduces a single character or for an apparent range that isn't. Only the value 1 matters for class_one_char, so don't increase it if it is already 2 or more ... just in case there's a class with a zillion characters in it. */ CLASS_SINGLE_CHARACTER: if (class_one_char < 2) class_one_char++; /* If xclass_has_prop is false and class_one_char is 1, we have the first single character in the class, and there have been no prior ranges, or XCLASS items generated by escapes. If this is the final character in the class, we can optimize by turning the item into a 1-character OP_CHAR[I] if it's positive, or OP_NOT[I] if it's negative. In the positive case, it can cause firstchar to be set. Otherwise, there can be no first char if this item is first, whatever repeat count may follow. In the case of reqchar, save the previous value for reinstating. */ if (!inescq && #ifdef SUPPORT_UCP !xclass_has_prop && #endif class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { ptr++; zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; if (negate_class) { #ifdef SUPPORT_UCP int d; #endif if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; /* For caseless UTF-8 mode when UCP support is available, check whether this character has more than one other case. If so, generate a special OP_NOTPROP item instead of OP_NOTI. */ #ifdef SUPPORT_UCP if (utf && (options & PCRE_CASELESS) != 0 && (d = UCD_CASESET(c)) != 0) { *code++ = OP_NOTPROP; *code++ = PT_CLIST; *code++ = d; } else #endif /* Char has only one other case, or UCP not available */ { *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) code += PRIV(ord2utf)(c, code); else #endif *code++ = c; } /* We are finished with this character class */ goto END_CLASS; } /* For a single, positive character, get the value into mcbuffer, and then we can handle this with the normal one-character code. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) mclength = PRIV(ord2utf)(c, mcbuffer); else #endif { mcbuffer[0] = c; mclength = 1; } goto ONE_CHAR; } /* End of 1-char optimization */ /* There is more than one character in the class, or an XCLASS item has been generated. Add this character to the class. */ class_has_8bitchar += add_to_class(classbits, &class_uchardata, options, cd, c, c); } /* Loop until ']' reached. This "while" is the end of the "do" far above. If we are at the end of an internal nested string, revert to the outer string. */ while (((c = *(++ptr)) != CHAR_NULL || (nestptr != NULL && (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != CHAR_NULL)) && (c != CHAR_RIGHT_SQUARE_BRACKET || inescq)); /* Check for missing terminating ']' */ if (c == CHAR_NULL) { *errorcodeptr = ERR6; goto FAILED; } /* We will need an XCLASS if data has been placed in class_uchardata. In the second phase this is a sufficient test. However, in the pre-compile phase, class_uchardata gets emptied to prevent workspace overflow, so it only if the very last character in the class needs XCLASS will it contain anything at this point. For this reason, xclass gets set TRUE above when uchar_classdata is emptied, and that's why this code is the way it is here instead of just doing a test on class_uchardata below. */ #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 if (class_uchardata > class_uchardata_base) xclass = TRUE; #endif /* If this is the first thing in the branch, there can be no first char setting, whatever the repeat count. Any reqchar setting must remain unchanged after any kind of repeat. */ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; /* If there are characters with values > 255, we have to compile an extended class, with its own opcode, unless there was a negated special such as \S in the class, and PCRE_UCP is not set, because in that case all characters > 255 are in the class, so any that were explicitly given as well can be ignored. If (when there are explicit characters > 255 that must be listed) there are no characters < 256, we can omit the bitmap in the actual compiled code. */ #ifdef SUPPORT_UTF if (xclass && (xclass_has_prop || !should_flip_negation || (options & PCRE_UCP) != 0)) #elif !defined COMPILE_PCRE8 if (xclass && (xclass_has_prop || !should_flip_negation)) #endif #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 { /* For non-UCP wide characters, in a non-negative class containing \S or similar (should_flip_negation is set), all characters greater than 255 must be in the class. */ if ( #if defined COMPILE_PCRE8 utf && #endif should_flip_negation && !negate_class && (options & PCRE_UCP) == 0) { *class_uchardata++ = XCL_RANGE; if (utf) /* Will always be utf in the 8-bit library */ { class_uchardata += PRIV(ord2utf)(0x100, class_uchardata); class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); } else /* Can only happen for the 16-bit & 32-bit libraries */ { #if defined COMPILE_PCRE16 *class_uchardata++ = 0x100; *class_uchardata++ = 0xffffu; #elif defined COMPILE_PCRE32 *class_uchardata++ = 0x100; *class_uchardata++ = 0xffffffffu; #endif } } *class_uchardata++ = XCL_END; /* Marks the end of extra data */ *code++ = OP_XCLASS; code += LINK_SIZE; *code = negate_class? XCL_NOT:0; if (xclass_has_prop) *code |= XCL_HASPROP; /* If the map is required, move up the extra data to make room for it; otherwise just move the code pointer to the end of the extra data. */ if (class_has_8bitchar > 0) { *code++ |= XCL_MAP; memmove(code + (32 / sizeof(pcre_uchar)), code, IN_UCHARS(class_uchardata - code)); if (negate_class && !xclass_has_prop) for (c = 0; c < 32; c++) classbits[c] = ~classbits[c]; memcpy(code, classbits, 32); code = class_uchardata + (32 / sizeof(pcre_uchar)); } else code = class_uchardata; /* Now fill in the complete length of the item */ PUT(previous, 1, (int)(code - previous)); break; /* End of class handling */ } /* Even though any XCLASS list is now discarded, we must allow for its memory. */ if (lengthptr != NULL) *lengthptr += (int)(class_uchardata - class_uchardata_base); #endif /* If there are no characters > 255, or they are all to be included or excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the whole class was negated and whether there were negative specials such as \S (non-UCP) in the class. Then copy the 32-byte map into the code vector, negating it if necessary. */ *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS; if (lengthptr == NULL) /* Save time in the pre-compile phase */ { if (negate_class) for (c = 0; c < 32; c++) classbits[c] = ~classbits[c]; memcpy(code, classbits, 32); } code += 32 / sizeof(pcre_uchar); END_CLASS: break; /* ===================================================================*/ /* Various kinds of repeat; '{' is not necessarily a quantifier, but this has been tested above. */ case CHAR_LEFT_CURLY_BRACKET: if (!is_quantifier) goto NORMAL_CHAR; ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr); if (*errorcodeptr != 0) goto FAILED; goto REPEAT; case CHAR_ASTERISK: repeat_min = 0; repeat_max = -1; goto REPEAT; case CHAR_PLUS: repeat_min = 1; repeat_max = -1; goto REPEAT; case CHAR_QUESTION_MARK: repeat_min = 0; repeat_max = 1; REPEAT: if (previous == NULL) { *errorcodeptr = ERR9; goto FAILED; } if (repeat_min == 0) { firstchar = zerofirstchar; /* Adjust for zero repeat */ firstcharflags = zerofirstcharflags; reqchar = zeroreqchar; /* Ditto */ reqcharflags = zeroreqcharflags; } /* Remember whether this is a variable length repeat */ reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; op_type = 0; /* Default single-char op codes */ possessive_quantifier = FALSE; /* Default not possessive quantifier */ /* Save start of previous item, in case we have to move it up in order to insert something before it. */ tempcode = previous; /* Before checking for a possessive quantifier, we must skip over whitespace and comments in extended mode because Perl allows white space at this point. */ if ((options & PCRE_EXTENDED) != 0) { const pcre_uchar *p = ptr + 1; for (;;) { while (MAX_255(*p) && (cd->ctypes[*p] & ctype_space) != 0) p++; if (*p != CHAR_NUMBER_SIGN) break; p++; while (*p != CHAR_NULL) { if (IS_NEWLINE(p)) /* For non-fixed-length newline cases, */ { /* IS_NEWLINE sets cd->nllen. */ p += cd->nllen; break; } p++; #ifdef SUPPORT_UTF if (utf) FORWARDCHAR(p); #endif } /* Loop for comment characters */ } /* Loop for multiple comments */ ptr = p - 1; /* Character before the next significant one. */ } /* We also need to skip over (?# comments, which are not dependent on extended mode. */ if (ptr[1] == CHAR_LEFT_PARENTHESIS && ptr[2] == CHAR_QUESTION_MARK && ptr[3] == CHAR_NUMBER_SIGN) { ptr += 4; while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; if (*ptr == CHAR_NULL) { *errorcodeptr = ERR18; goto FAILED; } } /* If the next character is '+', we have a possessive quantifier. This implies greediness, whatever the setting of the PCRE_UNGREEDY option. If the next character is '?' this is a minimizing repeat, by default, but if PCRE_UNGREEDY is set, it works the other way round. We change the repeat type to the non-default. */ if (ptr[1] == CHAR_PLUS) { repeat_type = 0; /* Force greedy */ possessive_quantifier = TRUE; ptr++; } else if (ptr[1] == CHAR_QUESTION_MARK) { repeat_type = greedy_non_default; ptr++; } else repeat_type = greedy_default; /* If previous was a recursion call, wrap it in atomic brackets so that previous becomes the atomic group. All recursions were so wrapped in the past, but it no longer happens for non-repeated recursions. In fact, the repeated ones could be re-implemented independently so as not to need this, but for the moment we rely on the code for repeating groups. */ if (*previous == OP_RECURSE) { memmove(previous + 1 + LINK_SIZE, previous, IN_UCHARS(1 + LINK_SIZE)); *previous = OP_ONCE; PUT(previous, 1, 2 + 2*LINK_SIZE); previous[2 + 2*LINK_SIZE] = OP_KET; PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE); code += 2 + 2 * LINK_SIZE; length_prevgroup = 3 + 3*LINK_SIZE; /* When actually compiling, we need to check whether this was a forward reference, and if so, adjust the offset. */ if (lengthptr == NULL && cd->hwm >= cd->start_workspace + LINK_SIZE) { int offset = GET(cd->hwm, -LINK_SIZE); if (offset == previous + 1 - cd->start_code) PUT(cd->hwm, -LINK_SIZE, offset + 1 + LINK_SIZE); } } /* Now handle repetition for the different types of item. */ /* If previous was a character or negated character match, abolish the item and generate a repeat item instead. If a char item has a minimum of more than one, ensure that it is set in reqchar - it might not be if a sequence such as x{3} is the first thing in a branch because the x will have gone into firstchar instead. */ if (*previous == OP_CHAR || *previous == OP_CHARI || *previous == OP_NOT || *previous == OP_NOTI) { switch (*previous) { default: /* Make compiler happy. */ case OP_CHAR: op_type = OP_STAR - OP_STAR; break; case OP_CHARI: op_type = OP_STARI - OP_STAR; break; case OP_NOT: op_type = OP_NOTSTAR - OP_STAR; break; case OP_NOTI: op_type = OP_NOTSTARI - OP_STAR; break; } /* Deal with UTF characters that take up more than one character. It's easier to write this out separately than try to macrify it. Use c to hold the length of the character in bytes, plus UTF_LENGTH to flag that it's a length rather than a small character. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && NOT_FIRSTCHAR(code[-1])) { pcre_uchar *lastchar = code - 1; BACKCHAR(lastchar); c = (int)(code - lastchar); /* Length of UTF-8 character */ memcpy(utf_chars, lastchar, IN_UCHARS(c)); /* Save the char */ c |= UTF_LENGTH; /* Flag c as a length */ } else #endif /* SUPPORT_UTF */ /* Handle the case of a single charater - either with no UTF support, or with UTF disabled, or for a single character UTF character. */ { c = code[-1]; if (*previous <= OP_CHARI && repeat_min > 1) { reqchar = c; reqcharflags = req_caseopt | cd->req_varyopt; } } goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ } /* If previous was a character type match (\d or similar), abolish it and create a suitable repeat item. The code is shared with single-character repeats by setting op_type to add a suitable offset into repeat_type. Note the the Unicode property types will be present only when SUPPORT_UCP is defined, but we don't wrap the little bits of code here because it just makes it horribly messy. */ else if (*previous < OP_EODN) { pcre_uchar *oldcode; int prop_type, prop_value; op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ c = *previous; OUTPUT_SINGLE_REPEAT: if (*previous == OP_PROP || *previous == OP_NOTPROP) { prop_type = previous[1]; prop_value = previous[2]; } else prop_type = prop_value = -1; oldcode = code; code = previous; /* Usually overwrite previous item */ /* If the maximum is zero then the minimum must also be zero; Perl allows this case, so we do too - by simply omitting the item altogether. */ if (repeat_max == 0) goto END_REPEAT; /* Combine the op_type with the repeat_type */ repeat_type += op_type; /* A minimum of zero is handled either as the special case * or ?, or as an UPTO, with the maximum given. */ if (repeat_min == 0) { if (repeat_max == -1) *code++ = OP_STAR + repeat_type; else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; else { *code++ = OP_UPTO + repeat_type; PUT2INC(code, 0, repeat_max); } } /* A repeat minimum of 1 is optimized into some special cases. If the maximum is unlimited, we use OP_PLUS. Otherwise, the original item is left in place and, if the maximum is greater than 1, we use OP_UPTO with one less than the maximum. */ else if (repeat_min == 1) { if (repeat_max == -1) *code++ = OP_PLUS + repeat_type; else { code = oldcode; /* leave previous item in place */ if (repeat_max == 1) goto END_REPEAT; *code++ = OP_UPTO + repeat_type; PUT2INC(code, 0, repeat_max - 1); } } /* The case {n,n} is just an EXACT, while the general case {n,m} is handled as an EXACT followed by an UPTO. */ else { *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ PUT2INC(code, 0, repeat_min); /* If the maximum is unlimited, insert an OP_STAR. Before doing so, we have to insert the character for the previous code. For a repeated Unicode property match, there are two extra bytes that define the required property. In UTF-8 mode, long characters have their length in c, with the UTF_LENGTH bit as a flag. */ if (repeat_max < 0) { #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && (c & UTF_LENGTH) != 0) { memcpy(code, utf_chars, IN_UCHARS(c & 7)); code += c & 7; } else #endif { *code++ = c; if (prop_type >= 0) { *code++ = prop_type; *code++ = prop_value; } } *code++ = OP_STAR + repeat_type; } /* Else insert an UPTO if the max is greater than the min, again preceded by the character, for the previously inserted code. If the UPTO is just for 1 instance, we can use QUERY instead. */ else if (repeat_max != repeat_min) { #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && (c & UTF_LENGTH) != 0) { memcpy(code, utf_chars, IN_UCHARS(c & 7)); code += c & 7; } else #endif *code++ = c; if (prop_type >= 0) { *code++ = prop_type; *code++ = prop_value; } repeat_max -= repeat_min; if (repeat_max == 1) { *code++ = OP_QUERY + repeat_type; } else { *code++ = OP_UPTO + repeat_type; PUT2INC(code, 0, repeat_max); } } } /* The character or character type itself comes last in all cases. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && (c & UTF_LENGTH) != 0) { memcpy(code, utf_chars, IN_UCHARS(c & 7)); code += c & 7; } else #endif *code++ = c; /* For a repeated Unicode property match, there are two extra bytes that define the required property. */ #ifdef SUPPORT_UCP if (prop_type >= 0) { *code++ = prop_type; *code++ = prop_value; } #endif } /* If previous was a character class or a back reference, we put the repeat stuff after it, but just skip the item if the repeat was {0,0}. */ else if (*previous == OP_CLASS || *previous == OP_NCLASS || #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 *previous == OP_XCLASS || #endif *previous == OP_REF || *previous == OP_REFI || *previous == OP_DNREF || *previous == OP_DNREFI) { if (repeat_max == 0) { code = previous; goto END_REPEAT; } if (repeat_min == 0 && repeat_max == -1) *code++ = OP_CRSTAR + repeat_type; else if (repeat_min == 1 && repeat_max == -1) *code++ = OP_CRPLUS + repeat_type; else if (repeat_min == 0 && repeat_max == 1) *code++ = OP_CRQUERY + repeat_type; else { *code++ = OP_CRRANGE + repeat_type; PUT2INC(code, 0, repeat_min); if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ PUT2INC(code, 0, repeat_max); } } /* If previous was a bracket group, we may have to replicate it in certain cases. Note that at this point we can encounter only the "basic" bracket opcodes such as BRA and CBRA, as this is the place where they get converted into the more special varieties such as BRAPOS and SBRA. A test for >= OP_ASSERT and <= OP_COND includes ASSERT, ASSERT_NOT, ASSERTBACK, ASSERTBACK_NOT, ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND. Originally, PCRE did not allow repetition of assertions, but now it does, for Perl compatibility. */ else if (*previous >= OP_ASSERT && *previous <= OP_COND) { register int i; int len = (int)(code - previous); size_t base_hwm_offset = item_hwm_offset; pcre_uchar *bralink = NULL; pcre_uchar *brazeroptr = NULL; /* Repeating a DEFINE group is pointless, but Perl allows the syntax, so we just ignore the repeat. */ if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF) goto END_REPEAT; /* There is no sense in actually repeating assertions. The only potential use of repetition is in cases when the assertion is optional. Therefore, if the minimum is greater than zero, just ignore the repeat. If the maximum is not zero or one, set it to 1. */ if (*previous < OP_ONCE) /* Assertion */ { if (repeat_min > 0) goto END_REPEAT; if (repeat_max < 0 || repeat_max > 1) repeat_max = 1; } /* The case of a zero minimum is special because of the need to stick OP_BRAZERO in front of it, and because the group appears once in the data, whereas in other cases it appears the minimum number of times. For this reason, it is simplest to treat this case separately, as otherwise the code gets far too messy. There are several special subcases when the minimum is zero. */ if (repeat_min == 0) { /* If the maximum is also zero, we used to just omit the group from the output altogether, like this: ** if (repeat_max == 0) ** { ** code = previous; ** goto END_REPEAT; ** } However, that fails when a group or a subgroup within it is referenced as a subroutine from elsewhere in the pattern, so now we stick in OP_SKIPZERO in front of it so that it is skipped on execution. As we don't have a list of which groups are referenced, we cannot do this selectively. If the maximum is 1 or unlimited, we just have to stick in the BRAZERO and do no more at this point. However, we do need to adjust any OP_RECURSE calls inside the group that refer to the group itself or any internal or forward referenced group, because the offset is from the start of the whole regex. Temporarily terminate the pattern while doing this. */ if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ { *code = OP_END; adjust_recurse(previous, 1, utf, cd, item_hwm_offset); memmove(previous + 1, previous, IN_UCHARS(len)); code++; if (repeat_max == 0) { *previous++ = OP_SKIPZERO; goto END_REPEAT; } brazeroptr = previous; /* Save for possessive optimizing */ *previous++ = OP_BRAZERO + repeat_type; } /* If the maximum is greater than 1 and limited, we have to replicate in a nested fashion, sticking OP_BRAZERO before each set of brackets. The first one has to be handled carefully because it's the original copy, which has to be moved up. The remainder can be handled by code that is common with the non-zero minimum case below. We have to adjust the value or repeat_max, since one less copy is required. Once again, we may have to adjust any OP_RECURSE calls inside the group. */ else { int offset; *code = OP_END; adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); code += 2 + LINK_SIZE; *previous++ = OP_BRAZERO + repeat_type; *previous++ = OP_BRA; /* We chain together the bracket offset fields that have to be filled in later when the ends of the brackets are reached. */ offset = (bralink == NULL)? 0 : (int)(previous - bralink); bralink = previous; PUTINC(previous, 0, offset); } repeat_max--; } /* If the minimum is greater than zero, replicate the group as many times as necessary, and adjust the maximum to the number of subsequent copies that we need. If we set a first char from the group, and didn't set a required char, copy the latter from the former. If there are any forward reference subroutine calls in the group, there will be entries on the workspace list; replicate these with an appropriate increment. */ else { if (repeat_min > 1) { /* In the pre-compile phase, we don't actually do the replication. We just adjust the length as if we had. Do some paranoid checks for potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit integer type when available, otherwise double. */ if (lengthptr != NULL) { int delta = (repeat_min - 1)*length_prevgroup; if ((INT64_OR_DOUBLE)(repeat_min - 1)* (INT64_OR_DOUBLE)length_prevgroup > (INT64_OR_DOUBLE)INT_MAX || OFLOW_MAX - *lengthptr < delta) { *errorcodeptr = ERR20; goto FAILED; } *lengthptr += delta; } /* This is compiling for real. If there is a set first byte for the group, and we have not yet set a "required byte", set it. Make sure there is enough workspace for copying forward references before doing the copy. */ else { if (groupsetfirstchar && reqcharflags < 0) { reqchar = firstchar; reqcharflags = firstcharflags; } for (i = 1; i < repeat_min; i++) { pcre_uchar *hc; size_t this_hwm_offset = cd->hwm - cd->start_workspace; memcpy(code, previous, IN_UCHARS(len)); while (cd->hwm > cd->start_workspace + cd->workspace_size - WORK_SIZE_SAFETY_MARGIN - (this_hwm_offset - base_hwm_offset)) { *errorcodeptr = expand_workspace(cd); if (*errorcodeptr != 0) goto FAILED; } for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset; hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset; hc += LINK_SIZE) { PUT(cd->hwm, 0, GET(hc, 0) + len); cd->hwm += LINK_SIZE; } base_hwm_offset = this_hwm_offset; code += len; } } } if (repeat_max > 0) repeat_max -= repeat_min; } /* This code is common to both the zero and non-zero minimum cases. If the maximum is limited, it replicates the group in a nested fashion, remembering the bracket starts on a stack. In the case of a zero minimum, the first one was set up above. In all cases the repeat_max now specifies the number of additional copies needed. Again, we must remember to replicate entries on the forward reference list. */ if (repeat_max >= 0) { /* In the pre-compile phase, we don't actually do the replication. We just adjust the length as if we had. For each repetition we must add 1 to the length for BRAZERO and for all but the last repetition we must add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type is a 64-bit integer type when available, otherwise double. */ if (lengthptr != NULL && repeat_max > 0) { int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) - 2 - 2*LINK_SIZE; /* Last one doesn't nest */ if ((INT64_OR_DOUBLE)repeat_max * (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE) > (INT64_OR_DOUBLE)INT_MAX || OFLOW_MAX - *lengthptr < delta) { *errorcodeptr = ERR20; goto FAILED; } *lengthptr += delta; } /* This is compiling for real */ else for (i = repeat_max - 1; i >= 0; i--) { pcre_uchar *hc; size_t this_hwm_offset = cd->hwm - cd->start_workspace; *code++ = OP_BRAZERO + repeat_type; /* All but the final copy start a new nesting, maintaining the chain of brackets outstanding. */ if (i != 0) { int offset; *code++ = OP_BRA; offset = (bralink == NULL)? 0 : (int)(code - bralink); bralink = code; PUTINC(code, 0, offset); } memcpy(code, previous, IN_UCHARS(len)); /* Ensure there is enough workspace for forward references before copying them. */ while (cd->hwm > cd->start_workspace + cd->workspace_size - WORK_SIZE_SAFETY_MARGIN - (this_hwm_offset - base_hwm_offset)) { *errorcodeptr = expand_workspace(cd); if (*errorcodeptr != 0) goto FAILED; } for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset; hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset; hc += LINK_SIZE) { PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1)); cd->hwm += LINK_SIZE; } base_hwm_offset = this_hwm_offset; code += len; } /* Now chain through the pending brackets, and fill in their length fields (which are holding the chain links pro tem). */ while (bralink != NULL) { int oldlinkoffset; int offset = (int)(code - bralink + 1); pcre_uchar *bra = code - offset; oldlinkoffset = GET(bra, 1); bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; *code++ = OP_KET; PUTINC(code, 0, offset); PUT(bra, 1, offset); } } /* If the maximum is unlimited, set a repeater in the final copy. For ONCE brackets, that's all we need to do. However, possessively repeated ONCE brackets can be converted into non-capturing brackets, as the behaviour of (?:xx)++ is the same as (?>xx)++ and this saves having to deal with possessive ONCEs specially. Otherwise, when we are doing the actual compile phase, check to see whether this group is one that could match an empty string. If so, convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so that runtime checking can be done. [This check is also applied to ONCE groups at runtime, but in a different way.] Then, if the quantifier was possessive and the bracket is not a conditional, we convert the BRA code to the POS form, and the KET code to KETRPOS. (It turns out to be convenient at runtime to detect this kind of subpattern at both the start and at the end.) The use of special opcodes makes it possible to reduce greatly the stack usage in pcre_exec(). If the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO. Then, if the minimum number of matches is 1 or 0, cancel the possessive flag so that the default action below, of wrapping everything inside atomic brackets, does not happen. When the minimum is greater than 1, there will be earlier copies of the group, and so we still have to wrap the whole thing. */ else { pcre_uchar *ketcode = code - 1 - LINK_SIZE; pcre_uchar *bracode = ketcode - GET(ketcode, 1); /* Convert possessive ONCE brackets to non-capturing */ if ((*bracode == OP_ONCE || *bracode == OP_ONCE_NC) && possessive_quantifier) *bracode = OP_BRA; /* For non-possessive ONCE brackets, all we need to do is to set the KET. */ if (*bracode == OP_ONCE || *bracode == OP_ONCE_NC) *ketcode = OP_KETRMAX + repeat_type; /* Handle non-ONCE brackets and possessive ONCEs (which have been converted to non-capturing above). */ else { /* In the compile phase, check for empty string matching. */ if (lengthptr == NULL) { pcre_uchar *scode = bracode; do { if (could_be_empty_branch(scode, ketcode, utf, cd, NULL)) { *bracode += OP_SBRA - OP_BRA; break; } scode += GET(scode, 1); } while (*scode == OP_ALT); } /* A conditional group with only one branch has an implicit empty alternative branch. */ if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT) *bracode = OP_SCOND; /* Handle possessive quantifiers. */ if (possessive_quantifier) { /* For COND brackets, we wrap the whole thing in a possessively repeated non-capturing bracket, because we have not invented POS versions of the COND opcodes. Because we are moving code along, we must ensure that any pending recursive references are updated. */ if (*bracode == OP_COND || *bracode == OP_SCOND) { int nlen = (int)(code - bracode); *code = OP_END; adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); code += 1 + LINK_SIZE; nlen += 1 + LINK_SIZE; *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS; *code++ = OP_KETRPOS; PUTINC(code, 0, nlen); PUT(bracode, 1, nlen); } /* For non-COND brackets, we modify the BRA code and use KETRPOS. */ else { *bracode += 1; /* Switch to xxxPOS opcodes */ *ketcode = OP_KETRPOS; } /* If the minimum is zero, mark it as possessive, then unset the possessive flag when the minimum is 0 or 1. */ if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO; if (repeat_min < 2) possessive_quantifier = FALSE; } /* Non-possessive quantifier */ else *ketcode = OP_KETRMAX + repeat_type; } } } /* If previous is OP_FAIL, it was generated by an empty class [] in JavaScript mode. The other ways in which OP_FAIL can be generated, that is by (*FAIL) or (?!) set previous to NULL, which gives a "nothing to repeat" error above. We can just ignore the repeat in JS case. */ else if (*previous == OP_FAIL) goto END_REPEAT; /* Else there's some kind of shambles */ else { *errorcodeptr = ERR11; goto FAILED; } /* If the character following a repeat is '+', possessive_quantifier is TRUE. For some opcodes, there are special alternative opcodes for this case. For anything else, we wrap the entire repeated item inside OP_ONCE brackets. Logically, the '+' notation is just syntactic sugar, taken from Sun's Java package, but the special opcodes can optimize it. Some (but not all) possessively repeated subpatterns have already been completely handled in the code just above. For them, possessive_quantifier is always FALSE at this stage. Note that the repeated item starts at tempcode, not at previous, which might be the first part of a string whose (former) last char we repeated. */ if (possessive_quantifier) { int len; /* Possessifying an EXACT quantifier has no effect, so we can ignore it. However, QUERY, STAR, or UPTO may follow (for quantifiers such as {5,6}, {5,}, or {5,10}). We skip over an EXACT item; if the length of what remains is greater than zero, there's a further opcode that can be handled. If not, do nothing, leaving the EXACT alone. */ switch(*tempcode) { case OP_TYPEEXACT: tempcode += PRIV(OP_lengths)[*tempcode] + ((tempcode[1 + IMM2_SIZE] == OP_PROP || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0); break; /* CHAR opcodes are used for exacts whose count is 1. */ case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_EXACT: case OP_EXACTI: case OP_NOTEXACT: case OP_NOTEXACTI: tempcode += PRIV(OP_lengths)[*tempcode]; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(tempcode[-1])) tempcode += GET_EXTRALEN(tempcode[-1]); #endif break; /* For the class opcodes, the repeat operator appears at the end; adjust tempcode to point to it. */ case OP_CLASS: case OP_NCLASS: tempcode += 1 + 32/sizeof(pcre_uchar); break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: tempcode += GET(tempcode, 1); break; #endif } /* If tempcode is equal to code (which points to the end of the repeated item), it means we have skipped an EXACT item but there is no following QUERY, STAR, or UPTO; the value of len will be 0, and we do nothing. In all other cases, tempcode will be pointing to the repeat opcode, and will be less than code, so the value of len will be greater than 0. */ len = (int)(code - tempcode); if (len > 0) { unsigned int repcode = *tempcode; /* There is a table for possessifying opcodes, all of which are less than OP_CALLOUT. A zero entry means there is no possessified version. */ if (repcode < OP_CALLOUT && opcode_possessify[repcode] > 0) *tempcode = opcode_possessify[repcode]; /* For opcode without a special possessified version, wrap the item in ONCE brackets. Because we are moving code along, we must ensure that any pending recursive references are updated. */ else { *code = OP_END; adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; tempcode[0] = OP_ONCE; *code++ = OP_KET; PUTINC(code, 0, len); PUT(tempcode, 1, len); } } #ifdef NEVER if (len > 0) switch (*tempcode) { case OP_STAR: *tempcode = OP_POSSTAR; break; case OP_PLUS: *tempcode = OP_POSPLUS; break; case OP_QUERY: *tempcode = OP_POSQUERY; break; case OP_UPTO: *tempcode = OP_POSUPTO; break; case OP_STARI: *tempcode = OP_POSSTARI; break; case OP_PLUSI: *tempcode = OP_POSPLUSI; break; case OP_QUERYI: *tempcode = OP_POSQUERYI; break; case OP_UPTOI: *tempcode = OP_POSUPTOI; break; case OP_NOTSTAR: *tempcode = OP_NOTPOSSTAR; break; case OP_NOTPLUS: *tempcode = OP_NOTPOSPLUS; break; case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break; case OP_NOTUPTO: *tempcode = OP_NOTPOSUPTO; break; case OP_NOTSTARI: *tempcode = OP_NOTPOSSTARI; break; case OP_NOTPLUSI: *tempcode = OP_NOTPOSPLUSI; break; case OP_NOTQUERYI: *tempcode = OP_NOTPOSQUERYI; break; case OP_NOTUPTOI: *tempcode = OP_NOTPOSUPTOI; break; case OP_TYPESTAR: *tempcode = OP_TYPEPOSSTAR; break; case OP_TYPEPLUS: *tempcode = OP_TYPEPOSPLUS; break; case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break; case OP_TYPEUPTO: *tempcode = OP_TYPEPOSUPTO; break; case OP_CRSTAR: *tempcode = OP_CRPOSSTAR; break; case OP_CRPLUS: *tempcode = OP_CRPOSPLUS; break; case OP_CRQUERY: *tempcode = OP_CRPOSQUERY; break; case OP_CRRANGE: *tempcode = OP_CRPOSRANGE; break; /* Because we are moving code along, we must ensure that any pending recursive references are updated. */ default: *code = OP_END; adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; tempcode[0] = OP_ONCE; *code++ = OP_KET; PUTINC(code, 0, len); PUT(tempcode, 1, len); break; } #endif } /* In all case we no longer have a previous item. We also set the "follows varying string" flag for subsequently encountered reqchars if it isn't already set and we have just passed a varying length item. */ END_REPEAT: previous = NULL; cd->req_varyopt |= reqvary; break; /* ===================================================================*/ /* Start of nested parenthesized sub-expression, or comment or lookahead or lookbehind or option setting or condition or all the other extended parenthesis forms. */ case CHAR_LEFT_PARENTHESIS: ptr++; /* Now deal with various "verbs" that can be introduced by '*'. */ if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':' || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0)))) { int i, namelen; int arglen = 0; const char *vn = verbnames; const pcre_uchar *name = ptr + 1; const pcre_uchar *arg = NULL; previous = NULL; ptr++; while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; namelen = (int)(ptr - name); /* It appears that Perl allows any characters whatsoever, other than a closing parenthesis, to appear in arguments, so we no longer insist on letters, digits, and underscores. */ if (*ptr == CHAR_COLON) { arg = ++ptr; while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; arglen = (int)(ptr - arg); if ((unsigned int)arglen > MAX_MARK) { *errorcodeptr = ERR75; goto FAILED; } } if (*ptr != CHAR_RIGHT_PARENTHESIS) { *errorcodeptr = ERR60; goto FAILED; } /* Scan the table of verb names */ for (i = 0; i < verbcount; i++) { if (namelen == verbs[i].len && STRNCMP_UC_C8(name, vn, namelen) == 0) { int setverb; /* Check for open captures before ACCEPT and convert it to ASSERT_ACCEPT if in an assertion. */ if (verbs[i].op == OP_ACCEPT) { open_capitem *oc; if (arglen != 0) { *errorcodeptr = ERR59; goto FAILED; } cd->had_accept = TRUE; for (oc = cd->open_caps; oc != NULL; oc = oc->next) { if (lengthptr != NULL) { #ifdef COMPILE_PCRE8 *lengthptr += 1 + IMM2_SIZE; #elif defined COMPILE_PCRE16 *lengthptr += 2 + IMM2_SIZE; #elif defined COMPILE_PCRE32 *lengthptr += 4 + IMM2_SIZE; #endif } else { *code++ = OP_CLOSE; PUT2INC(code, 0, oc->number); } } setverb = *code++ = (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT; /* Do not set firstchar after *ACCEPT */ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; } /* Handle other cases with/without an argument */ else if (arglen == 0) { if (verbs[i].op < 0) /* Argument is mandatory */ { *errorcodeptr = ERR66; goto FAILED; } setverb = *code++ = verbs[i].op; } else { if (verbs[i].op_arg < 0) /* Argument is forbidden */ { *errorcodeptr = ERR59; goto FAILED; } setverb = *code++ = verbs[i].op_arg; if (lengthptr != NULL) /* In pass 1 just add in the length */ { /* to avoid potential workspace */ *lengthptr += arglen; /* overflow. */ *code++ = 0; } else { *code++ = arglen; memcpy(code, arg, IN_UCHARS(arglen)); code += arglen; } *code++ = 0; } switch (setverb) { case OP_THEN: case OP_THEN_ARG: cd->external_flags |= PCRE_HASTHEN; break; case OP_PRUNE: case OP_PRUNE_ARG: case OP_SKIP: case OP_SKIP_ARG: cd->had_pruneorskip = TRUE; break; } break; /* Found verb, exit loop */ } vn += verbs[i].len + 1; } if (i < verbcount) continue; /* Successfully handled a verb */ *errorcodeptr = ERR60; /* Verb not recognized */ goto FAILED; } /* Initialize for "real" parentheses */ newoptions = options; skipbytes = 0; bravalue = OP_CBRA; item_hwm_offset = cd->hwm - cd->start_workspace; reset_bracount = FALSE; /* Deal with the extended parentheses; all are introduced by '?', and the appearance of any of them means that this is not a capturing group. */ if (*ptr == CHAR_QUESTION_MARK) { int i, set, unset, namelen; int *optset; const pcre_uchar *name; pcre_uchar *slot; switch (*(++ptr)) { /* ------------------------------------------------------------ */ case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ reset_bracount = TRUE; cd->dupgroups = TRUE; /* Record (?| encountered */ /* Fall through */ /* ------------------------------------------------------------ */ case CHAR_COLON: /* Non-capturing bracket */ bravalue = OP_BRA; ptr++; break; /* ------------------------------------------------------------ */ case CHAR_LEFT_PARENTHESIS: bravalue = OP_COND; /* Conditional group */ tempptr = ptr; /* A condition can be an assertion, a number (referring to a numbered group's having been set), a name (referring to a named group), or 'R', referring to recursion. R and R&name are also permitted for recursion tests. There are ways of testing a named group: (?(name)) is used by Python; Perl 5.10 onwards uses (?() or (?('name')). There is one unfortunate ambiguity, caused by history. 'R' can be the recursive thing or the name 'R' (and similarly for 'R' followed by digits). We look for a name first; if not found, we try the other case. For compatibility with auto-callouts, we allow a callout to be specified before a condition that is an assertion. First, check for the syntax of a callout; if found, adjust the temporary pointer that is used to check for an assertion condition. That's all that is needed! */ if (ptr[1] == CHAR_QUESTION_MARK && ptr[2] == CHAR_C) { for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break; if (ptr[i] == CHAR_RIGHT_PARENTHESIS) tempptr += i + 1; /* tempptr should now be pointing to the opening parenthesis of the assertion condition. */ if (*tempptr != CHAR_LEFT_PARENTHESIS) { *errorcodeptr = ERR28; goto FAILED; } } /* For conditions that are assertions, check the syntax, and then exit the switch. This will take control down to where bracketed groups, including assertions, are processed. */ if (tempptr[1] == CHAR_QUESTION_MARK && (tempptr[2] == CHAR_EQUALS_SIGN || tempptr[2] == CHAR_EXCLAMATION_MARK || (tempptr[2] == CHAR_LESS_THAN_SIGN && (tempptr[3] == CHAR_EQUALS_SIGN || tempptr[3] == CHAR_EXCLAMATION_MARK)))) { cd->iscondassert = TRUE; break; } /* Other conditions use OP_CREF/OP_DNCREF/OP_RREF/OP_DNRREF, and all need to skip at least 1+IMM2_SIZE bytes at the start of the group. */ code[1+LINK_SIZE] = OP_CREF; skipbytes = 1+IMM2_SIZE; refsign = -1; /* => not a number */ namelen = -1; /* => not a name; must set to avoid warning */ name = NULL; /* Always set to avoid warning */ recno = 0; /* Always set to avoid warning */ /* Check for a test for recursion in a named group. */ ptr++; if (*ptr == CHAR_R && ptr[1] == CHAR_AMPERSAND) { terminator = -1; ptr += 2; code[1+LINK_SIZE] = OP_RREF; /* Change the type of test */ } /* Check for a test for a named group's having been set, using the Perl syntax (?() or (?('name'), and also allow for the original PCRE syntax of (?(name) or for (?(+n), (?(-n), and just (?(n). */ else if (*ptr == CHAR_LESS_THAN_SIGN) { terminator = CHAR_GREATER_THAN_SIGN; ptr++; } else if (*ptr == CHAR_APOSTROPHE) { terminator = CHAR_APOSTROPHE; ptr++; } else { terminator = CHAR_NULL; if (*ptr == CHAR_MINUS || *ptr == CHAR_PLUS) refsign = *ptr++; else if (IS_DIGIT(*ptr)) refsign = 0; } /* Handle a number */ if (refsign >= 0) { while (IS_DIGIT(*ptr)) { if (recno > INT_MAX / 10 - 1) /* Integer overflow */ { while (IS_DIGIT(*ptr)) ptr++; *errorcodeptr = ERR61; goto FAILED; } recno = recno * 10 + (int)(*ptr - CHAR_0); ptr++; } } /* Otherwise we expect to read a name; anything else is an error. When a name is one of a number of duplicates, a different opcode is used and it needs more memory. Unfortunately we cannot tell whether a name is a duplicate in the first pass, so we have to allow for more memory. */ else { if (IS_DIGIT(*ptr)) { *errorcodeptr = ERR84; goto FAILED; } if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_word) == 0) { *errorcodeptr = ERR28; /* Assertion expected */ goto FAILED; } name = ptr++; while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) { ptr++; } namelen = (int)(ptr - name); if (lengthptr != NULL) skipbytes += IMM2_SIZE; } /* Check the terminator */ if ((terminator > 0 && *ptr++ != (pcre_uchar)terminator) || *ptr++ != CHAR_RIGHT_PARENTHESIS) { ptr--; /* Error offset */ *errorcodeptr = ERR26; /* Malformed number or name */ goto FAILED; } /* Do no further checking in the pre-compile phase. */ if (lengthptr != NULL) break; /* In the real compile we do the work of looking for the actual reference. If refsign is not negative, it means we have a number in recno. */ if (refsign >= 0) { if (recno <= 0) { *errorcodeptr = ERR35; goto FAILED; } if (refsign != 0) recno = (refsign == CHAR_MINUS)? cd->bracount - recno + 1 : recno + cd->bracount; if (recno <= 0 || recno > cd->final_bracount) { *errorcodeptr = ERR15; goto FAILED; } PUT2(code, 2+LINK_SIZE, recno); if (recno > cd->top_backref) cd->top_backref = recno; break; } /* Otherwise look for the name. */ slot = cd->name_table; for (i = 0; i < cd->names_found; i++) { if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 && slot[IMM2_SIZE+namelen] == 0) break; slot += cd->name_entry_size; } /* Found the named subpattern. If the name is duplicated, add one to the opcode to change CREF/RREF into DNCREF/DNRREF and insert appropriate data values. Otherwise, just insert the unique subpattern number. */ if (i < cd->names_found) { int offset = i++; int count = 1; recno = GET2(slot, 0); /* Number from first found */ if (recno > cd->top_backref) cd->top_backref = recno; for (; i < cd->names_found; i++) { slot += cd->name_entry_size; if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0 || (slot+IMM2_SIZE)[namelen] != 0) break; count++; } if (count > 1) { PUT2(code, 2+LINK_SIZE, offset); PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count); skipbytes += IMM2_SIZE; code[1+LINK_SIZE]++; } else /* Not a duplicated name */ { PUT2(code, 2+LINK_SIZE, recno); } } /* If terminator == CHAR_NULL it means that the name followed directly after the opening parenthesis [e.g. (?(abc)...] and in this case there are some further alternatives to try. For the cases where terminator != CHAR_NULL [things like (?(... or (?('name')... or (?(R&name)... ] we have now checked all the possibilities, so give an error. */ else if (terminator != CHAR_NULL) { *errorcodeptr = ERR15; goto FAILED; } /* Check for (?(R) for recursion. Allow digits after R to specify a specific group number. */ else if (*name == CHAR_R) { recno = 0; for (i = 1; i < namelen; i++) { if (!IS_DIGIT(name[i])) { *errorcodeptr = ERR15; goto FAILED; } if (recno > INT_MAX / 10 - 1) /* Integer overflow */ { *errorcodeptr = ERR61; goto FAILED; } recno = recno * 10 + name[i] - CHAR_0; } if (recno == 0) recno = RREF_ANY; code[1+LINK_SIZE] = OP_RREF; /* Change test type */ PUT2(code, 2+LINK_SIZE, recno); } /* Similarly, check for the (?(DEFINE) "condition", which is always false. */ else if (namelen == 6 && STRNCMP_UC_C8(name, STRING_DEFINE, 6) == 0) { code[1+LINK_SIZE] = OP_DEF; skipbytes = 1; } /* Reference to an unidentified subpattern. */ else { *errorcodeptr = ERR15; goto FAILED; } break; /* ------------------------------------------------------------ */ case CHAR_EQUALS_SIGN: /* Positive lookahead */ bravalue = OP_ASSERT; cd->assert_depth += 1; ptr++; break; /* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird thing to do, but Perl allows all assertions to be quantified, and when they contain capturing parentheses there may be a potential use for this feature. Not that that applies to a quantified (?!) but we allow it for uniformity. */ /* ------------------------------------------------------------ */ case CHAR_EXCLAMATION_MARK: /* Negative lookahead */ ptr++; if (*ptr == CHAR_RIGHT_PARENTHESIS && ptr[1] != CHAR_ASTERISK && ptr[1] != CHAR_PLUS && ptr[1] != CHAR_QUESTION_MARK && (ptr[1] != CHAR_LEFT_CURLY_BRACKET || !is_counted_repeat(ptr+2))) { *code++ = OP_FAIL; previous = NULL; continue; } bravalue = OP_ASSERT_NOT; cd->assert_depth += 1; break; /* ------------------------------------------------------------ */ case CHAR_LESS_THAN_SIGN: /* Lookbehind or named define */ switch (ptr[1]) { case CHAR_EQUALS_SIGN: /* Positive lookbehind */ bravalue = OP_ASSERTBACK; cd->assert_depth += 1; ptr += 2; break; case CHAR_EXCLAMATION_MARK: /* Negative lookbehind */ bravalue = OP_ASSERTBACK_NOT; cd->assert_depth += 1; ptr += 2; break; default: /* Could be name define, else bad */ if (MAX_255(ptr[1]) && (cd->ctypes[ptr[1]] & ctype_word) != 0) goto DEFINE_NAME; ptr++; /* Correct offset for error */ *errorcodeptr = ERR24; goto FAILED; } break; /* ------------------------------------------------------------ */ case CHAR_GREATER_THAN_SIGN: /* One-time brackets */ bravalue = OP_ONCE; ptr++; break; /* ------------------------------------------------------------ */ case CHAR_C: /* Callout - may be followed by digits; */ previous_callout = code; /* Save for later completion */ after_manual_callout = 1; /* Skip one item before completing */ *code++ = OP_CALLOUT; { int n = 0; ptr++; while(IS_DIGIT(*ptr)) n = n * 10 + *ptr++ - CHAR_0; if (*ptr != CHAR_RIGHT_PARENTHESIS) { *errorcodeptr = ERR39; goto FAILED; } if (n > 255) { *errorcodeptr = ERR38; goto FAILED; } *code++ = n; PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */ PUT(code, LINK_SIZE, 0); /* Default length */ code += 2 * LINK_SIZE; } previous = NULL; continue; /* ------------------------------------------------------------ */ case CHAR_P: /* Python-style named subpattern handling */ if (*(++ptr) == CHAR_EQUALS_SIGN || *ptr == CHAR_GREATER_THAN_SIGN) /* Reference or recursion */ { is_recurse = *ptr == CHAR_GREATER_THAN_SIGN; terminator = CHAR_RIGHT_PARENTHESIS; goto NAMED_REF_OR_RECURSE; } else if (*ptr != CHAR_LESS_THAN_SIGN) /* Test for Python-style defn */ { *errorcodeptr = ERR41; goto FAILED; } /* Fall through to handle (?P< as (?< is handled */ /* ------------------------------------------------------------ */ DEFINE_NAME: /* Come here from (?< handling */ case CHAR_APOSTROPHE: terminator = (*ptr == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; name = ++ptr; if (IS_DIGIT(*ptr)) { *errorcodeptr = ERR84; /* Group name must start with non-digit */ goto FAILED; } while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++; namelen = (int)(ptr - name); /* In the pre-compile phase, do a syntax check, remember the longest name, and then remember the group in a vector, expanding it if necessary. Duplicates for the same number are skipped; other duplicates are checked for validity. In the actual compile, there is nothing to do. */ if (lengthptr != NULL) { named_group *ng; pcre_uint32 number = cd->bracount + 1; if (*ptr != (pcre_uchar)terminator) { *errorcodeptr = ERR42; goto FAILED; } if (cd->names_found >= MAX_NAME_COUNT) { *errorcodeptr = ERR49; goto FAILED; } if (namelen + IMM2_SIZE + 1 > cd->name_entry_size) { cd->name_entry_size = namelen + IMM2_SIZE + 1; if (namelen > MAX_NAME_SIZE) { *errorcodeptr = ERR48; goto FAILED; } } /* Scan the list to check for duplicates. For duplicate names, if the number is the same, break the loop, which causes the name to be discarded; otherwise, if DUPNAMES is not set, give an error. If it is set, allow the name with a different number, but continue scanning in case this is a duplicate with the same number. For non-duplicate names, give an error if the number is duplicated. */ ng = cd->named_groups; for (i = 0; i < cd->names_found; i++, ng++) { if (namelen == ng->length && STRNCMP_UC_UC(name, ng->name, namelen) == 0) { if (ng->number == number) break; if ((options & PCRE_DUPNAMES) == 0) { *errorcodeptr = ERR43; goto FAILED; } cd->dupnames = TRUE; /* Duplicate names exist */ } else if (ng->number == number) { *errorcodeptr = ERR65; goto FAILED; } } if (i >= cd->names_found) /* Not a duplicate with same number */ { /* Increase the list size if necessary */ if (cd->names_found >= cd->named_group_list_size) { int newsize = cd->named_group_list_size * 2; named_group *newspace = (PUBL(malloc)) (newsize * sizeof(named_group)); if (newspace == NULL) { *errorcodeptr = ERR21; goto FAILED; } memcpy(newspace, cd->named_groups, cd->named_group_list_size * sizeof(named_group)); if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE) (PUBL(free))((void *)cd->named_groups); cd->named_groups = newspace; cd->named_group_list_size = newsize; } cd->named_groups[cd->names_found].name = name; cd->named_groups[cd->names_found].length = namelen; cd->named_groups[cd->names_found].number = number; cd->names_found++; } } ptr++; /* Move past > or ' in both passes. */ goto NUMBERED_GROUP; /* ------------------------------------------------------------ */ case CHAR_AMPERSAND: /* Perl recursion/subroutine syntax */ terminator = CHAR_RIGHT_PARENTHESIS; is_recurse = TRUE; /* Fall through */ /* We come here from the Python syntax above that handles both references (?P=name) and recursion (?P>name), as well as falling through from the Perl recursion syntax (?&name). We also come here from the Perl \k or \k'name' back reference syntax and the \k{name} .NET syntax, and the Oniguruma \g<...> and \g'...' subroutine syntax. */ NAMED_REF_OR_RECURSE: name = ++ptr; if (IS_DIGIT(*ptr)) { *errorcodeptr = ERR84; /* Group name must start with non-digit */ goto FAILED; } while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++; namelen = (int)(ptr - name); /* In the pre-compile phase, do a syntax check. We used to just set a dummy reference number, because it was not used in the first pass. However, with the change of recursive back references to be atomic, we have to look for the number so that this state can be identified, as otherwise the incorrect length is computed. If it's not a backwards reference, the dummy number will do. */ if (lengthptr != NULL) { named_group *ng; recno = 0; if (namelen == 0) { *errorcodeptr = ERR62; goto FAILED; } if (*ptr != (pcre_uchar)terminator) { *errorcodeptr = ERR42; goto FAILED; } if (namelen > MAX_NAME_SIZE) { *errorcodeptr = ERR48; goto FAILED; } /* Count named back references. */ if (!is_recurse) cd->namedrefcount++; /* We have to allow for a named reference to a duplicated name (this cannot be determined until the second pass). This needs an extra 16-bit data item. */ *lengthptr += IMM2_SIZE; /* If this is a forward reference and we are within a (?|...) group, the reference may end up as the number of a group which we are currently inside, that is, it could be a recursive reference. In the real compile this will be picked up and the reference wrapped with OP_ONCE to make it atomic, so we must space in case this occurs. */ /* In fact, this can happen for a non-forward reference because another group with the same number might be created later. This issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance only mode, we finesse the bug by allowing more memory always. */ *lengthptr += 4 + 4*LINK_SIZE; /* It is even worse than that. The current reference may be to an existing named group with a different number (so apparently not recursive) but which later on is also attached to a group with the current number. This can only happen if $(| has been previous encountered. In that case, we allow yet more memory, just in case. (Again, this is fixed "properly" in PCRE2. */ if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE; /* Otherwise, check for recursion here. The name table does not exist in the first pass; instead we must scan the list of names encountered so far in order to get the number. If the name is not found, leave the value of recno as 0 for a forward reference. */ /* This patch (removing "else") fixes a problem when a reference is to multiple identically named nested groups from within the nest. Once again, it is not the "proper" fix, and it results in an over-allocation of memory. */ /* else */ { ng = cd->named_groups; for (i = 0; i < cd->names_found; i++, ng++) { if (namelen == ng->length && STRNCMP_UC_UC(name, ng->name, namelen) == 0) { open_capitem *oc; recno = ng->number; if (is_recurse) break; for (oc = cd->open_caps; oc != NULL; oc = oc->next) { if (oc->number == recno) { oc->flag = TRUE; break; } } } } } } /* In the real compile, search the name table. We check the name first, and then check that we have reached the end of the name in the table. That way, if the name is longer than any in the table, the comparison will fail without reading beyond the table entry. */ else { slot = cd->name_table; for (i = 0; i < cd->names_found; i++) { if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 && slot[IMM2_SIZE+namelen] == 0) break; slot += cd->name_entry_size; } if (i < cd->names_found) { recno = GET2(slot, 0); } else { *errorcodeptr = ERR15; goto FAILED; } } /* In both phases, for recursions, we can now go to the code than handles numerical recursion. */ if (is_recurse) goto HANDLE_RECURSION; /* In the second pass we must see if the name is duplicated. If so, we generate a different opcode. */ if (lengthptr == NULL && cd->dupnames) { int count = 1; unsigned int index = i; pcre_uchar *cslot = slot + cd->name_entry_size; for (i++; i < cd->names_found; i++) { if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break; count++; cslot += cd->name_entry_size; } if (count > 1) { if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF; PUT2INC(code, 0, index); PUT2INC(code, 0, count); /* Process each potentially referenced group. */ for (; slot < cslot; slot += cd->name_entry_size) { open_capitem *oc; recno = GET2(slot, 0); cd->backref_map |= (recno < 32)? (1 << recno) : 1; if (recno > cd->top_backref) cd->top_backref = recno; /* Check to see if this back reference is recursive, that it, it is inside the group that it references. A flag is set so that the group can be made atomic. */ for (oc = cd->open_caps; oc != NULL; oc = oc->next) { if (oc->number == recno) { oc->flag = TRUE; break; } } } continue; /* End of back ref handling */ } } /* First pass, or a non-duplicated name. */ goto HANDLE_REFERENCE; /* ------------------------------------------------------------ */ case CHAR_R: /* Recursion, same as (?0) */ recno = 0; if (*(++ptr) != CHAR_RIGHT_PARENTHESIS) { *errorcodeptr = ERR29; goto FAILED; } goto HANDLE_RECURSION; /* ------------------------------------------------------------ */ case CHAR_MINUS: case CHAR_PLUS: /* Recursion or subroutine */ case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: { const pcre_uchar *called; terminator = CHAR_RIGHT_PARENTHESIS; /* Come here from the \g<...> and \g'...' code (Oniguruma compatibility). However, the syntax has been checked to ensure that the ... are a (signed) number, so that neither ERR63 nor ERR29 will be called on this path, nor with the jump to OTHER_CHAR_AFTER_QUERY ever be taken. */ HANDLE_NUMERICAL_RECURSION: if ((refsign = *ptr) == CHAR_PLUS) { ptr++; if (!IS_DIGIT(*ptr)) { *errorcodeptr = ERR63; goto FAILED; } } else if (refsign == CHAR_MINUS) { if (!IS_DIGIT(ptr[1])) goto OTHER_CHAR_AFTER_QUERY; ptr++; } recno = 0; while(IS_DIGIT(*ptr)) { if (recno > INT_MAX / 10 - 1) /* Integer overflow */ { while (IS_DIGIT(*ptr)) ptr++; *errorcodeptr = ERR61; goto FAILED; } recno = recno * 10 + *ptr++ - CHAR_0; } if (*ptr != (pcre_uchar)terminator) { *errorcodeptr = ERR29; goto FAILED; } if (refsign == CHAR_MINUS) { if (recno == 0) { *errorcodeptr = ERR58; goto FAILED; } recno = cd->bracount - recno + 1; if (recno <= 0) { *errorcodeptr = ERR15; goto FAILED; } } else if (refsign == CHAR_PLUS) { if (recno == 0) { *errorcodeptr = ERR58; goto FAILED; } recno += cd->bracount; } /* Come here from code above that handles a named recursion */ HANDLE_RECURSION: previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; called = cd->start_code; /* When we are actually compiling, find the bracket that is being referenced. Temporarily end the regex in case it doesn't exist before this point. If we end up with a forward reference, first check that the bracket does occur later so we can give the error (and position) now. Then remember this forward reference in the workspace so it can be filled in at the end. */ if (lengthptr == NULL) { *code = OP_END; if (recno != 0) called = PRIV(find_bracket)(cd->start_code, utf, recno); /* Forward reference */ if (called == NULL) { if (recno > cd->final_bracount) { *errorcodeptr = ERR15; goto FAILED; } /* Fudge the value of "called" so that when it is inserted as an offset below, what it actually inserted is the reference number of the group. Then remember the forward reference. */ called = cd->start_code + recno; if (cd->hwm >= cd->start_workspace + cd->workspace_size - WORK_SIZE_SAFETY_MARGIN) { *errorcodeptr = expand_workspace(cd); if (*errorcodeptr != 0) goto FAILED; } PUTINC(cd->hwm, 0, (int)(code + 1 - cd->start_code)); } /* If not a forward reference, and the subpattern is still open, this is a recursive call. We check to see if this is a left recursion that could loop for ever, and diagnose that case. We must not, however, do this check if we are in a conditional subpattern because the condition might be testing for recursion in a pattern such as /(?(R)a+|(?R)b)/, which is perfectly valid. Forever loops are also detected at runtime, so those that occur in conditional subpatterns will be picked up then. */ else if (GET(called, 1) == 0 && cond_depth <= 0 && could_be_empty(called, code, bcptr, utf, cd)) { *errorcodeptr = ERR40; goto FAILED; } } /* Insert the recursion/subroutine item. It does not have a set first character (relevant if it is repeated, because it will then be wrapped with ONCE brackets). */ *code = OP_RECURSE; PUT(code, 1, (int)(called - cd->start_code)); code += 1 + LINK_SIZE; groupsetfirstchar = FALSE; } /* Can't determine a first byte now */ if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; continue; /* ------------------------------------------------------------ */ default: /* Other characters: check option setting */ OTHER_CHAR_AFTER_QUERY: set = unset = 0; optset = &set; while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON) { switch (*ptr++) { case CHAR_MINUS: optset = &unset; break; case CHAR_J: /* Record that it changed in the external options */ *optset |= PCRE_DUPNAMES; cd->external_flags |= PCRE_JCHANGED; break; case CHAR_i: *optset |= PCRE_CASELESS; break; case CHAR_m: *optset |= PCRE_MULTILINE; break; case CHAR_s: *optset |= PCRE_DOTALL; break; case CHAR_x: *optset |= PCRE_EXTENDED; break; case CHAR_U: *optset |= PCRE_UNGREEDY; break; case CHAR_X: *optset |= PCRE_EXTRA; break; default: *errorcodeptr = ERR12; ptr--; /* Correct the offset */ goto FAILED; } } /* Set up the changed option bits, but don't change anything yet. */ newoptions = (options | set) & (~unset); /* If the options ended with ')' this is not the start of a nested group with option changes, so the options change at this level. If we are not at the pattern start, reset the greedy defaults and the case value for firstchar and reqchar. */ if (*ptr == CHAR_RIGHT_PARENTHESIS) { greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); greedy_non_default = greedy_default ^ 1; req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0; /* Change options at this level, and pass them back for use in subsequent branches. */ *optionsptr = options = newoptions; previous = NULL; /* This item can't be repeated */ continue; /* It is complete */ } /* If the options ended with ':' we are heading into a nested group with possible change of options. Such groups are non-capturing and are not assertions of any kind. All we need to do is skip over the ':'; the newoptions value is handled below. */ bravalue = OP_BRA; ptr++; } /* End of switch for character following (? */ } /* End of (? handling */ /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE is set, all unadorned brackets become non-capturing and behave like (?:...) brackets. */ else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) { bravalue = OP_BRA; } /* Else we have a capturing group. */ else { NUMBERED_GROUP: cd->bracount += 1; PUT2(code, 1+LINK_SIZE, cd->bracount); skipbytes = IMM2_SIZE; } /* Process nested bracketed regex. First check for parentheses nested too deeply. */ if ((cd->parens_depth += 1) > PARENS_NEST_LIMIT) { *errorcodeptr = ERR82; goto FAILED; } /* All assertions used not to be repeatable, but this was changed for Perl compatibility. All kinds can now be repeated except for assertions that are conditions (Perl also forbids these to be repeated). We copy code into a non-register variable (tempcode) in order to be able to pass its address because some compilers complain otherwise. At the start of a conditional group whose condition is an assertion, cd->iscondassert is set. We unset it here so as to allow assertions later in the group to be quantified. */ if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT && cd->iscondassert) { previous = NULL; cd->iscondassert = FALSE; } else { previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; } *code = bravalue; tempcode = code; tempreqvary = cd->req_varyopt; /* Save value before bracket */ tempbracount = cd->bracount; /* Save value before bracket */ length_prevgroup = 0; /* Initialize for pre-compile phase */ if (!compile_regex( newoptions, /* The complete new option state */ &tempcode, /* Where to put code (updated) */ &ptr, /* Input pointer (updated) */ errorcodeptr, /* Where to put an error message */ (bravalue == OP_ASSERTBACK || bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ reset_bracount, /* True if (?| group */ skipbytes, /* Skip over bracket number */ cond_depth + ((bravalue == OP_COND)?1:0), /* Depth of condition subpatterns */ &subfirstchar, /* For possible first char */ &subfirstcharflags, &subreqchar, /* For possible last char */ &subreqcharflags, bcptr, /* Current branch chain */ cd, /* Tables block */ (lengthptr == NULL)? NULL : /* Actual compile phase */ &length_prevgroup /* Pre-compile phase */ )) goto FAILED; cd->parens_depth -= 1; /* If this was an atomic group and there are no capturing groups within it, generate OP_ONCE_NC instead of OP_ONCE. */ if (bravalue == OP_ONCE && cd->bracount <= tempbracount) *code = OP_ONCE_NC; if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT) cd->assert_depth -= 1; /* At the end of compiling, code is still pointing to the start of the group, while tempcode has been updated to point past the end of the group. The pattern pointer (ptr) is on the bracket. If this is a conditional bracket, check that there are no more than two branches in the group, or just one if it's a DEFINE group. We do this in the real compile phase, not in the pre-pass, where the whole group may not be available. */ if (bravalue == OP_COND && lengthptr == NULL) { pcre_uchar *tc = code; int condcount = 0; do { condcount++; tc += GET(tc,1); } while (*tc != OP_KET); /* A DEFINE group is never obeyed inline (the "condition" is always false). It must have only one branch. */ if (code[LINK_SIZE+1] == OP_DEF) { if (condcount > 1) { *errorcodeptr = ERR54; goto FAILED; } bravalue = OP_DEF; /* Just a flag to suppress char handling below */ } /* A "normal" conditional group. If there is just one branch, we must not make use of its firstchar or reqchar, because this is equivalent to an empty second branch. */ else { if (condcount > 2) { *errorcodeptr = ERR27; goto FAILED; } if (condcount == 1) subfirstcharflags = subreqcharflags = REQ_NONE; } } /* Error if hit end of pattern */ if (*ptr != CHAR_RIGHT_PARENTHESIS) { *errorcodeptr = ERR14; goto FAILED; } /* In the pre-compile phase, update the length by the length of the group, less the brackets at either end. Then reduce the compiled code to just a set of non-capturing brackets so that it doesn't use much memory if it is duplicated by a quantifier.*/ if (lengthptr != NULL) { if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE) { *errorcodeptr = ERR20; goto FAILED; } *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE; code++; /* This already contains bravalue */ PUTINC(code, 0, 1 + LINK_SIZE); *code++ = OP_KET; PUTINC(code, 0, 1 + LINK_SIZE); break; /* No need to waste time with special character handling */ } /* Otherwise update the main code pointer to the end of the group. */ code = tempcode; /* For a DEFINE group, required and first character settings are not relevant. */ if (bravalue == OP_DEF) break; /* Handle updating of the required and first characters for other types of group. Update for normal brackets of all kinds, and conditions with two branches (see code above). If the bracket is followed by a quantifier with zero repeat, we have to back off. Hence the definition of zeroreqchar and zerofirstchar outside the main loop so that they can be accessed for the back off. */ zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; groupsetfirstchar = FALSE; if (bravalue >= OP_ONCE) { /* If we have not yet set a firstchar in this branch, take it from the subpattern, remembering that it was set here so that a repeat of more than one can replicate it as reqchar if necessary. If the subpattern has no firstchar, set "none" for the whole branch. In both cases, a zero repeat forces firstchar to "none". */ if (firstcharflags == REQ_UNSET) { if (subfirstcharflags >= 0) { firstchar = subfirstchar; firstcharflags = subfirstcharflags; groupsetfirstchar = TRUE; } else firstcharflags = REQ_NONE; zerofirstcharflags = REQ_NONE; } /* If firstchar was previously set, convert the subpattern's firstchar into reqchar if there wasn't one, using the vary flag that was in existence beforehand. */ else if (subfirstcharflags >= 0 && subreqcharflags < 0) { subreqchar = subfirstchar; subreqcharflags = subfirstcharflags | tempreqvary; } /* If the subpattern set a required byte (or set a first byte that isn't really the first byte - see above), set it. */ if (subreqcharflags >= 0) { reqchar = subreqchar; reqcharflags = subreqcharflags; } } /* For a forward assertion, we take the reqchar, if set, provided that the group has also set a first char. This can be helpful if the pattern that follows the assertion doesn't set a different char. For example, it's useful for /(?=abcde).+/. We can't set firstchar for an assertion, however because it leads to incorrect effect for patterns such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead of a firstchar. This is overcome by a scan at the end if there's no firstchar, looking for an asserted first char. */ else if (bravalue == OP_ASSERT && subreqcharflags >= 0 && subfirstcharflags >= 0) { reqchar = subreqchar; reqcharflags = subreqcharflags; } break; /* End of processing '(' */ /* ===================================================================*/ /* Handle metasequences introduced by \. For ones like \d, the ESC_ values are arranged to be the negation of the corresponding OP_values in the default case when PCRE_UCP is not set. For the back references, the values are negative the reference number. Only back references and those types that consume a character may be repeated. We can test for values between ESC_b and ESC_Z for the latter; this may have to change if any new ones are ever created. */ case CHAR_BACKSLASH: tempptr = ptr; escape = check_escape(&ptr, &ec, errorcodeptr, cd->bracount, options, FALSE); if (*errorcodeptr != 0) goto FAILED; if (escape == 0) /* The escape coded a single character */ c = ec; else { /* For metasequences that actually match a character, we disable the setting of a first character if it hasn't already been set. */ if (firstcharflags == REQ_UNSET && escape > ESC_b && escape < ESC_Z) firstcharflags = REQ_NONE; /* Set values to reset to if this is followed by a zero repeat. */ zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; /* \g or \g'name' is a subroutine call by name and \g or \g'n' is a subroutine call by number (Oniguruma syntax). In fact, the value ESC_g is returned only for these cases. So we don't need to check for < or ' if the value is ESC_g. For the Perl syntax \g{n} the value is -n, and for the Perl syntax \g{name} the result is ESC_k (as that is a synonym for a named back reference). */ if (escape == ESC_g) { const pcre_uchar *p; pcre_uint32 cf; item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; /* These two statements stop the compiler for warning about possibly unset variables caused by the jump to HANDLE_NUMERICAL_RECURSION. In fact, because we do the check for a number below, the paths that would actually be in error are never taken. */ skipbytes = 0; reset_bracount = FALSE; /* If it's not a signed or unsigned number, treat it as a name. */ cf = ptr[1]; if (cf != CHAR_PLUS && cf != CHAR_MINUS && !IS_DIGIT(cf)) { is_recurse = TRUE; goto NAMED_REF_OR_RECURSE; } /* Signed or unsigned number (cf = ptr[1]) is known to be plus or minus or a digit. */ p = ptr + 2; while (IS_DIGIT(*p)) p++; if (*p != (pcre_uchar)terminator) { *errorcodeptr = ERR57; goto FAILED; } ptr++; goto HANDLE_NUMERICAL_RECURSION; } /* \k or \k'name' is a back reference by name (Perl syntax). We also support \k{name} (.NET syntax). */ if (escape == ESC_k) { if ((ptr[1] != CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) { *errorcodeptr = ERR69; goto FAILED; } is_recurse = FALSE; terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)? CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET; goto NAMED_REF_OR_RECURSE; } /* Back references are handled specially; must disable firstchar if not set to cope with cases like (?=(\w+))\1: which would otherwise set ':' later. */ if (escape < 0) { open_capitem *oc; recno = -escape; /* Come here from named backref handling when the reference is to a single group (i.e. not to a duplicated name. */ HANDLE_REFERENCE: if (firstcharflags == REQ_UNSET) zerofirstcharflags = firstcharflags = REQ_NONE; previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, recno); cd->backref_map |= (recno < 32)? (1 << recno) : 1; if (recno > cd->top_backref) cd->top_backref = recno; /* Check to see if this back reference is recursive, that it, it is inside the group that it references. A flag is set so that the group can be made atomic. */ for (oc = cd->open_caps; oc != NULL; oc = oc->next) { if (oc->number == recno) { oc->flag = TRUE; break; } } } /* So are Unicode property matches, if supported. */ #ifdef SUPPORT_UCP else if (escape == ESC_P || escape == ESC_p) { BOOL negated; unsigned int ptype = 0, pdata = 0; if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) goto FAILED; previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP; *code++ = ptype; *code++ = pdata; } #else /* If Unicode properties are not supported, \X, \P, and \p are not allowed. */ else if (escape == ESC_X || escape == ESC_P || escape == ESC_p) { *errorcodeptr = ERR45; goto FAILED; } #endif /* For the rest (including \X when Unicode properties are supported), we can obtain the OP value by negating the escape value in the default situation when PCRE_UCP is not set. When it *is* set, we substitute Unicode property tests. Note that \b and \B do a one-character lookbehind, and \A also behaves as if it does. */ else { if ((escape == ESC_b || escape == ESC_B || escape == ESC_A) && cd->max_lookbehind == 0) cd->max_lookbehind = 1; #ifdef SUPPORT_UCP if (escape >= ESC_DU && escape <= ESC_wu) { nestptr = ptr + 1; /* Where to resume */ ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */ } else #endif /* In non-UTF-8 mode, we turn \C into OP_ALLANY instead of OP_ANYBYTE so that it works in DFA mode and in lookbehinds. */ { previous = (escape > ESC_b && escape < ESC_Z)? code : NULL; item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape; } } continue; } /* We have a data character whose value is in c. In UTF-8 mode it may have a value > 127. We set its representation in the length/buffer, and then handle it as a data character. */ #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) mclength = PRIV(ord2utf)(c, mcbuffer); else #endif { mcbuffer[0] = c; mclength = 1; } goto ONE_CHAR; /* ===================================================================*/ /* Handle a literal character. It is guaranteed not to be whitespace or # when the extended flag is set. If we are in a UTF mode, it may be a multi-unit literal character. */ default: NORMAL_CHAR: mclength = 1; mcbuffer[0] = c; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(c)) ACROSSCHAR(TRUE, ptr[1], mcbuffer[mclength++] = *(++ptr)); #endif /* At this point we have the character's bytes in mcbuffer, and the length in mclength. When not in UTF-8 mode, the length is always 1. */ ONE_CHAR: previous = code; item_hwm_offset = cd->hwm - cd->start_workspace; /* For caseless UTF-8 mode when UCP support is available, check whether this character has more than one other case. If so, generate a special OP_PROP item instead of OP_CHARI. */ #ifdef SUPPORT_UCP if (utf && (options & PCRE_CASELESS) != 0) { GETCHAR(c, mcbuffer); if ((c = UCD_CASESET(c)) != 0) { *code++ = OP_PROP; *code++ = PT_CLIST; *code++ = c; if (firstcharflags == REQ_UNSET) firstcharflags = zerofirstcharflags = REQ_NONE; break; } } #endif /* Caseful matches, or not one of the multicase characters. */ *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR; for (c = 0; c < mclength; c++) *code++ = mcbuffer[c]; /* Remember if \r or \n were seen */ if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; /* Set the first and required bytes appropriately. If no previous first byte, set it from this character, but revert to none on a zero repeat. Otherwise, leave the firstchar value alone, and don't change it on a zero repeat. */ if (firstcharflags == REQ_UNSET) { zerofirstcharflags = REQ_NONE; zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; /* If the character is more than one byte long, we can set firstchar only if it is not to be matched caselessly. */ if (mclength == 1 || req_caseopt == 0) { firstchar = mcbuffer[0]; firstcharflags = req_caseopt; if (mclength != 1) { reqchar = code[-1]; reqcharflags = cd->req_varyopt; } } else firstcharflags = reqcharflags = REQ_NONE; } /* firstchar was previously set; we can set reqchar only if the length is 1 or the matching is caseful. */ else { zerofirstchar = firstchar; zerofirstcharflags = firstcharflags; zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; if (mclength == 1 || req_caseopt == 0) { reqchar = code[-1]; reqcharflags = req_caseopt | cd->req_varyopt; } } break; /* End of literal character handling */ } } /* end of big loop */ /* Control never reaches here by falling through, only by a goto for all the error states. Pass back the position in the pattern so that it can be displayed to the user for diagnosing the error. */ FAILED: *ptrptr = ptr; return FALSE; } /************************************************* * Compile sequence of alternatives * *************************************************/ /* On entry, ptr is pointing past the bracket character, but on return it points to the closing bracket, or vertical bar, or end of string. The code variable is pointing at the byte into which the BRA operator has been stored. This function is used during the pre-compile phase when we are trying to find out the amount of memory needed, as well as during the real compile phase. The value of lengthptr distinguishes the two phases. Arguments: options option bits, including any changes for this subpattern codeptr -> the address of the current code pointer ptrptr -> the address of the current pattern pointer errorcodeptr -> pointer to error code variable lookbehind TRUE if this is a lookbehind assertion reset_bracount TRUE to reset the count for each branch skipbytes skip this many bytes at start (for brackets and OP_COND) cond_depth depth of nesting for conditional subpatterns firstcharptr place to put the first required character firstcharflagsptr place to put the first character flags, or a negative number reqcharptr place to put the last required character reqcharflagsptr place to put the last required character flags, or a negative number bcptr pointer to the chain of currently open branches cd points to the data block with tables pointers etc. lengthptr NULL during the real compile phase points to length accumulator during pre-compile phase Returns: TRUE on success */ static BOOL compile_regex(int options, pcre_uchar **codeptr, const pcre_uchar **ptrptr, int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes, int cond_depth, pcre_uint32 *firstcharptr, pcre_int32 *firstcharflagsptr, pcre_uint32 *reqcharptr, pcre_int32 *reqcharflagsptr, branch_chain *bcptr, compile_data *cd, int *lengthptr) { const pcre_uchar *ptr = *ptrptr; pcre_uchar *code = *codeptr; pcre_uchar *last_branch = code; pcre_uchar *start_bracket = code; pcre_uchar *reverse_count = NULL; open_capitem capitem; int capnumber = 0; pcre_uint32 firstchar, reqchar; pcre_int32 firstcharflags, reqcharflags; pcre_uint32 branchfirstchar, branchreqchar; pcre_int32 branchfirstcharflags, branchreqcharflags; int length; unsigned int orig_bracount; unsigned int max_bracount; branch_chain bc; size_t save_hwm_offset; /* If set, call the external function that checks for stack availability. */ if (PUBL(stack_guard) != NULL && PUBL(stack_guard)()) { *errorcodeptr= ERR85; return FALSE; } /* Miscellaneous initialization */ bc.outer = bcptr; bc.current_branch = code; firstchar = reqchar = 0; firstcharflags = reqcharflags = REQ_UNSET; save_hwm_offset = cd->hwm - cd->start_workspace; /* Accumulate the length for use in the pre-compile phase. Start with the length of the BRA and KET and any extra bytes that are required at the beginning. We accumulate in a local variable to save frequent testing of lenthptr for NULL. We cannot do this by looking at the value of code at the start and end of each alternative, because compiled items are discarded during the pre-compile phase so that the work space is not exceeded. */ length = 2 + 2*LINK_SIZE + skipbytes; /* WARNING: If the above line is changed for any reason, you must also change the code that abstracts option settings at the start of the pattern and makes them global. It tests the value of length for (2 + 2*LINK_SIZE) in the pre-compile phase to find out whether anything has yet been compiled or not. */ /* If this is a capturing subpattern, add to the chain of open capturing items so that we can detect them if (*ACCEPT) is encountered. This is also used to detect groups that contain recursive back references to themselves. Note that only OP_CBRA need be tested here; changing this opcode to one of its variants, e.g. OP_SCBRAPOS, happens later, after the group has been compiled. */ if (*code == OP_CBRA) { capnumber = GET2(code, 1 + LINK_SIZE); capitem.number = capnumber; capitem.next = cd->open_caps; capitem.flag = FALSE; cd->open_caps = &capitem; } /* Offset is set zero to mark that this bracket is still open */ PUT(code, 1, 0); code += 1 + LINK_SIZE + skipbytes; /* Loop for each alternative branch */ orig_bracount = max_bracount = cd->bracount; for (;;) { /* For a (?| group, reset the capturing bracket count so that each branch uses the same numbers. */ if (reset_bracount) cd->bracount = orig_bracount; /* Set up dummy OP_REVERSE if lookbehind assertion */ if (lookbehind) { *code++ = OP_REVERSE; reverse_count = code; PUTINC(code, 0, 0); length += 1 + LINK_SIZE; } /* Now compile the branch; in the pre-compile phase its length gets added into the length. */ if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstchar, &branchfirstcharflags, &branchreqchar, &branchreqcharflags, &bc, cond_depth, cd, (lengthptr == NULL)? NULL : &length)) { *ptrptr = ptr; return FALSE; } /* Keep the highest bracket count in case (?| was used and some branch has fewer than the rest. */ if (cd->bracount > max_bracount) max_bracount = cd->bracount; /* In the real compile phase, there is some post-processing to be done. */ if (lengthptr == NULL) { /* If this is the first branch, the firstchar and reqchar values for the branch become the values for the regex. */ if (*last_branch != OP_ALT) { firstchar = branchfirstchar; firstcharflags = branchfirstcharflags; reqchar = branchreqchar; reqcharflags = branchreqcharflags; } /* If this is not the first branch, the first char and reqchar have to match the values from all the previous branches, except that if the previous value for reqchar didn't have REQ_VARY set, it can still match, and we set REQ_VARY for the regex. */ else { /* If we previously had a firstchar, but it doesn't match the new branch, we have to abandon the firstchar for the regex, but if there was previously no reqchar, it takes on the value of the old firstchar. */ if (firstcharflags >= 0 && (firstcharflags != branchfirstcharflags || firstchar != branchfirstchar)) { if (reqcharflags < 0) { reqchar = firstchar; reqcharflags = firstcharflags; } firstcharflags = REQ_NONE; } /* If we (now or from before) have no firstchar, a firstchar from the branch becomes a reqchar if there isn't a branch reqchar. */ if (firstcharflags < 0 && branchfirstcharflags >= 0 && branchreqcharflags < 0) { branchreqchar = branchfirstchar; branchreqcharflags = branchfirstcharflags; } /* Now ensure that the reqchars match */ if (((reqcharflags & ~REQ_VARY) != (branchreqcharflags & ~REQ_VARY)) || reqchar != branchreqchar) reqcharflags = REQ_NONE; else { reqchar = branchreqchar; reqcharflags |= branchreqcharflags; /* To "or" REQ_VARY */ } } /* If lookbehind, check that this branch matches a fixed-length string, and put the length into the OP_REVERSE item. Temporarily mark the end of the branch with OP_END. If the branch contains OP_RECURSE, the result is -3 because there may be forward references that we can't check here. Set a flag to cause another lookbehind check at the end. Why not do it all at the end? Because common, erroneous checks are picked up here and the offset of the problem can be shown. */ if (lookbehind) { int fixed_length; *code = OP_END; fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0, FALSE, cd, NULL); DPRINTF(("fixed length = %d\n", fixed_length)); if (fixed_length == -3) { cd->check_lookbehind = TRUE; } else if (fixed_length < 0) { *errorcodeptr = (fixed_length == -2)? ERR36 : (fixed_length == -4)? ERR70: ERR25; *ptrptr = ptr; return FALSE; } else { if (fixed_length > cd->max_lookbehind) cd->max_lookbehind = fixed_length; PUT(reverse_count, 0, fixed_length); } } } /* Reached end of expression, either ')' or end of pattern. In the real compile phase, go back through the alternative branches and reverse the chain of offsets, with the field in the BRA item now becoming an offset to the first alternative. If there are no alternatives, it points to the end of the group. The length in the terminating ket is always the length of the whole bracketed item. Return leaving the pointer at the terminating char. */ if (*ptr != CHAR_VERTICAL_LINE) { if (lengthptr == NULL) { int branch_length = (int)(code - last_branch); do { int prev_length = GET(last_branch, 1); PUT(last_branch, 1, branch_length); branch_length = prev_length; last_branch -= branch_length; } while (branch_length > 0); } /* Fill in the ket */ *code = OP_KET; PUT(code, 1, (int)(code - start_bracket)); code += 1 + LINK_SIZE; /* If it was a capturing subpattern, check to see if it contained any recursive back references. If so, we must wrap it in atomic brackets. Because we are moving code along, we must ensure that any pending recursive references are updated. In any event, remove the block from the chain. */ if (capnumber > 0) { if (cd->open_caps->flag) { *code = OP_END; adjust_recurse(start_bracket, 1 + LINK_SIZE, (options & PCRE_UTF8) != 0, cd, save_hwm_offset); memmove(start_bracket + 1 + LINK_SIZE, start_bracket, IN_UCHARS(code - start_bracket)); *start_bracket = OP_ONCE; code += 1 + LINK_SIZE; PUT(start_bracket, 1, (int)(code - start_bracket)); *code = OP_KET; PUT(code, 1, (int)(code - start_bracket)); code += 1 + LINK_SIZE; length += 2 + 2*LINK_SIZE; } cd->open_caps = cd->open_caps->next; } /* Retain the highest bracket number, in case resetting was used. */ cd->bracount = max_bracount; /* Set values to pass back */ *codeptr = code; *ptrptr = ptr; *firstcharptr = firstchar; *firstcharflagsptr = firstcharflags; *reqcharptr = reqchar; *reqcharflagsptr = reqcharflags; if (lengthptr != NULL) { if (OFLOW_MAX - *lengthptr < length) { *errorcodeptr = ERR20; return FALSE; } *lengthptr += length; } return TRUE; } /* Another branch follows. In the pre-compile phase, we can move the code pointer back to where it was for the start of the first branch. (That is, pretend that each branch is the only one.) In the real compile phase, insert an ALT node. Its length field points back to the previous branch while the bracket remains open. At the end the chain is reversed. It's done like this so that the start of the bracket has a zero offset until it is closed, making it possible to detect recursion. */ if (lengthptr != NULL) { code = *codeptr + 1 + LINK_SIZE + skipbytes; length += 1 + LINK_SIZE; } else { *code = OP_ALT; PUT(code, 1, (int)(code - last_branch)); bc.current_branch = last_branch = code; code += 1 + LINK_SIZE; } ptr++; } /* Control never reaches here */ } /************************************************* * Check for anchored expression * *************************************************/ /* Try to find out if this is an anchored regular expression. Consider each alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then it's anchored. However, if this is a multiline pattern, then only OP_SOD will be found, because ^ generates OP_CIRCM in that mode. We can also consider a regex to be anchored if OP_SOM starts all its branches. This is the code for \G, which means "match at start of match position, taking into account the match offset". A branch is also implicitly anchored if it starts with .* and DOTALL is set, because that will try the rest of the pattern at all possible matching points, so there is no point trying again.... er .... .... except when the .* appears inside capturing parentheses, and there is a subsequent back reference to those parentheses. We haven't enough information to catch that case precisely. At first, the best we could do was to detect when .* was in capturing brackets and the highest back reference was greater than or equal to that level. However, by keeping a bitmap of the first 31 back references, we can catch some of the more common cases more precisely. ... A second exception is when the .* appears inside an atomic group, because this prevents the number of characters it matches from being adjusted. Arguments: code points to start of expression (the bracket) bracket_map a bitmap of which brackets we are inside while testing; this handles up to substring 31; after that we just have to take the less precise approach cd points to the compile data block atomcount atomic group level Returns: TRUE or FALSE */ static BOOL is_anchored(register const pcre_uchar *code, unsigned int bracket_map, compile_data *cd, int atomcount) { do { const pcre_uchar *scode = first_significant_code( code + PRIV(OP_lengths)[*code], FALSE); register int op = *scode; /* Non-capturing brackets */ if (op == OP_BRA || op == OP_BRAPOS || op == OP_SBRA || op == OP_SBRAPOS) { if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE; } /* Capturing brackets */ else if (op == OP_CBRA || op == OP_CBRAPOS || op == OP_SCBRA || op == OP_SCBRAPOS) { int n = GET2(scode, 1+LINK_SIZE); int new_map = bracket_map | ((n < 32)? (1 << n) : 1); if (!is_anchored(scode, new_map, cd, atomcount)) return FALSE; } /* Positive forward assertion */ else if (op == OP_ASSERT) { if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE; } /* Condition; not anchored if no second branch */ else if (op == OP_COND) { if (scode[GET(scode,1)] != OP_ALT) return FALSE; if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE; } /* Atomic groups */ else if (op == OP_ONCE || op == OP_ONCE_NC) { if (!is_anchored(scode, bracket_map, cd, atomcount + 1)) return FALSE; } /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and it isn't in brackets that are or may be referenced or inside an atomic group. */ else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)) { if (scode[1] != OP_ALLANY || (bracket_map & cd->backref_map) != 0 || atomcount > 0 || cd->had_pruneorskip) return FALSE; } /* Check for explicit anchoring */ else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE; code += GET(code, 1); } while (*code == OP_ALT); /* Loop for each alternative */ return TRUE; } /************************************************* * Check for starting with ^ or .* * *************************************************/ /* This is called to find out if every branch starts with ^ or .* so that "first char" processing can be done to speed things up in multiline matching and for non-DOTALL patterns that start with .* (which must start at the beginning or after \n). As in the case of is_anchored() (see above), we have to take account of back references to capturing brackets that contain .* because in that case we can't make the assumption. Also, the appearance of .* inside atomic brackets or in an assertion, or in a pattern that contains *PRUNE or *SKIP does not count, because once again the assumption no longer holds. Arguments: code points to start of expression (the bracket) bracket_map a bitmap of which brackets we are inside while testing; this handles up to substring 31; after that we just have to take the less precise approach cd points to the compile data atomcount atomic group level inassert TRUE if in an assertion Returns: TRUE or FALSE */ static BOOL is_startline(const pcre_uchar *code, unsigned int bracket_map, compile_data *cd, int atomcount, BOOL inassert) { do { const pcre_uchar *scode = first_significant_code( code + PRIV(OP_lengths)[*code], FALSE); register int op = *scode; /* If we are at the start of a conditional assertion group, *both* the conditional assertion *and* what follows the condition must satisfy the test for start of line. Other kinds of condition fail. Note that there may be an auto-callout at the start of a condition. */ if (op == OP_COND) { scode += 1 + LINK_SIZE; if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT]; switch (*scode) { case OP_CREF: case OP_DNCREF: case OP_RREF: case OP_DNRREF: case OP_DEF: case OP_FAIL: return FALSE; default: /* Assertion */ if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE; do scode += GET(scode, 1); while (*scode == OP_ALT); scode += 1 + LINK_SIZE; break; } scode = first_significant_code(scode, FALSE); op = *scode; } /* Non-capturing brackets */ if (op == OP_BRA || op == OP_BRAPOS || op == OP_SBRA || op == OP_SBRAPOS) { if (!is_startline(scode, bracket_map, cd, atomcount, inassert)) return FALSE; } /* Capturing brackets */ else if (op == OP_CBRA || op == OP_CBRAPOS || op == OP_SCBRA || op == OP_SCBRAPOS) { int n = GET2(scode, 1+LINK_SIZE); int new_map = bracket_map | ((n < 32)? (1 << n) : 1); if (!is_startline(scode, new_map, cd, atomcount, inassert)) return FALSE; } /* Positive forward assertions */ else if (op == OP_ASSERT) { if (!is_startline(scode, bracket_map, cd, atomcount, TRUE)) return FALSE; } /* Atomic brackets */ else if (op == OP_ONCE || op == OP_ONCE_NC) { if (!is_startline(scode, bracket_map, cd, atomcount + 1, inassert)) return FALSE; } /* .* means "start at start or after \n" if it isn't in atomic brackets or brackets that may be referenced or an assertion, as long as the pattern does not contain *PRUNE or *SKIP, because these break the feature. Consider, for example, /.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. not at the start of a line. */ else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR) { if (scode[1] != OP_ANY || (bracket_map & cd->backref_map) != 0 || atomcount > 0 || cd->had_pruneorskip || inassert) return FALSE; } /* Check for explicit circumflex; anything else gives a FALSE result. Note in particular that this includes atomic brackets OP_ONCE and OP_ONCE_NC because the number of characters matched by .* cannot be adjusted inside them. */ else if (op != OP_CIRC && op != OP_CIRCM) return FALSE; /* Move on to the next alternative */ code += GET(code, 1); } while (*code == OP_ALT); /* Loop for each alternative */ return TRUE; } /************************************************* * Check for asserted fixed first char * *************************************************/ /* During compilation, the "first char" settings from forward assertions are discarded, because they can cause conflicts with actual literals that follow. However, if we end up without a first char setting for an unanchored pattern, it is worth scanning the regex to see if there is an initial asserted first char. If all branches start with the same asserted char, or with a non-conditional bracket all of whose alternatives start with the same asserted char (recurse ad lib), then we return that char, with the flags set to zero or REQ_CASELESS; otherwise return zero with REQ_NONE in the flags. Arguments: code points to start of expression (the bracket) flags points to the first char flags, or to REQ_NONE inassert TRUE if in an assertion Returns: the fixed first char, or 0 with REQ_NONE in flags */ static pcre_uint32 find_firstassertedchar(const pcre_uchar *code, pcre_int32 *flags, BOOL inassert) { register pcre_uint32 c = 0; int cflags = REQ_NONE; *flags = REQ_NONE; do { pcre_uint32 d; int dflags; int xl = (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0; const pcre_uchar *scode = first_significant_code(code + 1+LINK_SIZE + xl, TRUE); register pcre_uchar op = *scode; switch(op) { default: return 0; case OP_BRA: case OP_BRAPOS: case OP_CBRA: case OP_SCBRA: case OP_CBRAPOS: case OP_SCBRAPOS: case OP_ASSERT: case OP_ONCE: case OP_ONCE_NC: d = find_firstassertedchar(scode, &dflags, op == OP_ASSERT); if (dflags < 0) return 0; if (cflags < 0) { c = d; cflags = dflags; } else if (c != d || cflags != dflags) return 0; break; case OP_EXACT: scode += IMM2_SIZE; /* Fall through */ case OP_CHAR: case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: if (!inassert) return 0; if (cflags < 0) { c = scode[1]; cflags = 0; } else if (c != scode[1]) return 0; break; case OP_EXACTI: scode += IMM2_SIZE; /* Fall through */ case OP_CHARI: case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: if (!inassert) return 0; if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; } else if (c != scode[1]) return 0; break; } code += GET(code, 1); } while (*code == OP_ALT); *flags = cflags; return c; } /************************************************* * Add an entry to the name/number table * *************************************************/ /* This function is called between compiling passes to add an entry to the name/number table, maintaining alphabetical order. Checking for permitted and forbidden duplicates has already been done. Arguments: cd the compile data block name the name to add length the length of the name groupno the group number Returns: nothing */ static void add_name(compile_data *cd, const pcre_uchar *name, int length, unsigned int groupno) { int i; pcre_uchar *slot = cd->name_table; for (i = 0; i < cd->names_found; i++) { int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(length)); if (crc == 0 && slot[IMM2_SIZE+length] != 0) crc = -1; /* Current name is a substring */ /* Make space in the table and break the loop for an earlier name. For a duplicate or later name, carry on. We do this for duplicates so that in the simple case (when ?(| is not used) they are in order of their numbers. In all cases they are in the order in which they appear in the pattern. */ if (crc < 0) { memmove(slot + cd->name_entry_size, slot, IN_UCHARS((cd->names_found - i) * cd->name_entry_size)); break; } /* Continue the loop for a later or duplicate name */ slot += cd->name_entry_size; } PUT2(slot, 0, groupno); memcpy(slot + IMM2_SIZE, name, IN_UCHARS(length)); slot[IMM2_SIZE + length] = 0; cd->names_found++; } /************************************************* * Compile a Regular Expression * *************************************************/ /* This function takes a string and returns a pointer to a block of store holding a compiled version of the expression. The original API for this function had no error code return variable; it is retained for backwards compatibility. The new function is given a new name. Arguments: pattern the regular expression options various option bits errorcodeptr pointer to error code variable (pcre_compile2() only) can be NULL if you don't want a code value errorptr pointer to pointer to error text erroroffset ptr offset in pattern where error was detected tables pointer to character tables or NULL Returns: pointer to compiled data block, or NULL on error, with errorptr and erroroffset set */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION pcre_compile(const char *pattern, int options, const char **errorptr, int *erroroffset, const unsigned char *tables) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr, int *erroroffset, const unsigned char *tables) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN pcre32 * PCRE_CALL_CONVENTION pcre32_compile(PCRE_SPTR32 pattern, int options, const char **errorptr, int *erroroffset, const unsigned char *tables) #endif { #if defined COMPILE_PCRE8 return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables); #elif defined COMPILE_PCRE16 return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables); #elif defined COMPILE_PCRE32 return pcre32_compile2(pattern, options, NULL, errorptr, erroroffset, tables); #endif } #if defined COMPILE_PCRE8 PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION pcre_compile2(const char *pattern, int options, int *errorcodeptr, const char **errorptr, int *erroroffset, const unsigned char *tables) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr, const char **errorptr, int *erroroffset, const unsigned char *tables) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN pcre32 * PCRE_CALL_CONVENTION pcre32_compile2(PCRE_SPTR32 pattern, int options, int *errorcodeptr, const char **errorptr, int *erroroffset, const unsigned char *tables) #endif { REAL_PCRE *re; int length = 1; /* For final END opcode */ pcre_int32 firstcharflags, reqcharflags; pcre_uint32 firstchar, reqchar; pcre_uint32 limit_match = PCRE_UINT32_MAX; pcre_uint32 limit_recursion = PCRE_UINT32_MAX; int newline; int errorcode = 0; int skipatstart = 0; BOOL utf; BOOL never_utf = FALSE; size_t size; pcre_uchar *code; const pcre_uchar *codestart; const pcre_uchar *ptr; compile_data compile_block; compile_data *cd = &compile_block; /* This space is used for "compiling" into during the first phase, when we are computing the amount of memory that is needed. Compiled items are thrown away as soon as possible, so that a fairly large buffer should be sufficient for this purpose. The same space is used in the second phase for remembering where to fill in forward references to subpatterns. That may overflow, in which case new memory is obtained from malloc(). */ pcre_uchar cworkspace[COMPILE_WORK_SIZE]; /* This vector is used for remembering name groups during the pre-compile. In a similar way to cworkspace, it can be expanded using malloc() if necessary. */ named_group named_groups[NAMED_GROUP_LIST_SIZE]; /* Set this early so that early errors get offset 0. */ ptr = (const pcre_uchar *)pattern; /* We can't pass back an error message if errorptr is NULL; I guess the best we can do is just return NULL, but we can set a code value if there is a code pointer. */ if (errorptr == NULL) { if (errorcodeptr != NULL) *errorcodeptr = 99; return NULL; } *errorptr = NULL; if (errorcodeptr != NULL) *errorcodeptr = ERR0; /* However, we can give a message for this error */ if (erroroffset == NULL) { errorcode = ERR16; goto PCRE_EARLY_ERROR_RETURN2; } *erroroffset = 0; /* Set up pointers to the individual character tables */ if (tables == NULL) tables = PRIV(default_tables); cd->lcc = tables + lcc_offset; cd->fcc = tables + fcc_offset; cd->cbits = tables + cbits_offset; cd->ctypes = tables + ctypes_offset; /* Check that all undefined public option bits are zero */ if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0) { errorcode = ERR17; goto PCRE_EARLY_ERROR_RETURN; } /* If PCRE_NEVER_UTF is set, remember it. */ if ((options & PCRE_NEVER_UTF) != 0) never_utf = TRUE; /* Check for global one-time settings at the start of the pattern, and remember the offset for later. */ cd->external_flags = 0; /* Initialize here for LIMIT_MATCH/RECURSION */ while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS && ptr[skipatstart+1] == CHAR_ASTERISK) { int newnl = 0; int newbsr = 0; /* For completeness and backward compatibility, (*UTFn) is supported in the relevant libraries, but (*UTF) is generic and always supported. Note that PCRE_UTF8 == PCRE_UTF16 == PCRE_UTF32. */ #ifdef COMPILE_PCRE8 if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF8_RIGHTPAR, 5) == 0) { skipatstart += 7; options |= PCRE_UTF8; continue; } #endif #ifdef COMPILE_PCRE16 if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF16_RIGHTPAR, 6) == 0) { skipatstart += 8; options |= PCRE_UTF16; continue; } #endif #ifdef COMPILE_PCRE32 if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF32_RIGHTPAR, 6) == 0) { skipatstart += 8; options |= PCRE_UTF32; continue; } #endif else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 4) == 0) { skipatstart += 6; options |= PCRE_UTF8; continue; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UCP_RIGHTPAR, 4) == 0) { skipatstart += 6; options |= PCRE_UCP; continue; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_AUTO_POSSESS_RIGHTPAR, 16) == 0) { skipatstart += 18; options |= PCRE_NO_AUTO_POSSESS; continue; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_START_OPT_RIGHTPAR, 13) == 0) { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; continue; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LIMIT_MATCH_EQ, 12) == 0) { pcre_uint32 c = 0; int p = skipatstart + 14; while (isdigit(ptr[p])) { if (c > PCRE_UINT32_MAX / 10 - 1) break; /* Integer overflow */ c = c*10 + ptr[p++] - CHAR_0; } if (ptr[p++] != CHAR_RIGHT_PARENTHESIS) break; if (c < limit_match) { limit_match = c; cd->external_flags |= PCRE_MLSET; } skipatstart = p; continue; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LIMIT_RECURSION_EQ, 16) == 0) { pcre_uint32 c = 0; int p = skipatstart + 18; while (isdigit(ptr[p])) { if (c > PCRE_UINT32_MAX / 10 - 1) break; /* Integer overflow check */ c = c*10 + ptr[p++] - CHAR_0; } if (ptr[p++] != CHAR_RIGHT_PARENTHESIS) break; if (c < limit_recursion) { limit_recursion = c; cd->external_flags |= PCRE_RLSET; } skipatstart = p; continue; } if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CR_RIGHTPAR, 3) == 0) { skipatstart += 5; newnl = PCRE_NEWLINE_CR; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LF_RIGHTPAR, 3) == 0) { skipatstart += 5; newnl = PCRE_NEWLINE_LF; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CRLF_RIGHTPAR, 5) == 0) { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANY_RIGHTPAR, 4) == 0) { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANYCRLF_RIGHTPAR, 8) == 0) { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_ANYCRLF_RIGHTPAR, 12) == 0) { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; } else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_UNICODE_RIGHTPAR, 12) == 0) { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; } if (newnl != 0) options = (options & ~PCRE_NEWLINE_BITS) | newnl; else if (newbsr != 0) options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr; else break; } /* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */ utf = (options & PCRE_UTF8) != 0; if (utf && never_utf) { errorcode = ERR78; goto PCRE_EARLY_ERROR_RETURN2; } /* Can't support UTF unless PCRE has been compiled to include the code. The return of an error code from PRIV(valid_utf)() is a new feature, introduced in release 8.13. It is passed back from pcre_[dfa_]exec(), but at the moment is not used here. */ #ifdef SUPPORT_UTF if (utf && (options & PCRE_NO_UTF8_CHECK) == 0 && (errorcode = PRIV(valid_utf)((PCRE_PUCHAR)pattern, -1, erroroffset)) != 0) { #if defined COMPILE_PCRE8 errorcode = ERR44; #elif defined COMPILE_PCRE16 errorcode = ERR74; #elif defined COMPILE_PCRE32 errorcode = ERR77; #endif goto PCRE_EARLY_ERROR_RETURN2; } #else if (utf) { errorcode = ERR32; goto PCRE_EARLY_ERROR_RETURN; } #endif /* Can't support UCP unless PCRE has been compiled to include the code. */ #ifndef SUPPORT_UCP if ((options & PCRE_UCP) != 0) { errorcode = ERR67; goto PCRE_EARLY_ERROR_RETURN; } #endif /* Check validity of \R options. */ if ((options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) { errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN; } /* Handle different types of newline. The three bits give seven cases. The current code allows for fixed one- or two-byte sequences, plus "any" and "anycrlf". */ switch (options & PCRE_NEWLINE_BITS) { case 0: newline = NEWLINE; break; /* Build-time default */ case PCRE_NEWLINE_CR: newline = CHAR_CR; break; case PCRE_NEWLINE_LF: newline = CHAR_NL; break; case PCRE_NEWLINE_CR+ PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; case PCRE_NEWLINE_ANY: newline = -1; break; case PCRE_NEWLINE_ANYCRLF: newline = -2; break; default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN; } if (newline == -2) { cd->nltype = NLTYPE_ANYCRLF; } else if (newline < 0) { cd->nltype = NLTYPE_ANY; } else { cd->nltype = NLTYPE_FIXED; if (newline > 255) { cd->nllen = 2; cd->nl[0] = (newline >> 8) & 255; cd->nl[1] = newline & 255; } else { cd->nllen = 1; cd->nl[0] = newline; } } /* Maximum back reference and backref bitmap. The bitmap records up to 31 back references to help in deciding whether (.*) can be treated as anchored or not. */ cd->top_backref = 0; cd->backref_map = 0; /* Reflect pattern for debugging output */ DPRINTF(("------------------------------------------------------------------\n")); #ifdef PCRE_DEBUG print_puchar(stdout, (PCRE_PUCHAR)pattern); #endif DPRINTF(("\n")); /* Pretend to compile the pattern while actually just accumulating the length of memory required. This behaviour is triggered by passing a non-NULL final argument to compile_regex(). We pass a block of workspace (cworkspace) for it to compile parts of the pattern into; the compiled code is discarded when it is no longer needed, so hopefully this workspace will never overflow, though there is a test for its doing so. */ cd->bracount = cd->final_bracount = 0; cd->names_found = 0; cd->name_entry_size = 0; cd->name_table = NULL; cd->dupnames = FALSE; cd->dupgroups = FALSE; cd->namedrefcount = 0; cd->start_code = cworkspace; cd->hwm = cworkspace; cd->iscondassert = FALSE; cd->start_workspace = cworkspace; cd->workspace_size = COMPILE_WORK_SIZE; cd->named_groups = named_groups; cd->named_group_list_size = NAMED_GROUP_LIST_SIZE; cd->start_pattern = (const pcre_uchar *)pattern; cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern)); cd->req_varyopt = 0; cd->parens_depth = 0; cd->assert_depth = 0; cd->max_lookbehind = 0; cd->external_options = options; cd->open_caps = NULL; /* Now do the pre-compile. On error, errorcode will be set non-zero, so we don't need to look at the result of the function here. The initial options have been put into the cd block so that they can be changed if an option setting is found within the regex right at the beginning. Bringing initial option settings outside can help speed up starting point checks. */ ptr += skipatstart; code = cworkspace; *code = OP_BRA; (void)compile_regex(cd->external_options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0, &firstchar, &firstcharflags, &reqchar, &reqcharflags, NULL, cd, &length); if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, (int)(cd->hwm - cworkspace))); if (length > MAX_PATTERN_SIZE) { errorcode = ERR20; goto PCRE_EARLY_ERROR_RETURN; } /* Compute the size of the data block for storing the compiled pattern. Integer overflow should no longer be possible because nowadays we limit the maximum value of cd->names_found and cd->name_entry_size. */ size = sizeof(REAL_PCRE) + (length + cd->names_found * cd->name_entry_size) * sizeof(pcre_uchar); /* Get the memory. */ re = (REAL_PCRE *)(PUBL(malloc))(size); if (re == NULL) { errorcode = ERR21; goto PCRE_EARLY_ERROR_RETURN; } /* Put in the magic number, and save the sizes, initial options, internal flags, and character table pointer. NULL is used for the default character tables. The nullpad field is at the end; it's there to help in the case when a regex compiled on a system with 4-byte pointers is run on another with 8-byte pointers. */ re->magic_number = MAGIC_NUMBER; re->size = (int)size; re->options = cd->external_options; re->flags = cd->external_flags; re->limit_match = limit_match; re->limit_recursion = limit_recursion; re->first_char = 0; re->req_char = 0; re->name_table_offset = sizeof(REAL_PCRE) / sizeof(pcre_uchar); re->name_entry_size = cd->name_entry_size; re->name_count = cd->names_found; re->ref_count = 0; re->tables = (tables == PRIV(default_tables))? NULL : tables; re->nullpad = NULL; #ifdef COMPILE_PCRE32 re->dummy = 0; #else re->dummy1 = re->dummy2 = re->dummy3 = 0; #endif /* The starting points of the name/number translation table and of the code are passed around in the compile data block. The start/end pattern and initial options are already set from the pre-compile phase, as is the name_entry_size field. Reset the bracket count and the names_found field. Also reset the hwm field; this time it's used for remembering forward references to subpatterns. */ cd->final_bracount = cd->bracount; /* Save for checking forward references */ cd->parens_depth = 0; cd->assert_depth = 0; cd->bracount = 0; cd->max_lookbehind = 0; cd->name_table = (pcre_uchar *)re + re->name_table_offset; codestart = cd->name_table + re->name_entry_size * re->name_count; cd->start_code = codestart; cd->hwm = (pcre_uchar *)(cd->start_workspace); cd->iscondassert = FALSE; cd->req_varyopt = 0; cd->had_accept = FALSE; cd->had_pruneorskip = FALSE; cd->check_lookbehind = FALSE; cd->open_caps = NULL; /* If any named groups were found, create the name/number table from the list created in the first pass. */ if (cd->names_found > 0) { int i = cd->names_found; named_group *ng = cd->named_groups; cd->names_found = 0; for (; i > 0; i--, ng++) add_name(cd, ng->name, ng->length, ng->number); if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE) (PUBL(free))((void *)cd->named_groups); } /* Set up a starting, non-extracting bracket, then compile the expression. On error, errorcode will be set non-zero, so we don't need to look at the result of the function here. */ ptr = (const pcre_uchar *)pattern + skipatstart; code = (pcre_uchar *)codestart; *code = OP_BRA; (void)compile_regex(re->options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0, &firstchar, &firstcharflags, &reqchar, &reqcharflags, NULL, cd, NULL); re->top_bracket = cd->bracount; re->top_backref = cd->top_backref; re->max_lookbehind = cd->max_lookbehind; re->flags = cd->external_flags | PCRE_MODE; if (cd->had_accept) { reqchar = 0; /* Must disable after (*ACCEPT) */ reqcharflags = REQ_NONE; } /* If not reached end of pattern on success, there's an excess bracket. */ if (errorcode == 0 && *ptr != CHAR_NULL) errorcode = ERR22; /* Fill in the terminating state and check for disastrous overflow, but if debugging, leave the test till after things are printed out. */ *code++ = OP_END; #ifndef PCRE_DEBUG if (code - codestart > length) errorcode = ERR23; #endif #ifdef SUPPORT_VALGRIND /* If the estimated length exceeds the really used length, mark the extra allocated memory as unaddressable, so that any out-of-bound reads can be detected. */ VALGRIND_MAKE_MEM_NOACCESS(code, (length - (code - codestart)) * sizeof(pcre_uchar)); #endif /* Fill in any forward references that are required. There may be repeated references; optimize for them, as searching a large regex takes time. */ if (cd->hwm > cd->start_workspace) { int prev_recno = -1; const pcre_uchar *groupptr = NULL; while (errorcode == 0 && cd->hwm > cd->start_workspace) { int offset, recno; cd->hwm -= LINK_SIZE; offset = GET(cd->hwm, 0); /* Check that the hwm handling hasn't gone wrong. This whole area is rewritten in PCRE2 because there are some obscure cases. */ if (offset == 0 || codestart[offset-1] != OP_RECURSE) { errorcode = ERR10; break; } recno = GET(codestart, offset); if (recno != prev_recno) { groupptr = PRIV(find_bracket)(codestart, utf, recno); prev_recno = recno; } if (groupptr == NULL) errorcode = ERR53; else PUT(((pcre_uchar *)codestart), offset, (int)(groupptr - codestart)); } } /* If the workspace had to be expanded, free the new memory. Set the pointer to NULL to indicate that forward references have been filled in. */ if (cd->workspace_size > COMPILE_WORK_SIZE) (PUBL(free))((void *)cd->start_workspace); cd->start_workspace = NULL; /* Give an error if there's back reference to a non-existent capturing subpattern. */ if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15; /* Unless disabled, check whether any single character iterators can be auto-possessified. The function overwrites the appropriate opcode values, so the type of the pointer must be cast. NOTE: the intermediate variable "temp" is used in this code because at least one compiler gives a warning about loss of "const" attribute if the cast (pcre_uchar *)codestart is used directly in the function call. */ if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0) { pcre_uchar *temp = (pcre_uchar *)codestart; auto_possessify(temp, utf, cd); } /* If there were any lookbehind assertions that contained OP_RECURSE (recursions or subroutine calls), a flag is set for them to be checked here, because they may contain forward references. Actual recursions cannot be fixed length, but subroutine calls can. It is done like this so that those without OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The exceptional ones forgo this. We scan the pattern to check that they are fixed length, and set their lengths. */ if (errorcode == 0 && cd->check_lookbehind) { pcre_uchar *cc = (pcre_uchar *)codestart; /* Loop, searching for OP_REVERSE items, and process those that do not have their length set. (Actually, it will also re-process any that have a length of zero, but that is a pathological case, and it does no harm.) When we find one, we temporarily terminate the branch it is in while we scan it. */ for (cc = (pcre_uchar *)PRIV(find_bracket)(codestart, utf, -1); cc != NULL; cc = (pcre_uchar *)PRIV(find_bracket)(cc, utf, -1)) { if (GET(cc, 1) == 0) { int fixed_length; pcre_uchar *be = cc - 1 - LINK_SIZE + GET(cc, -LINK_SIZE); int end_op = *be; *be = OP_END; fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE, cd, NULL); *be = end_op; DPRINTF(("fixed length = %d\n", fixed_length)); if (fixed_length < 0) { errorcode = (fixed_length == -2)? ERR36 : (fixed_length == -4)? ERR70 : ERR25; break; } if (fixed_length > cd->max_lookbehind) cd->max_lookbehind = fixed_length; PUT(cc, 1, fixed_length); } cc += 1 + LINK_SIZE; } } /* Failed to compile, or error while post-processing */ if (errorcode != 0) { (PUBL(free))(re); PCRE_EARLY_ERROR_RETURN: *erroroffset = (int)(ptr - (const pcre_uchar *)pattern); PCRE_EARLY_ERROR_RETURN2: *errorptr = find_error_text(errorcode); if (errorcodeptr != NULL) *errorcodeptr = errorcode; return NULL; } /* If the anchored option was not passed, set the flag if we can determine that the pattern is anchored by virtue of ^ characters or \A or anything else, such as starting with non-atomic .* when DOTALL is set and there are no occurrences of *PRUNE or *SKIP. Otherwise, if we know what the first byte has to be, save it, because that speeds up unanchored matches no end. If not, see if we can set the PCRE_STARTLINE flag. This is helpful for multiline matches when all branches start with ^. and also when all branches start with non-atomic .* for non-DOTALL matches when *PRUNE and SKIP are not present. */ if ((re->options & PCRE_ANCHORED) == 0) { if (is_anchored(codestart, 0, cd, 0)) re->options |= PCRE_ANCHORED; else { if (firstcharflags < 0) firstchar = find_firstassertedchar(codestart, &firstcharflags, FALSE); if (firstcharflags >= 0) /* Remove caseless flag for non-caseable chars */ { #if defined COMPILE_PCRE8 re->first_char = firstchar & 0xff; #elif defined COMPILE_PCRE16 re->first_char = firstchar & 0xffff; #elif defined COMPILE_PCRE32 re->first_char = firstchar; #endif if ((firstcharflags & REQ_CASELESS) != 0) { #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) /* We ignore non-ASCII first chars in 8 bit mode. */ if (utf) { if (re->first_char < 128) { if (cd->fcc[re->first_char] != re->first_char) re->flags |= PCRE_FCH_CASELESS; } else if (UCD_OTHERCASE(re->first_char) != re->first_char) re->flags |= PCRE_FCH_CASELESS; } else #endif if (MAX_255(re->first_char) && cd->fcc[re->first_char] != re->first_char) re->flags |= PCRE_FCH_CASELESS; } re->flags |= PCRE_FIRSTSET; } else if (is_startline(codestart, 0, cd, 0, FALSE)) re->flags |= PCRE_STARTLINE; } } /* For an anchored pattern, we use the "required byte" only if it follows a variable length item in the regex. Remove the caseless flag for non-caseable bytes. */ if (reqcharflags >= 0 && ((re->options & PCRE_ANCHORED) == 0 || (reqcharflags & REQ_VARY) != 0)) { #if defined COMPILE_PCRE8 re->req_char = reqchar & 0xff; #elif defined COMPILE_PCRE16 re->req_char = reqchar & 0xffff; #elif defined COMPILE_PCRE32 re->req_char = reqchar; #endif if ((reqcharflags & REQ_CASELESS) != 0) { #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) /* We ignore non-ASCII first chars in 8 bit mode. */ if (utf) { if (re->req_char < 128) { if (cd->fcc[re->req_char] != re->req_char) re->flags |= PCRE_RCH_CASELESS; } else if (UCD_OTHERCASE(re->req_char) != re->req_char) re->flags |= PCRE_RCH_CASELESS; } else #endif if (MAX_255(re->req_char) && cd->fcc[re->req_char] != re->req_char) re->flags |= PCRE_RCH_CASELESS; } re->flags |= PCRE_REQCHSET; } /* Print out the compiled data if debugging is enabled. This is never the case when building a production library. */ #ifdef PCRE_DEBUG printf("Length = %d top_bracket = %d top_backref = %d\n", length, re->top_bracket, re->top_backref); printf("Options=%08x\n", re->options); if ((re->flags & PCRE_FIRSTSET) != 0) { pcre_uchar ch = re->first_char; const char *caseless = ((re->flags & PCRE_FCH_CASELESS) == 0)? "" : " (caseless)"; if (PRINTABLE(ch)) printf("First char = %c%s\n", ch, caseless); else printf("First char = \\x%02x%s\n", ch, caseless); } if ((re->flags & PCRE_REQCHSET) != 0) { pcre_uchar ch = re->req_char; const char *caseless = ((re->flags & PCRE_RCH_CASELESS) == 0)? "" : " (caseless)"; if (PRINTABLE(ch)) printf("Req char = %c%s\n", ch, caseless); else printf("Req char = \\x%02x%s\n", ch, caseless); } #if defined COMPILE_PCRE8 pcre_printint((pcre *)re, stdout, TRUE); #elif defined COMPILE_PCRE16 pcre16_printint((pcre *)re, stdout, TRUE); #elif defined COMPILE_PCRE32 pcre32_printint((pcre *)re, stdout, TRUE); #endif /* This check is done here in the debugging case so that the code that was compiled can be seen. */ if (code - codestart > length) { (PUBL(free))(re); *errorptr = find_error_text(ERR23); *erroroffset = ptr - (pcre_uchar *)pattern; if (errorcodeptr != NULL) *errorcodeptr = ERR23; return NULL; } #endif /* PCRE_DEBUG */ /* Check for a pattern than can match an empty string, so that this information can be provided to applications. */ do { if (could_be_empty_branch(codestart, code, utf, cd, NULL)) { re->flags |= PCRE_MATCH_EMPTY; break; } codestart += GET(codestart, 1); } while (*codestart == OP_ALT); #if defined COMPILE_PCRE8 return (pcre *)re; #elif defined COMPILE_PCRE16 return (pcre16 *)re; #elif defined COMPILE_PCRE32 return (pcre32 *)re; #endif } /* End of pcre_compile.c */ ================================================ FILE: src/pcre/pcre_config.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_config(). */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Keep the original link size. */ static int real_link_size = LINK_SIZE; #include "pcre_internal.h" /************************************************* * Return info about what features are configured * *************************************************/ /* This function has an extensible interface so that additional items can be added compatibly. Arguments: what what information is required where where to put the information Returns: 0 if data returned, negative on error */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_config(int what, void *where) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_config(int what, void *where) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_config(int what, void *where) #endif { switch (what) { case PCRE_CONFIG_UTF8: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 *((int *)where) = 0; return PCRE_ERROR_BADOPTION; #else #if defined SUPPORT_UTF *((int *)where) = 1; #else *((int *)where) = 0; #endif break; #endif case PCRE_CONFIG_UTF16: #if defined COMPILE_PCRE8 || defined COMPILE_PCRE32 *((int *)where) = 0; return PCRE_ERROR_BADOPTION; #else #if defined SUPPORT_UTF *((int *)where) = 1; #else *((int *)where) = 0; #endif break; #endif case PCRE_CONFIG_UTF32: #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 *((int *)where) = 0; return PCRE_ERROR_BADOPTION; #else #if defined SUPPORT_UTF *((int *)where) = 1; #else *((int *)where) = 0; #endif break; #endif case PCRE_CONFIG_UNICODE_PROPERTIES: #ifdef SUPPORT_UCP *((int *)where) = 1; #else *((int *)where) = 0; #endif break; case PCRE_CONFIG_JIT: #ifdef SUPPORT_JIT *((int *)where) = 1; #else *((int *)where) = 0; #endif break; case PCRE_CONFIG_JITTARGET: #ifdef SUPPORT_JIT *((const char **)where) = PRIV(jit_get_target)(); #else *((const char **)where) = NULL; #endif break; case PCRE_CONFIG_NEWLINE: *((int *)where) = NEWLINE; break; case PCRE_CONFIG_BSR: #ifdef BSR_ANYCRLF *((int *)where) = 1; #else *((int *)where) = 0; #endif break; case PCRE_CONFIG_LINK_SIZE: *((int *)where) = real_link_size; break; case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: *((int *)where) = POSIX_MALLOC_THRESHOLD; break; case PCRE_CONFIG_PARENS_LIMIT: *((unsigned long int *)where) = PARENS_NEST_LIMIT; break; case PCRE_CONFIG_MATCH_LIMIT: *((unsigned long int *)where) = MATCH_LIMIT; break; case PCRE_CONFIG_MATCH_LIMIT_RECURSION: *((unsigned long int *)where) = MATCH_LIMIT_RECURSION; break; case PCRE_CONFIG_STACKRECURSE: #ifdef NO_RECURSE *((int *)where) = 0; #else *((int *)where) = 1; #endif break; default: return PCRE_ERROR_BADOPTION; } return 0; } /* End of pcre_config.c */ ================================================ FILE: src/pcre/pcre_dfa_exec.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language (but see below for why this module is different). Written by Philip Hazel Copyright (c) 1997-2017 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_dfa_exec(), which is an alternative matching function that uses a sort of DFA algorithm (not a true FSM). This is NOT Perl-compatible, but it has advantages in certain applications. */ /* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved the performance of his patterns greatly. I could not use it as it stood, as it was not thread safe, and made assumptions about pattern sizes. Also, it caused test 7 to loop, and test 9 to crash with a segfault. The issue is the check for duplicate states, which is done by a simple linear search up the state list. (Grep for "duplicate" below to find the code.) For many patterns, there will never be many states active at one time, so a simple linear search is fine. In patterns that have many active states, it might be a bottleneck. The suggested code used an indexing scheme to remember which states had previously been used for each character, and avoided the linear search when it knew there was no chance of a duplicate. This was implemented when adding states to the state lists. I wrote some thread-safe, not-limited code to try something similar at the time of checking for duplicates (instead of when adding states), using index vectors on the stack. It did give a 13% improvement with one specially constructed pattern for certain subject strings, but on other strings and on many of the simpler patterns in the test suite it did worse. The major problem, I think, was the extra time to initialize the index. This had to be done for each call of internal_dfa_exec(). (The supplied patch used a static vector, initialized only once - I suspect this was the cause of the problems with the tests.) Overall, I concluded that the gains in some cases did not outweigh the losses in others, so I abandoned this code. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define NLBLOCK md /* Block containing newline information */ #define PSSTART start_subject /* Field containing processed string start */ #define PSEND end_subject /* Field containing processed string end */ #include "pcre_internal.h" /* For use to indent debugging output */ #define SP " " /************************************************* * Code parameters and static tables * *************************************************/ /* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes into others, under special conditions. A gap of 20 between the blocks should be enough. The resulting opcodes don't have to be less than 256 because they are never stored, so we push them well clear of the normal opcodes. */ #define OP_PROP_EXTRA 300 #define OP_EXTUNI_EXTRA 320 #define OP_ANYNL_EXTRA 340 #define OP_HSPACE_EXTRA 360 #define OP_VSPACE_EXTRA 380 /* This table identifies those opcodes that are followed immediately by a character that is to be tested in some way. This makes it possible to centralize the loading of these characters. In the case of Type * etc, the "character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a small value. Non-zero values in the table are the offsets from the opcode where the character is to be found. ***NOTE*** If the start of this table is modified, the three tables that follow must also be modified. */ static const pcre_uint8 coptable[] = { 0, /* End */ 0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */ 0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */ 0, 0, 0, /* Any, AllAny, Anybyte */ 0, 0, /* \P, \p */ 0, 0, 0, 0, 0, /* \R, \H, \h, \V, \v */ 0, /* \X */ 0, 0, 0, 0, 0, 0, /* \Z, \z, $, $M, ^, ^M */ 1, /* Char */ 1, /* Chari */ 1, /* not */ 1, /* noti */ /* Positive single-char repeats */ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto, minupto */ 1+IMM2_SIZE, /* exact */ 1, 1, 1, 1+IMM2_SIZE, /* *+, ++, ?+, upto+ */ 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */ 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto I, minupto I */ 1+IMM2_SIZE, /* exact I */ 1, 1, 1, 1+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ /* Negative single-char repeats - only for chars < 256 */ 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto, minupto */ 1+IMM2_SIZE, /* NOT exact */ 1, 1, 1, 1+IMM2_SIZE, /* NOT *+, ++, ?+, upto+ */ 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */ 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto I, minupto I */ 1+IMM2_SIZE, /* NOT exact I */ 1, 1, 1, 1+IMM2_SIZE, /* NOT *+I, ++I, ?+I, upto+I */ /* Positive type repeats */ 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ 1+IMM2_SIZE, 1+IMM2_SIZE, /* Type upto, minupto */ 1+IMM2_SIZE, /* Type exact */ 1, 1, 1, 1+IMM2_SIZE, /* Type *+, ++, ?+, upto+ */ /* Character class & ref repeats */ 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */ 0, 0, /* CRRANGE, CRMINRANGE */ 0, 0, 0, 0, /* Possessive *+, ++, ?+, CRPOSRANGE */ 0, /* CLASS */ 0, /* NCLASS */ 0, /* XCLASS - variable length */ 0, /* REF */ 0, /* REFI */ 0, /* DNREF */ 0, /* DNREFI */ 0, /* RECURSE */ 0, /* CALLOUT */ 0, /* Alt */ 0, /* Ket */ 0, /* KetRmax */ 0, /* KetRmin */ 0, /* KetRpos */ 0, /* Reverse */ 0, /* Assert */ 0, /* Assert not */ 0, /* Assert behind */ 0, /* Assert behind not */ 0, 0, /* ONCE, ONCE_NC */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ 0, 0, /* CREF, DNCREF */ 0, 0, /* RREF, DNRREF */ 0, /* DEF */ 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ 0, 0 /* CLOSE, SKIPZERO */ }; /* This table identifies those opcodes that inspect a character. It is used to remember the fact that a character could have been inspected when the end of the subject is reached. ***NOTE*** If the start of this table is modified, the two tables that follow must also be modified. */ static const pcre_uint8 poptable[] = { 0, /* End */ 0, 0, 0, 1, 1, /* \A, \G, \K, \B, \b */ 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ 1, 1, 1, /* Any, AllAny, Anybyte */ 1, 1, /* \P, \p */ 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ 1, /* \X */ 0, 0, 0, 0, 0, 0, /* \Z, \z, $, $M, ^, ^M */ 1, /* Char */ 1, /* Chari */ 1, /* not */ 1, /* noti */ /* Positive single-char repeats */ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ 1, 1, 1, /* upto, minupto, exact */ 1, 1, 1, 1, /* *+, ++, ?+, upto+ */ 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */ 1, 1, 1, /* upto I, minupto I, exact I */ 1, 1, 1, 1, /* *+I, ++I, ?+I, upto+I */ /* Negative single-char repeats - only for chars < 256 */ 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ 1, 1, 1, /* NOT upto, minupto, exact */ 1, 1, 1, 1, /* NOT *+, ++, ?+, upto+ */ 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */ 1, 1, 1, /* NOT upto I, minupto I, exact I */ 1, 1, 1, 1, /* NOT *+I, ++I, ?+I, upto+I */ /* Positive type repeats */ 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ 1, 1, 1, /* Type upto, minupto, exact */ 1, 1, 1, 1, /* Type *+, ++, ?+, upto+ */ /* Character class & ref repeats */ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ 1, 1, /* CRRANGE, CRMINRANGE */ 1, 1, 1, 1, /* Possessive *+, ++, ?+, CRPOSRANGE */ 1, /* CLASS */ 1, /* NCLASS */ 1, /* XCLASS - variable length */ 0, /* REF */ 0, /* REFI */ 0, /* DNREF */ 0, /* DNREFI */ 0, /* RECURSE */ 0, /* CALLOUT */ 0, /* Alt */ 0, /* Ket */ 0, /* KetRmax */ 0, /* KetRmin */ 0, /* KetRpos */ 0, /* Reverse */ 0, /* Assert */ 0, /* Assert not */ 0, /* Assert behind */ 0, /* Assert behind not */ 0, 0, /* ONCE, ONCE_NC */ 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ 0, 0, /* CREF, DNCREF */ 0, 0, /* RREF, DNRREF */ 0, /* DEF */ 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */ 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ 0, 0 /* CLOSE, SKIPZERO */ }; /* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, and \w */ static const pcre_uint8 toptable1[] = { 0, 0, 0, 0, 0, 0, ctype_digit, ctype_digit, ctype_space, ctype_space, ctype_word, ctype_word, 0, 0 /* OP_ANY, OP_ALLANY */ }; static const pcre_uint8 toptable2[] = { 0, 0, 0, 0, 0, 0, ctype_digit, 0, ctype_space, 0, ctype_word, 0, 1, 1 /* OP_ANY, OP_ALLANY */ }; /* Structure for holding data about a particular state, which is in effect the current data for an active path through the match tree. It must consist entirely of ints because the working vector we are passed, and which we put these structures in, is a vector of ints. */ typedef struct stateblock { int offset; /* Offset to opcode */ int count; /* Count for repeats */ int data; /* Some use extra data */ } stateblock; #define INTS_PER_STATEBLOCK (int)(sizeof(stateblock)/sizeof(int)) #ifdef PCRE_DEBUG /************************************************* * Print character string * *************************************************/ /* Character string printing function for debugging. Arguments: p points to string length number of bytes f where to print Returns: nothing */ static void pchars(const pcre_uchar *p, int length, FILE *f) { pcre_uint32 c; while (length-- > 0) { if (isprint(c = *(p++))) fprintf(f, "%c", c); else fprintf(f, "\\x{%02x}", c); } } #endif /************************************************* * Execute a Regular Expression - DFA engine * *************************************************/ /* This internal function applies a compiled pattern to a subject string, starting at a given point, using a DFA engine. This function is called from the external one, possibly multiple times if the pattern is not anchored. The function calls itself recursively for some kinds of subpattern. Arguments: md the match_data block with fixed information this_start_code the opening bracket of this subexpression's code current_subject where we currently are in the subject string start_offset start offset in the subject string offsets vector to contain the matching string offsets offsetcount size of same workspace vector of workspace wscount size of same rlevel function call recursion level Returns: > 0 => number of match offset pairs placed in offsets = 0 => offsets overflowed; longest matches are present -1 => failed to match < -1 => some kind of unexpected problem The following macros are used for adding states to the two state vectors (one for the current character, one for the following character). */ #define ADD_ACTIVE(x,y) \ if (active_count++ < wscount) \ { \ next_active_state->offset = (x); \ next_active_state->count = (y); \ next_active_state++; \ DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ } \ else return PCRE_ERROR_DFA_WSSIZE #define ADD_ACTIVE_DATA(x,y,z) \ if (active_count++ < wscount) \ { \ next_active_state->offset = (x); \ next_active_state->count = (y); \ next_active_state->data = (z); \ next_active_state++; \ DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \ } \ else return PCRE_ERROR_DFA_WSSIZE #define ADD_NEW(x,y) \ if (new_count++ < wscount) \ { \ next_new_state->offset = (x); \ next_new_state->count = (y); \ next_new_state++; \ DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ } \ else return PCRE_ERROR_DFA_WSSIZE #define ADD_NEW_DATA(x,y,z) \ if (new_count++ < wscount) \ { \ next_new_state->offset = (x); \ next_new_state->count = (y); \ next_new_state->data = (z); \ next_new_state++; \ DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \ (x), (y), (z), __LINE__)); \ } \ else return PCRE_ERROR_DFA_WSSIZE /* And now, here is the code */ static int internal_dfa_exec( dfa_match_data *md, const pcre_uchar *this_start_code, const pcre_uchar *current_subject, int start_offset, int *offsets, int offsetcount, int *workspace, int wscount, int rlevel) { stateblock *active_states, *new_states, *temp_states; stateblock *next_active_state, *next_new_state; const pcre_uint8 *ctypes, *lcc, *fcc; const pcre_uchar *ptr; const pcre_uchar *end_code, *first_op; dfa_recursion_info new_recursive; int active_count, new_count, match_count; /* Some fields in the md block are frequently referenced, so we load them into independent variables in the hope that this will perform better. */ const pcre_uchar *start_subject = md->start_subject; const pcre_uchar *end_subject = md->end_subject; const pcre_uchar *start_code = md->start_code; #ifdef SUPPORT_UTF BOOL utf = (md->poptions & PCRE_UTF8) != 0; #else BOOL utf = FALSE; #endif BOOL reset_could_continue = FALSE; rlevel++; offsetcount &= (-2); wscount -= 2; wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) / (2 * INTS_PER_STATEBLOCK); DPRINTF(("\n%.*s---------------------\n" "%.*sCall to internal_dfa_exec f=%d\n", rlevel*2-2, SP, rlevel*2-2, SP, rlevel)); ctypes = md->tables + ctypes_offset; lcc = md->tables + lcc_offset; fcc = md->tables + fcc_offset; match_count = PCRE_ERROR_NOMATCH; /* A negative number */ active_states = (stateblock *)(workspace + 2); next_new_state = new_states = active_states + wscount; new_count = 0; first_op = this_start_code + 1 + LINK_SIZE + ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) ? IMM2_SIZE:0); /* The first thing in any (sub) pattern is a bracket of some sort. Push all the alternative states onto the list, and find out where the end is. This makes is possible to use this function recursively, when we want to stop at a matching internal ket rather than at the end. If the first opcode in the first alternative is OP_REVERSE, we are dealing with a backward assertion. In that case, we have to find out the maximum amount to move back, and set up each alternative appropriately. */ if (*first_op == OP_REVERSE) { int max_back = 0; int gone_back; end_code = this_start_code; do { int back = GET(end_code, 2+LINK_SIZE); if (back > max_back) max_back = back; end_code += GET(end_code, 1); } while (*end_code == OP_ALT); /* If we can't go back the amount required for the longest lookbehind pattern, go back as far as we can; some alternatives may still be viable. */ #ifdef SUPPORT_UTF /* In character mode we have to step back character by character */ if (utf) { for (gone_back = 0; gone_back < max_back; gone_back++) { if (current_subject <= start_subject) break; current_subject--; ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--); } } else #endif /* In byte-mode we can do this quickly. */ { gone_back = (current_subject - max_back < start_subject)? (int)(current_subject - start_subject) : max_back; current_subject -= gone_back; } /* Save the earliest consulted character */ if (current_subject < md->start_used_ptr) md->start_used_ptr = current_subject; /* Now we can process the individual branches. */ end_code = this_start_code; do { int back = GET(end_code, 2+LINK_SIZE); if (back <= gone_back) { int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE); ADD_NEW_DATA(-bstate, 0, gone_back - back); } end_code += GET(end_code, 1); } while (*end_code == OP_ALT); } /* This is the code for a "normal" subpattern (not a backward assertion). The start of a whole pattern is always one of these. If we are at the top level, we may be asked to restart matching from the same point that we reached for a previous partial match. We still have to scan through the top-level branches to find the end state. */ else { end_code = this_start_code; /* Restarting */ if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0) { do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT); new_count = workspace[1]; if (!workspace[0]) memcpy(new_states, active_states, new_count * sizeof(stateblock)); } /* Not restarting */ else { int length = 1 + LINK_SIZE + ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) ? IMM2_SIZE:0); do { ADD_NEW((int)(end_code - start_code + length), 0); end_code += GET(end_code, 1); length = 1 + LINK_SIZE; } while (*end_code == OP_ALT); } } workspace[0] = 0; /* Bit indicating which vector is current */ DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code))); /* Loop for scanning the subject */ ptr = current_subject; for (;;) { int i, j; int clen, dlen; pcre_uint32 c, d; int forced_fail = 0; BOOL partial_newline = FALSE; BOOL could_continue = reset_could_continue; reset_could_continue = FALSE; /* Make the new state list into the active state list and empty the new state list. */ temp_states = active_states; active_states = new_states; new_states = temp_states; active_count = new_count; new_count = 0; workspace[0] ^= 1; /* Remember for the restarting feature */ workspace[1] = active_count; #ifdef PCRE_DEBUG printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP); pchars(ptr, STRLEN_UC(ptr), stdout); printf("\"\n"); printf("%.*sActive states: ", rlevel*2-2, SP); for (i = 0; i < active_count; i++) printf("%d/%d ", active_states[i].offset, active_states[i].count); printf("\n"); #endif /* Set the pointers for adding new states */ next_active_state = active_states + active_count; next_new_state = new_states; /* Load the current character from the subject outside the loop, as many different states may want to look at it, and we assume that at least one will. */ if (ptr < end_subject) { clen = 1; /* Number of data items in the character */ #ifdef SUPPORT_UTF GETCHARLENTEST(c, ptr, clen); #else c = *ptr; #endif /* SUPPORT_UTF */ } else { clen = 0; /* This indicates the end of the subject */ c = NOTACHAR; /* This value should never actually be used */ } /* Scan up the active states and act on each one. The result of an action may be to add more states to the currently active list (e.g. on hitting a parenthesis) or it may be to put states on the new list, for considering when we move the character pointer on. */ for (i = 0; i < active_count; i++) { stateblock *current_state = active_states + i; BOOL caseless = FALSE; const pcre_uchar *code; int state_offset = current_state->offset; int codevalue, rrc; int count; #ifdef PCRE_DEBUG printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset); if (clen == 0) printf("EOL\n"); else if (c > 32 && c < 127) printf("'%c'\n", c); else printf("0x%02x\n", c); #endif /* A negative offset is a special case meaning "hold off going to this (negated) state until the number of characters in the data field have been skipped". If the could_continue flag was passed over from a previous state, arrange for it to passed on. */ if (state_offset < 0) { if (current_state->data > 0) { DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP)); ADD_NEW_DATA(state_offset, current_state->count, current_state->data - 1); if (could_continue) reset_could_continue = TRUE; continue; } else { current_state->offset = state_offset = -state_offset; } } /* Check for a duplicate state with the same count, and skip if found. See the note at the head of this module about the possibility of improving performance here. */ for (j = 0; j < i; j++) { if (active_states[j].offset == state_offset && active_states[j].count == current_state->count) { DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP)); goto NEXT_ACTIVE_STATE; } } /* The state offset is the offset to the opcode */ code = start_code + state_offset; codevalue = *code; /* If this opcode inspects a character, but we are at the end of the subject, remember the fact for use when testing for a partial match. */ if (clen == 0 && poptable[codevalue] != 0) could_continue = TRUE; /* If this opcode is followed by an inline character, load it. It is tempting to test for the presence of a subject character here, but that is wrong, because sometimes zero repetitions of the subject are permitted. We also use this mechanism for opcodes such as OP_TYPEPLUS that take an argument that is not a data character - but is always one byte long because the values are small. We have to take special action to deal with \P, \p, \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert these ones to new opcodes. */ if (coptable[codevalue] > 0) { dlen = 1; #ifdef SUPPORT_UTF if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else #endif /* SUPPORT_UTF */ d = code[coptable[codevalue]]; if (codevalue >= OP_TYPESTAR) { switch(d) { case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM; case OP_NOTPROP: case OP_PROP: codevalue += OP_PROP_EXTRA; break; case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break; case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break; case OP_NOT_HSPACE: case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break; case OP_NOT_VSPACE: case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break; default: break; } } } else { dlen = 0; /* Not strictly necessary, but compilers moan */ d = NOTACHAR; /* if these variables are not set. */ } /* Now process the individual opcodes */ switch (codevalue) { /* ========================================================================== */ /* These cases are never obeyed. This is a fudge that causes a compile- time error if the vectors coptable or poptable, which are indexed by opcode, are not the correct length. It seems to be the only way to do such a check at compile time, as the sizeof() operator does not work in the C preprocessor. */ case OP_TABLE_LENGTH: case OP_TABLE_LENGTH + ((sizeof(coptable) == OP_TABLE_LENGTH) && (sizeof(poptable) == OP_TABLE_LENGTH)): break; /* ========================================================================== */ /* Reached a closing bracket. If not at the end of the pattern, carry on with the next opcode. For repeating opcodes, also add the repeat state. Note that KETRPOS will always be encountered at the end of the subpattern, because the possessive subpattern repeats are always handled using recursive calls. Thus, it never adds any new states. At the end of the (sub)pattern, unless we have an empty string and PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the start of the subject, save the match data, shifting up all previous matches so we always have the longest first. */ case OP_KET: case OP_KETRMIN: case OP_KETRMAX: case OP_KETRPOS: if (code != end_code) { ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0); if (codevalue != OP_KET) { ADD_ACTIVE(state_offset - GET(code, 1), 0); } } else { if (ptr > current_subject || ((md->moptions & PCRE_NOTEMPTY) == 0 && ((md->moptions & PCRE_NOTEMPTY_ATSTART) == 0 || current_subject > start_subject + md->start_offset))) { if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0; else if (match_count > 0 && ++match_count * 2 > offsetcount) match_count = 0; count = ((match_count == 0)? offsetcount : match_count * 2) - 2; if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int)); if (offsetcount >= 2) { offsets[0] = (int)(current_subject - start_subject); offsets[1] = (int)(ptr - start_subject); DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP, offsets[1] - offsets[0], (char *)current_subject)); } if ((md->moptions & PCRE_DFA_SHORTEST) != 0) { DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count, rlevel*2-2, SP)); return match_count; } } } break; /* ========================================================================== */ /* These opcodes add to the current list of states without looking at the current character. */ /*-----------------------------------------------------------------*/ case OP_ALT: do { code += GET(code, 1); } while (*code == OP_ALT); ADD_ACTIVE((int)(code - start_code), 0); break; /*-----------------------------------------------------------------*/ case OP_BRA: case OP_SBRA: do { ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); code += GET(code, 1); } while (*code == OP_ALT); break; /*-----------------------------------------------------------------*/ case OP_CBRA: case OP_SCBRA: ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE), 0); code += GET(code, 1); while (*code == OP_ALT) { ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); code += GET(code, 1); } break; /*-----------------------------------------------------------------*/ case OP_BRAZERO: case OP_BRAMINZERO: ADD_ACTIVE(state_offset + 1, 0); code += 1 + GET(code, 2); while (*code == OP_ALT) code += GET(code, 1); ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); break; /*-----------------------------------------------------------------*/ case OP_SKIPZERO: code += 1 + GET(code, 2); while (*code == OP_ALT) code += GET(code, 1); ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); break; /*-----------------------------------------------------------------*/ case OP_CIRC: if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) { ADD_ACTIVE(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_CIRCM: if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) || (ptr != end_subject && WAS_NEWLINE(ptr))) { ADD_ACTIVE(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_EOD: if (ptr >= end_subject) { if ((md->moptions & PCRE_PARTIAL_HARD) != 0) could_continue = TRUE; else { ADD_ACTIVE(state_offset + 1, 0); } } break; /*-----------------------------------------------------------------*/ case OP_SOD: if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_SOM: if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); } break; /* ========================================================================== */ /* These opcodes inspect the next subject character, and sometimes the previous one as well, but do not have an argument. The variable clen contains the length of the current character and is zero if we are at the end of the subject. */ /*-----------------------------------------------------------------*/ case OP_ANY: if (clen > 0 && !IS_NEWLINE(ptr)) { if (ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { could_continue = partial_newline = TRUE; } else { ADD_NEW(state_offset + 1, 0); } } break; /*-----------------------------------------------------------------*/ case OP_ALLANY: if (clen > 0) { ADD_NEW(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_EODN: if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) could_continue = TRUE; else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen)) { ADD_ACTIVE(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_DOLL: if ((md->moptions & PCRE_NOTEOL) == 0) { if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) could_continue = TRUE; else if (clen == 0 || ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) && (ptr == end_subject - md->nllen) )) { ADD_ACTIVE(state_offset + 1, 0); } else if (ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { if ((md->moptions & PCRE_PARTIAL_HARD) != 0) { reset_could_continue = TRUE; ADD_NEW_DATA(-(state_offset + 1), 0, 1); } else could_continue = partial_newline = TRUE; } } break; /*-----------------------------------------------------------------*/ case OP_DOLLM: if ((md->moptions & PCRE_NOTEOL) == 0) { if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) could_continue = TRUE; else if (clen == 0 || ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr))) { ADD_ACTIVE(state_offset + 1, 0); } else if (ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { if ((md->moptions & PCRE_PARTIAL_HARD) != 0) { reset_could_continue = TRUE; ADD_NEW_DATA(-(state_offset + 1), 0, 1); } else could_continue = partial_newline = TRUE; } } else if (IS_NEWLINE(ptr)) { ADD_ACTIVE(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_DIGIT: case OP_WHITESPACE: case OP_WORDCHAR: if (clen > 0 && c < 256 && ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0) { ADD_NEW(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_NOT_DIGIT: case OP_NOT_WHITESPACE: case OP_NOT_WORDCHAR: if (clen > 0 && (c >= 256 || ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)) { ADD_NEW(state_offset + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_WORD_BOUNDARY: case OP_NOT_WORD_BOUNDARY: { int left_word, right_word; if (ptr > start_subject) { const pcre_uchar *temp = ptr - 1; if (temp < md->start_used_ptr) md->start_used_ptr = temp; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) { BACKCHAR(temp); } #endif GETCHARTEST(d, temp); #ifdef SUPPORT_UCP if ((md->poptions & PCRE_UCP) != 0) { if (d == '_') left_word = TRUE; else { int cat = UCD_CATEGORY(d); left_word = (cat == ucp_L || cat == ucp_N); } } else #endif left_word = d < 256 && (ctypes[d] & ctype_word) != 0; } else left_word = FALSE; if (clen > 0) { #ifdef SUPPORT_UCP if ((md->poptions & PCRE_UCP) != 0) { if (c == '_') right_word = TRUE; else { int cat = UCD_CATEGORY(c); right_word = (cat == ucp_L || cat == ucp_N); } } else #endif right_word = c < 256 && (ctypes[c] & ctype_word) != 0; } else right_word = FALSE; if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY)) { ADD_ACTIVE(state_offset + 1, 0); } } break; /*-----------------------------------------------------------------*/ /* Check the next character by Unicode property. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ #ifdef SUPPORT_UCP case OP_PROP: case OP_NOTPROP: if (clen > 0) { BOOL OK; const pcre_uint32 *cp; const ucd_record * prop = GET_UCD(c); switch(code[1]) { case PT_ANY: OK = TRUE; break; case PT_LAMP: OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt; break; case PT_GC: OK = PRIV(ucp_gentype)[prop->chartype] == code[2]; break; case PT_PC: OK = prop->chartype == code[2]; break; case PT_SC: OK = prop->script == code[2]; break; /* These are specials for combination cases. */ case PT_ALNUM: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: OK = TRUE; break; default: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z; break; } break; case PT_WORD: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE; break; case PT_CLIST: cp = PRIV(ucd_caseless_sets) + code[2]; for (;;) { if (c < *cp) { OK = FALSE; break; } if (c == *cp++) { OK = TRUE; break; } } break; case PT_UCNC: OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000; break; /* Should never occur, but keep compilers from grumbling. */ default: OK = codevalue != OP_PROP; break; } if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); } } break; #endif /* ========================================================================== */ /* These opcodes likewise inspect the subject character, but have an argument that is not a data character. It is one of these opcodes: OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE, OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */ case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } if (clen > 0) { if (d == OP_ANY && ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { could_continue = partial_newline = TRUE; } else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || (c < 256 && (d != OP_ANY || !IS_NEWLINE(ptr)) && ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) { if (count > 0 && codevalue == OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW(state_offset, count); } } break; /*-----------------------------------------------------------------*/ case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSQUERY: ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { if (d == OP_ANY && ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { could_continue = partial_newline = TRUE; } else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || (c < 256 && (d != OP_ANY || !IS_NEWLINE(ptr)) && ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) { if (codevalue == OP_TYPEPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(state_offset + 2, 0); } } break; /*-----------------------------------------------------------------*/ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPOSSTAR: ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { if (d == OP_ANY && ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { could_continue = partial_newline = TRUE; } else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || (c < 256 && (d != OP_ANY || !IS_NEWLINE(ptr)) && ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) { if (codevalue == OP_TYPEPOSSTAR) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(state_offset, 0); } } break; /*-----------------------------------------------------------------*/ case OP_TYPEEXACT: count = current_state->count; /* Number already matched */ if (clen > 0) { if (d == OP_ANY && ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { could_continue = partial_newline = TRUE; } else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || (c < 256 && (d != OP_ANY || !IS_NEWLINE(ptr)) && ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) { if (++count >= (int)GET2(code, 1)) { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); } else { ADD_NEW(state_offset, count); } } } break; /*-----------------------------------------------------------------*/ case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO: ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); count = current_state->count; /* Number already matched */ if (clen > 0) { if (d == OP_ANY && ptr + 1 >= md->end_subject && (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { could_continue = partial_newline = TRUE; } else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || (c < 256 && (d != OP_ANY || !IS_NEWLINE(ptr)) && ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) { if (codevalue == OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= (int)GET2(code, 1)) { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); } else { ADD_NEW(state_offset, count); } } } break; /* ========================================================================== */ /* These are virtual opcodes that are used when something like OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its argument. It keeps the code above fast for the other cases. The argument is in the d variable. */ #ifdef SUPPORT_UCP case OP_PROP_EXTRA + OP_TYPEPLUS: case OP_PROP_EXTRA + OP_TYPEMINPLUS: case OP_PROP_EXTRA + OP_TYPEPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); } if (clen > 0) { BOOL OK; const pcre_uint32 *cp; const ucd_record * prop = GET_UCD(c); switch(code[2]) { case PT_ANY: OK = TRUE; break; case PT_LAMP: OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt; break; case PT_GC: OK = PRIV(ucp_gentype)[prop->chartype] == code[3]; break; case PT_PC: OK = prop->chartype == code[3]; break; case PT_SC: OK = prop->script == code[3]; break; /* These are specials for combination cases. */ case PT_ALNUM: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: OK = TRUE; break; default: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z; break; } break; case PT_WORD: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE; break; case PT_CLIST: cp = PRIV(ucd_caseless_sets) + code[3]; for (;;) { if (c < *cp) { OK = FALSE; break; } if (c == *cp++) { OK = TRUE; break; } } break; case PT_UCNC: OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000; break; /* Should never occur, but keep compilers from grumbling. */ default: OK = codevalue != OP_PROP; break; } if (OK == (d == OP_PROP)) { if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW(state_offset, count); } } break; /*-----------------------------------------------------------------*/ case OP_EXTUNI_EXTRA + OP_TYPEPLUS: case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS: case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } if (clen > 0) { int lgb, rgb; const pcre_uchar *nptr = ptr + clen; int ncount = 0; if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } lgb = UCD_GRAPHBREAK(c); while (nptr < end_subject) { dlen = 1; if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } rgb = UCD_GRAPHBREAK(d); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; ncount++; lgb = rgb; nptr += dlen; } count++; ADD_NEW_DATA(-state_offset, count, ncount); } break; #endif /*-----------------------------------------------------------------*/ case OP_ANYNL_EXTRA + OP_TYPEPLUS: case OP_ANYNL_EXTRA + OP_TYPEMINPLUS: case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } if (clen > 0) { int ncount = 0; switch (c) { case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; goto ANYNL01; case CHAR_CR: if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1; /* Fall through */ ANYNL01: case CHAR_LF: if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW_DATA(-state_offset, count, ncount); break; default: break; } } break; /*-----------------------------------------------------------------*/ case OP_VSPACE_EXTRA + OP_TYPEPLUS: case OP_VSPACE_EXTRA + OP_TYPEMINPLUS: case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } if (clen > 0) { BOOL OK; switch (c) { VSPACE_CASES: OK = TRUE; break; default: OK = FALSE; break; } if (OK == (d == OP_VSPACE)) { if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW_DATA(-state_offset, count, 0); } } break; /*-----------------------------------------------------------------*/ case OP_HSPACE_EXTRA + OP_TYPEPLUS: case OP_HSPACE_EXTRA + OP_TYPEMINPLUS: case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } if (clen > 0) { BOOL OK; switch (c) { HSPACE_CASES: OK = TRUE; break; default: OK = FALSE; break; } if (OK == (d == OP_HSPACE)) { if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW_DATA(-state_offset, count, 0); } } break; /*-----------------------------------------------------------------*/ #ifdef SUPPORT_UCP case OP_PROP_EXTRA + OP_TYPEQUERY: case OP_PROP_EXTRA + OP_TYPEMINQUERY: case OP_PROP_EXTRA + OP_TYPEPOSQUERY: count = 4; goto QS1; case OP_PROP_EXTRA + OP_TYPESTAR: case OP_PROP_EXTRA + OP_TYPEMINSTAR: case OP_PROP_EXTRA + OP_TYPEPOSSTAR: count = 0; QS1: ADD_ACTIVE(state_offset + 4, 0); if (clen > 0) { BOOL OK; const pcre_uint32 *cp; const ucd_record * prop = GET_UCD(c); switch(code[2]) { case PT_ANY: OK = TRUE; break; case PT_LAMP: OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt; break; case PT_GC: OK = PRIV(ucp_gentype)[prop->chartype] == code[3]; break; case PT_PC: OK = prop->chartype == code[3]; break; case PT_SC: OK = prop->script == code[3]; break; /* These are specials for combination cases. */ case PT_ALNUM: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: OK = TRUE; break; default: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z; break; } break; case PT_WORD: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE; break; case PT_CLIST: cp = PRIV(ucd_caseless_sets) + code[3]; for (;;) { if (c < *cp) { OK = FALSE; break; } if (c == *cp++) { OK = TRUE; break; } } break; case PT_UCNC: OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000; break; /* Should never occur, but keep compilers from grumbling. */ default: OK = codevalue != OP_PROP; break; } if (OK == (d == OP_PROP)) { if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR || codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(state_offset + count, 0); } } break; /*-----------------------------------------------------------------*/ case OP_EXTUNI_EXTRA + OP_TYPEQUERY: case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY: case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY: count = 2; goto QS2; case OP_EXTUNI_EXTRA + OP_TYPESTAR: case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR: case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR: count = 0; QS2: ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { int lgb, rgb; const pcre_uchar *nptr = ptr + clen; int ncount = 0; if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR || codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } lgb = UCD_GRAPHBREAK(c); while (nptr < end_subject) { dlen = 1; if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } rgb = UCD_GRAPHBREAK(d); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; ncount++; lgb = rgb; nptr += dlen; } ADD_NEW_DATA(-(state_offset + count), 0, ncount); } break; #endif /*-----------------------------------------------------------------*/ case OP_ANYNL_EXTRA + OP_TYPEQUERY: case OP_ANYNL_EXTRA + OP_TYPEMINQUERY: case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY: count = 2; goto QS3; case OP_ANYNL_EXTRA + OP_TYPESTAR: case OP_ANYNL_EXTRA + OP_TYPEMINSTAR: case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR: count = 0; QS3: ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { int ncount = 0; switch (c) { case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; goto ANYNL02; case CHAR_CR: if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1; /* Fall through */ ANYNL02: case CHAR_LF: if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR || codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW_DATA(-(state_offset + (int)count), 0, ncount); break; default: break; } } break; /*-----------------------------------------------------------------*/ case OP_VSPACE_EXTRA + OP_TYPEQUERY: case OP_VSPACE_EXTRA + OP_TYPEMINQUERY: case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY: count = 2; goto QS4; case OP_VSPACE_EXTRA + OP_TYPESTAR: case OP_VSPACE_EXTRA + OP_TYPEMINSTAR: case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR: count = 0; QS4: ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { BOOL OK; switch (c) { VSPACE_CASES: OK = TRUE; break; default: OK = FALSE; break; } if (OK == (d == OP_VSPACE)) { if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR || codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW_DATA(-(state_offset + (int)count), 0, 0); } } break; /*-----------------------------------------------------------------*/ case OP_HSPACE_EXTRA + OP_TYPEQUERY: case OP_HSPACE_EXTRA + OP_TYPEMINQUERY: case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY: count = 2; goto QS5; case OP_HSPACE_EXTRA + OP_TYPESTAR: case OP_HSPACE_EXTRA + OP_TYPEMINSTAR: case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR: count = 0; QS5: ADD_ACTIVE(state_offset + 2, 0); if (clen > 0) { BOOL OK; switch (c) { HSPACE_CASES: OK = TRUE; break; default: OK = FALSE; break; } if (OK == (d == OP_HSPACE)) { if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR || codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW_DATA(-(state_offset + (int)count), 0, 0); } } break; /*-----------------------------------------------------------------*/ #ifdef SUPPORT_UCP case OP_PROP_EXTRA + OP_TYPEEXACT: case OP_PROP_EXTRA + OP_TYPEUPTO: case OP_PROP_EXTRA + OP_TYPEMINUPTO: case OP_PROP_EXTRA + OP_TYPEPOSUPTO: if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT) { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); } count = current_state->count; /* Number already matched */ if (clen > 0) { BOOL OK; const pcre_uint32 *cp; const ucd_record * prop = GET_UCD(c); switch(code[1 + IMM2_SIZE + 1]) { case PT_ANY: OK = TRUE; break; case PT_LAMP: OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt; break; case PT_GC: OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2]; break; case PT_PC: OK = prop->chartype == code[1 + IMM2_SIZE + 2]; break; case PT_SC: OK = prop->script == code[1 + IMM2_SIZE + 2]; break; /* These are specials for combination cases. */ case PT_ALNUM: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: OK = TRUE; break; default: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z; break; } break; case PT_WORD: OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE; break; case PT_CLIST: cp = PRIV(ucd_caseless_sets) + code[1 + IMM2_SIZE + 2]; for (;;) { if (c < *cp) { OK = FALSE; break; } if (c == *cp++) { OK = TRUE; break; } } break; case PT_UCNC: OK = c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000; break; /* Should never occur, but keep compilers from grumbling. */ default: OK = codevalue != OP_PROP; break; } if (OK == (d == OP_PROP)) { if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= (int)GET2(code, 1)) { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); } else { ADD_NEW(state_offset, count); } } } break; /*-----------------------------------------------------------------*/ case OP_EXTUNI_EXTRA + OP_TYPEEXACT: case OP_EXTUNI_EXTRA + OP_TYPEUPTO: case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO: case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO: if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT) { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } count = current_state->count; /* Number already matched */ if (clen > 0) { int lgb, rgb; const pcre_uchar *nptr = ptr + clen; int ncount = 0; if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } lgb = UCD_GRAPHBREAK(c); while (nptr < end_subject) { dlen = 1; if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } rgb = UCD_GRAPHBREAK(d); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; ncount++; lgb = rgb; nptr += dlen; } if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0) reset_could_continue = TRUE; if (++count >= (int)GET2(code, 1)) { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); } else { ADD_NEW_DATA(-state_offset, count, ncount); } } break; #endif /*-----------------------------------------------------------------*/ case OP_ANYNL_EXTRA + OP_TYPEEXACT: case OP_ANYNL_EXTRA + OP_TYPEUPTO: case OP_ANYNL_EXTRA + OP_TYPEMINUPTO: case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO: if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT) { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } count = current_state->count; /* Number already matched */ if (clen > 0) { int ncount = 0; switch (c) { case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; goto ANYNL03; case CHAR_CR: if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1; /* Fall through */ ANYNL03: case CHAR_LF: if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= (int)GET2(code, 1)) { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); } else { ADD_NEW_DATA(-state_offset, count, ncount); } break; default: break; } } break; /*-----------------------------------------------------------------*/ case OP_VSPACE_EXTRA + OP_TYPEEXACT: case OP_VSPACE_EXTRA + OP_TYPEUPTO: case OP_VSPACE_EXTRA + OP_TYPEMINUPTO: case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO: if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT) { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } count = current_state->count; /* Number already matched */ if (clen > 0) { BOOL OK; switch (c) { VSPACE_CASES: OK = TRUE; break; default: OK = FALSE; } if (OK == (d == OP_VSPACE)) { if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= (int)GET2(code, 1)) { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); } else { ADD_NEW_DATA(-state_offset, count, 0); } } } break; /*-----------------------------------------------------------------*/ case OP_HSPACE_EXTRA + OP_TYPEEXACT: case OP_HSPACE_EXTRA + OP_TYPEUPTO: case OP_HSPACE_EXTRA + OP_TYPEMINUPTO: case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO: if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT) { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } count = current_state->count; /* Number already matched */ if (clen > 0) { BOOL OK; switch (c) { HSPACE_CASES: OK = TRUE; break; default: OK = FALSE; break; } if (OK == (d == OP_HSPACE)) { if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= (int)GET2(code, 1)) { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); } else { ADD_NEW_DATA(-state_offset, count, 0); } } } break; /* ========================================================================== */ /* These opcodes are followed by a character that is usually compared to the current subject character; it is loaded into d. We still get here even if there is no subject character, because in some cases zero repetitions are permitted. */ /*-----------------------------------------------------------------*/ case OP_CHAR: if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); } break; /*-----------------------------------------------------------------*/ case OP_CHARI: if (clen == 0) break; #ifdef SUPPORT_UTF if (utf) { if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else { unsigned int othercase; if (c < 128) othercase = fcc[c]; else /* If we have Unicode property support, we can use it to test the other case of the character. */ #ifdef SUPPORT_UCP othercase = UCD_OTHERCASE(c); #else othercase = NOTACHAR; #endif if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); } } } else #endif /* SUPPORT_UTF */ /* Not UTF mode */ { if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d)) { ADD_NEW(state_offset + 2, 0); } } break; #ifdef SUPPORT_UCP /*-----------------------------------------------------------------*/ /* This is a tricky one because it can match more than one character. Find out how many characters to skip, and then set up a negative state to wait for them to pass before continuing. */ case OP_EXTUNI: if (clen > 0) { int lgb, rgb; const pcre_uchar *nptr = ptr + clen; int ncount = 0; lgb = UCD_GRAPHBREAK(c); while (nptr < end_subject) { dlen = 1; if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); } rgb = UCD_GRAPHBREAK(d); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; ncount++; lgb = rgb; nptr += dlen; } if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0) reset_could_continue = TRUE; ADD_NEW_DATA(-(state_offset + 1), 0, ncount); } break; #endif /*-----------------------------------------------------------------*/ /* This is a tricky like EXTUNI because it too can match more than one character (when CR is followed by LF). In this case, set up a negative state to wait for one character to pass before continuing. */ case OP_ANYNL: if (clen > 0) switch(c) { case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; case CHAR_LF: ADD_NEW(state_offset + 1, 0); break; case CHAR_CR: if (ptr + 1 >= end_subject) { ADD_NEW(state_offset + 1, 0); if ((md->moptions & PCRE_PARTIAL_HARD) != 0) reset_could_continue = TRUE; } else if (UCHAR21TEST(ptr + 1) == CHAR_LF) { ADD_NEW_DATA(-(state_offset + 1), 0, 1); } else { ADD_NEW(state_offset + 1, 0); } break; } break; /*-----------------------------------------------------------------*/ case OP_NOT_VSPACE: if (clen > 0) switch(c) { VSPACE_CASES: break; default: ADD_NEW(state_offset + 1, 0); break; } break; /*-----------------------------------------------------------------*/ case OP_VSPACE: if (clen > 0) switch(c) { VSPACE_CASES: ADD_NEW(state_offset + 1, 0); break; default: break; } break; /*-----------------------------------------------------------------*/ case OP_NOT_HSPACE: if (clen > 0) switch(c) { HSPACE_CASES: break; default: ADD_NEW(state_offset + 1, 0); break; } break; /*-----------------------------------------------------------------*/ case OP_HSPACE: if (clen > 0) switch(c) { HSPACE_CASES: ADD_NEW(state_offset + 1, 0); break; default: break; } break; /*-----------------------------------------------------------------*/ /* Match a negated single character casefully. */ case OP_NOT: if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); } break; /*-----------------------------------------------------------------*/ /* Match a negated single character caselessly. */ case OP_NOTI: if (clen > 0) { pcre_uint32 otherd; #ifdef SUPPORT_UTF if (utf && d >= 128) { #ifdef SUPPORT_UCP otherd = UCD_OTHERCASE(d); #else otherd = d; #endif /* SUPPORT_UCP */ } else #endif /* SUPPORT_UTF */ otherd = TABLE_GET(d, fcc, d); if (c != d && c != otherd) { ADD_NEW(state_offset + dlen + 1, 0); } } break; /*-----------------------------------------------------------------*/ case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTPOSPLUSI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR; /* Fall through */ case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); } if (clen > 0) { pcre_uint32 otherd = NOTACHAR; if (caseless) { #ifdef SUPPORT_UTF if (utf && d >= 128) { #ifdef SUPPORT_UCP otherd = UCD_OTHERCASE(d); #endif /* SUPPORT_UCP */ } else #endif /* SUPPORT_UTF */ otherd = TABLE_GET(d, fcc, d); } if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) { if (count > 0 && (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS)) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW(state_offset, count); } } break; /*-----------------------------------------------------------------*/ case OP_QUERYI: case OP_MINQUERYI: case OP_POSQUERYI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTPOSQUERYI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR; /* Fall through */ case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTPOSQUERY: ADD_ACTIVE(state_offset + dlen + 1, 0); if (clen > 0) { pcre_uint32 otherd = NOTACHAR; if (caseless) { #ifdef SUPPORT_UTF if (utf && d >= 128) { #ifdef SUPPORT_UCP otherd = UCD_OTHERCASE(d); #endif /* SUPPORT_UCP */ } else #endif /* SUPPORT_UTF */ otherd = TABLE_GET(d, fcc, d); } if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) { if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(state_offset + dlen + 1, 0); } } break; /*-----------------------------------------------------------------*/ case OP_STARI: case OP_MINSTARI: case OP_POSSTARI: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPOSSTARI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR; /* Fall through */ case OP_STAR: case OP_MINSTAR: case OP_POSSTAR: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPOSSTAR: ADD_ACTIVE(state_offset + dlen + 1, 0); if (clen > 0) { pcre_uint32 otherd = NOTACHAR; if (caseless) { #ifdef SUPPORT_UTF if (utf && d >= 128) { #ifdef SUPPORT_UCP otherd = UCD_OTHERCASE(d); #endif /* SUPPORT_UCP */ } else #endif /* SUPPORT_UTF */ otherd = TABLE_GET(d, fcc, d); } if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) { if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(state_offset, 0); } } break; /*-----------------------------------------------------------------*/ case OP_EXACTI: case OP_NOTEXACTI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR; /* Fall through */ case OP_EXACT: case OP_NOTEXACT: count = current_state->count; /* Number already matched */ if (clen > 0) { pcre_uint32 otherd = NOTACHAR; if (caseless) { #ifdef SUPPORT_UTF if (utf && d >= 128) { #ifdef SUPPORT_UCP otherd = UCD_OTHERCASE(d); #endif /* SUPPORT_UCP */ } else #endif /* SUPPORT_UTF */ otherd = TABLE_GET(d, fcc, d); } if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) { if (++count >= (int)GET2(code, 1)) { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); } else { ADD_NEW(state_offset, count); } } } break; /*-----------------------------------------------------------------*/ case OP_UPTOI: case OP_MINUPTOI: case OP_POSUPTOI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTPOSUPTOI: caseless = TRUE; codevalue -= OP_STARI - OP_STAR; /* Fall through */ case OP_UPTO: case OP_MINUPTO: case OP_POSUPTO: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTPOSUPTO: ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0); count = current_state->count; /* Number already matched */ if (clen > 0) { pcre_uint32 otherd = NOTACHAR; if (caseless) { #ifdef SUPPORT_UTF if (utf && d >= 128) { #ifdef SUPPORT_UCP otherd = UCD_OTHERCASE(d); #endif /* SUPPORT_UCP */ } else #endif /* SUPPORT_UTF */ otherd = TABLE_GET(d, fcc, d); } if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) { if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= (int)GET2(code, 1)) { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); } else { ADD_NEW(state_offset, count); } } } break; /* ========================================================================== */ /* These are the class-handling opcodes */ case OP_CLASS: case OP_NCLASS: case OP_XCLASS: { BOOL isinclass = FALSE; int next_state_offset; const pcre_uchar *ecode; /* For a simple class, there is always just a 32-byte table, and we can set isinclass from it. */ if (codevalue != OP_XCLASS) { ecode = code + 1 + (32 / sizeof(pcre_uchar)); if (clen > 0) { isinclass = (c > 255)? (codevalue == OP_NCLASS) : ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0); } } /* An extended class may have a table or a list of single characters, ranges, or both, and it may be positive or negative. There's a function that sorts all this out. */ else { ecode = code + GET(code, 1); if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf); } /* At this point, isinclass is set for all kinds of class, and ecode points to the byte after the end of the class. If there is a quantifier, this is where it will be. */ next_state_offset = (int)(ecode - start_code); switch (*ecode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPOSSTAR: ADD_ACTIVE(next_state_offset + 1, 0); if (isinclass) { if (*ecode == OP_CRPOSSTAR) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(state_offset, 0); } break; case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRPOSPLUS: count = current_state->count; /* Already matched */ if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); } if (isinclass) { if (count > 0 && *ecode == OP_CRPOSPLUS) { active_count--; /* Remove non-match possibility */ next_active_state--; } count++; ADD_NEW(state_offset, count); } break; case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSQUERY: ADD_ACTIVE(next_state_offset + 1, 0); if (isinclass) { if (*ecode == OP_CRPOSQUERY) { active_count--; /* Remove non-match possibility */ next_active_state--; } ADD_NEW(next_state_offset + 1, 0); } break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: count = current_state->count; /* Already matched */ if (count >= (int)GET2(ecode, 1)) { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } if (isinclass) { int max = (int)GET2(ecode, 1 + IMM2_SIZE); if (*ecode == OP_CRPOSRANGE && count >= (int)GET2(ecode, 1)) { active_count--; /* Remove non-match possibility */ next_active_state--; } if (++count >= max && max != 0) /* Max 0 => no limit */ { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } else { ADD_NEW(state_offset, count); } } break; default: if (isinclass) { ADD_NEW(next_state_offset, 0); } break; } } break; /* ========================================================================== */ /* These are the opcodes for fancy brackets of various kinds. We have to use recursion in order to handle them. The "always failing" assertion (?!) is optimised to OP_FAIL when compiling, so we have to support that, though the other "backtracking verbs" are not supported. */ case OP_FAIL: forced_fail++; /* Count FAILs for multiple states */ break; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: { int rc; int local_offsets[2]; int local_workspace[1000]; const pcre_uchar *endasscode = code + GET(code, 1); while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); rc = internal_dfa_exec( md, /* static match data */ code, /* this subexpression's code */ ptr, /* where we currently are */ (int)(ptr - start_subject), /* start offset */ local_offsets, /* offset vector */ sizeof(local_offsets)/sizeof(int), /* size of same */ local_workspace, /* workspace vector */ sizeof(local_workspace)/sizeof(int), /* size of same */ rlevel); /* function recursion level */ if (rc == PCRE_ERROR_DFA_UITEM) return rc; if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK)) { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); } } break; /*-----------------------------------------------------------------*/ case OP_COND: case OP_SCOND: { int local_offsets[1000]; int local_workspace[1000]; int codelink = GET(code, 1); int condcode; /* Because of the way auto-callout works during compile, a callout item is inserted between OP_COND and an assertion condition. This does not happen for the other conditions. */ if (code[LINK_SIZE+1] == OP_CALLOUT) { rrc = 0; if (PUBL(callout) != NULL) { PUBL(callout_block) cb; cb.version = 1; /* Version 1 of the callout block */ cb.callout_number = code[LINK_SIZE+2]; cb.offset_vector = offsets; #if defined COMPILE_PCRE8 cb.subject = (PCRE_SPTR)start_subject; #elif defined COMPILE_PCRE16 cb.subject = (PCRE_SPTR16)start_subject; #elif defined COMPILE_PCRE32 cb.subject = (PCRE_SPTR32)start_subject; #endif cb.subject_length = (int)(end_subject - start_subject); cb.start_match = (int)(current_subject - start_subject); cb.current_position = (int)(ptr - start_subject); cb.pattern_position = GET(code, LINK_SIZE + 3); cb.next_item_length = GET(code, 3 + 2*LINK_SIZE); cb.capture_top = 1; cb.capture_last = -1; cb.callout_data = md->callout_data; cb.mark = NULL; /* No (*MARK) support */ if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */ } if (rrc > 0) break; /* Fail this thread */ code += PRIV(OP_lengths)[OP_CALLOUT]; /* Skip callout data */ } condcode = code[LINK_SIZE+1]; /* Back reference conditions and duplicate named recursion conditions are not supported */ if (condcode == OP_CREF || condcode == OP_DNCREF || condcode == OP_DNRREF) return PCRE_ERROR_DFA_UCOND; /* The DEFINE condition is always false, and the assertion (?!) is converted to OP_FAIL. */ if (condcode == OP_DEF || condcode == OP_FAIL) { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } /* The only supported version of OP_RREF is for the value RREF_ANY, which means "test if in any recursion". We can't test for specifically recursed groups. */ else if (condcode == OP_RREF) { int value = GET2(code, LINK_SIZE + 2); if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND; if (md->recursive != NULL) { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); } else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } } /* Otherwise, the condition is an assertion */ else { int rc; const pcre_uchar *asscode = code + LINK_SIZE + 1; const pcre_uchar *endasscode = asscode + GET(asscode, 1); while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); rc = internal_dfa_exec( md, /* fixed match data */ asscode, /* this subexpression's code */ ptr, /* where we currently are */ (int)(ptr - start_subject), /* start offset */ local_offsets, /* offset vector */ sizeof(local_offsets)/sizeof(int), /* size of same */ local_workspace, /* workspace vector */ sizeof(local_workspace)/sizeof(int), /* size of same */ rlevel); /* function recursion level */ if (rc == PCRE_ERROR_DFA_UITEM) return rc; if ((rc >= 0) == (condcode == OP_ASSERT || condcode == OP_ASSERTBACK)) { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); } else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } } } break; /*-----------------------------------------------------------------*/ case OP_RECURSE: { dfa_recursion_info *ri; int local_offsets[1000]; int local_workspace[1000]; const pcre_uchar *callpat = start_code + GET(code, 1); int recno = (callpat == md->start_code)? 0 : GET2(callpat, 1 + LINK_SIZE); int rc; DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP)); /* Check for repeating a recursion without advancing the subject pointer. This should catch convoluted mutual recursions. (Some simple cases are caught at compile time.) */ for (ri = md->recursive; ri != NULL; ri = ri->prevrec) if (recno == ri->group_num && ptr == ri->subject_position) return PCRE_ERROR_RECURSELOOP; /* Remember this recursion and where we started it so as to catch infinite loops. */ new_recursive.group_num = recno; new_recursive.subject_position = ptr; new_recursive.prevrec = md->recursive; md->recursive = &new_recursive; rc = internal_dfa_exec( md, /* fixed match data */ callpat, /* this subexpression's code */ ptr, /* where we currently are */ (int)(ptr - start_subject), /* start offset */ local_offsets, /* offset vector */ sizeof(local_offsets)/sizeof(int), /* size of same */ local_workspace, /* workspace vector */ sizeof(local_workspace)/sizeof(int), /* size of same */ rlevel); /* function recursion level */ md->recursive = new_recursive.prevrec; /* Done this recursion */ DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP, rc)); /* Ran out of internal offsets */ if (rc == 0) return PCRE_ERROR_DFA_RECURSE; /* For each successful matched substring, set up the next state with a count of characters to skip before trying it. Note that the count is in characters, not bytes. */ if (rc > 0) { for (rc = rc*2 - 2; rc >= 0; rc -= 2) { int charcount = local_offsets[rc+1] - local_offsets[rc]; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) { const pcre_uchar *p = start_subject + local_offsets[rc]; const pcre_uchar *pp = start_subject + local_offsets[rc+1]; while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; } #endif if (charcount > 0) { ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1)); } else { ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0); } } } else if (rc != PCRE_ERROR_NOMATCH) return rc; } break; /*-----------------------------------------------------------------*/ case OP_BRAPOS: case OP_SBRAPOS: case OP_CBRAPOS: case OP_SCBRAPOS: case OP_BRAPOSZERO: { int charcount, matched_count; const pcre_uchar *local_ptr = ptr; BOOL allow_zero; if (codevalue == OP_BRAPOSZERO) { allow_zero = TRUE; codevalue = *(++code); /* Codevalue will be one of above BRAs */ } else allow_zero = FALSE; /* Loop to match the subpattern as many times as possible as if it were a complete pattern. */ for (matched_count = 0;; matched_count++) { int local_offsets[2]; int local_workspace[1000]; int rc = internal_dfa_exec( md, /* fixed match data */ code, /* this subexpression's code */ local_ptr, /* where we currently are */ (int)(ptr - start_subject), /* start offset */ local_offsets, /* offset vector */ sizeof(local_offsets)/sizeof(int), /* size of same */ local_workspace, /* workspace vector */ sizeof(local_workspace)/sizeof(int), /* size of same */ rlevel); /* function recursion level */ /* Failed to match */ if (rc < 0) { if (rc != PCRE_ERROR_NOMATCH) return rc; break; } /* Matched: break the loop if zero characters matched. */ charcount = local_offsets[1] - local_offsets[0]; if (charcount == 0) break; local_ptr += charcount; /* Advance temporary position ptr */ } /* At this point we have matched the subpattern matched_count times, and local_ptr is pointing to the character after the end of the last match. */ if (matched_count > 0 || allow_zero) { const pcre_uchar *end_subpattern = code; int next_state_offset; do { end_subpattern += GET(end_subpattern, 1); } while (*end_subpattern == OP_ALT); next_state_offset = (int)(end_subpattern - start_code + LINK_SIZE + 1); /* Optimization: if there are no more active states, and there are no new states yet set up, then skip over the subject string right here, to save looping. Otherwise, set up the new state to swing into action when the end of the matched substring is reached. */ if (i + 1 >= active_count && new_count == 0) { ptr = local_ptr; clen = 0; ADD_NEW(next_state_offset, 0); } else { const pcre_uchar *p = ptr; const pcre_uchar *pp = local_ptr; charcount = (int)(pp - p); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; #endif ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); } } } break; /*-----------------------------------------------------------------*/ case OP_ONCE: case OP_ONCE_NC: { int local_offsets[2]; int local_workspace[1000]; int rc = internal_dfa_exec( md, /* fixed match data */ code, /* this subexpression's code */ ptr, /* where we currently are */ (int)(ptr - start_subject), /* start offset */ local_offsets, /* offset vector */ sizeof(local_offsets)/sizeof(int), /* size of same */ local_workspace, /* workspace vector */ sizeof(local_workspace)/sizeof(int), /* size of same */ rlevel); /* function recursion level */ if (rc >= 0) { const pcre_uchar *end_subpattern = code; int charcount = local_offsets[1] - local_offsets[0]; int next_state_offset, repeat_state_offset; do { end_subpattern += GET(end_subpattern, 1); } while (*end_subpattern == OP_ALT); next_state_offset = (int)(end_subpattern - start_code + LINK_SIZE + 1); /* If the end of this subpattern is KETRMAX or KETRMIN, we must arrange for the repeat state also to be added to the relevant list. Calculate the offset, or set -1 for no repeat. */ repeat_state_offset = (*end_subpattern == OP_KETRMAX || *end_subpattern == OP_KETRMIN)? (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1; /* If we have matched an empty string, add the next state at the current character pointer. This is important so that the duplicate checking kicks in, which is what breaks infinite loops that match an empty string. */ if (charcount == 0) { ADD_ACTIVE(next_state_offset, 0); } /* Optimization: if there are no more active states, and there are no new states yet set up, then skip over the subject string right here, to save looping. Otherwise, set up the new state to swing into action when the end of the matched substring is reached. */ else if (i + 1 >= active_count && new_count == 0) { ptr += charcount; clen = 0; ADD_NEW(next_state_offset, 0); /* If we are adding a repeat state at the new character position, we must fudge things so that it is the only current state. Otherwise, it might be a duplicate of one we processed before, and that would cause it to be skipped. */ if (repeat_state_offset >= 0) { next_active_state = active_states; active_count = 0; i = -1; ADD_ACTIVE(repeat_state_offset, 0); } } else { #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (utf) { const pcre_uchar *p = start_subject + local_offsets[0]; const pcre_uchar *pp = start_subject + local_offsets[1]; while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; } #endif ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); if (repeat_state_offset >= 0) { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); } } } else if (rc != PCRE_ERROR_NOMATCH) return rc; } break; /* ========================================================================== */ /* Handle callouts */ case OP_CALLOUT: rrc = 0; if (PUBL(callout) != NULL) { PUBL(callout_block) cb; cb.version = 1; /* Version 1 of the callout block */ cb.callout_number = code[1]; cb.offset_vector = offsets; #if defined COMPILE_PCRE8 cb.subject = (PCRE_SPTR)start_subject; #elif defined COMPILE_PCRE16 cb.subject = (PCRE_SPTR16)start_subject; #elif defined COMPILE_PCRE32 cb.subject = (PCRE_SPTR32)start_subject; #endif cb.subject_length = (int)(end_subject - start_subject); cb.start_match = (int)(current_subject - start_subject); cb.current_position = (int)(ptr - start_subject); cb.pattern_position = GET(code, 2); cb.next_item_length = GET(code, 2 + LINK_SIZE); cb.capture_top = 1; cb.capture_last = -1; cb.callout_data = md->callout_data; cb.mark = NULL; /* No (*MARK) support */ if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */ } if (rrc == 0) { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); } break; /* ========================================================================== */ default: /* Unsupported opcode */ return PCRE_ERROR_DFA_UITEM; } NEXT_ACTIVE_STATE: continue; } /* End of loop scanning active states */ /* We have finished the processing at the current subject character. If no new states have been set for the next character, we have found all the matches that we are going to find. If we are at the top level and partial matching has been requested, check for appropriate conditions. The "forced_ fail" variable counts the number of (*F) encountered for the character. If it is equal to the original active_count (saved in workspace[1]) it means that (*F) was found on every active state. In this case we don't want to give a partial match. The "could_continue" variable is true if a state could have continued but for the fact that the end of the subject was reached. */ if (new_count <= 0) { if (rlevel == 1 && /* Top level, and */ could_continue && /* Some could go on, and */ forced_fail != workspace[1] && /* Not all forced fail & */ ( /* either... */ (md->moptions & PCRE_PARTIAL_HARD) != 0 /* Hard partial */ || /* or... */ ((md->moptions & PCRE_PARTIAL_SOFT) != 0 && /* Soft partial and */ match_count < 0) /* no matches */ ) && /* And... */ ( partial_newline || /* Either partial NL */ ( /* or ... */ ptr >= end_subject && /* End of subject and */ ptr > md->start_used_ptr) /* Inspected non-empty string */ ) ) match_count = PCRE_ERROR_PARTIAL; DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count, rlevel*2-2, SP)); break; /* In effect, "return", but see the comment below */ } /* One or more states are active for the next character. */ ptr += clen; /* Advance to next subject character */ } /* Loop to move along the subject string */ /* Control gets here from "break" a few lines above. We do it this way because if we use "return" above, we have compiler trouble. Some compilers warn if there's nothing here because they think the function doesn't return a value. On the other hand, if we put a dummy statement here, some more clever compilers complain that it can't be reached. Sigh. */ return match_count; } /************************************************* * Execute a Regular Expression - DFA engine * *************************************************/ /* This external function applies a compiled re to a subject string using a DFA engine. This function calls the internal function multiple times if the pattern is not anchored. Arguments: argument_re points to the compiled expression extra_data points to extra data or is NULL subject points to the subject string length length of subject string (may contain binary zeros) start_offset where to start in the subject string options option bits offsets vector of match offsets offsetcount size of same workspace workspace vector wscount size of same Returns: > 0 => number of match offset pairs placed in offsets = 0 => offsets overflowed; longest matches are present -1 => failed to match < -1 => some kind of unexpected problem */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data, const char *subject, int length, int start_offset, int options, int *offsets, int offsetcount, int *workspace, int wscount) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, int offsetcount, int *workspace, int wscount) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_dfa_exec(const pcre32 *argument_re, const pcre32_extra *extra_data, PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets, int offsetcount, int *workspace, int wscount) #endif { REAL_PCRE *re = (REAL_PCRE *)argument_re; dfa_match_data match_block; dfa_match_data *md = &match_block; BOOL utf, anchored, startline, firstline; const pcre_uchar *current_subject, *end_subject; const pcre_study_data *study = NULL; const pcre_uchar *req_char_ptr; const pcre_uint8 *start_bits = NULL; BOOL has_first_char = FALSE; BOOL has_req_char = FALSE; pcre_uchar first_char = 0; pcre_uchar first_char2 = 0; pcre_uchar req_char = 0; pcre_uchar req_char2 = 0; int newline; /* Plausibility checks */ if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; if (re == NULL || subject == NULL || workspace == NULL || (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE; if (length < 0) return PCRE_ERROR_BADLENGTH; if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; /* Check that the first field in the block is the magic number. If it is not, return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which means that the pattern is likely compiled with different endianness. */ if (re->magic_number != MAGIC_NUMBER) return re->magic_number == REVERSED_MAGIC_NUMBER? PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; /* If restarting after a partial match, do some sanity checks on the contents of the workspace. */ if ((options & PCRE_DFA_RESTART) != 0) { if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 || workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK) return PCRE_ERROR_DFA_BADRESTART; } /* Set up study, callout, and table data */ md->tables = re->tables; md->callout_data = NULL; if (extra_data != NULL) { unsigned long int flags = extra_data->flags; if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) study = (const pcre_study_data *)extra_data->study_data; if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT; if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0) return PCRE_ERROR_DFA_UMLIMIT; if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) md->callout_data = extra_data->callout_data; if ((flags & PCRE_EXTRA_TABLES) != 0) md->tables = extra_data->tables; } /* Set some local values */ current_subject = (const pcre_uchar *)subject + start_offset; end_subject = (const pcre_uchar *)subject + length; req_char_ptr = current_subject - 1; #ifdef SUPPORT_UTF /* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */ utf = (re->options & PCRE_UTF8) != 0; #else utf = FALSE; #endif anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 || (re->options & PCRE_ANCHORED) != 0; /* The remaining fixed data for passing around. */ md->start_code = (const pcre_uchar *)argument_re + re->name_table_offset + re->name_count * re->name_entry_size; md->start_subject = (const pcre_uchar *)subject; md->end_subject = end_subject; md->start_offset = start_offset; md->moptions = options; md->poptions = re->options; /* If the BSR option is not set at match time, copy what was set at compile time. */ if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0) { if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0) md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE); #ifdef BSR_ANYCRLF else md->moptions |= PCRE_BSR_ANYCRLF; #endif } /* Handle different types of newline. The three bits give eight cases. If nothing is set at run time, whatever was used at compile time applies. */ switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) & PCRE_NEWLINE_BITS) { case 0: newline = NEWLINE; break; /* Compile-time default */ case PCRE_NEWLINE_CR: newline = CHAR_CR; break; case PCRE_NEWLINE_LF: newline = CHAR_NL; break; case PCRE_NEWLINE_CR+ PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; case PCRE_NEWLINE_ANY: newline = -1; break; case PCRE_NEWLINE_ANYCRLF: newline = -2; break; default: return PCRE_ERROR_BADNEWLINE; } if (newline == -2) { md->nltype = NLTYPE_ANYCRLF; } else if (newline < 0) { md->nltype = NLTYPE_ANY; } else { md->nltype = NLTYPE_FIXED; if (newline > 255) { md->nllen = 2; md->nl[0] = (newline >> 8) & 255; md->nl[1] = newline & 255; } else { md->nllen = 1; md->nl[0] = newline; } } /* Check a UTF-8 string if required. Unfortunately there's no way of passing back the character offset. */ #ifdef SUPPORT_UTF if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) { int erroroffset; int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset); if (errorcode != 0) { if (offsetcount >= 2) { offsets[0] = erroroffset; offsets[1] = errorcode; } #if defined COMPILE_PCRE8 return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0) ? PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; #elif defined COMPILE_PCRE16 return (errorcode <= PCRE_UTF16_ERR1 && (options & PCRE_PARTIAL_HARD) != 0) ? PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16; #elif defined COMPILE_PCRE32 return PCRE_ERROR_BADUTF32; #endif } #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 if (start_offset > 0 && start_offset < length && NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset])) return PCRE_ERROR_BADUTF8_OFFSET; #endif } #endif /* If the exec call supplied NULL for tables, use the inbuilt ones. This is a feature that makes it possible to save compiled regex and re-use them in other programs later. */ if (md->tables == NULL) md->tables = PRIV(default_tables); /* The "must be at the start of a line" flags are used in a loop when finding where to start. */ startline = (re->flags & PCRE_STARTLINE) != 0; firstline = (re->options & PCRE_FIRSTLINE) != 0; /* Set up the first character to match, if available. The first_byte value is never set for an anchored regular expression, but the anchoring may be forced at run time, so we have to test for anchoring. The first char may be unset for an unanchored pattern, of course. If there's no first char and the pattern was studied, there may be a bitmap of possible first characters. */ if (!anchored) { if ((re->flags & PCRE_FIRSTSET) != 0) { has_first_char = TRUE; first_char = first_char2 = (pcre_uchar)(re->first_char); if ((re->flags & PCRE_FCH_CASELESS) != 0) { first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char); #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) if (utf && first_char > 127) first_char2 = UCD_OTHERCASE(first_char); #endif } } else { if (!startline && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) start_bits = study->start_bits; } } /* For anchored or unanchored matches, there may be a "last known required character" set. */ if ((re->flags & PCRE_REQCHSET) != 0) { has_req_char = TRUE; req_char = req_char2 = (pcre_uchar)(re->req_char); if ((re->flags & PCRE_RCH_CASELESS) != 0) { req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char); #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) if (utf && req_char > 127) req_char2 = UCD_OTHERCASE(req_char); #endif } } /* Call the main matching function, looping for a non-anchored regex after a failed match. If not restarting, perform certain optimizations at the start of a match. */ for (;;) { int rc; if ((options & PCRE_DFA_RESTART) == 0) { const pcre_uchar *save_end_subject = end_subject; /* If firstline is TRUE, the start of the match is constrained to the first line of a multiline string. Implement this by temporarily adjusting end_subject so that we stop scanning at a newline. If the match fails at the newline, later code breaks this loop. */ if (firstline) { PCRE_PUCHAR t = current_subject; #ifdef SUPPORT_UTF if (utf) { while (t < md->end_subject && !IS_NEWLINE(t)) { t++; ACROSSCHAR(t < end_subject, *t, t++); } } else #endif while (t < md->end_subject && !IS_NEWLINE(t)) t++; end_subject = t; } /* There are some optimizations that avoid running the match if a known starting point is not found. However, there is an option that disables these, for testing and for ensuring that all callouts do actually occur. The option can be set in the regex by (*NO_START_OPT) or passed in match-time options. */ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) { /* Advance to a known first pcre_uchar (i.e. data item) */ if (has_first_char) { if (first_char != first_char2) { pcre_uchar csc; while (current_subject < end_subject && (csc = UCHAR21TEST(current_subject)) != first_char && csc != first_char2) current_subject++; } else while (current_subject < end_subject && UCHAR21TEST(current_subject) != first_char) current_subject++; } /* Or to just after a linebreak for a multiline match if possible */ else if (startline) { if (current_subject > md->start_subject + start_offset) { #ifdef SUPPORT_UTF if (utf) { while (current_subject < end_subject && !WAS_NEWLINE(current_subject)) { current_subject++; ACROSSCHAR(current_subject < end_subject, *current_subject, current_subject++); } } else #endif while (current_subject < end_subject && !WAS_NEWLINE(current_subject)) current_subject++; /* If we have just passed a CR and the newline option is ANY or ANYCRLF, and we are now at a LF, advance the match position by one more character. */ if (UCHAR21TEST(current_subject - 1) == CHAR_CR && (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && current_subject < end_subject && UCHAR21TEST(current_subject) == CHAR_NL) current_subject++; } } /* Advance to a non-unique first pcre_uchar after study */ else if (start_bits != NULL) { while (current_subject < end_subject) { register pcre_uint32 c = UCHAR21TEST(current_subject); #ifndef COMPILE_PCRE8 if (c > 255) c = 255; #endif if ((start_bits[c/8] & (1 << (c&7))) != 0) break; current_subject++; } } } /* Restore fudged end_subject */ end_subject = save_end_subject; /* The following two optimizations are disabled for partial matching or if disabling is explicitly requested (and of course, by the test above, this code is not obeyed when restarting after a partial match). */ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0) { /* If the pattern was studied, a minimum subject length may be set. This is a lower bound; no actual string of that length may actually match the pattern. Although the value is, strictly, in characters, we treat it as in pcre_uchar units to avoid spending too much time in this optimization. */ if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && (pcre_uint32)(end_subject - current_subject) < study->minlength) return PCRE_ERROR_NOMATCH; /* If req_char is set, we know that that pcre_uchar must appear in the subject for the match to succeed. If the first pcre_uchar is set, req_char must be later in the subject; otherwise the test starts at the match point. This optimization can save a huge amount of work in patterns with nested unlimited repeats that aren't going to match. Writing separate code for cased/caseless versions makes it go faster, as does using an autoincrement and backing off on a match. HOWEVER: when the subject string is very, very long, searching to its end can take a long time, and give bad performance on quite ordinary patterns. This showed up when somebody was matching /^C/ on a 32-megabyte string... so we don't do this when the string is sufficiently long. */ if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX) { register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0); /* We don't need to repeat the search if we haven't yet reached the place we found it at last time. */ if (p > req_char_ptr) { if (req_char != req_char2) { while (p < end_subject) { register pcre_uint32 pp = UCHAR21INCTEST(p); if (pp == req_char || pp == req_char2) { p--; break; } } } else { while (p < end_subject) { if (UCHAR21INCTEST(p) == req_char) { p--; break; } } } /* If we can't find the required pcre_uchar, break the matching loop, which will cause a return or PCRE_ERROR_NOMATCH. */ if (p >= end_subject) break; /* If we have found the required pcre_uchar, save the point where we found it, so that we don't search again next time round the loop if the start hasn't passed this point yet. */ req_char_ptr = p; } } } } /* End of optimizations that are done when not restarting */ /* OK, now we can do the business */ md->start_used_ptr = current_subject; md->recursive = NULL; rc = internal_dfa_exec( md, /* fixed match data */ md->start_code, /* this subexpression's code */ current_subject, /* where we currently are */ start_offset, /* start offset in subject */ offsets, /* offset vector */ offsetcount, /* size of same */ workspace, /* workspace vector */ wscount, /* size of same */ 0); /* function recurse level */ /* Anything other than "no match" means we are done, always; otherwise, carry on only if not anchored. */ if (rc != PCRE_ERROR_NOMATCH || anchored) { if (rc == PCRE_ERROR_PARTIAL && offsetcount >= 2) { offsets[0] = (int)(md->start_used_ptr - (PCRE_PUCHAR)subject); offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject); if (offsetcount > 2) offsets[2] = (int)(current_subject - (PCRE_PUCHAR)subject); } return rc; } /* Advance to the next subject character unless we are at the end of a line and firstline is set. */ if (firstline && IS_NEWLINE(current_subject)) break; current_subject++; #ifdef SUPPORT_UTF if (utf) { ACROSSCHAR(current_subject < end_subject, *current_subject, current_subject++); } #endif if (current_subject > end_subject) break; /* If we have just passed a CR and we are now at a LF, and the pattern does not contain any explicit matches for \r or \n, and the newline option is CRLF or ANY or ANYCRLF, advance the match position by one more character. */ if (UCHAR21TEST(current_subject - 1) == CHAR_CR && current_subject < end_subject && UCHAR21TEST(current_subject) == CHAR_NL && (re->flags & PCRE_HASCRORLF) == 0 && (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF || md->nllen == 2)) current_subject++; } /* "Bumpalong" loop */ return PCRE_ERROR_NOMATCH; } /* End of pcre_dfa_exec.c */ ================================================ FILE: src/pcre/pcre_exec.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2018 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains pcre_exec(), the externally visible function that does pattern matching using an NFA algorithm, trying to mimic Perl as closely as possible. There are also some static supporting functions. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define NLBLOCK md /* Block containing newline information */ #define PSSTART start_subject /* Field containing processed string start */ #define PSEND end_subject /* Field containing processed string end */ #include "pcre_internal.h" /* Undefine some potentially clashing cpp symbols */ #undef min #undef max /* The md->capture_last field uses the lower 16 bits for the last captured substring (which can never be greater than 65535) and a bit in the top half to mean "capture vector overflowed". This odd way of doing things was implemented when it was realized that preserving and restoring the overflow bit whenever the last capture number was saved/restored made for a neater interface, and doing it this way saved on (a) another variable, which would have increased the stack frame size (a big NO-NO in PCRE) and (b) another separate set of save/restore instructions. The following defines are used in implementing this. */ #define CAPLMASK 0x0000ffff /* The bits used for last_capture */ #define OVFLMASK 0xffff0000 /* The bits used for the overflow flag */ #define OVFLBIT 0x00010000 /* The bit that is set for overflow */ /* Values for setting in md->match_function_type to indicate two special types of call to match(). We do it this way to save on using another stack variable, as stack usage is to be discouraged. */ #define MATCH_CONDASSERT 1 /* Called to check a condition assertion */ #define MATCH_CBEGROUP 2 /* Could-be-empty unlimited repeat group */ /* Non-error returns from the match() function. Error returns are externally defined PCRE_ERROR_xxx codes, which are all negative. */ #define MATCH_MATCH 1 #define MATCH_NOMATCH 0 /* Special internal returns from the match() function. Make them sufficiently negative to avoid the external error codes. */ #define MATCH_ACCEPT (-999) #define MATCH_KETRPOS (-998) #define MATCH_ONCE (-997) /* The next 5 must be kept together and in sequence so that a test that checks for any one of them can use a range. */ #define MATCH_COMMIT (-996) #define MATCH_PRUNE (-995) #define MATCH_SKIP (-994) #define MATCH_SKIP_ARG (-993) #define MATCH_THEN (-992) #define MATCH_BACKTRACK_MAX MATCH_THEN #define MATCH_BACKTRACK_MIN MATCH_COMMIT /* Maximum number of ints of offset to save on the stack for recursive calls. If the offset vector is bigger, malloc is used. This should be a multiple of 3, because the offset vector is always a multiple of 3 long. */ #define REC_STACK_SAVE_MAX 30 /* Min and max values for the common repeats; for the maxima, 0 => infinity */ static const char rep_min[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, }; static const char rep_max[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, }; #ifdef PCRE_DEBUG /************************************************* * Debugging function to print chars * *************************************************/ /* Print a sequence of chars in printable format, stopping at the end of the subject if the requested. Arguments: p points to characters length number to print is_subject TRUE if printing from within md->start_subject md pointer to matching data block, if is_subject is TRUE Returns: nothing */ static void pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md) { pcre_uint32 c; BOOL utf = md->utf; if (is_subject && length > md->end_subject - p) length = md->end_subject - p; while (length-- > 0) if (isprint(c = UCHAR21INCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c); } #endif /************************************************* * Match a back-reference * *************************************************/ /* Normally, if a back reference hasn't been set, the length that is passed is negative, so the match always fails. However, in JavaScript compatibility mode, the length passed is zero. Note that in caseless UTF-8 mode, the number of subject bytes matched may be different to the number of reference bytes. Arguments: offset index into the offset vector eptr pointer into the subject length length of reference to be matched (number of bytes) md points to match data block caseless TRUE if caseless Returns: >= 0 the number of subject bytes matched -1 no match -2 partial match; always given if at end subject */ static int match_ref(int offset, register PCRE_PUCHAR eptr, int length, match_data *md, BOOL caseless) { PCRE_PUCHAR eptr_start = eptr; register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset]; #if defined SUPPORT_UTF && defined SUPPORT_UCP BOOL utf = md->utf; #endif #ifdef PCRE_DEBUG if (eptr >= md->end_subject) printf("matching subject "); else { printf("matching subject "); pchars(eptr, length, TRUE, md); } printf(" against backref "); pchars(p, length, FALSE, md); printf("\n"); #endif /* Always fail if reference not set (and not JavaScript compatible - in that case the length is passed as zero). */ if (length < 0) return -1; /* Separate the caseless case for speed. In UTF-8 mode we can only do this properly if Unicode properties are supported. Otherwise, we can check only ASCII characters. */ if (caseless) { #if defined SUPPORT_UTF && defined SUPPORT_UCP if (utf) { /* Match characters up to the end of the reference. NOTE: the number of data units matched may differ, because in UTF-8 there are some characters whose upper and lower case versions code have different numbers of bytes. For example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65 (3 bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a sequence of two of the latter. It is important, therefore, to check the length along the reference, not along the subject (earlier code did this wrong). */ PCRE_PUCHAR endptr = p + length; while (p < endptr) { pcre_uint32 c, d; const ucd_record *ur; if (eptr >= md->end_subject) return -2; /* Partial match */ GETCHARINC(c, eptr); GETCHARINC(d, p); ur = GET_UCD(d); if (c != d && c != d + ur->other_case) { const pcre_uint32 *pp = PRIV(ucd_caseless_sets) + ur->caseset; for (;;) { if (c < *pp) return -1; if (c == *pp++) break; } } } } else #endif /* The same code works when not in UTF-8 mode and in UTF-8 mode when there is no UCP support. */ { while (length-- > 0) { pcre_uint32 cc, cp; if (eptr >= md->end_subject) return -2; /* Partial match */ cc = UCHAR21TEST(eptr); cp = UCHAR21TEST(p); if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1; p++; eptr++; } } } /* In the caseful case, we can just compare the bytes, whether or not we are in UTF-8 mode. */ else { while (length-- > 0) { if (eptr >= md->end_subject) return -2; /* Partial match */ if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1; } } return (int)(eptr - eptr_start); } /*************************************************************************** **************************************************************************** RECURSION IN THE match() FUNCTION The match() function is highly recursive, though not every recursive call increases the recursive depth. Nevertheless, some regular expressions can cause it to recurse to a great depth. I was writing for Unix, so I just let it call itself recursively. This uses the stack for saving everything that has to be saved for a recursive call. On Unix, the stack can be large, and this works fine. It turns out that on some non-Unix-like systems there are problems with programs that use a lot of stack. (This despite the fact that every last chip has oodles of memory these days, and techniques for extending the stack have been known for decades.) So.... There is a fudge, triggered by defining NO_RECURSE, which avoids recursive calls by keeping local variables that need to be preserved in blocks of memory obtained from malloc() instead instead of on the stack. Macros are used to achieve this so that the actual code doesn't look very different to what it always used to. The original heap-recursive code used longjmp(). However, it seems that this can be very slow on some operating systems. Following a suggestion from Stan Switzer, the use of longjmp() has been abolished, at the cost of having to provide a unique number for each call to RMATCH. There is no way of generating a sequence of numbers at compile time in C. I have given them names, to make them stand out more clearly. Crude tests on x86 Linux show a small speedup of around 5-8%. However, on FreeBSD, avoiding longjmp() more than halves the time taken to run the standard tests. Furthermore, not using longjmp() means that local dynamic variables don't have indeterminate values; this has meant that the frame size can be reduced because the result can be "passed back" by straight setting of the variable instead of being passed in the frame. **************************************************************************** ***************************************************************************/ /* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN below must be updated in sync. */ enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40, RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50, RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60, RM61, RM62, RM63, RM64, RM65, RM66, RM67 }; /* These versions of the macros use the stack, as normal. There are debugging versions and production versions. Note that the "rw" argument of RMATCH isn't actually used in this definition. */ #ifndef NO_RECURSE #define REGISTER register #ifdef PCRE_DEBUG #define RMATCH(ra,rb,rc,rd,re,rw) \ { \ printf("match() called in line %d\n", __LINE__); \ rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1); \ printf("to line %d\n", __LINE__); \ } #define RRETURN(ra) \ { \ printf("match() returned %d from line %d\n", ra, __LINE__); \ return ra; \ } #else #define RMATCH(ra,rb,rc,rd,re,rw) \ rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1) #define RRETURN(ra) return ra #endif #else /* These versions of the macros manage a private stack on the heap. Note that the "rd" argument of RMATCH isn't actually used in this definition. It's the md argument of match(), which never changes. */ #define REGISTER #define RMATCH(ra,rb,rc,rd,re,rw)\ {\ heapframe *newframe = frame->Xnextframe;\ if (newframe == NULL)\ {\ newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\ if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ newframe->Xnextframe = NULL;\ frame->Xnextframe = newframe;\ }\ frame->Xwhere = rw;\ newframe->Xeptr = ra;\ newframe->Xecode = rb;\ newframe->Xmstart = mstart;\ newframe->Xoffset_top = rc;\ newframe->Xeptrb = re;\ newframe->Xrdepth = frame->Xrdepth + 1;\ newframe->Xprevframe = frame;\ frame = newframe;\ DPRINTF(("restarting from line %d\n", __LINE__));\ goto HEAP_RECURSE;\ L_##rw:\ DPRINTF(("jumped back to line %d\n", __LINE__));\ } #define RRETURN(ra)\ {\ heapframe *oldframe = frame;\ frame = oldframe->Xprevframe;\ if (frame != NULL)\ {\ rrc = ra;\ goto HEAP_RETURN;\ }\ return ra;\ } /* Structure for remembering the local variables in a private frame */ typedef struct heapframe { struct heapframe *Xprevframe; struct heapframe *Xnextframe; /* Function arguments that may change */ PCRE_PUCHAR Xeptr; const pcre_uchar *Xecode; PCRE_PUCHAR Xmstart; int Xoffset_top; eptrblock *Xeptrb; unsigned int Xrdepth; /* Function local variables */ PCRE_PUCHAR Xcallpat; #ifdef SUPPORT_UTF PCRE_PUCHAR Xcharptr; #endif PCRE_PUCHAR Xdata; PCRE_PUCHAR Xnext; PCRE_PUCHAR Xpp; PCRE_PUCHAR Xprev; PCRE_PUCHAR Xsaved_eptr; recursion_info Xnew_recursive; BOOL Xcur_is_word; BOOL Xcondition; BOOL Xprev_is_word; #ifdef SUPPORT_UCP int Xprop_type; unsigned int Xprop_value; int Xprop_fail_result; int Xoclength; pcre_uchar Xocchars[6]; #endif int Xcodelink; int Xctype; unsigned int Xfc; int Xfi; int Xlength; int Xmax; int Xmin; unsigned int Xnumber; int Xoffset; unsigned int Xop; pcre_int32 Xsave_capture_last; int Xsave_offset1, Xsave_offset2, Xsave_offset3; int Xstacksave[REC_STACK_SAVE_MAX]; eptrblock Xnewptrb; /* Where to jump back to */ int Xwhere; } heapframe; #endif /*************************************************************************** ***************************************************************************/ /************************************************* * Match from current position * *************************************************/ /* This function is called recursively in many circumstances. Whenever it returns a negative (error) response, the outer incarnation must also return the same response. */ /* These macros pack up tests that are used for partial matching, and which appear several times in the code. We set the "hit end" flag if the pointer is at the end of the subject and also past the start of the subject (i.e. something has been matched). For hard partial matching, we then return immediately. The second one is used when we already know we are past the end of the subject. */ #define CHECK_PARTIAL()\ if (md->partial != 0 && eptr >= md->end_subject && \ eptr > md->start_used_ptr) \ { \ md->hitend = TRUE; \ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \ } #define SCHECK_PARTIAL()\ if (md->partial != 0 && eptr > md->start_used_ptr) \ { \ md->hitend = TRUE; \ if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \ } /* Performance note: It might be tempting to extract commonly used fields from the md structure (e.g. utf, end_subject) into individual variables to improve performance. Tests using gcc on a SPARC disproved this; in the first case, it made performance worse. Arguments: eptr pointer to current character in subject ecode pointer to current position in compiled code mstart pointer to the current match start position (can be modified by encountering \K) offset_top current top pointer md pointer to "static" info for the match eptrb pointer to chain of blocks containing eptr at start of brackets - for testing for empty matches rdepth the recursion depth Returns: MATCH_MATCH if matched ) these values are >= 0 MATCH_NOMATCH if failed to match ) a negative MATCH_xxx value for PRUNE, SKIP, etc a negative PCRE_ERROR_xxx value if aborted by an error condition (e.g. stopped by repeated call or recursion limit) */ static int match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode, PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb, unsigned int rdepth) { /* These variables do not need to be preserved over recursion in this function, so they can be ordinary variables in all cases. Mark some of them with "register" because they are used a lot in loops. */ register int rrc; /* Returns from recursive calls */ register int i; /* Used for loops not involving calls to RMATCH() */ register pcre_uint32 c; /* Character values not kept over RMATCH() calls */ register BOOL utf; /* Local copy of UTF flag for speed */ BOOL minimize, possessive; /* Quantifier options */ BOOL caseless; int condcode; /* When recursion is not being used, all "local" variables that have to be preserved over calls to RMATCH() are part of a "frame". We set up the top-level frame on the stack here; subsequent instantiations are obtained from the heap whenever RMATCH() does a "recursion". See the macro definitions above. Putting the top-level on the stack rather than malloc-ing them all gives a performance boost in many cases where there is not much "recursion". */ #ifdef NO_RECURSE heapframe *frame = (heapframe *)md->match_frames_base; /* Copy in the original argument variables */ frame->Xeptr = eptr; frame->Xecode = ecode; frame->Xmstart = mstart; frame->Xoffset_top = offset_top; frame->Xeptrb = eptrb; frame->Xrdepth = rdepth; /* This is where control jumps back to to effect "recursion" */ HEAP_RECURSE: /* Macros make the argument variables come from the current frame */ #define eptr frame->Xeptr #define ecode frame->Xecode #define mstart frame->Xmstart #define offset_top frame->Xoffset_top #define eptrb frame->Xeptrb #define rdepth frame->Xrdepth /* Ditto for the local variables */ #ifdef SUPPORT_UTF #define charptr frame->Xcharptr #endif #define callpat frame->Xcallpat #define codelink frame->Xcodelink #define data frame->Xdata #define next frame->Xnext #define pp frame->Xpp #define prev frame->Xprev #define saved_eptr frame->Xsaved_eptr #define new_recursive frame->Xnew_recursive #define cur_is_word frame->Xcur_is_word #define condition frame->Xcondition #define prev_is_word frame->Xprev_is_word #ifdef SUPPORT_UCP #define prop_type frame->Xprop_type #define prop_value frame->Xprop_value #define prop_fail_result frame->Xprop_fail_result #define oclength frame->Xoclength #define occhars frame->Xocchars #endif #define ctype frame->Xctype #define fc frame->Xfc #define fi frame->Xfi #define length frame->Xlength #define max frame->Xmax #define min frame->Xmin #define number frame->Xnumber #define offset frame->Xoffset #define op frame->Xop #define save_capture_last frame->Xsave_capture_last #define save_offset1 frame->Xsave_offset1 #define save_offset2 frame->Xsave_offset2 #define save_offset3 frame->Xsave_offset3 #define stacksave frame->Xstacksave #define newptrb frame->Xnewptrb /* When recursion is being used, local variables are allocated on the stack and get preserved during recursion in the normal way. In this environment, fi and i, and fc and c, can be the same variables. */ #else /* NO_RECURSE not defined */ #define fi i #define fc c /* Many of the following variables are used only in small blocks of the code. My normal style of coding would have declared them within each of those blocks. However, in order to accommodate the version of this code that uses an external "stack" implemented on the heap, it is easier to declare them all here, so the declarations can be cut out in a block. The only declarations within blocks below are for variables that do not have to be preserved over a recursive call to RMATCH(). */ #ifdef SUPPORT_UTF const pcre_uchar *charptr; #endif const pcre_uchar *callpat; const pcre_uchar *data; const pcre_uchar *next; PCRE_PUCHAR pp; const pcre_uchar *prev; PCRE_PUCHAR saved_eptr; recursion_info new_recursive; BOOL cur_is_word; BOOL condition; BOOL prev_is_word; #ifdef SUPPORT_UCP int prop_type; unsigned int prop_value; int prop_fail_result; int oclength; pcre_uchar occhars[6]; #endif int codelink; int ctype; int length; int max; int min; unsigned int number; int offset; unsigned int op; pcre_int32 save_capture_last; int save_offset1, save_offset2, save_offset3; int stacksave[REC_STACK_SAVE_MAX]; eptrblock newptrb; /* There is a special fudge for calling match() in a way that causes it to measure the size of its basic stack frame when the stack is being used for recursion. The second argument (ecode) being NULL triggers this behaviour. It cannot normally ever be NULL. The return is the negated value of the frame size. */ if (ecode == NULL) { if (rdepth == 0) return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1); else { int len = (int)((char *)&rdepth - (char *)eptr); return (len > 0)? -len : len; } } #endif /* NO_RECURSE */ /* To save space on the stack and in the heap frame, I have doubled up on some of the local variables that are used only in localised parts of the code, but still need to be preserved over recursive calls of match(). These macros define the alternative names that are used. */ #define allow_zero cur_is_word #define cbegroup condition #define code_offset codelink #define condassert condition #define matched_once prev_is_word #define foc number #define save_mark data /* These statements are here to stop the compiler complaining about unitialized variables. */ #ifdef SUPPORT_UCP prop_value = 0; prop_fail_result = 0; #endif /* This label is used for tail recursion, which is used in a few cases even when NO_RECURSE is not defined, in order to reduce the amount of stack that is used. Thanks to Ian Taylor for noticing this possibility and sending the original patch. */ TAIL_RECURSE: /* OK, now we can get on with the real code of the function. Recursive calls are specified by the macro RMATCH and RRETURN is used to return. When NO_RECURSE is *not* defined, these just turn into a recursive call to match() and a "return", respectively (possibly with some debugging if PCRE_DEBUG is defined). However, RMATCH isn't like a function call because it's quite a complicated macro. It has to be used in one particular way. This shouldn't, however, impact performance when true recursion is being used. */ #ifdef SUPPORT_UTF utf = md->utf; /* Local copy of the flag */ #else utf = FALSE; #endif /* First check that we haven't called match() too many times, or that we haven't exceeded the recursive call limit. */ if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT); if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT); /* At the start of a group with an unlimited repeat that may match an empty string, the variable md->match_function_type is set to MATCH_CBEGROUP. It is done this way to save having to use another function argument, which would take up space on the stack. See also MATCH_CONDASSERT below. When MATCH_CBEGROUP is set, add the current subject pointer to the chain of such remembered pointers, to be checked when we hit the closing ket, in order to break infinite loops that match no characters. When match() is called in other circumstances, don't add to the chain. The MATCH_CBEGROUP feature must NOT be used with tail recursion, because the memory block that is used is on the stack, so a new one may be required for each match(). */ if (md->match_function_type == MATCH_CBEGROUP) { newptrb.epb_saved_eptr = eptr; newptrb.epb_prev = eptrb; eptrb = &newptrb; md->match_function_type = 0; } /* Now start processing the opcodes. */ for (;;) { minimize = possessive = FALSE; op = *ecode; switch(op) { case OP_MARK: md->nomatch_mark = ecode + 2; md->mark = NULL; /* In case previously set by assertion */ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, eptrb, RM55); if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && md->mark == NULL) md->mark = ecode + 2; /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an argument, and we must check whether that argument matches this MARK's argument. It is passed back in md->start_match_ptr (an overloading of that variable). If it does match, we reset that variable to the current subject position and return MATCH_SKIP. Otherwise, pass back the return code unaltered. */ else if (rrc == MATCH_SKIP_ARG && STRCMP_UC_UC_TEST(ecode + 2, md->start_match_ptr) == 0) { md->start_match_ptr = eptr; RRETURN(MATCH_SKIP); } RRETURN(rrc); case OP_FAIL: RRETURN(MATCH_NOMATCH); case OP_COMMIT: RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM52); if (rrc != MATCH_NOMATCH) RRETURN(rrc); RRETURN(MATCH_COMMIT); case OP_PRUNE: RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM51); if (rrc != MATCH_NOMATCH) RRETURN(rrc); RRETURN(MATCH_PRUNE); case OP_PRUNE_ARG: md->nomatch_mark = ecode + 2; md->mark = NULL; /* In case previously set by assertion */ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, eptrb, RM56); if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && md->mark == NULL) md->mark = ecode + 2; if (rrc != MATCH_NOMATCH) RRETURN(rrc); RRETURN(MATCH_PRUNE); case OP_SKIP: RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM53); if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->start_match_ptr = eptr; /* Pass back current position */ RRETURN(MATCH_SKIP); /* Note that, for Perl compatibility, SKIP with an argument does NOT set nomatch_mark. When a pattern match ends with a SKIP_ARG for which there was not a matching mark, we have to re-run the match, ignoring the SKIP_ARG that failed and any that precede it (either they also failed, or were not triggered). To do this, we maintain a count of executed SKIP_ARGs. If a SKIP_ARG gets to top level, the match is re-run with md->ignore_skip_arg set to the count of the one that failed. */ case OP_SKIP_ARG: md->skip_arg_count++; if (md->skip_arg_count <= md->ignore_skip_arg) { ecode += PRIV(OP_lengths)[*ecode] + ecode[1]; break; } RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, eptrb, RM57); if (rrc != MATCH_NOMATCH) RRETURN(rrc); /* Pass back the current skip name by overloading md->start_match_ptr and returning the special MATCH_SKIP_ARG return code. This will either be caught by a matching MARK, or get to the top, where it causes a rematch with md->ignore_skip_arg set to the value of md->skip_arg_count. */ md->start_match_ptr = ecode + 2; RRETURN(MATCH_SKIP_ARG); /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that the branch in which it occurs can be determined. Overload the start of match pointer to do this. */ case OP_THEN: RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM54); if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->start_match_ptr = ecode; RRETURN(MATCH_THEN); case OP_THEN_ARG: md->nomatch_mark = ecode + 2; md->mark = NULL; /* In case previously set by assertion */ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, eptrb, RM58); if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && md->mark == NULL) md->mark = ecode + 2; if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->start_match_ptr = ecode; RRETURN(MATCH_THEN); /* Handle an atomic group that does not contain any capturing parentheses. This can be handled like an assertion. Prior to 8.13, all atomic groups were handled this way. In 8.13, the code was changed as below for ONCE, so that backups pass through the group and thereby reset captured values. However, this uses a lot more stack, so in 8.20, atomic groups that do not contain any captures generate OP_ONCE_NC, which can be handled in the old, less stack intensive way. Check the alternative branches in turn - the matching won't pass the KET for this kind of subpattern. If any one branch matches, we carry on as at the end of a normal bracket, leaving the subject pointer, but resetting the start-of-match value in case it was changed by \K. */ case OP_ONCE_NC: prev = ecode; saved_eptr = eptr; save_mark = md->mark; do { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64); if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */ { mstart = md->start_match_ptr; break; } if (rrc == MATCH_THEN) { next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) rrc = MATCH_NOMATCH; } if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode,1); md->mark = save_mark; } while (*ecode == OP_ALT); /* If hit the end of the group (which could be repeated), fail */ if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); /* Continue as from after the group, updating the offsets high water mark, since extracts may have been taken. */ do ecode += GET(ecode, 1); while (*ecode == OP_ALT); offset_top = md->end_offset_top; eptr = md->end_match_ptr; /* For a non-repeating ket, just continue at this level. This also happens for a repeating ket if no characters were matched in the group. This is the forcible breaking of infinite loops as implemented in Perl 5.005. */ if (*ecode == OP_KET || eptr == saved_eptr) { ecode += 1+LINK_SIZE; break; } /* The repeating kets try the rest of the pattern or restart from the preceding bracket, in the appropriate order. The second "call" of match() uses tail recursion, to avoid using another stack frame. */ if (*ecode == OP_KETRMIN) { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode = prev; goto TAIL_RECURSE; } else /* OP_KETRMAX */ { RMATCH(eptr, prev, offset_top, md, eptrb, RM66); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += 1 + LINK_SIZE; goto TAIL_RECURSE; } /* Control never gets here */ /* Handle a capturing bracket, other than those that are possessive with an unlimited repeat. If there is space in the offset vector, save the current subject position in the working slot at the top of the vector. We mustn't change the current values of the data slot, because they may be set from a previous iteration of this group, and be referred to by a reference inside the group. A failure to match might occur after the group has succeeded, if something later on doesn't match. For this reason, we need to restore the working value and also the values of the final offsets, in case they were set by a previous iteration of the same bracket. If there isn't enough space in the offset vector, treat this as if it were a non-capturing bracket. Don't worry about setting the flag for the error case here; that is handled in the code for KET. */ case OP_CBRA: case OP_SCBRA: number = GET2(ecode, 1+LINK_SIZE); offset = number << 1; #ifdef PCRE_DEBUG printf("start bracket %d\n", number); printf("subject="); pchars(eptr, 16, TRUE, md); printf("\n"); #endif if (offset < md->offset_max) { save_offset1 = md->offset_vector[offset]; save_offset2 = md->offset_vector[offset+1]; save_offset3 = md->offset_vector[md->offset_end - number]; save_capture_last = md->capture_last; save_mark = md->mark; DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); md->offset_vector[md->offset_end - number] = (int)(eptr - md->start_subject); for (;;) { if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM1); if (rrc == MATCH_ONCE) break; /* Backing up through an atomic group */ /* If we backed up to a THEN, check whether it is within the current branch by comparing the address of the THEN that is passed back with the end of the branch. If it is within the current branch, and the branch is one of two or more alternatives (it either starts or ends with OP_ALT), we have reached the limit of THEN's action, so convert the return code to NOMATCH, which will cause normal backtracking to happen from now on. Otherwise, THEN is passed back to an outer alternative. This implements Perl's treatment of parenthesized groups, where a group not containing | does not affect the current alternative, that is, (X) is NOT the same as (X|(*F)). */ if (rrc == MATCH_THEN) { next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) rrc = MATCH_NOMATCH; } /* Anything other than NOMATCH is passed back. */ if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->capture_last = save_capture_last; ecode += GET(ecode, 1); md->mark = save_mark; if (*ecode != OP_ALT) break; } DPRINTF(("bracket %d failed\n", number)); md->offset_vector[offset] = save_offset1; md->offset_vector[offset+1] = save_offset2; md->offset_vector[md->offset_end - number] = save_offset3; /* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */ RRETURN(rrc); } /* FALL THROUGH ... Insufficient room for saving captured contents. Treat as a non-capturing bracket. */ /* VVVVVVVVVVVVVVVVVVVVVVVVV */ /* VVVVVVVVVVVVVVVVVVVVVVVVV */ DPRINTF(("insufficient capture room: treat as non-capturing\n")); /* VVVVVVVVVVVVVVVVVVVVVVVVV */ /* VVVVVVVVVVVVVVVVVVVVVVVVV */ /* Non-capturing or atomic group, except for possessive with unlimited repeat and ONCE group with no captures. Loop for all the alternatives. When we get to the final alternative within the brackets, we used to return the result of a recursive call to match() whatever happened so it was possible to reduce stack usage by turning this into a tail recursion, except in the case of a possibly empty group. However, now that there is the possiblity of (*THEN) occurring in the final alternative, this optimization is no longer always possible. We can optimize if we know there are no (*THEN)s in the pattern; at present this is the best that can be done. MATCH_ONCE is returned when the end of an atomic group is successfully reached, but subsequent matching fails. It passes back up the tree (causing captured values to be reset) until the original atomic group level is reached. This is tested by comparing md->once_target with the start of the group. At this point, the return is converted into MATCH_NOMATCH so that previous backup points can be taken. */ case OP_ONCE: case OP_BRA: case OP_SBRA: DPRINTF(("start non-capturing bracket\n")); for (;;) { if (op >= OP_SBRA || op == OP_ONCE) md->match_function_type = MATCH_CBEGROUP; /* If this is not a possibly empty group, and there are no (*THEN)s in the pattern, and this is the final alternative, optimize as described above. */ else if (!md->hasthen && ecode[GET(ecode, 1)] != OP_ALT) { ecode += PRIV(OP_lengths)[*ecode]; goto TAIL_RECURSE; } /* In all other cases, we have to make another call to match(). */ save_mark = md->mark; save_capture_last = md->capture_last; RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM2); /* See comment in the code for capturing groups above about handling THEN. */ if (rrc == MATCH_THEN) { next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) rrc = MATCH_NOMATCH; } if (rrc != MATCH_NOMATCH) { if (rrc == MATCH_ONCE) { const pcre_uchar *scode = ecode; if (*scode != OP_ONCE) /* If not at start, find it */ { while (*scode == OP_ALT) scode += GET(scode, 1); scode -= GET(scode, 1); } if (md->once_target == scode) rrc = MATCH_NOMATCH; } RRETURN(rrc); } ecode += GET(ecode, 1); md->mark = save_mark; if (*ecode != OP_ALT) break; md->capture_last = save_capture_last; } RRETURN(MATCH_NOMATCH); /* Handle possessive capturing brackets with an unlimited repeat. We come here from BRAZERO with allow_zero set TRUE. The offset_vector values are handled similarly to the normal case above. However, the matching is different. The end of these brackets will always be OP_KETRPOS, which returns MATCH_KETRPOS without going further in the pattern. By this means we can handle the group by iteration rather than recursion, thereby reducing the amount of stack needed. */ case OP_CBRAPOS: case OP_SCBRAPOS: allow_zero = FALSE; POSSESSIVE_CAPTURE: number = GET2(ecode, 1+LINK_SIZE); offset = number << 1; #ifdef PCRE_DEBUG printf("start possessive bracket %d\n", number); printf("subject="); pchars(eptr, 16, TRUE, md); printf("\n"); #endif if (offset >= md->offset_max) goto POSSESSIVE_NON_CAPTURE; matched_once = FALSE; code_offset = (int)(ecode - md->start_code); save_offset1 = md->offset_vector[offset]; save_offset2 = md->offset_vector[offset+1]; save_offset3 = md->offset_vector[md->offset_end - number]; save_capture_last = md->capture_last; DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); /* Each time round the loop, save the current subject position for use when the group matches. For MATCH_MATCH, the group has matched, so we restart it with a new subject starting position, remembering that we had at least one match. For MATCH_NOMATCH, carry on with the alternatives, as usual. If we haven't matched any alternatives in any iteration, check to see if a previous iteration matched. If so, the group has matched; continue from afterwards. Otherwise it has failed; restore the previous capture values before returning NOMATCH. */ for (;;) { md->offset_vector[md->offset_end - number] = (int)(eptr - md->start_subject); if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM63); if (rrc == MATCH_KETRPOS) { offset_top = md->end_offset_top; ecode = md->start_code + code_offset; save_capture_last = md->capture_last; matched_once = TRUE; mstart = md->start_match_ptr; /* In case \K changed it */ if (eptr == md->end_match_ptr) /* Matched an empty string */ { do ecode += GET(ecode, 1); while (*ecode == OP_ALT); break; } eptr = md->end_match_ptr; continue; } /* See comment in the code for capturing groups above about handling THEN. */ if (rrc == MATCH_THEN) { next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) rrc = MATCH_NOMATCH; } if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->capture_last = save_capture_last; ecode += GET(ecode, 1); if (*ecode != OP_ALT) break; } if (!matched_once) { md->offset_vector[offset] = save_offset1; md->offset_vector[offset+1] = save_offset2; md->offset_vector[md->offset_end - number] = save_offset3; } if (allow_zero || matched_once) { ecode += 1 + LINK_SIZE; break; } RRETURN(MATCH_NOMATCH); /* Non-capturing possessive bracket with unlimited repeat. We come here from BRAZERO with allow_zero = TRUE. The code is similar to the above, without the capturing complication. It is written out separately for speed and cleanliness. */ case OP_BRAPOS: case OP_SBRAPOS: allow_zero = FALSE; POSSESSIVE_NON_CAPTURE: matched_once = FALSE; code_offset = (int)(ecode - md->start_code); save_capture_last = md->capture_last; for (;;) { if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, RM48); if (rrc == MATCH_KETRPOS) { offset_top = md->end_offset_top; ecode = md->start_code + code_offset; matched_once = TRUE; mstart = md->start_match_ptr; /* In case \K reset it */ if (eptr == md->end_match_ptr) /* Matched an empty string */ { do ecode += GET(ecode, 1); while (*ecode == OP_ALT); break; } eptr = md->end_match_ptr; continue; } /* See comment in the code for capturing groups above about handling THEN. */ if (rrc == MATCH_THEN) { next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) rrc = MATCH_NOMATCH; } if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode, 1); if (*ecode != OP_ALT) break; md->capture_last = save_capture_last; } if (matched_once || allow_zero) { ecode += 1 + LINK_SIZE; break; } RRETURN(MATCH_NOMATCH); /* Control never reaches here. */ /* Conditional group: compilation checked that there are no more than two branches. If the condition is false, skipping the first branch takes us past the end of the item if there is only one branch, but that's exactly what we want. */ case OP_COND: case OP_SCOND: /* The variable codelink will be added to ecode when the condition is false, to get to the second branch. Setting it to the offset to the ALT or KET, then incrementing ecode achieves this effect. We now have ecode pointing to the condition or callout. */ codelink = GET(ecode, 1); /* Offset to the second branch */ ecode += 1 + LINK_SIZE; /* From this opcode */ /* Because of the way auto-callout works during compile, a callout item is inserted between OP_COND and an assertion condition. */ if (*ecode == OP_CALLOUT) { if (PUBL(callout) != NULL) { PUBL(callout_block) cb; cb.version = 2; /* Version 1 of the callout block */ cb.callout_number = ecode[1]; cb.offset_vector = md->offset_vector; #if defined COMPILE_PCRE8 cb.subject = (PCRE_SPTR)md->start_subject; #elif defined COMPILE_PCRE16 cb.subject = (PCRE_SPTR16)md->start_subject; #elif defined COMPILE_PCRE32 cb.subject = (PCRE_SPTR32)md->start_subject; #endif cb.subject_length = (int)(md->end_subject - md->start_subject); cb.start_match = (int)(mstart - md->start_subject); cb.current_position = (int)(eptr - md->start_subject); cb.pattern_position = GET(ecode, 2); cb.next_item_length = GET(ecode, 2 + LINK_SIZE); cb.capture_top = offset_top/2; cb.capture_last = md->capture_last & CAPLMASK; /* Internal change requires this for API compatibility. */ if (cb.capture_last == 0) cb.capture_last = -1; cb.callout_data = md->callout_data; cb.mark = md->nomatch_mark; if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH); if (rrc < 0) RRETURN(rrc); } /* Advance ecode past the callout, so it now points to the condition. We must adjust codelink so that the value of ecode+codelink is unchanged. */ ecode += PRIV(OP_lengths)[OP_CALLOUT]; codelink -= PRIV(OP_lengths)[OP_CALLOUT]; } /* Test the various possible conditions */ condition = FALSE; switch(condcode = *ecode) { case OP_RREF: /* Numbered group recursion test */ if (md->recursive != NULL) /* Not recursing => FALSE */ { unsigned int recno = GET2(ecode, 1); /* Recursion group number*/ condition = (recno == RREF_ANY || recno == md->recursive->group_num); } break; case OP_DNRREF: /* Duplicate named group recursion test */ if (md->recursive != NULL) { int count = GET2(ecode, 1 + IMM2_SIZE); pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size; while (count-- > 0) { unsigned int recno = GET2(slot, 0); condition = recno == md->recursive->group_num; if (condition) break; slot += md->name_entry_size; } } break; case OP_CREF: /* Numbered group used test */ offset = GET2(ecode, 1) << 1; /* Doubled ref number */ condition = offset < offset_top && md->offset_vector[offset] >= 0; break; case OP_DNCREF: /* Duplicate named group used test */ { int count = GET2(ecode, 1 + IMM2_SIZE); pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size; while (count-- > 0) { offset = GET2(slot, 0) << 1; condition = offset < offset_top && md->offset_vector[offset] >= 0; if (condition) break; slot += md->name_entry_size; } } break; case OP_DEF: /* DEFINE - always false */ case OP_FAIL: /* From optimized (?!) condition */ break; /* The condition is an assertion. Call match() to evaluate it - setting md->match_function_type to MATCH_CONDASSERT causes it to stop at the end of an assertion. */ default: md->match_function_type = MATCH_CONDASSERT; RMATCH(eptr, ecode, offset_top, md, NULL, RM3); if (rrc == MATCH_MATCH) { if (md->end_offset_top > offset_top) offset_top = md->end_offset_top; /* Captures may have happened */ condition = TRUE; /* Advance ecode past the assertion to the start of the first branch, but adjust it so that the general choosing code below works. If the assertion has a quantifier that allows zero repeats we must skip over the BRAZERO. This is a lunatic thing to do, but somebody did! */ if (*ecode == OP_BRAZERO) ecode++; ecode += GET(ecode, 1); while (*ecode == OP_ALT) ecode += GET(ecode, 1); ecode += 1 + LINK_SIZE - PRIV(OP_lengths)[condcode]; } /* PCRE doesn't allow the effect of (*THEN) to escape beyond an assertion; it is therefore treated as NOMATCH. Any other return is an error. */ else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) { RRETURN(rrc); /* Need braces because of following else */ } break; } /* Choose branch according to the condition */ ecode += condition? PRIV(OP_lengths)[condcode] : codelink; /* We are now at the branch that is to be obeyed. As there is only one, we can use tail recursion to avoid using another stack frame, except when there is unlimited repeat of a possibly empty group. In the latter case, a recursive call to match() is always required, unless the second alternative doesn't exist, in which case we can just plough on. Note that, for compatibility with Perl, the | in a conditional group is NOT treated as creating two alternatives. If a THEN is encountered in the branch, it propagates out to the enclosing alternative (unless nested in a deeper set of alternatives, of course). */ if (condition || ecode[-(1+LINK_SIZE)] == OP_ALT) { if (op != OP_SCOND) { goto TAIL_RECURSE; } md->match_function_type = MATCH_CBEGROUP; RMATCH(eptr, ecode, offset_top, md, eptrb, RM49); RRETURN(rrc); } /* Condition false & no alternative; continue after the group. */ else { } break; /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, to close any currently open capturing brackets. */ case OP_CLOSE: number = GET2(ecode, 1); /* Must be less than 65536 */ offset = number << 1; #ifdef PCRE_DEBUG printf("end bracket %d at *ACCEPT", number); printf("\n"); #endif md->capture_last = (md->capture_last & OVFLMASK) | number; if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else { md->offset_vector[offset] = md->offset_vector[md->offset_end - number]; md->offset_vector[offset+1] = (int)(eptr - md->start_subject); /* If this group is at or above the current highwater mark, ensure that any groups between the current high water mark and this group are marked unset and then update the high water mark. */ if (offset >= offset_top) { register int *iptr = md->offset_vector + offset_top; register int *iend = md->offset_vector + offset; while (iptr < iend) *iptr++ = -1; offset_top = offset + 2; } } ecode += 1 + IMM2_SIZE; break; /* End of the pattern, either real or forced. */ case OP_END: case OP_ACCEPT: case OP_ASSERT_ACCEPT: /* If we have matched an empty string, fail if not in an assertion and not in a recursion if either PCRE_NOTEMPTY is set, or if PCRE_NOTEMPTY_ATSTART is set and we have matched at the start of the subject. In both cases, backtracking will then try other alternatives, if any. */ if (eptr == mstart && op != OP_ASSERT_ACCEPT && md->recursive == NULL && (md->notempty || (md->notempty_atstart && mstart == md->start_subject + md->start_offset))) RRETURN(MATCH_NOMATCH); /* Otherwise, we have a match. */ md->end_match_ptr = eptr; /* Record where we ended */ md->end_offset_top = offset_top; /* and how many extracts were taken */ md->start_match_ptr = mstart; /* and the start (\K can modify) */ /* For some reason, the macros don't work properly if an expression is given as the argument to RRETURN when the heap is in use. */ rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT; RRETURN(rrc); /* Assertion brackets. Check the alternative branches in turn - the matching won't pass the KET for an assertion. If any one branch matches, the assertion is true. Lookbehind assertions have an OP_REVERSE item at the start of each branch to move the current point backwards, so the code at this level is identical to the lookahead case. When the assertion is part of a condition, we want to return immediately afterwards. The caller of this incarnation of the match() function will have set MATCH_CONDASSERT in md->match_function type, and one of these opcodes will be the first opcode that is processed. We use a local variable that is preserved over calls to match() to remember this case. */ case OP_ASSERT: case OP_ASSERTBACK: save_mark = md->mark; if (md->match_function_type == MATCH_CONDASSERT) { condassert = TRUE; md->match_function_type = 0; } else condassert = FALSE; /* Loop for each branch */ do { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4); /* A match means that the assertion is true; break out of the loop that matches its alternatives. */ if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) { mstart = md->start_match_ptr; /* In case \K reset it */ break; } /* If not matched, restore the previous mark setting. */ md->mark = save_mark; /* See comment in the code for capturing groups above about handling THEN. */ if (rrc == MATCH_THEN) { next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) rrc = MATCH_NOMATCH; } /* Anything other than NOMATCH causes the entire assertion to fail, passing back the return code. This includes COMMIT, SKIP, PRUNE and an uncaptured THEN, which means they take their normal effect. This consistent approach does not always have exactly the same effect as in Perl. */ if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode += GET(ecode, 1); } while (*ecode == OP_ALT); /* Continue for next alternative */ /* If we have tried all the alternative branches, the assertion has failed. If not, we broke out after a match. */ if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); /* If checking an assertion for a condition, return MATCH_MATCH. */ if (condassert) RRETURN(MATCH_MATCH); /* Continue from after a successful assertion, updating the offsets high water mark, since extracts may have been taken during the assertion. */ do ecode += GET(ecode,1); while (*ecode == OP_ALT); ecode += 1 + LINK_SIZE; offset_top = md->end_offset_top; continue; /* Negative assertion: all branches must fail to match for the assertion to succeed. */ case OP_ASSERT_NOT: case OP_ASSERTBACK_NOT: save_mark = md->mark; if (md->match_function_type == MATCH_CONDASSERT) { condassert = TRUE; md->match_function_type = 0; } else condassert = FALSE; /* Loop for each alternative branch. */ do { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5); md->mark = save_mark; /* Always restore the mark setting */ switch(rrc) { case MATCH_MATCH: /* A successful match means */ case MATCH_ACCEPT: /* the assertion has failed. */ RRETURN(MATCH_NOMATCH); case MATCH_NOMATCH: /* Carry on with next branch */ break; /* See comment in the code for capturing groups above about handling THEN. */ case MATCH_THEN: next = ecode + GET(ecode,1); if (md->start_match_ptr < next && (*ecode == OP_ALT || *next == OP_ALT)) { rrc = MATCH_NOMATCH; break; } /* Otherwise fall through. */ /* COMMIT, SKIP, PRUNE, and an uncaptured THEN cause the whole assertion to fail to match, without considering any more alternatives. Failing to match means the assertion is true. This is a consistent approach, but does not always have the same effect as in Perl. */ case MATCH_COMMIT: case MATCH_SKIP: case MATCH_SKIP_ARG: case MATCH_PRUNE: do ecode += GET(ecode,1); while (*ecode == OP_ALT); goto NEG_ASSERT_TRUE; /* Break out of alternation loop */ /* Anything else is an error */ default: RRETURN(rrc); } /* Continue with next branch */ ecode += GET(ecode,1); } while (*ecode == OP_ALT); /* All branches in the assertion failed to match. */ NEG_ASSERT_TRUE: if (condassert) RRETURN(MATCH_MATCH); /* Condition assertion */ ecode += 1 + LINK_SIZE; /* Continue with current branch */ continue; /* Move the subject pointer back. This occurs only at the start of each branch of a lookbehind assertion. If we are too close to the start to move back, this match function fails. When working with UTF-8 we move back a number of characters, not bytes. */ case OP_REVERSE: #ifdef SUPPORT_UTF if (utf) { i = GET(ecode, 1); while (i-- > 0) { eptr--; if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); BACKCHAR(eptr); } } else #endif /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ { eptr -= GET(ecode, 1); if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); } /* Save the earliest consulted character, then skip to next op code */ if (eptr < md->start_used_ptr) md->start_used_ptr = eptr; ecode += 1 + LINK_SIZE; break; /* The callout item calls an external function, if one is provided, passing details of the match so far. This is mainly for debugging, though the function is able to force a failure. */ case OP_CALLOUT: if (PUBL(callout) != NULL) { PUBL(callout_block) cb; cb.version = 2; /* Version 1 of the callout block */ cb.callout_number = ecode[1]; cb.offset_vector = md->offset_vector; #if defined COMPILE_PCRE8 cb.subject = (PCRE_SPTR)md->start_subject; #elif defined COMPILE_PCRE16 cb.subject = (PCRE_SPTR16)md->start_subject; #elif defined COMPILE_PCRE32 cb.subject = (PCRE_SPTR32)md->start_subject; #endif cb.subject_length = (int)(md->end_subject - md->start_subject); cb.start_match = (int)(mstart - md->start_subject); cb.current_position = (int)(eptr - md->start_subject); cb.pattern_position = GET(ecode, 2); cb.next_item_length = GET(ecode, 2 + LINK_SIZE); cb.capture_top = offset_top/2; cb.capture_last = md->capture_last & CAPLMASK; /* Internal change requires this for API compatibility. */ if (cb.capture_last == 0) cb.capture_last = -1; cb.callout_data = md->callout_data; cb.mark = md->nomatch_mark; if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH); if (rrc < 0) RRETURN(rrc); } ecode += 2 + 2*LINK_SIZE; break; /* Recursion either matches the current regex, or some subexpression. The offset data is the offset to the starting bracket from the start of the whole pattern. (This is so that it works from duplicated subpatterns.) The state of the capturing groups is preserved over recursion, and re-instated afterwards. We don't know how many are started and not yet finished (offset_top records the completed total) so we just have to save all the potential data. There may be up to 65535 such values, which is too large to put on the stack, but using malloc for small numbers seems expensive. As a compromise, the stack is used when there are no more than REC_STACK_SAVE_MAX values to store; otherwise malloc is used. There are also other values that have to be saved. We use a chained sequence of blocks that actually live on the stack. Thanks to Robin Houston for the original version of this logic. It has, however, been hacked around a lot, so he is not to blame for the current way it works. */ case OP_RECURSE: { recursion_info *ri; unsigned int recno; callpat = md->start_code + GET(ecode, 1); recno = (callpat == md->start_code)? 0 : GET2(callpat, 1 + LINK_SIZE); /* Check for repeating a recursion without advancing the subject pointer. This should catch convoluted mutual recursions. (Some simple cases are caught at compile time.) */ for (ri = md->recursive; ri != NULL; ri = ri->prevrec) if (recno == ri->group_num && eptr == ri->subject_position) RRETURN(PCRE_ERROR_RECURSELOOP); /* Add to "recursing stack" */ new_recursive.group_num = recno; new_recursive.saved_capture_last = md->capture_last; new_recursive.subject_position = eptr; new_recursive.prevrec = md->recursive; md->recursive = &new_recursive; /* Where to continue from afterwards */ ecode += 1 + LINK_SIZE; /* Now save the offset data */ new_recursive.saved_max = md->offset_end; if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) new_recursive.offset_save = stacksave; else { new_recursive.offset_save = (int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int)); if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY); } memcpy(new_recursive.offset_save, md->offset_vector, new_recursive.saved_max * sizeof(int)); /* OK, now we can do the recursion. After processing each alternative, restore the offset data and the last captured value. If there were nested recursions, md->recursive might be changed, so reset it before looping. */ DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); cbegroup = (*callpat >= OP_SBRA); do { if (cbegroup) md->match_function_type = MATCH_CBEGROUP; RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top, md, eptrb, RM6); memcpy(md->offset_vector, new_recursive.offset_save, new_recursive.saved_max * sizeof(int)); md->capture_last = new_recursive.saved_capture_last; md->recursive = new_recursive.prevrec; if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) { DPRINTF(("Recursion matched\n")); if (new_recursive.offset_save != stacksave) (PUBL(free))(new_recursive.offset_save); /* Set where we got to in the subject, and reset the start in case it was changed by \K. This *is* propagated back out of a recursion, for Perl compatibility. */ eptr = md->end_match_ptr; mstart = md->start_match_ptr; goto RECURSION_MATCHED; /* Exit loop; end processing */ } /* PCRE does not allow THEN, SKIP, PRUNE or COMMIT to escape beyond a recursion; they cause a NOMATCH for the entire recursion. These codes are defined in a range that can be tested for. */ if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX) { if (new_recursive.offset_save != stacksave) (PUBL(free))(new_recursive.offset_save); RRETURN(MATCH_NOMATCH); } /* Any return code other than NOMATCH is an error. */ if (rrc != MATCH_NOMATCH) { DPRINTF(("Recursion gave error %d\n", rrc)); if (new_recursive.offset_save != stacksave) (PUBL(free))(new_recursive.offset_save); RRETURN(rrc); } md->recursive = &new_recursive; callpat += GET(callpat, 1); } while (*callpat == OP_ALT); DPRINTF(("Recursion didn't match\n")); md->recursive = new_recursive.prevrec; if (new_recursive.offset_save != stacksave) (PUBL(free))(new_recursive.offset_save); RRETURN(MATCH_NOMATCH); } RECURSION_MATCHED: break; /* An alternation is the end of a branch; scan along to find the end of the bracketed group and go to there. */ case OP_ALT: do ecode += GET(ecode,1); while (*ecode == OP_ALT); break; /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group, indicating that it may occur zero times. It may repeat infinitely, or not at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets with fixed upper repeat limits are compiled as a number of copies, with the optional ones preceded by BRAZERO or BRAMINZERO. */ case OP_BRAZERO: next = ecode + 1; RMATCH(eptr, next, offset_top, md, eptrb, RM10); if (rrc != MATCH_NOMATCH) RRETURN(rrc); do next += GET(next, 1); while (*next == OP_ALT); ecode = next + 1 + LINK_SIZE; break; case OP_BRAMINZERO: next = ecode + 1; do next += GET(next, 1); while (*next == OP_ALT); RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, RM11); if (rrc != MATCH_NOMATCH) RRETURN(rrc); ecode++; break; case OP_SKIPZERO: next = ecode+1; do next += GET(next,1); while (*next == OP_ALT); ecode = next + 1 + LINK_SIZE; break; /* BRAPOSZERO occurs before a possessive bracket group. Don't do anything here; just jump to the group, with allow_zero set TRUE. */ case OP_BRAPOSZERO: op = *(++ecode); allow_zero = TRUE; if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE; goto POSSESSIVE_NON_CAPTURE; /* End of a group, repeated or non-repeating. */ case OP_KET: case OP_KETRMIN: case OP_KETRMAX: case OP_KETRPOS: prev = ecode - GET(ecode, 1); /* If this was a group that remembered the subject start, in order to break infinite repeats of empty string matches, retrieve the subject start from the chain. Otherwise, set it NULL. */ if (*prev >= OP_SBRA || *prev == OP_ONCE) { saved_eptr = eptrb->epb_saved_eptr; /* Value at start of group */ eptrb = eptrb->epb_prev; /* Backup to previous group */ } else saved_eptr = NULL; /* If we are at the end of an assertion group or a non-capturing atomic group, stop matching and return MATCH_MATCH, but record the current high water mark for use by positive assertions. We also need to record the match start in case it was changed by \K. */ if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) || *prev == OP_ONCE_NC) { md->end_match_ptr = eptr; /* For ONCE_NC */ md->end_offset_top = offset_top; md->start_match_ptr = mstart; RRETURN(MATCH_MATCH); /* Sets md->mark */ } /* For capturing groups we have to check the group number back at the start and if necessary complete handling an extraction by setting the offsets and bumping the high water mark. Whole-pattern recursion is coded as a recurse into group 0, so it won't be picked up here. Instead, we catch it when the OP_END is reached. Other recursion is handled here. We just have to record the current subject position and start match pointer and give a MATCH return. */ if (*prev == OP_CBRA || *prev == OP_SCBRA || *prev == OP_CBRAPOS || *prev == OP_SCBRAPOS) { number = GET2(prev, 1+LINK_SIZE); offset = number << 1; #ifdef PCRE_DEBUG printf("end bracket %d", number); printf("\n"); #endif /* Handle a recursively called group. */ if (md->recursive != NULL && md->recursive->group_num == number) { md->end_match_ptr = eptr; md->start_match_ptr = mstart; RRETURN(MATCH_MATCH); } /* Deal with capturing */ md->capture_last = (md->capture_last & OVFLMASK) | number; if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else { /* If offset is greater than offset_top, it means that we are "skipping" a capturing group, and that group's offsets must be marked unset. In earlier versions of PCRE, all the offsets were unset at the start of matching, but this doesn't work because atomic groups and assertions can cause a value to be set that should later be unset. Example: matching /(?>(a))b|(a)c/ against "ac". This sets group 1 as part of the atomic group, but this is not on the final matching path, so must be unset when 2 is set. (If there is no group 2, there is no problem, because offset_top will then be 2, indicating no capture.) */ if (offset > offset_top) { register int *iptr = md->offset_vector + offset_top; register int *iend = md->offset_vector + offset; while (iptr < iend) *iptr++ = -1; } /* Now make the extraction */ md->offset_vector[offset] = md->offset_vector[md->offset_end - number]; md->offset_vector[offset+1] = (int)(eptr - md->start_subject); if (offset_top <= offset) offset_top = offset + 2; } } /* OP_KETRPOS is a possessive repeating ket. Remember the current position, and return the MATCH_KETRPOS. This makes it possible to do the repeats one at a time from the outer level, thus saving stack. This must precede the empty string test - in this case that test is done at the outer level. */ if (*ecode == OP_KETRPOS) { md->start_match_ptr = mstart; /* In case \K reset it */ md->end_match_ptr = eptr; md->end_offset_top = offset_top; RRETURN(MATCH_KETRPOS); } /* For an ordinary non-repeating ket, just continue at this level. This also happens for a repeating ket if no characters were matched in the group. This is the forcible breaking of infinite loops as implemented in Perl 5.005. For a non-repeating atomic group that includes captures, establish a backup point by processing the rest of the pattern at a lower level. If this results in a NOMATCH return, pass MATCH_ONCE back to the original OP_ONCE level, thereby bypassing intermediate backup points, but resetting any captures that happened along the way. */ if (*ecode == OP_KET || eptr == saved_eptr) { if (*prev == OP_ONCE) { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12); if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ RRETURN(MATCH_ONCE); } ecode += 1 + LINK_SIZE; /* Carry on at this level */ break; } /* The normal repeating kets try the rest of the pattern or restart from the preceding bracket, in the appropriate order. In the second case, we can use tail recursion to avoid using another stack frame, unless we have an an atomic group or an unlimited repeat of a group that can match an empty string. */ if (*ecode == OP_KETRMIN) { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (*prev == OP_ONCE) { RMATCH(eptr, prev, offset_top, md, eptrb, RM8); if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ RRETURN(MATCH_ONCE); } if (*prev >= OP_SBRA) /* Could match an empty string */ { RMATCH(eptr, prev, offset_top, md, eptrb, RM50); RRETURN(rrc); } ecode = prev; goto TAIL_RECURSE; } else /* OP_KETRMAX */ { RMATCH(eptr, prev, offset_top, md, eptrb, RM13); if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH; if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (*prev == OP_ONCE) { RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM9); if (rrc != MATCH_NOMATCH) RRETURN(rrc); md->once_target = prev; RRETURN(MATCH_ONCE); } ecode += 1 + LINK_SIZE; goto TAIL_RECURSE; } /* Control never gets here */ /* Not multiline mode: start of subject assertion, unless notbol. */ case OP_CIRC: if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); /* Start of subject assertion */ case OP_SOD: if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); ecode++; break; /* Multiline mode: start of subject unless notbol, or after any newline. */ case OP_CIRCM: if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); if (eptr != md->start_subject && (eptr == md->end_subject || !WAS_NEWLINE(eptr))) RRETURN(MATCH_NOMATCH); ecode++; break; /* Start of match assertion */ case OP_SOM: if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); ecode++; break; /* Reset the start of match point */ case OP_SET_SOM: mstart = eptr; ecode++; break; /* Multiline mode: assert before any newline, or before end of subject unless noteol is set. */ case OP_DOLLM: if (eptr < md->end_subject) { if (!IS_NEWLINE(eptr)) { if (md->partial != 0 && eptr + 1 >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && UCHAR21TEST(eptr) == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } RRETURN(MATCH_NOMATCH); } } else { if (md->noteol) RRETURN(MATCH_NOMATCH); SCHECK_PARTIAL(); } ecode++; break; /* Not multiline mode: assert before a terminating newline or before end of subject unless noteol is set. */ case OP_DOLL: if (md->noteol) RRETURN(MATCH_NOMATCH); if (!md->endonly) goto ASSERT_NL_OR_EOS; /* ... else fall through for endonly */ /* End of subject assertion (\z) */ case OP_EOD: if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); SCHECK_PARTIAL(); ecode++; break; /* End of subject or ending \n assertion (\Z) */ case OP_EODN: ASSERT_NL_OR_EOS: if (eptr < md->end_subject && (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) { if (md->partial != 0 && eptr + 1 >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && UCHAR21TEST(eptr) == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } RRETURN(MATCH_NOMATCH); } /* Either at end of string or \n before end. */ SCHECK_PARTIAL(); ecode++; break; /* Word boundary assertions */ case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: { /* Find out if the previous and current characters are "word" characters. It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to be "non-word" characters. Remember the earliest consulted character for partial matching. */ #ifdef SUPPORT_UTF if (utf) { /* Get status of previous character */ if (eptr == md->start_subject) prev_is_word = FALSE; else { PCRE_PUCHAR lastptr = eptr - 1; BACKCHAR(lastptr); if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr; GETCHAR(c, lastptr); #ifdef SUPPORT_UCP if (md->use_ucp) { if (c == '_') prev_is_word = TRUE; else { int cat = UCD_CATEGORY(c); prev_is_word = (cat == ucp_L || cat == ucp_N); } } else #endif prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; } /* Get status of next character */ if (eptr >= md->end_subject) { SCHECK_PARTIAL(); cur_is_word = FALSE; } else { GETCHAR(c, eptr); #ifdef SUPPORT_UCP if (md->use_ucp) { if (c == '_') cur_is_word = TRUE; else { int cat = UCD_CATEGORY(c); cur_is_word = (cat == ucp_L || cat == ucp_N); } } else #endif cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; } } else #endif /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for consistency with the behaviour of \w we do use it in this case. */ { /* Get status of previous character */ if (eptr == md->start_subject) prev_is_word = FALSE; else { if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1; #ifdef SUPPORT_UCP if (md->use_ucp) { c = eptr[-1]; if (c == '_') prev_is_word = TRUE; else { int cat = UCD_CATEGORY(c); prev_is_word = (cat == ucp_L || cat == ucp_N); } } else #endif prev_is_word = MAX_255(eptr[-1]) && ((md->ctypes[eptr[-1]] & ctype_word) != 0); } /* Get status of next character */ if (eptr >= md->end_subject) { SCHECK_PARTIAL(); cur_is_word = FALSE; } else #ifdef SUPPORT_UCP if (md->use_ucp) { c = *eptr; if (c == '_') cur_is_word = TRUE; else { int cat = UCD_CATEGORY(c); cur_is_word = (cat == ucp_L || cat == ucp_N); } } else #endif cur_is_word = MAX_255(*eptr) && ((md->ctypes[*eptr] & ctype_word) != 0); } /* Now see if the situation is what we want */ if ((*ecode++ == OP_WORD_BOUNDARY)? cur_is_word == prev_is_word : cur_is_word != prev_is_word) RRETURN(MATCH_NOMATCH); } break; /* Match any single character type except newline; have to take care with CRLF newlines and partial matching. */ case OP_ANY: if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); if (md->partial != 0 && eptr == md->end_subject - 1 && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && UCHAR21TEST(eptr) == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } /* Fall through */ /* Match any single character whatsoever. */ case OP_ALLANY: if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ { /* not be updated before SCHECK_PARTIAL. */ SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr++; #ifdef SUPPORT_UTF if (utf) ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); #endif ecode++; break; /* Match a single byte, even in UTF-8 mode. This opcode really does match any byte, even newline, independent of the setting of PCRE_DOTALL. */ case OP_ANYBYTE: if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ { /* not be updated before SCHECK_PARTIAL. */ SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr++; ecode++; break; case OP_NOT_DIGIT: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ( #if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) c < 256 && #endif (md->ctypes[c] & ctype_digit) != 0 ) RRETURN(MATCH_NOMATCH); ecode++; break; case OP_DIGIT: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ( #if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) c > 255 || #endif (md->ctypes[c] & ctype_digit) == 0 ) RRETURN(MATCH_NOMATCH); ecode++; break; case OP_NOT_WHITESPACE: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ( #if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) c < 256 && #endif (md->ctypes[c] & ctype_space) != 0 ) RRETURN(MATCH_NOMATCH); ecode++; break; case OP_WHITESPACE: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ( #if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) c > 255 || #endif (md->ctypes[c] & ctype_space) == 0 ) RRETURN(MATCH_NOMATCH); ecode++; break; case OP_NOT_WORDCHAR: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ( #if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) c < 256 && #endif (md->ctypes[c] & ctype_word) != 0 ) RRETURN(MATCH_NOMATCH); ecode++; break; case OP_WORDCHAR: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ( #if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) c > 255 || #endif (md->ctypes[c] & ctype_word) == 0 ) RRETURN(MATCH_NOMATCH); ecode++; break; case OP_ANYNL: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); } else if (UCHAR21TEST(eptr) == CHAR_LF) eptr++; break; case CHAR_LF: break; case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); break; } ecode++; break; case OP_NOT_HSPACE: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */ default: break; } ecode++; break; case OP_HSPACE: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { HSPACE_CASES: break; /* Byte and multibyte cases */ default: RRETURN(MATCH_NOMATCH); } ecode++; break; case OP_NOT_VSPACE: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { VSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; } ecode++; break; case OP_VSPACE: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { VSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); } ecode++; break; #ifdef SUPPORT_UCP /* Check the next character by Unicode property. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ case OP_PROP: case OP_NOTPROP: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); { const pcre_uint32 *cp; const ucd_record *prop = GET_UCD(c); switch(ecode[1]) { case PT_ANY: if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); break; case PT_LAMP: if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; case PT_GC: if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP)) RRETURN(MATCH_NOMATCH); break; case PT_PC: if ((ecode[2] != prop->chartype) == (op == OP_PROP)) RRETURN(MATCH_NOMATCH); break; case PT_SC: if ((ecode[2] != prop->script) == (op == OP_PROP)) RRETURN(MATCH_NOMATCH); break; /* These are specials */ case PT_ALNUM: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); break; default: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; } break; case PT_WORD: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; case PT_CLIST: cp = PRIV(ucd_caseless_sets) + ecode[2]; for (;;) { if (c < *cp) { if (op == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; } if (c == *cp++) { if (op == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } } } break; case PT_UCNC: if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000) == (op == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); break; /* This should never occur */ default: RRETURN(PCRE_ERROR_INTERNAL); } ecode += 3; } break; /* Match an extended Unicode sequence. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ case OP_EXTUNI: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } else { int lgb, rgb; GETCHARINCTEST(c, eptr); lgb = UCD_GRAPHBREAK(c); while (eptr < md->end_subject) { int len = 1; if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } rgb = UCD_GRAPHBREAK(c); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; lgb = rgb; eptr += len; } } CHECK_PARTIAL(); ecode++; break; #endif /* SUPPORT_UCP */ /* Match a back reference, possibly repeatedly. Look past the end of the item to see if there is repeat information following. The code is similar to that for character classes, but repeated for efficiency. Then obey similar code to character type repeats - written out again for speed. However, if the referenced string is the empty string, always treat it as matched, any number of times (otherwise there could be infinite loops). If the reference is unset, there are two possibilities: (a) In the default, Perl-compatible state, set the length negative; this ensures that every attempt at a match fails. We can't just fail here, because of the possibility of quantifiers with zero minima. (b) If the JavaScript compatibility flag is set, set the length to zero so that the back reference matches an empty string. Otherwise, set the length to the length of what was matched by the referenced subpattern. The OP_REF and OP_REFI opcodes are used for a reference to a numbered group or to a non-duplicated named group. For a duplicated named group, OP_DNREF and OP_DNREFI are used. In this case we must scan the list of groups to which the name refers, and use the first one that is set. */ case OP_DNREF: case OP_DNREFI: caseless = op == OP_DNREFI; { int count = GET2(ecode, 1+IMM2_SIZE); pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size; ecode += 1 + 2*IMM2_SIZE; /* Setting the default length first and initializing 'offset' avoids compiler warnings in the REF_REPEAT code. */ length = (md->jscript_compat)? 0 : -1; offset = 0; while (count-- > 0) { offset = GET2(slot, 0) << 1; if (offset < offset_top && md->offset_vector[offset] >= 0) { length = md->offset_vector[offset+1] - md->offset_vector[offset]; break; } slot += md->name_entry_size; } } goto REF_REPEAT; case OP_REF: case OP_REFI: caseless = op == OP_REFI; offset = GET2(ecode, 1) << 1; /* Doubled ref number */ ecode += 1 + IMM2_SIZE; if (offset >= offset_top || md->offset_vector[offset] < 0) length = (md->jscript_compat)? 0 : -1; else length = md->offset_vector[offset+1] - md->offset_vector[offset]; /* Set up for repetition, or handle the non-repeated case */ REF_REPEAT: switch (*ecode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: c = *ecode++ - OP_CRSTAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; break; case OP_CRRANGE: case OP_CRMINRANGE: minimize = (*ecode == OP_CRMINRANGE); min = GET2(ecode, 1); max = GET2(ecode, 1 + IMM2_SIZE); if (max == 0) max = INT_MAX; ecode += 1 + 2 * IMM2_SIZE; break; default: /* No repeat follows */ if ((length = match_ref(offset, eptr, length, md, caseless)) < 0) { if (length == -2) eptr = md->end_subject; /* Partial match */ CHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr += length; continue; /* With the main loop */ } /* Handle repeated back references. If the length of the reference is zero, just continue with the main loop. If the length is negative, it means the reference is unset in non-Java-compatible mode. If the minimum is zero, we can continue at the same level without recursion. For any other minimum, carrying on will result in NOMATCH. */ if (length == 0) continue; if (length < 0 && min == 0) continue; /* First, ensure the minimum number of matches are present. We get back the length of the reference string explicitly rather than passing the address of eptr, so that eptr can be a register variable. */ for (i = 1; i <= min; i++) { int slength; if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) { if (slength == -2) eptr = md->end_subject; /* Partial match */ CHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr += slength; } /* If min = max, continue at the same level without recursion. They are not both allowed to be zero. */ if (min == max) continue; /* If minimizing, keep trying and advancing the pointer */ if (minimize) { for (fi = min;; fi++) { int slength; RMATCH(eptr, ecode, offset_top, md, eptrb, RM14); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) { if (slength == -2) eptr = md->end_subject; /* Partial match */ CHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr += slength; } /* Control never gets here */ } /* If maximizing, find the longest string and work backwards */ else { pp = eptr; for (i = min; i < max; i++) { int slength; if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) { /* Can't use CHECK_PARTIAL because we don't want to update eptr in the soft partial matching case. */ if (slength == -2 && md->partial != 0 && md->end_subject > md->start_used_ptr) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } break; } eptr += slength; } while (eptr >= pp) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM15); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr -= length; } RRETURN(MATCH_NOMATCH); } /* Control never gets here */ /* Match a bit-mapped character class, possibly repeatedly. This op code is used when all the characters in the class have values in the range 0-255, and either the matching is caseful, or the characters are in the range 0-127 when UTF-8 processing is enabled. The only difference between OP_CLASS and OP_NCLASS occurs when a data character outside the range is encountered. First, look past the end of the item to see if there is repeat information following. Then obey similar code to character type repeats - written out again for speed. */ case OP_NCLASS: case OP_CLASS: { /* The data variable is saved across frames, so the byte map needs to be stored there. */ #define BYTE_MAP ((pcre_uint8 *)data) data = ecode + 1; /* Save for matching */ ecode += 1 + (32 / sizeof(pcre_uchar)); /* Advance past the item */ switch (*ecode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: c = *ecode++ - OP_CRSTAR; if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0; else possessive = TRUE; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: minimize = (*ecode == OP_CRMINRANGE); possessive = (*ecode == OP_CRPOSRANGE); min = GET2(ecode, 1); max = GET2(ecode, 1 + IMM2_SIZE); if (max == 0) max = INT_MAX; ecode += 1 + 2 * IMM2_SIZE; break; default: /* No repeat follows */ min = max = 1; break; } /* First, ensure the minimum number of matches are present. */ #ifdef SUPPORT_UTF if (utf) { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); if (c > 255) { if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); } else if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); } } else #endif /* Not UTF mode */ { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } c = *eptr++; #ifndef COMPILE_PCRE8 if (c > 255) { if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); } else #endif if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); } } /* If max == min we can continue with the main loop without the need to recurse. */ if (min == max) continue; /* If minimizing, keep testing the rest of the expression and advancing the pointer while it matches the class. */ if (minimize) { #ifdef SUPPORT_UTF if (utf) { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM16); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); if (c > 255) { if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); } else if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); } } else #endif /* Not UTF mode */ { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM17); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } c = *eptr++; #ifndef COMPILE_PCRE8 if (c > 255) { if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); } else #endif if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); } } /* Control never gets here */ } /* If maximizing, find the longest possible run, then work backwards. */ else { pp = eptr; #ifdef SUPPORT_UTF if (utf) { for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c > 255) { if (op == OP_CLASS) break; } else if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; eptr += len; } if (possessive) continue; /* No backtracking */ for (;;) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM18); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- <= pp) break; /* Stop if tried at original pos */ BACKCHAR(eptr); } } else #endif /* Not UTF mode */ { for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } c = *eptr; #ifndef COMPILE_PCRE8 if (c > 255) { if (op == OP_CLASS) break; } else #endif if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; eptr++; } if (possessive) continue; /* No backtracking */ while (eptr >= pp) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM19); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; } } RRETURN(MATCH_NOMATCH); } #undef BYTE_MAP } /* Control never gets here */ /* Match an extended character class. In the 8-bit library, this opcode is encountered only when UTF-8 mode mode is supported. In the 16-bit and 32-bit libraries, codepoints greater than 255 may be encountered even when UTF is not supported. */ #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: { data = ecode + 1 + LINK_SIZE; /* Save for matching */ ecode += GET(ecode, 1); /* Advance past the item */ switch (*ecode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: c = *ecode++ - OP_CRSTAR; if (c < OP_CRPOSSTAR - OP_CRSTAR) minimize = (c & 1) != 0; else possessive = TRUE; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: minimize = (*ecode == OP_CRMINRANGE); possessive = (*ecode == OP_CRPOSRANGE); min = GET2(ecode, 1); max = GET2(ecode, 1 + IMM2_SIZE); if (max == 0) max = INT_MAX; ecode += 1 + 2 * IMM2_SIZE; break; default: /* No repeat follows */ min = max = 1; break; } /* First, ensure the minimum number of matches are present. */ for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); } /* If max == min we can continue with the main loop without the need to recurse. */ if (min == max) continue; /* If minimizing, keep testing the rest of the expression and advancing the pointer while it matches the class. */ if (minimize) { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM20); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ } /* If maximizing, find the longest possible run, then work backwards. */ else { pp = eptr; for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } #ifdef SUPPORT_UTF GETCHARLENTEST(c, eptr, len); #else c = *eptr; #endif if (!PRIV(xclass)(c, data, utf)) break; eptr += len; } if (possessive) continue; /* No backtracking */ for(;;) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM21); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (eptr-- <= pp) break; /* Stop if tried at original pos */ #ifdef SUPPORT_UTF if (utf) BACKCHAR(eptr); #endif } RRETURN(MATCH_NOMATCH); } /* Control never gets here */ } #endif /* End of XCLASS */ /* Match a single character, casefully */ case OP_CHAR: #ifdef SUPPORT_UTF if (utf) { length = 1; ecode++; GETCHARLEN(fc, ecode, length); if (length > md->end_subject - eptr) { CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ RRETURN(MATCH_NOMATCH); } while (length-- > 0) if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH); } else #endif /* Not UTF mode */ { if (md->end_subject - eptr < 1) { SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ RRETURN(MATCH_NOMATCH); } if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); ecode += 2; } break; /* Match a single character, caselessly. If we are at the end of the subject, give up immediately. */ case OP_CHARI: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } #ifdef SUPPORT_UTF if (utf) { length = 1; ecode++; GETCHARLEN(fc, ecode, length); /* If the pattern character's value is < 128, we have only one byte, and we know that its other case must also be one byte long, so we can use the fast lookup table. We know that there is at least one byte left in the subject. */ if (fc < 128) { pcre_uint32 cc = UCHAR21(eptr); if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH); ecode++; eptr++; } /* Otherwise we must pick up the subject character. Note that we cannot use the value of "length" to check for sufficient bytes left, because the other case of the character may have more or fewer bytes. */ else { pcre_uint32 dc; GETCHARINC(dc, eptr); ecode += length; /* If we have Unicode property support, we can use it to test the other case of the character, if there is one. */ if (fc != dc) { #ifdef SUPPORT_UCP if (dc != UCD_OTHERCASE(fc)) #endif RRETURN(MATCH_NOMATCH); } } } else #endif /* SUPPORT_UTF */ /* Not UTF mode */ { if (TABLE_GET(ecode[1], md->lcc, ecode[1]) != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH); eptr++; ecode += 2; } break; /* Match a single character repeatedly. */ case OP_EXACT: case OP_EXACTI: min = max = GET2(ecode, 1); ecode += 1 + IMM2_SIZE; goto REPEATCHAR; case OP_POSUPTO: case OP_POSUPTOI: possessive = TRUE; /* Fall through */ case OP_UPTO: case OP_UPTOI: case OP_MINUPTO: case OP_MINUPTOI: min = 0; max = GET2(ecode, 1); minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI; ecode += 1 + IMM2_SIZE; goto REPEATCHAR; case OP_POSSTAR: case OP_POSSTARI: possessive = TRUE; min = 0; max = INT_MAX; ecode++; goto REPEATCHAR; case OP_POSPLUS: case OP_POSPLUSI: possessive = TRUE; min = 1; max = INT_MAX; ecode++; goto REPEATCHAR; case OP_POSQUERY: case OP_POSQUERYI: possessive = TRUE; min = 0; max = 1; ecode++; goto REPEATCHAR; case OP_STAR: case OP_STARI: case OP_MINSTAR: case OP_MINSTARI: case OP_PLUS: case OP_PLUSI: case OP_MINPLUS: case OP_MINPLUSI: case OP_QUERY: case OP_QUERYI: case OP_MINQUERY: case OP_MINQUERYI: c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI); minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; /* Common code for all repeated single-character matches. We first check for the minimum number of characters. If the minimum equals the maximum, we are done. Otherwise, if minimizing, check the rest of the pattern for a match; if there isn't one, advance up to the maximum, one character at a time. If maximizing, advance up to the maximum number of matching characters, until eptr is past the end of the maximum run. If possessive, we are then done (no backing up). Otherwise, match at this position; anything other than no match is immediately returned. For nomatch, back up one character, unless we are matching \R and the last thing matched was \r\n, in which case, back up two bytes. When we reach the first optional character position, we can save stack by doing a tail recurse. The various UTF/non-UTF and caseful/caseless cases are handled separately, for speed. */ REPEATCHAR: #ifdef SUPPORT_UTF if (utf) { length = 1; charptr = ecode; GETCHARLEN(fc, ecode, length); ecode += length; /* Handle multibyte character matching specially here. There is support for caseless matching if UCP support is present. */ if (length > 1) { #ifdef SUPPORT_UCP pcre_uint32 othercase; if (op >= OP_STARI && /* Caseless */ (othercase = UCD_OTHERCASE(fc)) != fc) oclength = PRIV(ord2utf)(othercase, occhars); else oclength = 0; #endif /* SUPPORT_UCP */ for (i = 1; i <= min; i++) { if (eptr <= md->end_subject - length && memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; #ifdef SUPPORT_UCP else if (oclength > 0 && eptr <= md->end_subject - oclength && memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; #endif /* SUPPORT_UCP */ else { CHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } } if (min == max) continue; if (minimize) { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM22); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr <= md->end_subject - length && memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; #ifdef SUPPORT_UCP else if (oclength > 0 && eptr <= md->end_subject - oclength && memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; #endif /* SUPPORT_UCP */ else { CHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } } /* Control never gets here */ } else /* Maximize */ { pp = eptr; for (i = min; i < max; i++) { if (eptr <= md->end_subject - length && memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; #ifdef SUPPORT_UCP else if (oclength > 0 && eptr <= md->end_subject - oclength && memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; #endif /* SUPPORT_UCP */ else { CHECK_PARTIAL(); break; } } if (possessive) continue; /* No backtracking */ for(;;) { if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM23); if (rrc != MATCH_NOMATCH) RRETURN(rrc); #ifdef SUPPORT_UCP eptr--; BACKCHAR(eptr); #else /* without SUPPORT_UCP */ eptr -= length; #endif /* SUPPORT_UCP */ } } /* Control never gets here */ } /* If the length of a UTF-8 character is 1, we fall through here, and obey the code as for non-UTF-8 characters below, though in this case the value of fc will always be < 128. */ } else #endif /* SUPPORT_UTF */ /* When not in UTF-8 mode, load a single-byte character. */ fc = *ecode++; /* The value of fc at this point is always one character, though we may or may not be in UTF mode. The code is duplicated for the caseless and caseful cases, for speed, since matching characters is likely to be quite common. First, ensure the minimum number of matches are present. If min = max, continue at the same level without recursing. Otherwise, if minimizing, keep trying the rest of the expression and advancing one matching character if failing, up to the maximum. Alternatively, if maximizing, find the maximum number of characters and work backwards. */ DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, max, (char *)eptr)); if (op >= OP_STARI) /* Caseless */ { #ifdef COMPILE_PCRE8 /* fc must be < 128 if UTF is enabled. */ foc = md->fcc[fc]; #else #ifdef SUPPORT_UTF #ifdef SUPPORT_UCP if (utf && fc > 127) foc = UCD_OTHERCASE(fc); #else if (utf && fc > 127) foc = fc; #endif /* SUPPORT_UCP */ else #endif /* SUPPORT_UTF */ foc = TABLE_GET(fc, md->fcc, fc); #endif /* COMPILE_PCRE8 */ for (i = 1; i <= min; i++) { pcre_uint32 cc; /* Faster than pcre_uchar */ if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21TEST(eptr); if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH); eptr++; } if (min == max) continue; if (minimize) { for (fi = min;; fi++) { pcre_uint32 cc; /* Faster than pcre_uchar */ RMATCH(eptr, ecode, offset_top, md, eptrb, RM24); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21TEST(eptr); if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH); eptr++; } /* Control never gets here */ } else /* Maximize */ { pp = eptr; for (i = min; i < max; i++) { pcre_uint32 cc; /* Faster than pcre_uchar */ if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } cc = UCHAR21TEST(eptr); if (fc != cc && foc != cc) break; eptr++; } if (possessive) continue; /* No backtracking */ for (;;) { if (eptr == pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM25); eptr--; if (rrc != MATCH_NOMATCH) RRETURN(rrc); } /* Control never gets here */ } } /* Caseful comparisons (includes all multi-byte characters) */ else { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH); } if (min == max) continue; if (minimize) { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM26); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ } else /* Maximize */ { pp = eptr; for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (fc != UCHAR21TEST(eptr)) break; eptr++; } if (possessive) continue; /* No backtracking */ for (;;) { if (eptr == pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM27); eptr--; if (rrc != MATCH_NOMATCH) RRETURN(rrc); } /* Control never gets here */ } } /* Control never gets here */ /* Match a negated single one-byte character. The character we are checking can be multibyte. */ case OP_NOT: case OP_NOTI: if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 ch, och; ecode++; GETCHARINC(ch, ecode); GETCHARINC(c, eptr); if (op == OP_NOT) { if (ch == c) RRETURN(MATCH_NOMATCH); } else { #ifdef SUPPORT_UCP if (ch > 127) och = UCD_OTHERCASE(ch); #else if (ch > 127) och = ch; #endif /* SUPPORT_UCP */ else och = TABLE_GET(ch, md->fcc, ch); if (ch == c || och == c) RRETURN(MATCH_NOMATCH); } } else #endif { register pcre_uint32 ch = ecode[1]; c = *eptr++; if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c)) RRETURN(MATCH_NOMATCH); ecode += 2; } break; /* Match a negated single one-byte character repeatedly. This is almost a repeat of the code for a repeated single character, but I haven't found a nice way of commoning these up that doesn't require a test of the positive/negative option for each character match. Maybe that wouldn't add very much to the time taken, but character matching *is* what this is all about... */ case OP_NOTEXACT: case OP_NOTEXACTI: min = max = GET2(ecode, 1); ecode += 1 + IMM2_SIZE; goto REPEATNOTCHAR; case OP_NOTUPTO: case OP_NOTUPTOI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: min = 0; max = GET2(ecode, 1); minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI; ecode += 1 + IMM2_SIZE; goto REPEATNOTCHAR; case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: possessive = TRUE; min = 0; max = INT_MAX; ecode++; goto REPEATNOTCHAR; case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: possessive = TRUE; min = 1; max = INT_MAX; ecode++; goto REPEATNOTCHAR; case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: possessive = TRUE; min = 0; max = 1; ecode++; goto REPEATNOTCHAR; case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: possessive = TRUE; min = 0; max = GET2(ecode, 1); ecode += 1 + IMM2_SIZE; goto REPEATNOTCHAR; case OP_NOTSTAR: case OP_NOTSTARI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR); minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; /* Common code for all repeated single-byte matches. */ REPEATNOTCHAR: GETCHARINCTEST(fc, ecode); /* The code is duplicated for the caseless and caseful cases, for speed, since matching characters is likely to be quite common. First, ensure the minimum number of matches are present. If min = max, continue at the same level without recursing. Otherwise, if minimizing, keep trying the rest of the expression and advancing one matching character if failing, up to the maximum. Alternatively, if maximizing, find the maximum number of characters and work backwards. */ DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, max, (char *)eptr)); if (op >= OP_NOTSTARI) /* Caseless */ { #ifdef SUPPORT_UTF #ifdef SUPPORT_UCP if (utf && fc > 127) foc = UCD_OTHERCASE(fc); #else if (utf && fc > 127) foc = fc; #endif /* SUPPORT_UCP */ else #endif /* SUPPORT_UTF */ foc = TABLE_GET(fc, md->fcc, fc); #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 d; for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(d, eptr); if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH); } } else #endif /* SUPPORT_UTF */ /* Not UTF mode */ { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); eptr++; } } if (min == max) continue; if (minimize) { #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 d; for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM28); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(d, eptr); if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH); } } else #endif /*SUPPORT_UTF */ /* Not UTF mode */ { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM29); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); eptr++; } } /* Control never gets here */ } /* Maximize case */ else { pp = eptr; #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 d; for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(d, eptr, len); if (fc == d || (unsigned int)foc == d) break; eptr += len; } if (possessive) continue; /* No backtracking */ for(;;) { if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM30); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; BACKCHAR(eptr); } } else #endif /* SUPPORT_UTF */ /* Not UTF mode */ { for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (fc == *eptr || foc == *eptr) break; eptr++; } if (possessive) continue; /* No backtracking */ for (;;) { if (eptr == pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM31); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; } } /* Control never gets here */ } } /* Caseful comparisons */ else { #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 d; for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(d, eptr); if (fc == d) RRETURN(MATCH_NOMATCH); } } else #endif /* Not UTF mode */ { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (fc == *eptr++) RRETURN(MATCH_NOMATCH); } } if (min == max) continue; if (minimize) { #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 d; for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM32); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(d, eptr); if (fc == d) RRETURN(MATCH_NOMATCH); } } else #endif /* Not UTF mode */ { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM33); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (fc == *eptr++) RRETURN(MATCH_NOMATCH); } } /* Control never gets here */ } /* Maximize case */ else { pp = eptr; #ifdef SUPPORT_UTF if (utf) { register pcre_uint32 d; for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(d, eptr, len); if (fc == d) break; eptr += len; } if (possessive) continue; /* No backtracking */ for(;;) { if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM34); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; BACKCHAR(eptr); } } else #endif /* Not UTF mode */ { for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (fc == *eptr) break; eptr++; } if (possessive) continue; /* No backtracking */ for (;;) { if (eptr == pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM35); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; } } /* Control never gets here */ } } /* Control never gets here */ /* Match a single character type repeatedly; several different opcodes share code. This is very similar to the code for single characters, but we repeat it in the interests of efficiency. */ case OP_TYPEEXACT: min = max = GET2(ecode, 1); minimize = TRUE; ecode += 1 + IMM2_SIZE; goto REPEATTYPE; case OP_TYPEUPTO: case OP_TYPEMINUPTO: min = 0; max = GET2(ecode, 1); minimize = *ecode == OP_TYPEMINUPTO; ecode += 1 + IMM2_SIZE; goto REPEATTYPE; case OP_TYPEPOSSTAR: possessive = TRUE; min = 0; max = INT_MAX; ecode++; goto REPEATTYPE; case OP_TYPEPOSPLUS: possessive = TRUE; min = 1; max = INT_MAX; ecode++; goto REPEATTYPE; case OP_TYPEPOSQUERY: possessive = TRUE; min = 0; max = 1; ecode++; goto REPEATTYPE; case OP_TYPEPOSUPTO: possessive = TRUE; min = 0; max = GET2(ecode, 1); ecode += 1 + IMM2_SIZE; goto REPEATTYPE; case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: c = *ecode++ - OP_TYPESTAR; minimize = (c & 1) != 0; min = rep_min[c]; /* Pick up values from tables; */ max = rep_max[c]; /* zero for max => infinity */ if (max == 0) max = INT_MAX; /* Common code for all repeated single character type matches. Note that in UTF-8 mode, '.' matches a character of any length, but for the other character types, the valid characters are all one-byte long. */ REPEATTYPE: ctype = *ecode++; /* Code for the character type */ #ifdef SUPPORT_UCP if (ctype == OP_PROP || ctype == OP_NOTPROP) { prop_fail_result = ctype == OP_NOTPROP; prop_type = *ecode++; prop_value = *ecode++; } else prop_type = -1; #endif /* First, ensure the minimum number of matches are present. Use inline code for maximizing the speed, and do the type test once at the start (i.e. keep it out of the loop). Separate the UTF-8 code completely as that is tidier. Also separate the UCP code, which can be the same for both UTF-8 and single-bytes. */ if (min > 0) { #ifdef SUPPORT_UCP if (prop_type >= 0) { switch(prop_type) { case PT_ANY: if (prop_fail_result) RRETURN(MATCH_NOMATCH); for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); } break; case PT_LAMP: for (i = 1; i <= min; i++) { int chartype; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); chartype = UCD_CHARTYPE(c); if ((chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; case PT_GC: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; case PT_PC: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; case PT_SC: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; case PT_ALNUM: for (i = 1; i <= min; i++) { int category; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); category = UCD_CATEGORY(c); if ((category == ucp_L || category == ucp_N) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { HSPACE_CASES: VSPACE_CASES: if (prop_fail_result) RRETURN(MATCH_NOMATCH); break; default: if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result) RRETURN(MATCH_NOMATCH); break; } } break; case PT_WORD: for (i = 1; i <= min; i++) { int category; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); category = UCD_CATEGORY(c); if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; case PT_CLIST: for (i = 1; i <= min; i++) { const pcre_uint32 *cp; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); cp = PRIV(ucd_caseless_sets) + prop_value; for (;;) { if (c < *cp) { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } } if (c == *cp++) { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; } } } break; case PT_UCNC: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000) == prop_fail_result) RRETURN(MATCH_NOMATCH); } break; /* This should not occur */ default: RRETURN(PCRE_ERROR_INTERNAL); } } /* Match extended Unicode sequences. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ else if (ctype == OP_EXTUNI) { for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } else { int lgb, rgb; GETCHARINCTEST(c, eptr); lgb = UCD_GRAPHBREAK(c); while (eptr < md->end_subject) { int len = 1; if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } rgb = UCD_GRAPHBREAK(c); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; lgb = rgb; eptr += len; } } CHECK_PARTIAL(); } } else #endif /* SUPPORT_UCP */ /* Handle all other cases when the coding is UTF-8 */ #ifdef SUPPORT_UTF if (utf) switch(ctype) { case OP_ANY: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); if (md->partial != 0 && eptr + 1 >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && UCHAR21(eptr) == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } eptr++; ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } break; case OP_ALLANY: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr++; ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } break; case OP_ANYBYTE: if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH); eptr += min; break; case OP_ANYNL: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); switch(c) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++; break; case CHAR_LF: break; case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); break; } } break; case OP_NOT_HSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); switch(c) { HSPACE_CASES: RRETURN(MATCH_NOMATCH); /* Byte and multibyte cases */ default: break; } } break; case OP_HSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); switch(c) { HSPACE_CASES: break; /* Byte and multibyte cases */ default: RRETURN(MATCH_NOMATCH); } } break; case OP_NOT_VSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); switch(c) { VSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; } } break; case OP_VSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); switch(c) { VSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); } } break; case OP_NOT_DIGIT: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINC(c, eptr); if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); } break; case OP_DIGIT: for (i = 1; i <= min; i++) { pcre_uint32 cc; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21(eptr); if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); eptr++; /* No need to skip more bytes - we know it's a 1-byte character */ } break; case OP_NOT_WHITESPACE: for (i = 1; i <= min; i++) { pcre_uint32 cc; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21(eptr); if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); eptr++; ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } break; case OP_WHITESPACE: for (i = 1; i <= min; i++) { pcre_uint32 cc; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21(eptr); if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); eptr++; /* No need to skip more bytes - we know it's a 1-byte character */ } break; case OP_NOT_WORDCHAR: for (i = 1; i <= min; i++) { pcre_uint32 cc; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21(eptr); if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); eptr++; ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } break; case OP_WORDCHAR: for (i = 1; i <= min; i++) { pcre_uint32 cc; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } cc = UCHAR21(eptr); if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); eptr++; /* No need to skip more bytes - we know it's a 1-byte character */ } break; default: RRETURN(PCRE_ERROR_INTERNAL); } /* End switch(ctype) */ else #endif /* SUPPORT_UTF */ /* Code for the non-UTF-8 case for minimum matching of operators other than OP_PROP and OP_NOTPROP. */ switch(ctype) { case OP_ANY: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); if (md->partial != 0 && eptr + 1 >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && *eptr == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } eptr++; } break; case OP_ALLANY: if (eptr > md->end_subject - min) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr += min; break; case OP_ANYBYTE: if (eptr > md->end_subject - min) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } eptr += min; break; case OP_ANYNL: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } switch(*eptr++) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++; break; case CHAR_LF: break; case CHAR_VT: case CHAR_FF: case CHAR_NEL: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case 0x2028: case 0x2029: #endif if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); break; } } break; case OP_NOT_HSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } switch(*eptr++) { default: break; HSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 HSPACE_MULTIBYTE_CASES: #endif RRETURN(MATCH_NOMATCH); } } break; case OP_HSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } switch(*eptr++) { default: RRETURN(MATCH_NOMATCH); HSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 HSPACE_MULTIBYTE_CASES: #endif break; } } break; case OP_NOT_VSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } switch(*eptr++) { VSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 VSPACE_MULTIBYTE_CASES: #endif RRETURN(MATCH_NOMATCH); default: break; } } break; case OP_VSPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } switch(*eptr++) { default: RRETURN(MATCH_NOMATCH); VSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 VSPACE_MULTIBYTE_CASES: #endif break; } } break; case OP_NOT_DIGIT: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); eptr++; } break; case OP_DIGIT: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); eptr++; } break; case OP_NOT_WHITESPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); eptr++; } break; case OP_WHITESPACE: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); eptr++; } break; case OP_NOT_WORDCHAR: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); eptr++; } break; case OP_WORDCHAR: for (i = 1; i <= min; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); eptr++; } break; default: RRETURN(PCRE_ERROR_INTERNAL); } } /* If min = max, continue at the same level without recursing */ if (min == max) continue; /* If minimizing, we have to test the rest of the pattern before each subsequent match. Again, separate the UTF-8 case for speed, and also separate the UCP cases. */ if (minimize) { #ifdef SUPPORT_UCP if (prop_type >= 0) { switch(prop_type) { case PT_ANY: for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM36); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if (prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_LAMP: for (fi = min;; fi++) { int chartype; RMATCH(eptr, ecode, offset_top, md, eptrb, RM37); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); chartype = UCD_CHARTYPE(c); if ((chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_GC: for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM38); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_PC: for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM39); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_SC: for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM40); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_ALNUM: for (fi = min;; fi++) { int category; RMATCH(eptr, ecode, offset_top, md, eptrb, RM59); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); category = UCD_CATEGORY(c); if ((category == ucp_L || category == ucp_N) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM61); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); switch(c) { HSPACE_CASES: VSPACE_CASES: if (prop_fail_result) RRETURN(MATCH_NOMATCH); break; default: if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result) RRETURN(MATCH_NOMATCH); break; } } /* Control never gets here */ case PT_WORD: for (fi = min;; fi++) { int category; RMATCH(eptr, ecode, offset_top, md, eptrb, RM62); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); category = UCD_CATEGORY(c); if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ case PT_CLIST: for (fi = min;; fi++) { const pcre_uint32 *cp; RMATCH(eptr, ecode, offset_top, md, eptrb, RM67); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); cp = PRIV(ucd_caseless_sets) + prop_value; for (;;) { if (c < *cp) { if (prop_fail_result) break; else { RRETURN(MATCH_NOMATCH); } } if (c == *cp++) { if (prop_fail_result) { RRETURN(MATCH_NOMATCH); } else break; } } } /* Control never gets here */ case PT_UCNC: for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM60); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } GETCHARINCTEST(c, eptr); if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000) == prop_fail_result) RRETURN(MATCH_NOMATCH); } /* Control never gets here */ /* This should never occur */ default: RRETURN(PCRE_ERROR_INTERNAL); } } /* Match extended Unicode sequences. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ else if (ctype == OP_EXTUNI) { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM41); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } else { int lgb, rgb; GETCHARINCTEST(c, eptr); lgb = UCD_GRAPHBREAK(c); while (eptr < md->end_subject) { int len = 1; if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } rgb = UCD_GRAPHBREAK(c); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; lgb = rgb; eptr += len; } } CHECK_PARTIAL(); } } else #endif /* SUPPORT_UCP */ #ifdef SUPPORT_UTF if (utf) { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM42); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (ctype == OP_ANY && IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); GETCHARINC(c, eptr); switch(ctype) { case OP_ANY: /* This is the non-NL case */ if (md->partial != 0 && /* Take care with CRLF partial */ eptr >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } break; case OP_ALLANY: case OP_ANYBYTE: break; case OP_ANYNL: switch(c) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++; break; case CHAR_LF: break; case CHAR_VT: case CHAR_FF: case CHAR_NEL: #ifndef EBCDIC case 0x2028: case 0x2029: #endif /* Not EBCDIC */ if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); break; } break; case OP_NOT_HSPACE: switch(c) { HSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; } break; case OP_HSPACE: switch(c) { HSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); } break; case OP_NOT_VSPACE: switch(c) { VSPACE_CASES: RRETURN(MATCH_NOMATCH); default: break; } break; case OP_VSPACE: switch(c) { VSPACE_CASES: break; default: RRETURN(MATCH_NOMATCH); } break; case OP_NOT_DIGIT: if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); break; case OP_DIGIT: if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); break; case OP_NOT_WHITESPACE: if (c < 256 && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); break; case OP_WHITESPACE: if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); break; case OP_NOT_WORDCHAR: if (c < 256 && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); break; case OP_WORDCHAR: if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); break; default: RRETURN(PCRE_ERROR_INTERNAL); } } } else #endif /* Not UTF mode */ { for (fi = min;; fi++) { RMATCH(eptr, ecode, offset_top, md, eptrb, RM43); if (rrc != MATCH_NOMATCH) RRETURN(rrc); if (fi >= max) RRETURN(MATCH_NOMATCH); if (eptr >= md->end_subject) { SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } if (ctype == OP_ANY && IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); c = *eptr++; switch(ctype) { case OP_ANY: /* This is the non-NL case */ if (md->partial != 0 && /* Take care with CRLF partial */ eptr >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && c == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } break; case OP_ALLANY: case OP_ANYBYTE: break; case OP_ANYNL: switch(c) { default: RRETURN(MATCH_NOMATCH); case CHAR_CR: if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++; break; case CHAR_LF: break; case CHAR_VT: case CHAR_FF: case CHAR_NEL: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case 0x2028: case 0x2029: #endif if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); break; } break; case OP_NOT_HSPACE: switch(c) { default: break; HSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 HSPACE_MULTIBYTE_CASES: #endif RRETURN(MATCH_NOMATCH); } break; case OP_HSPACE: switch(c) { default: RRETURN(MATCH_NOMATCH); HSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 HSPACE_MULTIBYTE_CASES: #endif break; } break; case OP_NOT_VSPACE: switch(c) { default: break; VSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 VSPACE_MULTIBYTE_CASES: #endif RRETURN(MATCH_NOMATCH); } break; case OP_VSPACE: switch(c) { default: RRETURN(MATCH_NOMATCH); VSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 VSPACE_MULTIBYTE_CASES: #endif break; } break; case OP_NOT_DIGIT: if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); break; case OP_DIGIT: if (!MAX_255(c) || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); break; case OP_NOT_WHITESPACE: if (MAX_255(c) && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); break; case OP_WHITESPACE: if (!MAX_255(c) || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); break; case OP_NOT_WORDCHAR: if (MAX_255(c) && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); break; case OP_WORDCHAR: if (!MAX_255(c) || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); break; default: RRETURN(PCRE_ERROR_INTERNAL); } } } /* Control never gets here */ } /* If maximizing, it is worth using inline code for speed, doing the type test once at the start (i.e. keep it out of the loop). Again, keep the UTF-8 and UCP stuff separate. */ else { pp = eptr; /* Remember where we started */ #ifdef SUPPORT_UCP if (prop_type >= 0) { switch(prop_type) { case PT_ANY: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); if (prop_fail_result) break; eptr+= len; } break; case PT_LAMP: for (i = min; i < max; i++) { int chartype; int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); chartype = UCD_CHARTYPE(c); if ((chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt) == prop_fail_result) break; eptr+= len; } break; case PT_GC: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break; eptr+= len; } break; case PT_PC: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break; eptr+= len; } break; case PT_SC: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break; eptr+= len; } break; case PT_ALNUM: for (i = min; i < max; i++) { int category; int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); category = UCD_CATEGORY(c); if ((category == ucp_L || category == ucp_N) == prop_fail_result) break; eptr+= len; } break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); switch(c) { HSPACE_CASES: VSPACE_CASES: if (prop_fail_result) goto ENDLOOP99; /* Break the loop */ break; default: if ((UCD_CATEGORY(c) == ucp_Z) == prop_fail_result) goto ENDLOOP99; /* Break the loop */ break; } eptr+= len; } ENDLOOP99: break; case PT_WORD: for (i = min; i < max; i++) { int category; int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); category = UCD_CATEGORY(c); if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE) == prop_fail_result) break; eptr+= len; } break; case PT_CLIST: for (i = min; i < max; i++) { const pcre_uint32 *cp; int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); cp = PRIV(ucd_caseless_sets) + prop_value; for (;;) { if (c < *cp) { if (prop_fail_result) break; else goto GOT_MAX; } if (c == *cp++) { if (prop_fail_result) goto GOT_MAX; else break; } } eptr += len; } GOT_MAX: break; case PT_UCNC: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLENTEST(c, eptr, len); if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT || (c >= 0xa0 && c <= 0xd7ff) || c >= 0xe000) == prop_fail_result) break; eptr += len; } break; default: RRETURN(PCRE_ERROR_INTERNAL); } /* eptr is now past the end of the maximum run */ if (possessive) continue; /* No backtracking */ for(;;) { if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM44); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; if (utf) BACKCHAR(eptr); } } /* Match extended Unicode grapheme clusters. We will get here only if the support is in the binary; otherwise a compile-time error occurs. */ else if (ctype == OP_EXTUNI) { for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } else { int lgb, rgb; GETCHARINCTEST(c, eptr); lgb = UCD_GRAPHBREAK(c); while (eptr < md->end_subject) { int len = 1; if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } rgb = UCD_GRAPHBREAK(c); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; lgb = rgb; eptr += len; } } CHECK_PARTIAL(); } /* eptr is now past the end of the maximum run */ if (possessive) continue; /* No backtracking */ /* We use <= pp rather than == pp to detect the start of the run while backtracking because the use of \C in UTF mode can cause BACKCHAR to move back past pp. This is just palliative; the use of \C in UTF mode is fraught with danger. */ for(;;) { int lgb, rgb; PCRE_PUCHAR fptr; if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ RMATCH(eptr, ecode, offset_top, md, eptrb, RM45); if (rrc != MATCH_NOMATCH) RRETURN(rrc); /* Backtracking over an extended grapheme cluster involves inspecting the previous two characters (if present) to see if a break is permitted between them. */ eptr--; if (!utf) c = *eptr; else { BACKCHAR(eptr); GETCHAR(c, eptr); } rgb = UCD_GRAPHBREAK(c); for (;;) { if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */ fptr = eptr - 1; if (!utf) c = *fptr; else { BACKCHAR(fptr); GETCHAR(c, fptr); } lgb = UCD_GRAPHBREAK(c); if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break; eptr = fptr; rgb = lgb; } } } else #endif /* SUPPORT_UCP */ #ifdef SUPPORT_UTF if (utf) { switch(ctype) { case OP_ANY: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (IS_NEWLINE(eptr)) break; if (md->partial != 0 && /* Take care with CRLF partial */ eptr + 1 >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && UCHAR21(eptr) == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } eptr++; ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } break; case OP_ALLANY: if (max < INT_MAX) { for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } eptr++; ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); } } else { eptr = md->end_subject; /* Unlimited UTF-8 repeat */ SCHECK_PARTIAL(); } break; /* The byte case is the same as non-UTF8 */ case OP_ANYBYTE: c = max - min; if (c > (unsigned int)(md->end_subject - eptr)) { eptr = md->end_subject; SCHECK_PARTIAL(); } else eptr += c; break; case OP_ANYNL: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c == CHAR_CR) { if (++eptr >= md->end_subject) break; if (UCHAR21(eptr) == CHAR_LF) eptr++; } else { if (c != CHAR_LF && (md->bsr_anycrlf || (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL #ifndef EBCDIC && c != 0x2028 && c != 0x2029 #endif /* Not EBCDIC */ ))) break; eptr += len; } } break; case OP_NOT_HSPACE: case OP_HSPACE: for (i = min; i < max; i++) { BOOL gotspace; int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); switch(c) { HSPACE_CASES: gotspace = TRUE; break; default: gotspace = FALSE; break; } if (gotspace == (ctype == OP_NOT_HSPACE)) break; eptr += len; } break; case OP_NOT_VSPACE: case OP_VSPACE: for (i = min; i < max; i++) { BOOL gotspace; int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); switch(c) { VSPACE_CASES: gotspace = TRUE; break; default: gotspace = FALSE; break; } if (gotspace == (ctype == OP_NOT_VSPACE)) break; eptr += len; } break; case OP_NOT_DIGIT: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; eptr+= len; } break; case OP_DIGIT: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; eptr+= len; } break; case OP_NOT_WHITESPACE: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; eptr+= len; } break; case OP_WHITESPACE: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; eptr+= len; } break; case OP_NOT_WORDCHAR: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; eptr+= len; } break; case OP_WORDCHAR: for (i = min; i < max; i++) { int len = 1; if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } GETCHARLEN(c, eptr, len); if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; eptr+= len; } break; default: RRETURN(PCRE_ERROR_INTERNAL); } if (possessive) continue; /* No backtracking */ for(;;) { if (eptr <= pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM46); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; BACKCHAR(eptr); if (ctype == OP_ANYNL && eptr > pp && UCHAR21(eptr) == CHAR_NL && UCHAR21(eptr - 1) == CHAR_CR) eptr--; } } else #endif /* SUPPORT_UTF */ /* Not UTF mode */ { switch(ctype) { case OP_ANY: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (IS_NEWLINE(eptr)) break; if (md->partial != 0 && /* Take care with CRLF partial */ eptr + 1 >= md->end_subject && NLBLOCK->nltype == NLTYPE_FIXED && NLBLOCK->nllen == 2 && *eptr == NLBLOCK->nl[0]) { md->hitend = TRUE; if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); } eptr++; } break; case OP_ALLANY: case OP_ANYBYTE: c = max - min; if (c > (unsigned int)(md->end_subject - eptr)) { eptr = md->end_subject; SCHECK_PARTIAL(); } else eptr += c; break; case OP_ANYNL: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } c = *eptr; if (c == CHAR_CR) { if (++eptr >= md->end_subject) break; if (*eptr == CHAR_LF) eptr++; } else { if (c != CHAR_LF && (md->bsr_anycrlf || (c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 && c != 0x2028 && c != 0x2029 #endif ))) break; eptr++; } } break; case OP_NOT_HSPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } switch(*eptr) { default: eptr++; break; HSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 HSPACE_MULTIBYTE_CASES: #endif goto ENDLOOP00; } } ENDLOOP00: break; case OP_HSPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } switch(*eptr) { default: goto ENDLOOP01; HSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 HSPACE_MULTIBYTE_CASES: #endif eptr++; break; } } ENDLOOP01: break; case OP_NOT_VSPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } switch(*eptr) { default: eptr++; break; VSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 VSPACE_MULTIBYTE_CASES: #endif goto ENDLOOP02; } } ENDLOOP02: break; case OP_VSPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } switch(*eptr) { default: goto ENDLOOP03; VSPACE_BYTE_CASES: #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 VSPACE_MULTIBYTE_CASES: #endif eptr++; break; } } ENDLOOP03: break; case OP_NOT_DIGIT: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break; eptr++; } break; case OP_DIGIT: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break; eptr++; } break; case OP_NOT_WHITESPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break; eptr++; } break; case OP_WHITESPACE: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break; eptr++; } break; case OP_NOT_WORDCHAR: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break; eptr++; } break; case OP_WORDCHAR: for (i = min; i < max; i++) { if (eptr >= md->end_subject) { SCHECK_PARTIAL(); break; } if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break; eptr++; } break; default: RRETURN(PCRE_ERROR_INTERNAL); } if (possessive) continue; /* No backtracking */ for (;;) { if (eptr == pp) goto TAIL_RECURSE; RMATCH(eptr, ecode, offset_top, md, eptrb, RM47); if (rrc != MATCH_NOMATCH) RRETURN(rrc); eptr--; if (ctype == OP_ANYNL && eptr > pp && *eptr == CHAR_LF && eptr[-1] == CHAR_CR) eptr--; } } /* Control never gets here */ } /* There's been some horrible disaster. Arrival here can only mean there is something seriously wrong in the code above or the OP_xxx definitions. */ default: DPRINTF(("Unknown opcode %d\n", *ecode)); RRETURN(PCRE_ERROR_UNKNOWN_OPCODE); } /* Do not stick any code in here without much thought; it is assumed that "continue" in the code above comes out to here to repeat the main loop. */ } /* End of main loop */ /* Control never reaches here */ /* When compiling to use the heap rather than the stack for recursive calls to match(), the RRETURN() macro jumps here. The number that is saved in frame->Xwhere indicates which label we actually want to return to. */ #ifdef NO_RECURSE #define LBL(val) case val: goto L_RM##val; HEAP_RETURN: switch (frame->Xwhere) { LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8) LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17) LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33) LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52) LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64) LBL(65) LBL(66) #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 LBL(20) LBL(21) #endif #ifdef SUPPORT_UTF LBL(16) LBL(18) LBL(22) LBL(23) LBL(28) LBL(30) LBL(32) LBL(34) LBL(42) LBL(46) #ifdef SUPPORT_UCP LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45) LBL(59) LBL(60) LBL(61) LBL(62) LBL(67) #endif /* SUPPORT_UCP */ #endif /* SUPPORT_UTF */ default: DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere)); return PCRE_ERROR_INTERNAL; } #undef LBL #endif /* NO_RECURSE */ } /*************************************************************************** **************************************************************************** RECURSION IN THE match() FUNCTION Undefine all the macros that were defined above to handle this. */ #ifdef NO_RECURSE #undef eptr #undef ecode #undef mstart #undef offset_top #undef eptrb #undef flags #undef callpat #undef charptr #undef data #undef next #undef pp #undef prev #undef saved_eptr #undef new_recursive #undef cur_is_word #undef condition #undef prev_is_word #undef ctype #undef length #undef max #undef min #undef number #undef offset #undef op #undef save_capture_last #undef save_offset1 #undef save_offset2 #undef save_offset3 #undef stacksave #undef newptrb #endif /* These two are defined as macros in both cases */ #undef fc #undef fi /*************************************************************************** ***************************************************************************/ #ifdef NO_RECURSE /************************************************* * Release allocated heap frames * *************************************************/ /* This function releases all the allocated frames. The base frame is on the machine stack, and so must not be freed. Argument: the address of the base frame Returns: nothing */ static void release_match_heapframes (heapframe *frame_base) { heapframe *nextframe = frame_base->Xnextframe; while (nextframe != NULL) { heapframe *oldframe = nextframe; nextframe = nextframe->Xnextframe; (PUBL(stack_free))(oldframe); } } #endif /************************************************* * Execute a Regular Expression * *************************************************/ /* This function applies a compiled re to a subject string and picks out portions of the string if it matches. Two elements in the vector are set for each substring: the offsets to the start and end of the substring. Arguments: argument_re points to the compiled expression extra_data points to extra data or is NULL subject points to the subject string length length of subject string (may contain binary zeros) start_offset where to start in the subject string options option bits offsets points to a vector of ints to be filled in with offsets offsetcount the number of elements in the vector Returns: > 0 => success; value is the number of elements filled in = 0 => success, but offsets is not big enough -1 => failed to match < -1 => some kind of unexpected problem */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_exec(const pcre *argument_re, const pcre_extra *extra_data, PCRE_SPTR subject, int length, int start_offset, int options, int *offsets, int offsetcount) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, int offsetcount) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_exec(const pcre32 *argument_re, const pcre32_extra *extra_data, PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets, int offsetcount) #endif { int rc, ocount, arg_offset_max; int newline; BOOL using_temporary_offsets = FALSE; BOOL anchored; BOOL startline; BOOL firstline; BOOL utf; BOOL has_first_char = FALSE; BOOL has_req_char = FALSE; pcre_uchar first_char = 0; pcre_uchar first_char2 = 0; pcre_uchar req_char = 0; pcre_uchar req_char2 = 0; match_data match_block; match_data *md = &match_block; const pcre_uint8 *tables; const pcre_uint8 *start_bits = NULL; PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset; PCRE_PUCHAR end_subject; PCRE_PUCHAR start_partial = NULL; PCRE_PUCHAR match_partial = NULL; PCRE_PUCHAR req_char_ptr = start_match - 1; const pcre_study_data *study; const REAL_PCRE *re = (const REAL_PCRE *)argument_re; #ifdef NO_RECURSE heapframe frame_zero; frame_zero.Xprevframe = NULL; /* Marks the top level */ frame_zero.Xnextframe = NULL; /* None are allocated yet */ md->match_frames_base = &frame_zero; #endif /* Check for the special magic call that measures the size of the stack used per recursive call of match(). Without the funny casting for sizeof, a Windows compiler gave this error: "unary minus operator applied to unsigned type, result still unsigned". Hopefully the cast fixes that. */ if (re == NULL && extra_data == NULL && subject == NULL && length == -999 && start_offset == -999) #ifdef NO_RECURSE return -((int)sizeof(heapframe)); #else return match(NULL, NULL, NULL, 0, NULL, NULL, 0); #endif /* Plausibility checks */ if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; if (length < 0) return PCRE_ERROR_BADLENGTH; if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; /* Check that the first field in the block is the magic number. If it is not, return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which means that the pattern is likely compiled with different endianness. */ if (re->magic_number != MAGIC_NUMBER) return re->magic_number == REVERSED_MAGIC_NUMBER? PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; /* These two settings are used in the code for checking a UTF-8 string that follows immediately afterwards. Other values in the md block are used only during "normal" pcre_exec() processing, not when the JIT support is in use, so they are set up later. */ /* PCRE_UTF16 has the same value as PCRE_UTF8. */ utf = md->utf = (re->options & PCRE_UTF8) != 0; md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 : ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0; /* Check a UTF-8 string if required. Pass back the character offset and error code for an invalid string if a results vector is available. */ #ifdef SUPPORT_UTF if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) { int erroroffset; int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset); if (errorcode != 0) { if (offsetcount >= 2) { offsets[0] = erroroffset; offsets[1] = errorcode; } #if defined COMPILE_PCRE8 return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)? PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; #elif defined COMPILE_PCRE16 return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)? PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16; #elif defined COMPILE_PCRE32 return PCRE_ERROR_BADUTF32; #endif } #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 /* Check that a start_offset points to the start of a UTF character. */ if (start_offset > 0 && start_offset < length && NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset])) return PCRE_ERROR_BADUTF8_OFFSET; #endif } #endif /* If the pattern was successfully studied with JIT support, run the JIT executable instead of the rest of this function. Most options must be set at compile time for the JIT code to be usable. Fallback to the normal code path if an unsupported flag is set. */ #ifdef SUPPORT_JIT if (extra_data != NULL && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT | PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT && extra_data->executable_jit != NULL && (options & ~PUBLIC_JIT_EXEC_OPTIONS) == 0) { rc = PRIV(jit_exec)(extra_data, (const pcre_uchar *)subject, length, start_offset, options, offsets, offsetcount); /* PCRE_ERROR_NULL means that the selected normal or partial matching mode is not compiled. In this case we simply fallback to interpreter. */ if (rc != PCRE_ERROR_JIT_BADOPTION) return rc; } #endif /* Carry on with non-JIT matching. This information is for finding all the numbers associated with a given name, for condition testing. */ md->name_table = (pcre_uchar *)re + re->name_table_offset; md->name_count = re->name_count; md->name_entry_size = re->name_entry_size; /* Fish out the optional data from the extra_data structure, first setting the default values. */ study = NULL; md->match_limit = MATCH_LIMIT; md->match_limit_recursion = MATCH_LIMIT_RECURSION; md->callout_data = NULL; /* The table pointer is always in native byte order. */ tables = re->tables; /* The two limit values override the defaults, whatever their value. */ if (extra_data != NULL) { unsigned long int flags = extra_data->flags; if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) study = (const pcre_study_data *)extra_data->study_data; if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) md->match_limit = extra_data->match_limit; if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0) md->match_limit_recursion = extra_data->match_limit_recursion; if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) md->callout_data = extra_data->callout_data; if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables; } /* Limits in the regex override only if they are smaller. */ if ((re->flags & PCRE_MLSET) != 0 && re->limit_match < md->match_limit) md->match_limit = re->limit_match; if ((re->flags & PCRE_RLSET) != 0 && re->limit_recursion < md->match_limit_recursion) md->match_limit_recursion = re->limit_recursion; /* If the exec call supplied NULL for tables, use the inbuilt ones. This is a feature that makes it possible to save compiled regex and re-use them in other programs later. */ if (tables == NULL) tables = PRIV(default_tables); /* Set up other data */ anchored = ((re->options | options) & PCRE_ANCHORED) != 0; startline = (re->flags & PCRE_STARTLINE) != 0; firstline = (re->options & PCRE_FIRSTLINE) != 0; /* The code starts after the real_pcre block and the capture name table. */ md->start_code = (const pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size; md->start_subject = (PCRE_PUCHAR)subject; md->start_offset = start_offset; md->end_subject = md->start_subject + length; end_subject = md->end_subject; md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; md->use_ucp = (re->options & PCRE_UCP) != 0; md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; md->ignore_skip_arg = 0; /* Some options are unpacked into BOOL variables in the hope that testing them will be faster than individual option bits. */ md->notbol = (options & PCRE_NOTBOL) != 0; md->noteol = (options & PCRE_NOTEOL) != 0; md->notempty = (options & PCRE_NOTEMPTY) != 0; md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; md->hitend = FALSE; md->mark = md->nomatch_mark = NULL; /* In case never set */ md->recursive = NULL; /* No recursion at top level */ md->hasthen = (re->flags & PCRE_HASTHEN) != 0; md->lcc = tables + lcc_offset; md->fcc = tables + fcc_offset; md->ctypes = tables + ctypes_offset; /* Handle different \R options. */ switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) { case 0: if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0) md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0; else #ifdef BSR_ANYCRLF md->bsr_anycrlf = TRUE; #else md->bsr_anycrlf = FALSE; #endif break; case PCRE_BSR_ANYCRLF: md->bsr_anycrlf = TRUE; break; case PCRE_BSR_UNICODE: md->bsr_anycrlf = FALSE; break; default: return PCRE_ERROR_BADNEWLINE; } /* Handle different types of newline. The three bits give eight cases. If nothing is set at run time, whatever was used at compile time applies. */ switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) & PCRE_NEWLINE_BITS) { case 0: newline = NEWLINE; break; /* Compile-time default */ case PCRE_NEWLINE_CR: newline = CHAR_CR; break; case PCRE_NEWLINE_LF: newline = CHAR_NL; break; case PCRE_NEWLINE_CR+ PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; case PCRE_NEWLINE_ANY: newline = -1; break; case PCRE_NEWLINE_ANYCRLF: newline = -2; break; default: return PCRE_ERROR_BADNEWLINE; } if (newline == -2) { md->nltype = NLTYPE_ANYCRLF; } else if (newline < 0) { md->nltype = NLTYPE_ANY; } else { md->nltype = NLTYPE_FIXED; if (newline > 255) { md->nllen = 2; md->nl[0] = (newline >> 8) & 255; md->nl[1] = newline & 255; } else { md->nllen = 1; md->nl[0] = newline; } } /* Partial matching was originally supported only for a restricted set of regexes; from release 8.00 there are no restrictions, but the bits are still defined (though never set). So there's no harm in leaving this code. */ if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0) return PCRE_ERROR_BADPARTIAL; /* If the expression has got more back references than the offsets supplied can hold, we get a temporary chunk of working store to use during the matching. Otherwise, we can use the vector supplied, rounding down its size to a multiple of 3. */ ocount = offsetcount - (offsetcount % 3); arg_offset_max = (2*ocount)/3; if (re->top_backref > 0 && re->top_backref >= ocount/3) { ocount = re->top_backref * 3 + 3; md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int)); if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY; using_temporary_offsets = TRUE; DPRINTF(("Got memory to hold back references\n")); } else md->offset_vector = offsets; md->offset_end = ocount; md->offset_max = (2*ocount)/3; md->capture_last = 0; /* Reset the working variable associated with each extraction. These should never be used unless previously set, but they get saved and restored, and so we initialize them to avoid reading uninitialized locations. Also, unset the offsets for the matched string. This is really just for tidiness with callouts, in case they inspect these fields. */ if (md->offset_vector != NULL) { register int *iptr = md->offset_vector + ocount; register int *iend = iptr - re->top_bracket; if (iend < md->offset_vector + 2) iend = md->offset_vector + 2; while (--iptr >= iend) *iptr = -1; if (offsetcount > 0) md->offset_vector[0] = -1; if (offsetcount > 1) md->offset_vector[1] = -1; } /* Set up the first character to match, if available. The first_char value is never set for an anchored regular expression, but the anchoring may be forced at run time, so we have to test for anchoring. The first char may be unset for an unanchored pattern, of course. If there's no first char and the pattern was studied, there may be a bitmap of possible first characters. */ if (!anchored) { if ((re->flags & PCRE_FIRSTSET) != 0) { has_first_char = TRUE; first_char = first_char2 = (pcre_uchar)(re->first_char); if ((re->flags & PCRE_FCH_CASELESS) != 0) { first_char2 = TABLE_GET(first_char, md->fcc, first_char); #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) if (utf && first_char > 127) first_char2 = UCD_OTHERCASE(first_char); #endif } } else if (!startline && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) start_bits = study->start_bits; } /* For anchored or unanchored matches, there may be a "last known required character" set. */ if ((re->flags & PCRE_REQCHSET) != 0) { has_req_char = TRUE; req_char = req_char2 = (pcre_uchar)(re->req_char); if ((re->flags & PCRE_RCH_CASELESS) != 0) { req_char2 = TABLE_GET(req_char, md->fcc, req_char); #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) if (utf && req_char > 127) req_char2 = UCD_OTHERCASE(req_char); #endif } } /* ==========================================================================*/ /* Loop for handling unanchored repeated matching attempts; for anchored regexs the loop runs just once. */ for(;;) { PCRE_PUCHAR save_end_subject = end_subject; PCRE_PUCHAR new_start_match; /* If firstline is TRUE, the start of the match is constrained to the first line of a multiline string. That is, the match must be before or at the first newline. Implement this by temporarily adjusting end_subject so that we stop scanning at a newline. If the match fails at the newline, later code breaks this loop. */ if (firstline) { PCRE_PUCHAR t = start_match; #ifdef SUPPORT_UTF if (utf) { while (t < md->end_subject && !IS_NEWLINE(t)) { t++; ACROSSCHAR(t < end_subject, *t, t++); } } else #endif while (t < md->end_subject && !IS_NEWLINE(t)) t++; end_subject = t; } /* There are some optimizations that avoid running the match if a known starting point is not found, or if a known later character is not present. However, there is an option that disables these, for testing and for ensuring that all callouts do actually occur. The option can be set in the regex by (*NO_START_OPT) or passed in match-time options. */ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) { /* Advance to a unique first char if there is one. */ if (has_first_char) { pcre_uchar smc; if (first_char != first_char2) while (start_match < end_subject && (smc = UCHAR21TEST(start_match)) != first_char && smc != first_char2) start_match++; else while (start_match < end_subject && UCHAR21TEST(start_match) != first_char) start_match++; } /* Or to just after a linebreak for a multiline match */ else if (startline) { if (start_match > md->start_subject + start_offset) { #ifdef SUPPORT_UTF if (utf) { while (start_match < end_subject && !WAS_NEWLINE(start_match)) { start_match++; ACROSSCHAR(start_match < end_subject, *start_match, start_match++); } } else #endif while (start_match < end_subject && !WAS_NEWLINE(start_match)) start_match++; /* If we have just passed a CR and the newline option is ANY or ANYCRLF, and we are now at a LF, advance the match position by one more character. */ if (start_match[-1] == CHAR_CR && (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && start_match < end_subject && UCHAR21TEST(start_match) == CHAR_NL) start_match++; } } /* Or to a non-unique first byte after study */ else if (start_bits != NULL) { while (start_match < end_subject) { register pcre_uint32 c = UCHAR21TEST(start_match); #ifndef COMPILE_PCRE8 if (c > 255) c = 255; #endif if ((start_bits[c/8] & (1 << (c&7))) != 0) break; start_match++; } } } /* Starting optimizations */ /* Restore fudged end_subject */ end_subject = save_end_subject; /* The following two optimizations are disabled for partial matching or if disabling is explicitly requested. */ if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial) { /* If the pattern was studied, a minimum subject length may be set. This is a lower bound; no actual string of that length may actually match the pattern. Although the value is, strictly, in characters, we treat it as bytes to avoid spending too much time in this optimization. */ if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && (pcre_uint32)(end_subject - start_match) < study->minlength) { rc = MATCH_NOMATCH; break; } /* If req_char is set, we know that that character must appear in the subject for the match to succeed. If the first character is set, req_char must be later in the subject; otherwise the test starts at the match point. This optimization can save a huge amount of backtracking in patterns with nested unlimited repeats that aren't going to match. Writing separate code for cased/caseless versions makes it go faster, as does using an autoincrement and backing off on a match. HOWEVER: when the subject string is very, very long, searching to its end can take a long time, and give bad performance on quite ordinary patterns. This showed up when somebody was matching something like /^\d+C/ on a 32-megabyte string... so we don't do this when the string is sufficiently long. */ if (has_req_char && end_subject - start_match < REQ_BYTE_MAX) { register PCRE_PUCHAR p = start_match + (has_first_char? 1:0); /* We don't need to repeat the search if we haven't yet reached the place we found it at last time. */ if (p > req_char_ptr) { if (req_char != req_char2) { while (p < end_subject) { register pcre_uint32 pp = UCHAR21INCTEST(p); if (pp == req_char || pp == req_char2) { p--; break; } } } else { while (p < end_subject) { if (UCHAR21INCTEST(p) == req_char) { p--; break; } } } /* If we can't find the required character, break the matching loop, forcing a match failure. */ if (p >= end_subject) { rc = MATCH_NOMATCH; break; } /* If we have found the required character, save the point where we found it, so that we don't search again next time round the loop if the start hasn't passed this character yet. */ req_char_ptr = p; } } } #ifdef PCRE_DEBUG /* Sigh. Some compilers never learn. */ printf(">>>> Match against: "); pchars(start_match, end_subject - start_match, TRUE, md); printf("\n"); #endif /* OK, we can now run the match. If "hitend" is set afterwards, remember the first starting point for which a partial match was found. */ md->start_match_ptr = start_match; md->start_used_ptr = start_match; md->match_call_count = 0; md->match_function_type = 0; md->end_offset_top = 0; md->skip_arg_count = 0; rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0); if (md->hitend && start_partial == NULL) { start_partial = md->start_used_ptr; match_partial = start_match; } switch(rc) { /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched the SKIP's arg was not found. In this circumstance, Perl ignores the SKIP entirely. The only way we can do that is to re-do the match at the same point, with a flag to force SKIP with an argument to be ignored. Just treating this case as NOMATCH does not work because it does not check other alternatives in patterns such as A(*SKIP:A)B|AC when the subject is AC. */ case MATCH_SKIP_ARG: new_start_match = start_match; md->ignore_skip_arg = md->skip_arg_count; break; /* SKIP passes back the next starting point explicitly, but if it is no greater than the match we have just done, treat it as NOMATCH. */ case MATCH_SKIP: if (md->start_match_ptr > start_match) { new_start_match = md->start_match_ptr; break; } /* Fall through */ /* NOMATCH and PRUNE advance by one character. THEN at this level acts exactly like PRUNE. Unset ignore SKIP-with-argument. */ case MATCH_NOMATCH: case MATCH_PRUNE: case MATCH_THEN: md->ignore_skip_arg = 0; new_start_match = start_match + 1; #ifdef SUPPORT_UTF if (utf) ACROSSCHAR(new_start_match < end_subject, *new_start_match, new_start_match++); #endif break; /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */ case MATCH_COMMIT: rc = MATCH_NOMATCH; goto ENDLOOP; /* Any other return is either a match, or some kind of error. */ default: goto ENDLOOP; } /* Control reaches here for the various types of "no match at this point" result. Reset the code to MATCH_NOMATCH for subsequent checking. */ rc = MATCH_NOMATCH; /* If PCRE_FIRSTLINE is set, the match must happen before or at the first newline in the subject (though it may continue over the newline). Therefore, if we have just failed to match, starting at a newline, do not continue. */ if (firstline && IS_NEWLINE(start_match)) break; /* Advance to new matching position */ start_match = new_start_match; /* Break the loop if the pattern is anchored or if we have passed the end of the subject. */ if (anchored || start_match > end_subject) break; /* If we have just passed a CR and we are now at a LF, and the pattern does not contain any explicit matches for \r or \n, and the newline option is CRLF or ANY or ANYCRLF, advance the match position by one more character. In normal matching start_match will aways be greater than the first position at this stage, but a failed *SKIP can cause a return at the same point, which is why the first test exists. */ if (start_match > (PCRE_PUCHAR)subject + start_offset && start_match[-1] == CHAR_CR && start_match < end_subject && *start_match == CHAR_NL && (re->flags & PCRE_HASCRORLF) == 0 && (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF || md->nllen == 2)) start_match++; md->mark = NULL; /* Reset for start of next match attempt */ } /* End of for(;;) "bumpalong" loop */ /* ==========================================================================*/ /* We reach here when rc is not MATCH_NOMATCH, or if one of the stopping conditions is true: (1) The pattern is anchored or the match was failed by (*COMMIT); (2) We are past the end of the subject; (3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because this option requests that a match occur at or before the first newline in the subject. When we have a match and the offset vector is big enough to deal with any backreferences, captured substring offsets will already be set up. In the case where we had to get some local store to hold offsets for backreference processing, copy those that we can. In this case there need not be overflow if certain parts of the pattern were not used, even though there are more capturing parentheses than vector slots. */ ENDLOOP: if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) { if (using_temporary_offsets) { if (arg_offset_max >= 4) { memcpy(offsets + 2, md->offset_vector + 2, (arg_offset_max - 2) * sizeof(int)); DPRINTF(("Copied offsets from temporary memory\n")); } if (md->end_offset_top > arg_offset_max) md->capture_last |= OVFLBIT; DPRINTF(("Freeing temporary memory\n")); (PUBL(free))(md->offset_vector); } /* Set the return code to the number of captured strings, or 0 if there were too many to fit into the vector. */ rc = ((md->capture_last & OVFLBIT) != 0 && md->end_offset_top >= arg_offset_max)? 0 : md->end_offset_top/2; /* If there is space in the offset vector, set any unused pairs at the end of the pattern to -1 for backwards compatibility. It is documented that this happens. In earlier versions, the whole set of potential capturing offsets was set to -1 each time round the loop, but this is handled differently now. "Gaps" are set to -1 dynamically instead (this fixes a bug). Thus, it is only those at the end that need unsetting here. We can't just unset them all at the start of the whole thing because they may get set in one branch that is not the final matching branch. */ if (md->end_offset_top/2 <= re->top_bracket && offsets != NULL) { register int *iptr, *iend; int resetcount = 2 + re->top_bracket * 2; if (resetcount > offsetcount) resetcount = offsetcount; iptr = offsets + md->end_offset_top; iend = offsets + resetcount; while (iptr < iend) *iptr++ = -1; } /* If there is space, set up the whole thing as substring 0. The value of md->start_match_ptr might be modified if \K was encountered on the success matching path. */ if (offsetcount < 2) rc = 0; else { offsets[0] = (int)(md->start_match_ptr - md->start_subject); offsets[1] = (int)(md->end_match_ptr - md->start_subject); } /* Return MARK data if requested */ if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) *(extra_data->mark) = (pcre_uchar *)md->mark; DPRINTF((">>>> returning %d\n", rc)); #ifdef NO_RECURSE release_match_heapframes(&frame_zero); #endif return rc; } /* Control gets here if there has been an error, or if the overall match attempt has failed at all permitted starting positions. */ if (using_temporary_offsets) { DPRINTF(("Freeing temporary memory\n")); (PUBL(free))(md->offset_vector); } /* For anything other than nomatch or partial match, just return the code. */ if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) { DPRINTF((">>>> error: returning %d\n", rc)); #ifdef NO_RECURSE release_match_heapframes(&frame_zero); #endif return rc; } /* Handle partial matches - disable any mark data */ if (match_partial != NULL) { DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); md->mark = NULL; if (offsetcount > 1) { offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject); offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject); if (offsetcount > 2) offsets[2] = (int)(match_partial - (PCRE_PUCHAR)subject); } rc = PCRE_ERROR_PARTIAL; } /* This is the classic nomatch case */ else { DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); rc = PCRE_ERROR_NOMATCH; } /* Return the MARK data if it has been requested. */ if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark; #ifdef NO_RECURSE release_match_heapframes(&frame_zero); #endif return rc; } /* End of pcre_exec.c */ ================================================ FILE: src/pcre/pcre_fullinfo.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2013 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_fullinfo(), which returns information about a compiled pattern. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Return info about compiled pattern * *************************************************/ /* This is a newer "info" function which has an extensible interface so that additional items can be added compatibly. Arguments: argument_re points to compiled code extra_data points extra data, or NULL what what information is required where where to put the information Returns: 0 if data returned, negative on error */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, int what, void *where) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data, int what, void *where) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_fullinfo(const pcre32 *argument_re, const pcre32_extra *extra_data, int what, void *where) #endif { const REAL_PCRE *re = (const REAL_PCRE *)argument_re; const pcre_study_data *study = NULL; if (re == NULL || where == NULL) return PCRE_ERROR_NULL; if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) study = (const pcre_study_data *)extra_data->study_data; /* Check that the first field in the block is the magic number. If it is not, return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which means that the pattern is likely compiled with different endianness. */ if (re->magic_number != MAGIC_NUMBER) return re->magic_number == REVERSED_MAGIC_NUMBER? PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; /* Check that this pattern was compiled in the correct bit mode */ if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; switch (what) { case PCRE_INFO_OPTIONS: *((unsigned long int *)where) = re->options & PUBLIC_COMPILE_OPTIONS; break; case PCRE_INFO_SIZE: *((size_t *)where) = re->size; break; case PCRE_INFO_STUDYSIZE: *((size_t *)where) = (study == NULL)? 0 : study->size; break; case PCRE_INFO_JITSIZE: #ifdef SUPPORT_JIT *((size_t *)where) = (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra_data->executable_jit != NULL)? PRIV(jit_get_size)(extra_data->executable_jit) : 0; #else *((size_t *)where) = 0; #endif break; case PCRE_INFO_CAPTURECOUNT: *((int *)where) = re->top_bracket; break; case PCRE_INFO_BACKREFMAX: *((int *)where) = re->top_backref; break; case PCRE_INFO_FIRSTBYTE: *((int *)where) = ((re->flags & PCRE_FIRSTSET) != 0)? (int)re->first_char : ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2; break; case PCRE_INFO_FIRSTCHARACTER: *((pcre_uint32 *)where) = (re->flags & PCRE_FIRSTSET) != 0 ? re->first_char : 0; break; case PCRE_INFO_FIRSTCHARACTERFLAGS: *((int *)where) = ((re->flags & PCRE_FIRSTSET) != 0) ? 1 : ((re->flags & PCRE_STARTLINE) != 0) ? 2 : 0; break; /* Make sure we pass back the pointer to the bit vector in the external block, not the internal copy (with flipped integer fields). */ case PCRE_INFO_FIRSTTABLE: *((const pcre_uint8 **)where) = (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)? ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL; break; case PCRE_INFO_MINLENGTH: *((int *)where) = (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)? (int)(study->minlength) : -1; break; case PCRE_INFO_JIT: *((int *)where) = extra_data != NULL && (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra_data->executable_jit != NULL; break; case PCRE_INFO_LASTLITERAL: *((int *)where) = ((re->flags & PCRE_REQCHSET) != 0)? (int)re->req_char : -1; break; case PCRE_INFO_REQUIREDCHAR: *((pcre_uint32 *)where) = ((re->flags & PCRE_REQCHSET) != 0) ? re->req_char : 0; break; case PCRE_INFO_REQUIREDCHARFLAGS: *((int *)where) = ((re->flags & PCRE_REQCHSET) != 0); break; case PCRE_INFO_NAMEENTRYSIZE: *((int *)where) = re->name_entry_size; break; case PCRE_INFO_NAMECOUNT: *((int *)where) = re->name_count; break; case PCRE_INFO_NAMETABLE: *((const pcre_uchar **)where) = (const pcre_uchar *)re + re->name_table_offset; break; case PCRE_INFO_DEFAULT_TABLES: *((const pcre_uint8 **)where) = (const pcre_uint8 *)(PRIV(default_tables)); break; /* From release 8.00 this will always return TRUE because NOPARTIAL is no longer ever set (the restrictions have been removed). */ case PCRE_INFO_OKPARTIAL: *((int *)where) = (re->flags & PCRE_NOPARTIAL) == 0; break; case PCRE_INFO_JCHANGED: *((int *)where) = (re->flags & PCRE_JCHANGED) != 0; break; case PCRE_INFO_HASCRORLF: *((int *)where) = (re->flags & PCRE_HASCRORLF) != 0; break; case PCRE_INFO_MAXLOOKBEHIND: *((int *)where) = re->max_lookbehind; break; case PCRE_INFO_MATCHLIMIT: if ((re->flags & PCRE_MLSET) == 0) return PCRE_ERROR_UNSET; *((pcre_uint32 *)where) = re->limit_match; break; case PCRE_INFO_RECURSIONLIMIT: if ((re->flags & PCRE_RLSET) == 0) return PCRE_ERROR_UNSET; *((pcre_uint32 *)where) = re->limit_recursion; break; case PCRE_INFO_MATCH_EMPTY: *((int *)where) = (re->flags & PCRE_MATCH_EMPTY) != 0; break; default: return PCRE_ERROR_BADOPTION; } return 0; } /* End of pcre_fullinfo.c */ ================================================ FILE: src/pcre/pcre_get.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains some convenience functions for extracting substrings from the subject string after a regex match has succeeded. The original idea for these functions came from Scott Wimer. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Find number for named string * *************************************************/ /* This function is used by the get_first_set() function below, as well as being generally available. It assumes that names are unique. Arguments: code the compiled regex stringname the name whose number is required Returns: the number of the named parentheses, or a negative number (PCRE_ERROR_NOSUBSTRING) if not found */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_get_stringnumber(const pcre *code, const char *stringname) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 stringname) #endif { int rc; int entrysize; int top, bot; pcre_uchar *nametable; #ifdef COMPILE_PCRE8 if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) return rc; if (top <= 0) return PCRE_ERROR_NOSUBSTRING; if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) return rc; if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) return rc; #endif #ifdef COMPILE_PCRE16 if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) return rc; if (top <= 0) return PCRE_ERROR_NOSUBSTRING; if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) return rc; if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) return rc; #endif #ifdef COMPILE_PCRE32 if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) return rc; if (top <= 0) return PCRE_ERROR_NOSUBSTRING; if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) return rc; if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) return rc; #endif bot = 0; while (top > bot) { int mid = (top + bot) / 2; pcre_uchar *entry = nametable + entrysize*mid; int c = STRCMP_UC_UC((pcre_uchar *)stringname, (pcre_uchar *)(entry + IMM2_SIZE)); if (c == 0) return GET2(entry, 0); if (c > 0) bot = mid + 1; else top = mid; } return PCRE_ERROR_NOSUBSTRING; } /************************************************* * Find (multiple) entries for named string * *************************************************/ /* This is used by the get_first_set() function below, as well as being generally available. It is used when duplicated names are permitted. Arguments: code the compiled regex stringname the name whose entries required firstptr where to put the pointer to the first entry lastptr where to put the pointer to the last entry Returns: the length of each entry, or a negative number (PCRE_ERROR_NOSUBSTRING) if not found */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_get_stringtable_entries(const pcre *code, const char *stringname, char **firstptr, char **lastptr) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname, PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 stringname, PCRE_UCHAR32 **firstptr, PCRE_UCHAR32 **lastptr) #endif { int rc; int entrysize; int top, bot; pcre_uchar *nametable, *lastentry; #ifdef COMPILE_PCRE8 if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) return rc; if (top <= 0) return PCRE_ERROR_NOSUBSTRING; if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) return rc; if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) return rc; #endif #ifdef COMPILE_PCRE16 if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) return rc; if (top <= 0) return PCRE_ERROR_NOSUBSTRING; if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) return rc; if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) return rc; #endif #ifdef COMPILE_PCRE32 if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) return rc; if (top <= 0) return PCRE_ERROR_NOSUBSTRING; if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) return rc; if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) return rc; #endif lastentry = nametable + entrysize * (top - 1); bot = 0; while (top > bot) { int mid = (top + bot) / 2; pcre_uchar *entry = nametable + entrysize*mid; int c = STRCMP_UC_UC((pcre_uchar *)stringname, (pcre_uchar *)(entry + IMM2_SIZE)); if (c == 0) { pcre_uchar *first = entry; pcre_uchar *last = entry; while (first > nametable) { if (STRCMP_UC_UC((pcre_uchar *)stringname, (pcre_uchar *)(first - entrysize + IMM2_SIZE)) != 0) break; first -= entrysize; } while (last < lastentry) { if (STRCMP_UC_UC((pcre_uchar *)stringname, (pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break; last += entrysize; } #if defined COMPILE_PCRE8 *firstptr = (char *)first; *lastptr = (char *)last; #elif defined COMPILE_PCRE16 *firstptr = (PCRE_UCHAR16 *)first; *lastptr = (PCRE_UCHAR16 *)last; #elif defined COMPILE_PCRE32 *firstptr = (PCRE_UCHAR32 *)first; *lastptr = (PCRE_UCHAR32 *)last; #endif return entrysize; } if (c > 0) bot = mid + 1; else top = mid; } return PCRE_ERROR_NOSUBSTRING; } /************************************************* * Find first set of multiple named strings * *************************************************/ /* This function allows for duplicate names in the table of named substrings. It returns the number of the first one that was set in a pattern match. Arguments: code the compiled regex stringname the name of the capturing substring ovector the vector of matched substrings stringcount number of captured substrings Returns: the number of the first that is set, or the number of the last one if none are set, or a negative number on error */ #if defined COMPILE_PCRE8 static int get_first_set(const pcre *code, const char *stringname, int *ovector, int stringcount) #elif defined COMPILE_PCRE16 static int get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector, int stringcount) #elif defined COMPILE_PCRE32 static int get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector, int stringcount) #endif { const REAL_PCRE *re = (const REAL_PCRE *)code; int entrysize; pcre_uchar *entry; #if defined COMPILE_PCRE8 char *first, *last; #elif defined COMPILE_PCRE16 PCRE_UCHAR16 *first, *last; #elif defined COMPILE_PCRE32 PCRE_UCHAR32 *first, *last; #endif #if defined COMPILE_PCRE8 if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) return pcre_get_stringnumber(code, stringname); entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last); #elif defined COMPILE_PCRE16 if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) return pcre16_get_stringnumber(code, stringname); entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last); #elif defined COMPILE_PCRE32 if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) return pcre32_get_stringnumber(code, stringname); entrysize = pcre32_get_stringtable_entries(code, stringname, &first, &last); #endif if (entrysize <= 0) return entrysize; for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize) { int n = GET2(entry, 0); if (n < stringcount && ovector[n*2] >= 0) return n; } return GET2(entry, 0); } /************************************************* * Copy captured string to given buffer * *************************************************/ /* This function copies a single captured substring into a given buffer. Note that we use memcpy() rather than strncpy() in case there are binary zeros in the string. Arguments: subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) stringnumber the number of the required substring buffer where to put the substring size the size of the buffer Returns: if successful: the length of the copied string, not including the zero that is put on the end; can be zero if not successful: PCRE_ERROR_NOMEMORY (-6) buffer too small PCRE_ERROR_NOSUBSTRING (-7) no such captured substring */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int size) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR16 *buffer, int size) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_UCHAR32 *buffer, int size) #endif { int yield; if (stringnumber < 0 || stringnumber >= stringcount) return PCRE_ERROR_NOSUBSTRING; stringnumber *= 2; yield = ovector[stringnumber+1] - ovector[stringnumber]; if (size < yield + 1) return PCRE_ERROR_NOMEMORY; memcpy(buffer, subject + ovector[stringnumber], IN_UCHARS(yield)); buffer[yield] = 0; return yield; } /************************************************* * Copy named captured string to given buffer * *************************************************/ /* This function copies a single captured substring into a given buffer, identifying it by name. If the regex permits duplicate names, the first substring that is set is chosen. Arguments: code the compiled regex subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) stringname the name of the required substring buffer where to put the substring size the size of the buffer Returns: if successful: the length of the copied string, not including the zero that is put on the end; can be zero if not successful: PCRE_ERROR_NOMEMORY (-6) buffer too small PCRE_ERROR_NOSUBSTRING (-7) no such captured substring */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_copy_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int size) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_UCHAR16 *buffer, int size) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_UCHAR32 *buffer, int size) #endif { int n = get_first_set(code, stringname, ovector, stringcount); if (n <= 0) return n; #if defined COMPILE_PCRE8 return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); #elif defined COMPILE_PCRE16 return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size); #elif defined COMPILE_PCRE32 return pcre32_copy_substring(subject, ovector, stringcount, n, buffer, size); #endif } /************************************************* * Copy all captured strings to new store * *************************************************/ /* This function gets one chunk of store and builds a list of pointers and all of the captured substrings in it. A NULL pointer is put on the end of the list. Arguments: subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) listptr set to point to the list of pointers Returns: if successful: 0 if not successful: PCRE_ERROR_NOMEMORY (-6) failed to get store */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_get_substring_list(const char *subject, int *ovector, int stringcount, const char ***listptr) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 **listptr) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 **listptr) #endif { int i; int size = sizeof(pcre_uchar *); int double_count = stringcount * 2; pcre_uchar **stringlist; pcre_uchar *p; for (i = 0; i < double_count; i += 2) { size += sizeof(pcre_uchar *) + IN_UCHARS(1); if (ovector[i+1] > ovector[i]) size += IN_UCHARS(ovector[i+1] - ovector[i]); } stringlist = (pcre_uchar **)(PUBL(malloc))(size); if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; #if defined COMPILE_PCRE8 *listptr = (const char **)stringlist; #elif defined COMPILE_PCRE16 *listptr = (PCRE_SPTR16 *)stringlist; #elif defined COMPILE_PCRE32 *listptr = (PCRE_SPTR32 *)stringlist; #endif p = (pcre_uchar *)(stringlist + stringcount + 1); for (i = 0; i < double_count; i += 2) { int len = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0; memcpy(p, subject + ovector[i], IN_UCHARS(len)); *stringlist++ = p; p += len; *p++ = 0; } *stringlist = NULL; return 0; } /************************************************* * Free store obtained by get_substring_list * *************************************************/ /* This function exists for the benefit of people calling PCRE from non-C programs that can call its functions, but not free() or (PUBL(free))() directly. Argument: the result of a previous pcre_get_substring_list() Returns: nothing */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN void PCRE_CALL_CONVENTION pcre_free_substring_list(const char **pointer) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN void PCRE_CALL_CONVENTION pcre16_free_substring_list(PCRE_SPTR16 *pointer) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN void PCRE_CALL_CONVENTION pcre32_free_substring_list(PCRE_SPTR32 *pointer) #endif { (PUBL(free))((void *)pointer); } /************************************************* * Copy captured string to new store * *************************************************/ /* This function copies a single captured substring into a piece of new store Arguments: subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) stringnumber the number of the required substring stringptr where to put a pointer to the substring Returns: if successful: the length of the string, not including the zero that is put on the end; can be zero if not successful: PCRE_ERROR_NOMEMORY (-6) failed to get store PCRE_ERROR_NOSUBSTRING (-7) substring not present */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_get_substring(const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR16 *stringptr) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount, int stringnumber, PCRE_SPTR32 *stringptr) #endif { int yield; pcre_uchar *substring; if (stringnumber < 0 || stringnumber >= stringcount) return PCRE_ERROR_NOSUBSTRING; stringnumber *= 2; yield = ovector[stringnumber+1] - ovector[stringnumber]; substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1)); if (substring == NULL) return PCRE_ERROR_NOMEMORY; memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield)); substring[yield] = 0; #if defined COMPILE_PCRE8 *stringptr = (const char *)substring; #elif defined COMPILE_PCRE16 *stringptr = (PCRE_SPTR16)substring; #elif defined COMPILE_PCRE32 *stringptr = (PCRE_SPTR32)substring; #endif return yield; } /************************************************* * Copy named captured string to new store * *************************************************/ /* This function copies a single captured substring, identified by name, into new store. If the regex permits duplicate names, the first substring that is set is chosen. Arguments: code the compiled regex subject the subject string that was matched ovector pointer to the offsets table stringcount the number of substrings that were captured (i.e. the yield of the pcre_exec call, unless that was zero, in which case it should be 1/3 of the offset table size) stringname the name of the required substring stringptr where to put the pointer Returns: if successful: the length of the copied string, not including the zero that is put on the end; can be zero if not successful: PCRE_ERROR_NOMEMORY (-6) couldn't get memory PCRE_ERROR_NOSUBSTRING (-7) no such captured substring */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_get_named_substring(const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, const char **stringptr) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, int *ovector, int stringcount, PCRE_SPTR16 stringname, PCRE_SPTR16 *stringptr) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject, int *ovector, int stringcount, PCRE_SPTR32 stringname, PCRE_SPTR32 *stringptr) #endif { int n = get_first_set(code, stringname, ovector, stringcount); if (n <= 0) return n; #if defined COMPILE_PCRE8 return pcre_get_substring(subject, ovector, stringcount, n, stringptr); #elif defined COMPILE_PCRE16 return pcre16_get_substring(subject, ovector, stringcount, n, stringptr); #elif defined COMPILE_PCRE32 return pcre32_get_substring(subject, ovector, stringcount, n, stringptr); #endif } /************************************************* * Free store obtained by get_substring * *************************************************/ /* This function exists for the benefit of people calling PCRE from non-C programs that can call its functions, but not free() or (PUBL(free))() directly. Argument: the result of a previous pcre_get_substring() Returns: nothing */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN void PCRE_CALL_CONVENTION pcre_free_substring(const char *pointer) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN void PCRE_CALL_CONVENTION pcre16_free_substring(PCRE_SPTR16 pointer) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN void PCRE_CALL_CONVENTION pcre32_free_substring(PCRE_SPTR32 pointer) #endif { (PUBL(free))((void *)pointer); } /* End of pcre_get.c */ ================================================ FILE: src/pcre/pcre_globals.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2014 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains global variables that are exported by the PCRE library. PCRE is thread-clean and doesn't use any global variables in the normal sense. However, it calls memory allocation and freeing functions via the four indirections below, and it can optionally do callouts, using the fifth indirection. These values can be changed by the caller, but are shared between all threads. For MS Visual Studio and Symbian OS, there are problems in initializing these variables to non-local functions. In these cases, therefore, an indirection via a local function is used. Also, when compiling for Virtual Pascal, things are done differently, and global variables are not used. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" #if defined _MSC_VER || defined __SYMBIAN32__ static void* LocalPcreMalloc(size_t aSize) { return malloc(aSize); } static void LocalPcreFree(void* aPtr) { free(aPtr); } PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = LocalPcreMalloc; PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree; PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc; PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree; PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL; #elif !defined VPCOMPAT PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc; PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free; PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc; PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free; PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL; #endif /* End of pcre_globals.c */ ================================================ FILE: src/pcre/pcre_internal.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2016 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This header contains definitions that are shared between the different modules, but which are not relevant to the exported API. This includes some functions whose names all begin with "_pcre_", "_pcre16_" or "_pcre32_" depending on the PRIV macro. */ #ifndef PCRE_INTERNAL_H #define PCRE_INTERNAL_H /* Define PCRE_DEBUG to get debugging output on stdout. */ #if 0 #define PCRE_DEBUG #endif /* PCRE is compiled as an 8 bit library if it is not requested otherwise. */ #if !defined COMPILE_PCRE16 && !defined COMPILE_PCRE32 #define COMPILE_PCRE8 #endif /* If SUPPORT_UCP is defined, SUPPORT_UTF must also be defined. The "configure" script ensures this, but not everybody uses "configure". */ #if defined SUPPORT_UCP && !(defined SUPPORT_UTF) #define SUPPORT_UTF 1 #endif /* We define SUPPORT_UTF if SUPPORT_UTF8 is enabled for compatibility reasons with existing code. */ #if defined SUPPORT_UTF8 && !(defined SUPPORT_UTF) #define SUPPORT_UTF 1 #endif /* Fixme: SUPPORT_UTF8 should be eventually disappear from the code. Until then we define it if SUPPORT_UTF is defined. */ #if defined SUPPORT_UTF && !(defined SUPPORT_UTF8) #define SUPPORT_UTF8 1 #endif /* We do not support both EBCDIC and UTF-8/16/32 at the same time. The "configure" script prevents both being selected, but not everybody uses "configure". */ #if defined EBCDIC && defined SUPPORT_UTF #error The use of both EBCDIC and SUPPORT_UTF is not supported. #endif /* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef inline, and there are *still* stupid compilers about that don't like indented pre-processor statements, or at least there were when I first wrote this. After all, it had only been about 10 years then... It turns out that the Mac Debugging.h header also defines the macro DPRINTF, so be absolutely sure we get our version. */ #undef DPRINTF #ifdef PCRE_DEBUG #define DPRINTF(p) printf p #else #define DPRINTF(p) /* Nothing */ #endif /* Standard C headers plus the external interface definition. The only time setjmp and stdarg are used is when NO_RECURSE is set. */ #include #include #include #include #include #include /* Valgrind (memcheck) support */ #ifdef SUPPORT_VALGRIND #include #endif /* When compiling a DLL for Windows, the exported symbols have to be declared using some MS magic. I found some useful information on this web page: http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the information there, using __declspec(dllexport) without "extern" we have a definition; with "extern" we have a declaration. The settings here override the setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL, which is all that is needed for applications (they just import the symbols). We use: PCRE_EXP_DECL for declarations PCRE_EXP_DEFN for definitions of exported functions PCRE_EXP_DATA_DEFN for definitions of exported variables The reason for the two DEFN macros is that in non-Windows environments, one does not want to have "extern" before variable definitions because it leads to compiler warnings. So we distinguish between functions and variables. In Windows, the two should always be the same. The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that pcretest, which is an application, but needs to import this file in order to "peek" at internals, can #include pcre.h first to get an application's-eye view. In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon, special-purpose environments) might want to stick other stuff in front of exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and PCRE_EXP_DATA_DEFN only if they are not already set. */ #ifndef PCRE_EXP_DECL # ifdef _WIN32 # ifndef PCRE_STATIC # define PCRE_EXP_DECL extern __declspec(dllexport) # define PCRE_EXP_DEFN __declspec(dllexport) # define PCRE_EXP_DATA_DEFN __declspec(dllexport) # else # define PCRE_EXP_DECL extern # define PCRE_EXP_DEFN # define PCRE_EXP_DATA_DEFN # endif # else # ifdef __cplusplus # define PCRE_EXP_DECL extern "C" # else # define PCRE_EXP_DECL extern # endif # ifndef PCRE_EXP_DEFN # define PCRE_EXP_DEFN PCRE_EXP_DECL # endif # ifndef PCRE_EXP_DATA_DEFN # define PCRE_EXP_DATA_DEFN # endif # endif #endif /* When compiling with the MSVC compiler, it is sometimes necessary to include a "calling convention" before exported function names. (This is secondhand information; I know nothing about MSVC myself). For example, something like void __cdecl function(....) might be needed. In order so make this easy, all the exported functions have PCRE_CALL_CONVENTION just before their names. It is rarely needed; if not set, we ensure here that it has no effect. */ #ifndef PCRE_CALL_CONVENTION #define PCRE_CALL_CONVENTION #endif /* We need to have types that specify unsigned 8, 16 and 32-bit integers. We cannot determine these outside the compilation (e.g. by running a program as part of "configure") because PCRE is often cross-compiled for use on other systems. Instead we make use of the maximum sizes that are available at preprocessor time in standard C environments. */ typedef unsigned char pcre_uint8; #if USHRT_MAX == 65535 typedef unsigned short pcre_uint16; typedef short pcre_int16; #define PCRE_UINT16_MAX USHRT_MAX #define PCRE_INT16_MAX SHRT_MAX #elif UINT_MAX == 65535 typedef unsigned int pcre_uint16; typedef int pcre_int16; #define PCRE_UINT16_MAX UINT_MAX #define PCRE_INT16_MAX INT_MAX #else #error Cannot determine a type for 16-bit integers #endif #if UINT_MAX == 4294967295U typedef unsigned int pcre_uint32; typedef int pcre_int32; #define PCRE_UINT32_MAX UINT_MAX #define PCRE_INT32_MAX INT_MAX #elif ULONG_MAX == 4294967295UL typedef unsigned long int pcre_uint32; typedef long int pcre_int32; #define PCRE_UINT32_MAX ULONG_MAX #define PCRE_INT32_MAX LONG_MAX #else #error Cannot determine a type for 32-bit integers #endif /* When checking for integer overflow in pcre_compile(), we need to handle large integers. If a 64-bit integer type is available, we can use that. Otherwise we have to cast to double, which of course requires floating point arithmetic. Handle this by defining a macro for the appropriate type. If stdint.h is available, include it; it may define INT64_MAX. Systems that do not have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set by "configure". */ #if defined HAVE_STDINT_H #include #elif defined HAVE_INTTYPES_H #include #endif #if defined INT64_MAX || defined int64_t #define INT64_OR_DOUBLE int64_t #else #define INT64_OR_DOUBLE double #endif /* All character handling must be done as unsigned characters. Otherwise there are problems with top-bit-set characters and functions such as isspace(). However, we leave the interface to the outside world as char * or short *, because that should make things easier for callers. This character type is called pcre_uchar. The IN_UCHARS macro multiply its argument with the byte size of the current pcre_uchar type. Useful for memcpy and such operations, whose require the byte size of their input/output buffers. The MAX_255 macro checks whether its pcre_uchar input is less than 256. The TABLE_GET macro is designed for accessing elements of tables whose contain exactly 256 items. When the character is able to contain more than 256 items, some check is needed before accessing these tables. */ #if defined COMPILE_PCRE8 typedef unsigned char pcre_uchar; #define IN_UCHARS(x) (x) #define MAX_255(c) 1 #define TABLE_GET(c, table, default) ((table)[c]) #elif defined COMPILE_PCRE16 #if USHRT_MAX != 65535 /* This is a warning message. Change PCRE_UCHAR16 to a 16 bit data type in pcre.h(.in) and disable (comment out) this message. */ #error Warning: PCRE_UCHAR16 is not a 16 bit data type. #endif typedef pcre_uint16 pcre_uchar; #define UCHAR_SHIFT (1) #define IN_UCHARS(x) ((x) * 2) #define MAX_255(c) ((c) <= 255u) #define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default)) #elif defined COMPILE_PCRE32 typedef pcre_uint32 pcre_uchar; #define UCHAR_SHIFT (2) #define IN_UCHARS(x) ((x) * 4) #define MAX_255(c) ((c) <= 255u) #define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default)) #else #error Unsupported compiling mode #endif /* COMPILE_PCRE[8|16|32] */ /* This is an unsigned int value that no character can ever have. UTF-8 characters only go up to 0x7fffffff (though Unicode doesn't go beyond 0x0010ffff). */ #define NOTACHAR 0xffffffff /* PCRE is able to support several different kinds of newline (CR, LF, CRLF, "any" and "anycrlf" at present). The following macros are used to package up testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various modules to indicate in which datablock the parameters exist, and what the start/end of string field names are. */ #define NLTYPE_FIXED 0 /* Newline is a fixed length string */ #define NLTYPE_ANY 1 /* Newline is any Unicode line ending */ #define NLTYPE_ANYCRLF 2 /* Newline is CR, LF, or CRLF */ /* This macro checks for a newline at the given position */ #define IS_NEWLINE(p) \ ((NLBLOCK->nltype != NLTYPE_FIXED)? \ ((p) < NLBLOCK->PSEND && \ PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \ &(NLBLOCK->nllen), utf)) \ : \ ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \ UCHAR21TEST(p) == NLBLOCK->nl[0] && \ (NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \ ) \ ) /* This macro checks for a newline immediately preceding the given position */ #define WAS_NEWLINE(p) \ ((NLBLOCK->nltype != NLTYPE_FIXED)? \ ((p) > NLBLOCK->PSSTART && \ PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \ &(NLBLOCK->nllen), utf)) \ : \ ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \ UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \ (NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \ ) \ ) /* When PCRE is compiled as a C++ library, the subject pointer can be replaced with a custom type. This makes it possible, for example, to allow pcre_exec() to process subject strings that are discontinuous by using a smart pointer class. It must always be possible to inspect all of the subject string in pcre_exec() because of the way it backtracks. Two macros are required in the normal case, for sign-unspecified and unsigned char pointers. The former is used for the external interface and appears in pcre.h, which is why its name must begin with PCRE_. */ #ifdef CUSTOM_SUBJECT_PTR #define PCRE_PUCHAR CUSTOM_SUBJECT_PTR #else #define PCRE_PUCHAR const pcre_uchar * #endif /* Include the public PCRE header and the definitions of UCP character property values. */ #include "pcre.h" #include "ucp.h" #ifdef COMPILE_PCRE32 /* Assert that the public PCRE_UCHAR32 is a 32-bit type */ typedef int __assert_pcre_uchar32_size[sizeof(PCRE_UCHAR32) == 4 ? 1 : -1]; #endif /* When compiling for use with the Virtual Pascal compiler, these functions need to have their names changed. PCRE must be compiled with the -DVPCOMPAT option on the command line. */ #ifdef VPCOMPAT #define strlen(s) _strlen(s) #define strncmp(s1,s2,m) _strncmp(s1,s2,m) #define memcmp(s,c,n) _memcmp(s,c,n) #define memcpy(d,s,n) _memcpy(d,s,n) #define memmove(d,s,n) _memmove(d,s,n) #define memset(s,c,n) _memset(s,c,n) #else /* VPCOMPAT */ /* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY is set. Otherwise, include an emulating function for those systems that have neither (there some non-Unix environments where this is the case). */ #ifndef HAVE_MEMMOVE #undef memmove /* some systems may have a macro */ #ifdef HAVE_BCOPY #define memmove(a, b, c) bcopy(b, a, c) #else /* HAVE_BCOPY */ static void * pcre_memmove(void *d, const void *s, size_t n) { size_t i; unsigned char *dest = (unsigned char *)d; const unsigned char *src = (const unsigned char *)s; if (dest > src) { dest += n; src += n; for (i = 0; i < n; ++i) *(--dest) = *(--src); return (void *)dest; } else { for (i = 0; i < n; ++i) *dest++ = *src++; return (void *)(dest - n); } } #define memmove(a, b, c) pcre_memmove(a, b, c) #endif /* not HAVE_BCOPY */ #endif /* not HAVE_MEMMOVE */ #endif /* not VPCOMPAT */ /* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored in big-endian order) by default. These are used, for example, to link from the start of a subpattern to its alternatives and its end. The use of 2 bytes per offset limits the size of the compiled regex to around 64K, which is big enough for almost everybody. However, I received a request for an even bigger limit. For this reason, and also to make the code easier to maintain, the storing and loading of offsets from the byte string is now handled by the macros that are defined here. The macros are controlled by the value of LINK_SIZE. This defaults to 2 in the config.h file, but can be overridden by using -D on the command line. This is automated on Unix systems via the "configure" command. */ #if defined COMPILE_PCRE8 #if LINK_SIZE == 2 #define PUT(a,n,d) \ (a[n] = (d) >> 8), \ (a[(n)+1] = (d) & 255) #define GET(a,n) \ (((a)[n] << 8) | (a)[(n)+1]) #define MAX_PATTERN_SIZE (1 << 16) #elif LINK_SIZE == 3 #define PUT(a,n,d) \ (a[n] = (d) >> 16), \ (a[(n)+1] = (d) >> 8), \ (a[(n)+2] = (d) & 255) #define GET(a,n) \ (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) #define MAX_PATTERN_SIZE (1 << 24) #elif LINK_SIZE == 4 #define PUT(a,n,d) \ (a[n] = (d) >> 24), \ (a[(n)+1] = (d) >> 16), \ (a[(n)+2] = (d) >> 8), \ (a[(n)+3] = (d) & 255) #define GET(a,n) \ (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) /* Keep it positive */ #define MAX_PATTERN_SIZE (1 << 30) #else #error LINK_SIZE must be either 2, 3, or 4 #endif #elif defined COMPILE_PCRE16 #if LINK_SIZE == 2 /* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */ #undef LINK_SIZE #define LINK_SIZE 1 #define PUT(a,n,d) \ (a[n] = (d)) #define GET(a,n) \ (a[n]) #define MAX_PATTERN_SIZE (1 << 16) #elif LINK_SIZE == 3 || LINK_SIZE == 4 /* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */ #undef LINK_SIZE #define LINK_SIZE 2 #define PUT(a,n,d) \ (a[n] = (d) >> 16), \ (a[(n)+1] = (d) & 65535) #define GET(a,n) \ (((a)[n] << 16) | (a)[(n)+1]) /* Keep it positive */ #define MAX_PATTERN_SIZE (1 << 30) #else #error LINK_SIZE must be either 2, 3, or 4 #endif #elif defined COMPILE_PCRE32 /* Only supported LINK_SIZE is 4 */ /* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */ #undef LINK_SIZE #define LINK_SIZE 1 #define PUT(a,n,d) \ (a[n] = (d)) #define GET(a,n) \ (a[n]) /* Keep it positive */ #define MAX_PATTERN_SIZE (1 << 30) #else #error Unsupported compiling mode #endif /* COMPILE_PCRE[8|16|32] */ /* Convenience macro defined in terms of the others */ #define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE /* PCRE uses some other 2-byte quantities that do not change when the size of offsets changes. There are used for repeat counts and for other things such as capturing parenthesis numbers in back references. */ #if defined COMPILE_PCRE8 #define IMM2_SIZE 2 #define PUT2(a,n,d) \ a[n] = (d) >> 8; \ a[(n)+1] = (d) & 255 /* For reasons that I do not understand, the expression in this GET2 macro is treated by gcc as a signed expression, even when a is declared as unsigned. It seems that any kind of arithmetic results in a signed value. */ #define GET2(a,n) \ (unsigned int)(((a)[n] << 8) | (a)[(n)+1]) #elif defined COMPILE_PCRE16 #define IMM2_SIZE 1 #define PUT2(a,n,d) \ a[n] = d #define GET2(a,n) \ a[n] #elif defined COMPILE_PCRE32 #define IMM2_SIZE 1 #define PUT2(a,n,d) \ a[n] = d #define GET2(a,n) \ a[n] #else #error Unsupported compiling mode #endif /* COMPILE_PCRE[8|16|32] */ #define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE /* The maximum length of a MARK name is currently one data unit; it may be changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */ #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #define MAX_MARK ((1u << 16) - 1) #else #define MAX_MARK ((1u << 8) - 1) #endif /* There is a proposed future special "UTF-21" mode, in which only the lowest 21 bits of a 32-bit character are interpreted as UTF, with the remaining 11 high-order bits available to the application for other uses. In preparation for the future implementation of this mode, there are macros that load a data item and, if in this special mode, mask it to 21 bits. These macros all have names starting with UCHAR21. In all other modes, including the normal 32-bit library, the macros all have the same simple definitions. When the new mode is implemented, it is expected that these definitions will be varied appropriately using #ifdef when compiling the library that supports the special mode. */ #define UCHAR21(eptr) (*(eptr)) #define UCHAR21TEST(eptr) (*(eptr)) #define UCHAR21INC(eptr) (*(eptr)++) #define UCHAR21INCTEST(eptr) (*(eptr)++) /* When UTF encoding is being used, a character is no longer just a single byte in 8-bit mode or a single short in 16-bit mode. The macros for character handling generate simple sequences when used in the basic mode, and more complicated ones for UTF characters. GETCHARLENTEST and other macros are not used when UTF is not supported. To make sure they can never even appear when UTF support is omitted, we don't even define them. */ #ifndef SUPPORT_UTF /* #define MAX_VALUE_FOR_SINGLE_CHAR */ /* #define HAS_EXTRALEN(c) */ /* #define GET_EXTRALEN(c) */ /* #define NOT_FIRSTCHAR(c) */ #define GETCHAR(c, eptr) c = *eptr; #define GETCHARTEST(c, eptr) c = *eptr; #define GETCHARINC(c, eptr) c = *eptr++; #define GETCHARINCTEST(c, eptr) c = *eptr++; #define GETCHARLEN(c, eptr, len) c = *eptr; /* #define GETCHARLENTEST(c, eptr, len) */ /* #define BACKCHAR(eptr) */ /* #define FORWARDCHAR(eptr) */ /* #define ACROSSCHAR(condition, eptr, action) */ #else /* SUPPORT_UTF */ /* Tests whether the code point needs extra characters to decode. */ #define HASUTF8EXTRALEN(c) ((c) >= 0xc0) /* Base macro to pick up the remaining bytes of a UTF-8 character, not advancing the pointer. */ #define GETUTF8(c, eptr) \ { \ if ((c & 0x20) == 0) \ c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \ else if ((c & 0x10) == 0) \ c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ else if ((c & 0x08) == 0) \ c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \ ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \ else if ((c & 0x04) == 0) \ c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \ ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \ (eptr[4] & 0x3f); \ else \ c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \ ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \ ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \ } /* Base macro to pick up the remaining bytes of a UTF-8 character, advancing the pointer. */ #define GETUTF8INC(c, eptr) \ { \ if ((c & 0x20) == 0) \ c = ((c & 0x1f) << 6) | (*eptr++ & 0x3f); \ else if ((c & 0x10) == 0) \ { \ c = ((c & 0x0f) << 12) | ((*eptr & 0x3f) << 6) | (eptr[1] & 0x3f); \ eptr += 2; \ } \ else if ((c & 0x08) == 0) \ { \ c = ((c & 0x07) << 18) | ((*eptr & 0x3f) << 12) | \ ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ eptr += 3; \ } \ else if ((c & 0x04) == 0) \ { \ c = ((c & 0x03) << 24) | ((*eptr & 0x3f) << 18) | \ ((eptr[1] & 0x3f) << 12) | ((eptr[2] & 0x3f) << 6) | \ (eptr[3] & 0x3f); \ eptr += 4; \ } \ else \ { \ c = ((c & 0x01) << 30) | ((*eptr & 0x3f) << 24) | \ ((eptr[1] & 0x3f) << 18) | ((eptr[2] & 0x3f) << 12) | \ ((eptr[3] & 0x3f) << 6) | (eptr[4] & 0x3f); \ eptr += 5; \ } \ } #if defined COMPILE_PCRE8 /* These macros were originally written in the form of loops that used data from the tables whose names start with PRIV(utf8_table). They were rewritten by a user so as not to use loops, because in some environments this gives a significant performance advantage, and it seems never to do any harm. */ /* Tells the biggest code point which can be encoded as a single character. */ #define MAX_VALUE_FOR_SINGLE_CHAR 127 /* Tests whether the code point needs extra characters to decode. */ #define HAS_EXTRALEN(c) ((c) >= 0xc0) /* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE. Otherwise it has an undefined behaviour. */ #define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3f]) /* Returns TRUE, if the given character is not the first character of a UTF sequence. */ #define NOT_FIRSTCHAR(c) (((c) & 0xc0) == 0x80) /* Get the next UTF-8 character, not advancing the pointer. This is called when we know we are in UTF-8 mode. */ #define GETCHAR(c, eptr) \ c = *eptr; \ if (c >= 0xc0) GETUTF8(c, eptr); /* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the pointer. */ #define GETCHARTEST(c, eptr) \ c = *eptr; \ if (utf && c >= 0xc0) GETUTF8(c, eptr); /* Get the next UTF-8 character, advancing the pointer. This is called when we know we are in UTF-8 mode. */ #define GETCHARINC(c, eptr) \ c = *eptr++; \ if (c >= 0xc0) GETUTF8INC(c, eptr); /* Get the next character, testing for UTF-8 mode, and advancing the pointer. This is called when we don't know if we are in UTF-8 mode. */ #define GETCHARINCTEST(c, eptr) \ c = *eptr++; \ if (utf && c >= 0xc0) GETUTF8INC(c, eptr); /* Base macro to pick up the remaining bytes of a UTF-8 character, not advancing the pointer, incrementing the length. */ #define GETUTF8LEN(c, eptr, len) \ { \ if ((c & 0x20) == 0) \ { \ c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \ len++; \ } \ else if ((c & 0x10) == 0) \ { \ c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ len += 2; \ } \ else if ((c & 0x08) == 0) \ {\ c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \ ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \ len += 3; \ } \ else if ((c & 0x04) == 0) \ { \ c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \ ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \ (eptr[4] & 0x3f); \ len += 4; \ } \ else \ {\ c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \ ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \ ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \ len += 5; \ } \ } /* Get the next UTF-8 character, not advancing the pointer, incrementing length if there are extra bytes. This is called when we know we are in UTF-8 mode. */ #define GETCHARLEN(c, eptr, len) \ c = *eptr; \ if (c >= 0xc0) GETUTF8LEN(c, eptr, len); /* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the pointer, incrementing length if there are extra bytes. This is called when we do not know if we are in UTF-8 mode. */ #define GETCHARLENTEST(c, eptr, len) \ c = *eptr; \ if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len); /* If the pointer is not at the start of a character, move it back until it is. This is called only in UTF-8 mode - we don't put a test within the macro because almost all calls are already within a block of UTF-8 only code. */ #define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr-- /* Same as above, just in the other direction. */ #define FORWARDCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr++ /* Same as above, but it allows a fully customizable form. */ #define ACROSSCHAR(condition, eptr, action) \ while((condition) && ((eptr) & 0xc0) == 0x80) action #elif defined COMPILE_PCRE16 /* Tells the biggest code point which can be encoded as a single character. */ #define MAX_VALUE_FOR_SINGLE_CHAR 65535 /* Tests whether the code point needs extra characters to decode. */ #define HAS_EXTRALEN(c) (((c) & 0xfc00) == 0xd800) /* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE. Otherwise it has an undefined behaviour. */ #define GET_EXTRALEN(c) 1 /* Returns TRUE, if the given character is not the first character of a UTF sequence. */ #define NOT_FIRSTCHAR(c) (((c) & 0xfc00) == 0xdc00) /* Base macro to pick up the low surrogate of a UTF-16 character, not advancing the pointer. */ #define GETUTF16(c, eptr) \ { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; } /* Get the next UTF-16 character, not advancing the pointer. This is called when we know we are in UTF-16 mode. */ #define GETCHAR(c, eptr) \ c = *eptr; \ if ((c & 0xfc00) == 0xd800) GETUTF16(c, eptr); /* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the pointer. */ #define GETCHARTEST(c, eptr) \ c = *eptr; \ if (utf && (c & 0xfc00) == 0xd800) GETUTF16(c, eptr); /* Base macro to pick up the low surrogate of a UTF-16 character, advancing the pointer. */ #define GETUTF16INC(c, eptr) \ { c = (((c & 0x3ff) << 10) | (*eptr++ & 0x3ff)) + 0x10000; } /* Get the next UTF-16 character, advancing the pointer. This is called when we know we are in UTF-16 mode. */ #define GETCHARINC(c, eptr) \ c = *eptr++; \ if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr); /* Get the next character, testing for UTF-16 mode, and advancing the pointer. This is called when we don't know if we are in UTF-16 mode. */ #define GETCHARINCTEST(c, eptr) \ c = *eptr++; \ if (utf && (c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr); /* Base macro to pick up the low surrogate of a UTF-16 character, not advancing the pointer, incrementing the length. */ #define GETUTF16LEN(c, eptr, len) \ { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; len++; } /* Get the next UTF-16 character, not advancing the pointer, incrementing length if there is a low surrogate. This is called when we know we are in UTF-16 mode. */ #define GETCHARLEN(c, eptr, len) \ c = *eptr; \ if ((c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len); /* Get the next UTF-816character, testing for UTF-16 mode, not advancing the pointer, incrementing length if there is a low surrogate. This is called when we do not know if we are in UTF-16 mode. */ #define GETCHARLENTEST(c, eptr, len) \ c = *eptr; \ if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len); /* If the pointer is not at the start of a character, move it back until it is. This is called only in UTF-16 mode - we don't put a test within the macro because almost all calls are already within a block of UTF-16 only code. */ #define BACKCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr-- /* Same as above, just in the other direction. */ #define FORWARDCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr++ /* Same as above, but it allows a fully customizable form. */ #define ACROSSCHAR(condition, eptr, action) \ if ((condition) && ((eptr) & 0xfc00) == 0xdc00) action #elif defined COMPILE_PCRE32 /* These are trivial for the 32-bit library, since all UTF-32 characters fit into one pcre_uchar unit. */ #define MAX_VALUE_FOR_SINGLE_CHAR (0x10ffffu) #define HAS_EXTRALEN(c) (0) #define GET_EXTRALEN(c) (0) #define NOT_FIRSTCHAR(c) (0) /* Get the next UTF-32 character, not advancing the pointer. This is called when we know we are in UTF-32 mode. */ #define GETCHAR(c, eptr) \ c = *(eptr); /* Get the next UTF-32 character, testing for UTF-32 mode, and not advancing the pointer. */ #define GETCHARTEST(c, eptr) \ c = *(eptr); /* Get the next UTF-32 character, advancing the pointer. This is called when we know we are in UTF-32 mode. */ #define GETCHARINC(c, eptr) \ c = *((eptr)++); /* Get the next character, testing for UTF-32 mode, and advancing the pointer. This is called when we don't know if we are in UTF-32 mode. */ #define GETCHARINCTEST(c, eptr) \ c = *((eptr)++); /* Get the next UTF-32 character, not advancing the pointer, not incrementing length (since all UTF-32 is of length 1). This is called when we know we are in UTF-32 mode. */ #define GETCHARLEN(c, eptr, len) \ GETCHAR(c, eptr) /* Get the next UTF-32character, testing for UTF-32 mode, not advancing the pointer, not incrementing the length (since all UTF-32 is of length 1). This is called when we do not know if we are in UTF-32 mode. */ #define GETCHARLENTEST(c, eptr, len) \ GETCHARTEST(c, eptr) /* If the pointer is not at the start of a character, move it back until it is. This is called only in UTF-32 mode - we don't put a test within the macro because almost all calls are already within a block of UTF-32 only code. These are all no-ops since all UTF-32 characters fit into one pcre_uchar. */ #define BACKCHAR(eptr) do { } while (0) /* Same as above, just in the other direction. */ #define FORWARDCHAR(eptr) do { } while (0) /* Same as above, but it allows a fully customizable form. */ #define ACROSSCHAR(condition, eptr, action) do { } while (0) #else #error Unsupported compiling mode #endif /* COMPILE_PCRE[8|16|32] */ #endif /* SUPPORT_UTF */ /* Tests for Unicode horizontal and vertical whitespace characters must check a number of different values. Using a switch statement for this generates the fastest code (no loop, no memory access), and there are several places in the interpreter code where this happens. In order to ensure that all the case lists remain in step, we use macros so that there is only one place where the lists are defined. These values are also required as lists in pcre_compile.c when processing \h, \H, \v and \V in a character class. The lists are defined in pcre_tables.c, but macros that define the values are here so that all the definitions are together. The lists must be in ascending character order, terminated by NOTACHAR (which is 0xffffffff). Any changes should ensure that the various macros are kept in step with each other. NOTE: The values also appear in pcre_jit_compile.c. */ /* ------ ASCII/Unicode environments ------ */ #ifndef EBCDIC #define HSPACE_LIST \ CHAR_HT, CHAR_SPACE, CHAR_NBSP, \ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \ NOTACHAR #define HSPACE_MULTIBYTE_CASES \ case 0x1680: /* OGHAM SPACE MARK */ \ case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ \ case 0x2000: /* EN QUAD */ \ case 0x2001: /* EM QUAD */ \ case 0x2002: /* EN SPACE */ \ case 0x2003: /* EM SPACE */ \ case 0x2004: /* THREE-PER-EM SPACE */ \ case 0x2005: /* FOUR-PER-EM SPACE */ \ case 0x2006: /* SIX-PER-EM SPACE */ \ case 0x2007: /* FIGURE SPACE */ \ case 0x2008: /* PUNCTUATION SPACE */ \ case 0x2009: /* THIN SPACE */ \ case 0x200A: /* HAIR SPACE */ \ case 0x202f: /* NARROW NO-BREAK SPACE */ \ case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ \ case 0x3000 /* IDEOGRAPHIC SPACE */ #define HSPACE_BYTE_CASES \ case CHAR_HT: \ case CHAR_SPACE: \ case CHAR_NBSP #define HSPACE_CASES \ HSPACE_BYTE_CASES: \ HSPACE_MULTIBYTE_CASES #define VSPACE_LIST \ CHAR_LF, CHAR_VT, CHAR_FF, CHAR_CR, CHAR_NEL, 0x2028, 0x2029, NOTACHAR #define VSPACE_MULTIBYTE_CASES \ case 0x2028: /* LINE SEPARATOR */ \ case 0x2029 /* PARAGRAPH SEPARATOR */ #define VSPACE_BYTE_CASES \ case CHAR_LF: \ case CHAR_VT: \ case CHAR_FF: \ case CHAR_CR: \ case CHAR_NEL #define VSPACE_CASES \ VSPACE_BYTE_CASES: \ VSPACE_MULTIBYTE_CASES /* ------ EBCDIC environments ------ */ #else #define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR #define HSPACE_BYTE_CASES \ case CHAR_HT: \ case CHAR_SPACE: \ case CHAR_NBSP #define HSPACE_CASES HSPACE_BYTE_CASES #ifdef EBCDIC_NL25 #define VSPACE_LIST \ CHAR_VT, CHAR_FF, CHAR_CR, CHAR_NEL, CHAR_LF, NOTACHAR #else #define VSPACE_LIST \ CHAR_VT, CHAR_FF, CHAR_CR, CHAR_LF, CHAR_NEL, NOTACHAR #endif #define VSPACE_BYTE_CASES \ case CHAR_LF: \ case CHAR_VT: \ case CHAR_FF: \ case CHAR_CR: \ case CHAR_NEL #define VSPACE_CASES VSPACE_BYTE_CASES #endif /* EBCDIC */ /* ------ End of whitespace macros ------ */ /* Private flags containing information about the compiled regex. They used to live at the top end of the options word, but that got almost full, so they were moved to a 16-bit flags word - which got almost full, so now they are in a 32-bit flags word. From release 8.00, PCRE_NOPARTIAL is unused, as the restrictions on partial matching have been lifted. It remains for backwards compatibility. */ #define PCRE_MODE8 0x00000001 /* compiled in 8 bit mode */ #define PCRE_MODE16 0x00000002 /* compiled in 16 bit mode */ #define PCRE_MODE32 0x00000004 /* compiled in 32 bit mode */ #define PCRE_FIRSTSET 0x00000010 /* first_char is set */ #define PCRE_FCH_CASELESS 0x00000020 /* caseless first char */ #define PCRE_REQCHSET 0x00000040 /* req_byte is set */ #define PCRE_RCH_CASELESS 0x00000080 /* caseless requested char */ #define PCRE_STARTLINE 0x00000100 /* start after \n for multiline */ #define PCRE_NOPARTIAL 0x00000200 /* can't use partial with this regex */ #define PCRE_JCHANGED 0x00000400 /* j option used in regex */ #define PCRE_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */ #define PCRE_HASTHEN 0x00001000 /* pattern contains (*THEN) */ #define PCRE_MLSET 0x00002000 /* match limit set by regex */ #define PCRE_RLSET 0x00004000 /* recursion limit set by regex */ #define PCRE_MATCH_EMPTY 0x00008000 /* pattern can match empty string */ #if defined COMPILE_PCRE8 #define PCRE_MODE PCRE_MODE8 #elif defined COMPILE_PCRE16 #define PCRE_MODE PCRE_MODE16 #elif defined COMPILE_PCRE32 #define PCRE_MODE PCRE_MODE32 #endif #define PCRE_MODE_MASK (PCRE_MODE8 | PCRE_MODE16 | PCRE_MODE32) /* Flags for the "extra" block produced by pcre_study(). */ #define PCRE_STUDY_MAPPED 0x0001 /* a map of starting chars exists */ #define PCRE_STUDY_MINLEN 0x0002 /* a minimum length field exists */ /* Masks for identifying the public options that are permitted at compile time, run time, or study time, respectively. */ #define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \ PCRE_NEWLINE_ANYCRLF) #define PUBLIC_COMPILE_OPTIONS \ (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ PCRE_NO_AUTO_CAPTURE|PCRE_NO_AUTO_POSSESS| \ PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \ PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \ PCRE_JAVASCRIPT_COMPAT|PCRE_UCP|PCRE_NO_START_OPTIMIZE|PCRE_NEVER_UTF) #define PUBLIC_EXEC_OPTIONS \ (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \ PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_NEWLINE_BITS| \ PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE|PCRE_NO_START_OPTIMIZE) #define PUBLIC_DFA_EXEC_OPTIONS \ (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \ PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_SHORTEST| \ PCRE_DFA_RESTART|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \ PCRE_NO_START_OPTIMIZE) #define PUBLIC_STUDY_OPTIONS \ (PCRE_STUDY_JIT_COMPILE|PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE| \ PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE|PCRE_STUDY_EXTRA_NEEDED) #define PUBLIC_JIT_EXEC_OPTIONS \ (PCRE_NO_UTF8_CHECK|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|\ PCRE_NOTEMPTY_ATSTART|PCRE_PARTIAL_SOFT|PCRE_PARTIAL_HARD) /* Magic number to provide a small check against being handed junk. */ #define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ /* This variable is used to detect a loaded regular expression in different endianness. */ #define REVERSED_MAGIC_NUMBER 0x45524350UL /* 'ERCP' */ /* The maximum remaining length of subject we are prepared to search for a req_byte match. */ #define REQ_BYTE_MAX 1000 /* Miscellaneous definitions. The #ifndef is to pacify compiler warnings in environments where these macros are defined elsewhere. Unfortunately, there is no way to do the same for the typedef. */ typedef int BOOL; #ifndef FALSE #define FALSE 0 #define TRUE 1 #endif /* If PCRE is to support UTF-8 on EBCDIC platforms, we cannot use normal character constants like '*' because the compiler would emit their EBCDIC code, which is different from their ASCII/UTF-8 code. Instead we define macros for the characters so that they always use the ASCII/UTF-8 code when UTF-8 support is enabled. When UTF-8 support is not enabled, the definitions use character literals. Both character and string versions of each character are needed, and there are some longer strings as well. This means that, on EBCDIC platforms, the PCRE library can handle either EBCDIC, or UTF-8, but not both. To support both in the same compiled library would need different lookups depending on whether PCRE_UTF8 was set or not. This would make it impossible to use characters in switch/case statements, which would reduce performance. For a theoretical use (which nobody has asked for) in a minority area (EBCDIC platforms), this is not sensible. Any application that did need both could compile two versions of the library, using macros to give the functions distinct names. */ #ifndef SUPPORT_UTF /* UTF-8 support is not enabled; use the platform-dependent character literals so that PCRE works in both ASCII and EBCDIC environments, but only in non-UTF mode. Newline characters are problematic in EBCDIC. Though it has CR and LF characters, a common practice has been to use its NL (0x15) character as the line terminator in C-like processing environments. However, sometimes the LF (0x25) character is used instead, according to this Unicode document: http://unicode.org/standard/reports/tr13/tr13-5.html PCRE defaults EBCDIC NL to 0x15, but has a build-time option to select 0x25 instead. Whichever is *not* chosen is defined as NEL. In both ASCII and EBCDIC environments, CHAR_NL and CHAR_LF are synonyms for the same code point. */ #ifdef EBCDIC #ifndef EBCDIC_NL25 #define CHAR_NL '\x15' #define CHAR_NEL '\x25' #define STR_NL "\x15" #define STR_NEL "\x25" #else #define CHAR_NL '\x25' #define CHAR_NEL '\x15' #define STR_NL "\x25" #define STR_NEL "\x15" #endif #define CHAR_LF CHAR_NL #define STR_LF STR_NL #define CHAR_ESC '\047' #define CHAR_DEL '\007' #define CHAR_NBSP '\x41' #define STR_ESC "\047" #define STR_DEL "\007" #else /* Not EBCDIC */ /* In ASCII/Unicode, linefeed is '\n' and we equate this to NL for compatibility. NEL is the Unicode newline character; make sure it is a positive value. */ #define CHAR_LF '\n' #define CHAR_NL CHAR_LF #define CHAR_NEL ((unsigned char)'\x85') #define CHAR_ESC '\033' #define CHAR_DEL '\177' #define CHAR_NBSP ((unsigned char)'\xa0') #define STR_LF "\n" #define STR_NL STR_LF #define STR_NEL "\x85" #define STR_ESC "\033" #define STR_DEL "\177" #endif /* EBCDIC */ /* The remaining definitions work in both environments. */ #define CHAR_NULL '\0' #define CHAR_HT '\t' #define CHAR_VT '\v' #define CHAR_FF '\f' #define CHAR_CR '\r' #define CHAR_BS '\b' #define CHAR_BEL '\a' #define CHAR_SPACE ' ' #define CHAR_EXCLAMATION_MARK '!' #define CHAR_QUOTATION_MARK '"' #define CHAR_NUMBER_SIGN '#' #define CHAR_DOLLAR_SIGN '$' #define CHAR_PERCENT_SIGN '%' #define CHAR_AMPERSAND '&' #define CHAR_APOSTROPHE '\'' #define CHAR_LEFT_PARENTHESIS '(' #define CHAR_RIGHT_PARENTHESIS ')' #define CHAR_ASTERISK '*' #define CHAR_PLUS '+' #define CHAR_COMMA ',' #define CHAR_MINUS '-' #define CHAR_DOT '.' #define CHAR_SLASH '/' #define CHAR_0 '0' #define CHAR_1 '1' #define CHAR_2 '2' #define CHAR_3 '3' #define CHAR_4 '4' #define CHAR_5 '5' #define CHAR_6 '6' #define CHAR_7 '7' #define CHAR_8 '8' #define CHAR_9 '9' #define CHAR_COLON ':' #define CHAR_SEMICOLON ';' #define CHAR_LESS_THAN_SIGN '<' #define CHAR_EQUALS_SIGN '=' #define CHAR_GREATER_THAN_SIGN '>' #define CHAR_QUESTION_MARK '?' #define CHAR_COMMERCIAL_AT '@' #define CHAR_A 'A' #define CHAR_B 'B' #define CHAR_C 'C' #define CHAR_D 'D' #define CHAR_E 'E' #define CHAR_F 'F' #define CHAR_G 'G' #define CHAR_H 'H' #define CHAR_I 'I' #define CHAR_J 'J' #define CHAR_K 'K' #define CHAR_L 'L' #define CHAR_M 'M' #define CHAR_N 'N' #define CHAR_O 'O' #define CHAR_P 'P' #define CHAR_Q 'Q' #define CHAR_R 'R' #define CHAR_S 'S' #define CHAR_T 'T' #define CHAR_U 'U' #define CHAR_V 'V' #define CHAR_W 'W' #define CHAR_X 'X' #define CHAR_Y 'Y' #define CHAR_Z 'Z' #define CHAR_LEFT_SQUARE_BRACKET '[' #define CHAR_BACKSLASH '\\' #define CHAR_RIGHT_SQUARE_BRACKET ']' #define CHAR_CIRCUMFLEX_ACCENT '^' #define CHAR_UNDERSCORE '_' #define CHAR_GRAVE_ACCENT '`' #define CHAR_a 'a' #define CHAR_b 'b' #define CHAR_c 'c' #define CHAR_d 'd' #define CHAR_e 'e' #define CHAR_f 'f' #define CHAR_g 'g' #define CHAR_h 'h' #define CHAR_i 'i' #define CHAR_j 'j' #define CHAR_k 'k' #define CHAR_l 'l' #define CHAR_m 'm' #define CHAR_n 'n' #define CHAR_o 'o' #define CHAR_p 'p' #define CHAR_q 'q' #define CHAR_r 'r' #define CHAR_s 's' #define CHAR_t 't' #define CHAR_u 'u' #define CHAR_v 'v' #define CHAR_w 'w' #define CHAR_x 'x' #define CHAR_y 'y' #define CHAR_z 'z' #define CHAR_LEFT_CURLY_BRACKET '{' #define CHAR_VERTICAL_LINE '|' #define CHAR_RIGHT_CURLY_BRACKET '}' #define CHAR_TILDE '~' #define STR_HT "\t" #define STR_VT "\v" #define STR_FF "\f" #define STR_CR "\r" #define STR_BS "\b" #define STR_BEL "\a" #define STR_SPACE " " #define STR_EXCLAMATION_MARK "!" #define STR_QUOTATION_MARK "\"" #define STR_NUMBER_SIGN "#" #define STR_DOLLAR_SIGN "$" #define STR_PERCENT_SIGN "%" #define STR_AMPERSAND "&" #define STR_APOSTROPHE "'" #define STR_LEFT_PARENTHESIS "(" #define STR_RIGHT_PARENTHESIS ")" #define STR_ASTERISK "*" #define STR_PLUS "+" #define STR_COMMA "," #define STR_MINUS "-" #define STR_DOT "." #define STR_SLASH "/" #define STR_0 "0" #define STR_1 "1" #define STR_2 "2" #define STR_3 "3" #define STR_4 "4" #define STR_5 "5" #define STR_6 "6" #define STR_7 "7" #define STR_8 "8" #define STR_9 "9" #define STR_COLON ":" #define STR_SEMICOLON ";" #define STR_LESS_THAN_SIGN "<" #define STR_EQUALS_SIGN "=" #define STR_GREATER_THAN_SIGN ">" #define STR_QUESTION_MARK "?" #define STR_COMMERCIAL_AT "@" #define STR_A "A" #define STR_B "B" #define STR_C "C" #define STR_D "D" #define STR_E "E" #define STR_F "F" #define STR_G "G" #define STR_H "H" #define STR_I "I" #define STR_J "J" #define STR_K "K" #define STR_L "L" #define STR_M "M" #define STR_N "N" #define STR_O "O" #define STR_P "P" #define STR_Q "Q" #define STR_R "R" #define STR_S "S" #define STR_T "T" #define STR_U "U" #define STR_V "V" #define STR_W "W" #define STR_X "X" #define STR_Y "Y" #define STR_Z "Z" #define STR_LEFT_SQUARE_BRACKET "[" #define STR_BACKSLASH "\\" #define STR_RIGHT_SQUARE_BRACKET "]" #define STR_CIRCUMFLEX_ACCENT "^" #define STR_UNDERSCORE "_" #define STR_GRAVE_ACCENT "`" #define STR_a "a" #define STR_b "b" #define STR_c "c" #define STR_d "d" #define STR_e "e" #define STR_f "f" #define STR_g "g" #define STR_h "h" #define STR_i "i" #define STR_j "j" #define STR_k "k" #define STR_l "l" #define STR_m "m" #define STR_n "n" #define STR_o "o" #define STR_p "p" #define STR_q "q" #define STR_r "r" #define STR_s "s" #define STR_t "t" #define STR_u "u" #define STR_v "v" #define STR_w "w" #define STR_x "x" #define STR_y "y" #define STR_z "z" #define STR_LEFT_CURLY_BRACKET "{" #define STR_VERTICAL_LINE "|" #define STR_RIGHT_CURLY_BRACKET "}" #define STR_TILDE "~" #define STRING_ACCEPT0 "ACCEPT\0" #define STRING_COMMIT0 "COMMIT\0" #define STRING_F0 "F\0" #define STRING_FAIL0 "FAIL\0" #define STRING_MARK0 "MARK\0" #define STRING_PRUNE0 "PRUNE\0" #define STRING_SKIP0 "SKIP\0" #define STRING_THEN "THEN" #define STRING_alpha0 "alpha\0" #define STRING_lower0 "lower\0" #define STRING_upper0 "upper\0" #define STRING_alnum0 "alnum\0" #define STRING_ascii0 "ascii\0" #define STRING_blank0 "blank\0" #define STRING_cntrl0 "cntrl\0" #define STRING_digit0 "digit\0" #define STRING_graph0 "graph\0" #define STRING_print0 "print\0" #define STRING_punct0 "punct\0" #define STRING_space0 "space\0" #define STRING_word0 "word\0" #define STRING_xdigit "xdigit" #define STRING_DEFINE "DEFINE" #define STRING_WEIRD_STARTWORD "[:<:]]" #define STRING_WEIRD_ENDWORD "[:>:]]" #define STRING_CR_RIGHTPAR "CR)" #define STRING_LF_RIGHTPAR "LF)" #define STRING_CRLF_RIGHTPAR "CRLF)" #define STRING_ANY_RIGHTPAR "ANY)" #define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)" #define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)" #define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)" #define STRING_UTF8_RIGHTPAR "UTF8)" #define STRING_UTF16_RIGHTPAR "UTF16)" #define STRING_UTF32_RIGHTPAR "UTF32)" #define STRING_UTF_RIGHTPAR "UTF)" #define STRING_UCP_RIGHTPAR "UCP)" #define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)" #define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)" #define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH=" #define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION=" #else /* SUPPORT_UTF */ /* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode only. */ #define CHAR_HT '\011' #define CHAR_VT '\013' #define CHAR_FF '\014' #define CHAR_CR '\015' #define CHAR_LF '\012' #define CHAR_NL CHAR_LF #define CHAR_NEL ((unsigned char)'\x85') #define CHAR_BS '\010' #define CHAR_BEL '\007' #define CHAR_ESC '\033' #define CHAR_DEL '\177' #define CHAR_NULL '\0' #define CHAR_SPACE '\040' #define CHAR_EXCLAMATION_MARK '\041' #define CHAR_QUOTATION_MARK '\042' #define CHAR_NUMBER_SIGN '\043' #define CHAR_DOLLAR_SIGN '\044' #define CHAR_PERCENT_SIGN '\045' #define CHAR_AMPERSAND '\046' #define CHAR_APOSTROPHE '\047' #define CHAR_LEFT_PARENTHESIS '\050' #define CHAR_RIGHT_PARENTHESIS '\051' #define CHAR_ASTERISK '\052' #define CHAR_PLUS '\053' #define CHAR_COMMA '\054' #define CHAR_MINUS '\055' #define CHAR_DOT '\056' #define CHAR_SLASH '\057' #define CHAR_0 '\060' #define CHAR_1 '\061' #define CHAR_2 '\062' #define CHAR_3 '\063' #define CHAR_4 '\064' #define CHAR_5 '\065' #define CHAR_6 '\066' #define CHAR_7 '\067' #define CHAR_8 '\070' #define CHAR_9 '\071' #define CHAR_COLON '\072' #define CHAR_SEMICOLON '\073' #define CHAR_LESS_THAN_SIGN '\074' #define CHAR_EQUALS_SIGN '\075' #define CHAR_GREATER_THAN_SIGN '\076' #define CHAR_QUESTION_MARK '\077' #define CHAR_COMMERCIAL_AT '\100' #define CHAR_A '\101' #define CHAR_B '\102' #define CHAR_C '\103' #define CHAR_D '\104' #define CHAR_E '\105' #define CHAR_F '\106' #define CHAR_G '\107' #define CHAR_H '\110' #define CHAR_I '\111' #define CHAR_J '\112' #define CHAR_K '\113' #define CHAR_L '\114' #define CHAR_M '\115' #define CHAR_N '\116' #define CHAR_O '\117' #define CHAR_P '\120' #define CHAR_Q '\121' #define CHAR_R '\122' #define CHAR_S '\123' #define CHAR_T '\124' #define CHAR_U '\125' #define CHAR_V '\126' #define CHAR_W '\127' #define CHAR_X '\130' #define CHAR_Y '\131' #define CHAR_Z '\132' #define CHAR_LEFT_SQUARE_BRACKET '\133' #define CHAR_BACKSLASH '\134' #define CHAR_RIGHT_SQUARE_BRACKET '\135' #define CHAR_CIRCUMFLEX_ACCENT '\136' #define CHAR_UNDERSCORE '\137' #define CHAR_GRAVE_ACCENT '\140' #define CHAR_a '\141' #define CHAR_b '\142' #define CHAR_c '\143' #define CHAR_d '\144' #define CHAR_e '\145' #define CHAR_f '\146' #define CHAR_g '\147' #define CHAR_h '\150' #define CHAR_i '\151' #define CHAR_j '\152' #define CHAR_k '\153' #define CHAR_l '\154' #define CHAR_m '\155' #define CHAR_n '\156' #define CHAR_o '\157' #define CHAR_p '\160' #define CHAR_q '\161' #define CHAR_r '\162' #define CHAR_s '\163' #define CHAR_t '\164' #define CHAR_u '\165' #define CHAR_v '\166' #define CHAR_w '\167' #define CHAR_x '\170' #define CHAR_y '\171' #define CHAR_z '\172' #define CHAR_LEFT_CURLY_BRACKET '\173' #define CHAR_VERTICAL_LINE '\174' #define CHAR_RIGHT_CURLY_BRACKET '\175' #define CHAR_TILDE '\176' #define CHAR_NBSP ((unsigned char)'\xa0') #define STR_HT "\011" #define STR_VT "\013" #define STR_FF "\014" #define STR_CR "\015" #define STR_NL "\012" #define STR_BS "\010" #define STR_BEL "\007" #define STR_ESC "\033" #define STR_DEL "\177" #define STR_SPACE "\040" #define STR_EXCLAMATION_MARK "\041" #define STR_QUOTATION_MARK "\042" #define STR_NUMBER_SIGN "\043" #define STR_DOLLAR_SIGN "\044" #define STR_PERCENT_SIGN "\045" #define STR_AMPERSAND "\046" #define STR_APOSTROPHE "\047" #define STR_LEFT_PARENTHESIS "\050" #define STR_RIGHT_PARENTHESIS "\051" #define STR_ASTERISK "\052" #define STR_PLUS "\053" #define STR_COMMA "\054" #define STR_MINUS "\055" #define STR_DOT "\056" #define STR_SLASH "\057" #define STR_0 "\060" #define STR_1 "\061" #define STR_2 "\062" #define STR_3 "\063" #define STR_4 "\064" #define STR_5 "\065" #define STR_6 "\066" #define STR_7 "\067" #define STR_8 "\070" #define STR_9 "\071" #define STR_COLON "\072" #define STR_SEMICOLON "\073" #define STR_LESS_THAN_SIGN "\074" #define STR_EQUALS_SIGN "\075" #define STR_GREATER_THAN_SIGN "\076" #define STR_QUESTION_MARK "\077" #define STR_COMMERCIAL_AT "\100" #define STR_A "\101" #define STR_B "\102" #define STR_C "\103" #define STR_D "\104" #define STR_E "\105" #define STR_F "\106" #define STR_G "\107" #define STR_H "\110" #define STR_I "\111" #define STR_J "\112" #define STR_K "\113" #define STR_L "\114" #define STR_M "\115" #define STR_N "\116" #define STR_O "\117" #define STR_P "\120" #define STR_Q "\121" #define STR_R "\122" #define STR_S "\123" #define STR_T "\124" #define STR_U "\125" #define STR_V "\126" #define STR_W "\127" #define STR_X "\130" #define STR_Y "\131" #define STR_Z "\132" #define STR_LEFT_SQUARE_BRACKET "\133" #define STR_BACKSLASH "\134" #define STR_RIGHT_SQUARE_BRACKET "\135" #define STR_CIRCUMFLEX_ACCENT "\136" #define STR_UNDERSCORE "\137" #define STR_GRAVE_ACCENT "\140" #define STR_a "\141" #define STR_b "\142" #define STR_c "\143" #define STR_d "\144" #define STR_e "\145" #define STR_f "\146" #define STR_g "\147" #define STR_h "\150" #define STR_i "\151" #define STR_j "\152" #define STR_k "\153" #define STR_l "\154" #define STR_m "\155" #define STR_n "\156" #define STR_o "\157" #define STR_p "\160" #define STR_q "\161" #define STR_r "\162" #define STR_s "\163" #define STR_t "\164" #define STR_u "\165" #define STR_v "\166" #define STR_w "\167" #define STR_x "\170" #define STR_y "\171" #define STR_z "\172" #define STR_LEFT_CURLY_BRACKET "\173" #define STR_VERTICAL_LINE "\174" #define STR_RIGHT_CURLY_BRACKET "\175" #define STR_TILDE "\176" #define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0" #define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0" #define STRING_F0 STR_F "\0" #define STRING_FAIL0 STR_F STR_A STR_I STR_L "\0" #define STRING_MARK0 STR_M STR_A STR_R STR_K "\0" #define STRING_PRUNE0 STR_P STR_R STR_U STR_N STR_E "\0" #define STRING_SKIP0 STR_S STR_K STR_I STR_P "\0" #define STRING_THEN STR_T STR_H STR_E STR_N #define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0" #define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0" #define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0" #define STRING_alnum0 STR_a STR_l STR_n STR_u STR_m "\0" #define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0" #define STRING_blank0 STR_b STR_l STR_a STR_n STR_k "\0" #define STRING_cntrl0 STR_c STR_n STR_t STR_r STR_l "\0" #define STRING_digit0 STR_d STR_i STR_g STR_i STR_t "\0" #define STRING_graph0 STR_g STR_r STR_a STR_p STR_h "\0" #define STRING_print0 STR_p STR_r STR_i STR_n STR_t "\0" #define STRING_punct0 STR_p STR_u STR_n STR_c STR_t "\0" #define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0" #define STRING_word0 STR_w STR_o STR_r STR_d "\0" #define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t #define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E #define STRING_WEIRD_STARTWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_LESS_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET #define STRING_WEIRD_ENDWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_GREATER_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET #define STRING_CR_RIGHTPAR STR_C STR_R STR_RIGHT_PARENTHESIS #define STRING_LF_RIGHTPAR STR_L STR_F STR_RIGHT_PARENTHESIS #define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS #define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS #define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS #define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS #define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS #define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS #define STRING_UTF16_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS #define STRING_UTF32_RIGHTPAR STR_U STR_T STR_F STR_3 STR_2 STR_RIGHT_PARENTHESIS #define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_RIGHT_PARENTHESIS #define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS #define STRING_NO_AUTO_POSSESS_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_A STR_U STR_T STR_O STR_UNDERSCORE STR_P STR_O STR_S STR_S STR_E STR_S STR_S STR_RIGHT_PARENTHESIS #define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS #define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN #define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN #endif /* SUPPORT_UTF */ /* Escape items that are just an encoding of a particular data value. */ #ifndef ESC_a #define ESC_a CHAR_BEL #endif #ifndef ESC_e #define ESC_e CHAR_ESC #endif #ifndef ESC_f #define ESC_f CHAR_FF #endif #ifndef ESC_n #define ESC_n CHAR_LF #endif #ifndef ESC_r #define ESC_r CHAR_CR #endif /* We can't officially use ESC_t because it is a POSIX reserved identifier (presumably because of all the others like size_t). */ #ifndef ESC_tee #define ESC_tee CHAR_HT #endif /* Codes for different types of Unicode property */ #define PT_ANY 0 /* Any property - matches all chars */ #define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */ #define PT_GC 2 /* Specified general characteristic (e.g. L) */ #define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */ #define PT_SC 4 /* Script (e.g. Han) */ #define PT_ALNUM 5 /* Alphanumeric - the union of L and N */ #define PT_SPACE 6 /* Perl space - Z plus 9,10,12,13 */ #define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */ #define PT_WORD 8 /* Word - L plus N plus underscore */ #define PT_CLIST 9 /* Pseudo-property: match character list */ #define PT_UCNC 10 /* Universal Character nameable character */ #define PT_TABSIZE 11 /* Size of square table for autopossessify tests */ /* The following special properties are used only in XCLASS items, when POSIX classes are specified and PCRE_UCP is set - in other words, for Unicode handling of these classes. They are not available via the \p or \P escapes like those in the above list, and so they do not take part in the autopossessifying table. */ #define PT_PXGRAPH 11 /* [:graph:] - characters that mark the paper */ #define PT_PXPRINT 12 /* [:print:] - [:graph:] plus non-control spaces */ #define PT_PXPUNCT 13 /* [:punct:] - punctuation characters */ /* Flag bits and data types for the extended class (OP_XCLASS) for classes that contain characters with values greater than 255. */ #define XCL_NOT 0x01 /* Flag: this is a negative class */ #define XCL_MAP 0x02 /* Flag: a 32-byte map is present */ #define XCL_HASPROP 0x04 /* Flag: property checks are present. */ #define XCL_END 0 /* Marks end of individual items */ #define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ #define XCL_RANGE 2 /* A range (two multibyte chars) follows */ #define XCL_PROP 3 /* Unicode property (2-byte property code follows) */ #define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ /* These are escaped items that aren't just an encoding of a particular data value such as \n. They must have non-zero values, as check_escape() returns 0 for a data character. Also, they must appear in the same order as in the opcode definitions below, up to ESC_z. There's a dummy for OP_ALLANY because it corresponds to "." in DOTALL mode rather than an escape sequence. It is also used for [^] in JavaScript compatibility mode, and for \C in non-utf mode. In non-DOTALL mode, "." behaves like \N. The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc. when PCRE_UCP is set and replacement of \d etc by \p sequences is required. They must be contiguous, and remain in order so that the replacements can be looked up from a table. Negative numbers are used to encode a backreference (\1, \2, \3, etc.) in check_escape(). There are two tests in the code for an escape greater than ESC_b and less than ESC_Z to detect the types that may be repeated. These are the types that consume characters. If any new escapes are put in between that don't consume a character, that code will have to change. */ enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H, ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z, ESC_E, ESC_Q, ESC_g, ESC_k, ESC_DU, ESC_du, ESC_SU, ESC_su, ESC_WU, ESC_wu }; /********************** Opcode definitions ******************/ /****** NOTE NOTE NOTE ****** Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in order to the list of escapes immediately above. Furthermore, values up to OP_DOLLM must not be changed without adjusting the table called autoposstab in pcre_compile.c Whenever this list is updated, the two macro definitions that follow must be updated to match. The possessification table called "opcode_possessify" in pcre_compile.c must also be updated, and also the tables called "coptable" and "poptable" in pcre_dfa_exec.c. ****** NOTE NOTE NOTE ******/ /* The values between FIRST_AUTOTAB_OP and LAST_AUTOTAB_RIGHT_OP, inclusive, are used in a table for deciding whether a repeated character type can be auto-possessified. */ #define FIRST_AUTOTAB_OP OP_NOT_DIGIT #define LAST_AUTOTAB_LEFT_OP OP_EXTUNI #define LAST_AUTOTAB_RIGHT_OP OP_DOLLM enum { OP_END, /* 0 End of pattern */ /* Values corresponding to backslashed metacharacters */ OP_SOD, /* 1 Start of data: \A */ OP_SOM, /* 2 Start of match (subject + offset): \G */ OP_SET_SOM, /* 3 Set start of match (\K) */ OP_NOT_WORD_BOUNDARY, /* 4 \B */ OP_WORD_BOUNDARY, /* 5 \b */ OP_NOT_DIGIT, /* 6 \D */ OP_DIGIT, /* 7 \d */ OP_NOT_WHITESPACE, /* 8 \S */ OP_WHITESPACE, /* 9 \s */ OP_NOT_WORDCHAR, /* 10 \W */ OP_WORDCHAR, /* 11 \w */ OP_ANY, /* 12 Match any character except newline (\N) */ OP_ALLANY, /* 13 Match any character */ OP_ANYBYTE, /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */ OP_NOTPROP, /* 15 \P (not Unicode property) */ OP_PROP, /* 16 \p (Unicode property) */ OP_ANYNL, /* 17 \R (any newline sequence) */ OP_NOT_HSPACE, /* 18 \H (not horizontal whitespace) */ OP_HSPACE, /* 19 \h (horizontal whitespace) */ OP_NOT_VSPACE, /* 20 \V (not vertical whitespace) */ OP_VSPACE, /* 21 \v (vertical whitespace) */ OP_EXTUNI, /* 22 \X (extended Unicode sequence */ OP_EODN, /* 23 End of data or \n at end of data (\Z) */ OP_EOD, /* 24 End of data (\z) */ /* Line end assertions */ OP_DOLL, /* 25 End of line - not multiline */ OP_DOLLM, /* 26 End of line - multiline */ OP_CIRC, /* 27 Start of line - not multiline */ OP_CIRCM, /* 28 Start of line - multiline */ /* Single characters; caseful must precede the caseless ones */ OP_CHAR, /* 29 Match one character, casefully */ OP_CHARI, /* 30 Match one character, caselessly */ OP_NOT, /* 31 Match one character, not the given one, casefully */ OP_NOTI, /* 32 Match one character, not the given one, caselessly */ /* The following sets of 13 opcodes must always be kept in step because the offset from the first one is used to generate the others. */ /* Repeated characters; caseful must precede the caseless ones */ OP_STAR, /* 33 The maximizing and minimizing versions of */ OP_MINSTAR, /* 34 these six opcodes must come in pairs, with */ OP_PLUS, /* 35 the minimizing one second. */ OP_MINPLUS, /* 36 */ OP_QUERY, /* 37 */ OP_MINQUERY, /* 38 */ OP_UPTO, /* 39 From 0 to n matches of one character, caseful*/ OP_MINUPTO, /* 40 */ OP_EXACT, /* 41 Exactly n matches */ OP_POSSTAR, /* 42 Possessified star, caseful */ OP_POSPLUS, /* 43 Possessified plus, caseful */ OP_POSQUERY, /* 44 Posesssified query, caseful */ OP_POSUPTO, /* 45 Possessified upto, caseful */ /* Repeated characters; caseless must follow the caseful ones */ OP_STARI, /* 46 */ OP_MINSTARI, /* 47 */ OP_PLUSI, /* 48 */ OP_MINPLUSI, /* 49 */ OP_QUERYI, /* 50 */ OP_MINQUERYI, /* 51 */ OP_UPTOI, /* 52 From 0 to n matches of one character, caseless */ OP_MINUPTOI, /* 53 */ OP_EXACTI, /* 54 */ OP_POSSTARI, /* 55 Possessified star, caseless */ OP_POSPLUSI, /* 56 Possessified plus, caseless */ OP_POSQUERYI, /* 57 Posesssified query, caseless */ OP_POSUPTOI, /* 58 Possessified upto, caseless */ /* The negated ones must follow the non-negated ones, and match them */ /* Negated repeated character, caseful; must precede the caseless ones */ OP_NOTSTAR, /* 59 The maximizing and minimizing versions of */ OP_NOTMINSTAR, /* 60 these six opcodes must come in pairs, with */ OP_NOTPLUS, /* 61 the minimizing one second. They must be in */ OP_NOTMINPLUS, /* 62 exactly the same order as those above. */ OP_NOTQUERY, /* 63 */ OP_NOTMINQUERY, /* 64 */ OP_NOTUPTO, /* 65 From 0 to n matches, caseful */ OP_NOTMINUPTO, /* 66 */ OP_NOTEXACT, /* 67 Exactly n matches */ OP_NOTPOSSTAR, /* 68 Possessified versions, caseful */ OP_NOTPOSPLUS, /* 69 */ OP_NOTPOSQUERY, /* 70 */ OP_NOTPOSUPTO, /* 71 */ /* Negated repeated character, caseless; must follow the caseful ones */ OP_NOTSTARI, /* 72 */ OP_NOTMINSTARI, /* 73 */ OP_NOTPLUSI, /* 74 */ OP_NOTMINPLUSI, /* 75 */ OP_NOTQUERYI, /* 76 */ OP_NOTMINQUERYI, /* 77 */ OP_NOTUPTOI, /* 78 From 0 to n matches, caseless */ OP_NOTMINUPTOI, /* 79 */ OP_NOTEXACTI, /* 80 Exactly n matches */ OP_NOTPOSSTARI, /* 81 Possessified versions, caseless */ OP_NOTPOSPLUSI, /* 82 */ OP_NOTPOSQUERYI, /* 83 */ OP_NOTPOSUPTOI, /* 84 */ /* Character types */ OP_TYPESTAR, /* 85 The maximizing and minimizing versions of */ OP_TYPEMINSTAR, /* 86 these six opcodes must come in pairs, with */ OP_TYPEPLUS, /* 87 the minimizing one second. These codes must */ OP_TYPEMINPLUS, /* 88 be in exactly the same order as those above. */ OP_TYPEQUERY, /* 89 */ OP_TYPEMINQUERY, /* 90 */ OP_TYPEUPTO, /* 91 From 0 to n matches */ OP_TYPEMINUPTO, /* 92 */ OP_TYPEEXACT, /* 93 Exactly n matches */ OP_TYPEPOSSTAR, /* 94 Possessified versions */ OP_TYPEPOSPLUS, /* 95 */ OP_TYPEPOSQUERY, /* 96 */ OP_TYPEPOSUPTO, /* 97 */ /* These are used for character classes and back references; only the first six are the same as the sets above. */ OP_CRSTAR, /* 98 The maximizing and minimizing versions of */ OP_CRMINSTAR, /* 99 all these opcodes must come in pairs, with */ OP_CRPLUS, /* 100 the minimizing one second. These codes must */ OP_CRMINPLUS, /* 101 be in exactly the same order as those above. */ OP_CRQUERY, /* 102 */ OP_CRMINQUERY, /* 103 */ OP_CRRANGE, /* 104 These are different to the three sets above. */ OP_CRMINRANGE, /* 105 */ OP_CRPOSSTAR, /* 106 Possessified versions */ OP_CRPOSPLUS, /* 107 */ OP_CRPOSQUERY, /* 108 */ OP_CRPOSRANGE, /* 109 */ /* End of quantifier opcodes */ OP_CLASS, /* 110 Match a character class, chars < 256 only */ OP_NCLASS, /* 111 Same, but the bitmap was created from a negative class - the difference is relevant only when a character > 255 is encountered. */ OP_XCLASS, /* 112 Extended class for handling > 255 chars within the class. This does both positive and negative. */ OP_REF, /* 113 Match a back reference, casefully */ OP_REFI, /* 114 Match a back reference, caselessly */ OP_DNREF, /* 115 Match a duplicate name backref, casefully */ OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */ OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */ OP_CALLOUT, /* 118 Call out to external function if provided */ OP_ALT, /* 119 Start of alternation */ OP_KET, /* 120 End of group that doesn't have an unbounded repeat */ OP_KETRMAX, /* 121 These two must remain together and in this */ OP_KETRMIN, /* 122 order. They are for groups the repeat for ever. */ OP_KETRPOS, /* 123 Possessive unlimited repeat. */ /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four asserts must remain in order. */ OP_REVERSE, /* 124 Move pointer back - used in lookbehind assertions */ OP_ASSERT, /* 125 Positive lookahead */ OP_ASSERT_NOT, /* 126 Negative lookahead */ OP_ASSERTBACK, /* 127 Positive lookbehind */ OP_ASSERTBACK_NOT, /* 128 Negative lookbehind */ /* ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately after the assertions, with ONCE first, as there's a test for >= ONCE for a subpattern that isn't an assertion. The POS versions must immediately follow the non-POS versions in each case. */ OP_ONCE, /* 129 Atomic group, contains captures */ OP_ONCE_NC, /* 130 Atomic group containing no captures */ OP_BRA, /* 131 Start of non-capturing bracket */ OP_BRAPOS, /* 132 Ditto, with unlimited, possessive repeat */ OP_CBRA, /* 133 Start of capturing bracket */ OP_CBRAPOS, /* 134 Ditto, with unlimited, possessive repeat */ OP_COND, /* 135 Conditional group */ /* These five must follow the previous five, in the same order. There's a check for >= SBRA to distinguish the two sets. */ OP_SBRA, /* 136 Start of non-capturing bracket, check empty */ OP_SBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */ OP_SCBRA, /* 138 Start of capturing bracket, check empty */ OP_SCBRAPOS, /* 139 Ditto, with unlimited, possessive repeat */ OP_SCOND, /* 140 Conditional group, check empty */ /* The next two pairs must (respectively) be kept together. */ OP_CREF, /* 141 Used to hold a capture number as condition */ OP_DNCREF, /* 142 Used to point to duplicate names as a condition */ OP_RREF, /* 143 Used to hold a recursion number as condition */ OP_DNRREF, /* 144 Used to point to duplicate names as a condition */ OP_DEF, /* 145 The DEFINE condition */ OP_BRAZERO, /* 146 These two must remain together and in this */ OP_BRAMINZERO, /* 147 order. */ OP_BRAPOSZERO, /* 148 */ /* These are backtracking control verbs */ OP_MARK, /* 149 always has an argument */ OP_PRUNE, /* 150 */ OP_PRUNE_ARG, /* 151 same, but with argument */ OP_SKIP, /* 152 */ OP_SKIP_ARG, /* 153 same, but with argument */ OP_THEN, /* 154 */ OP_THEN_ARG, /* 155 same, but with argument */ OP_COMMIT, /* 156 */ /* These are forced failure and success verbs */ OP_FAIL, /* 157 */ OP_ACCEPT, /* 158 */ OP_ASSERT_ACCEPT, /* 159 Used inside assertions */ OP_CLOSE, /* 160 Used before OP_ACCEPT to close open captures */ /* This is used to skip a subpattern with a {0} quantifier */ OP_SKIPZERO, /* 161 */ /* This is not an opcode, but is used to check that tables indexed by opcode are the correct length, in order to catch updating errors - there have been some in the past. */ OP_TABLE_LENGTH }; /* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro definitions that follow must also be updated to match. There are also tables called "opcode_possessify" in pcre_compile.c and "coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */ /* This macro defines textual names for all the opcodes. These are used only for debugging, and some of them are only partial names. The macro is referenced only in pcre_printint.c, which fills out the full names in many cases (and in some cases doesn't actually use these names at all). */ #define OP_NAME_LIST \ "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \ "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte", \ "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \ "extuni", "\\Z", "\\z", \ "$", "$", "^", "^", "char", "chari", "not", "noti", \ "*", "*?", "+", "+?", "?", "??", \ "{", "{", "{", \ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", \ "{", "{", "{", \ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", \ "{", "{", "{", \ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", \ "{", "{", "{", \ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ "*+","++", "?+", "{", \ "*", "*?", "+", "+?", "?", "??", "{", "{", \ "*+","++", "?+", "{", \ "class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \ "Recurse", "Callout", \ "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \ "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \ "Once", "Once_NC", \ "Bra", "BraPos", "CBra", "CBraPos", \ "Cond", \ "SBra", "SBraPos", "SCBra", "SCBraPos", \ "SCond", \ "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", "Cond def", \ "Brazero", "Braminzero", "Braposzero", \ "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \ "*THEN", "*THEN", "*COMMIT", "*FAIL", \ "*ACCEPT", "*ASSERT_ACCEPT", \ "Close", "Skip zero" /* This macro defines the length of fixed length operations in the compiled regex. The lengths are used when searching for specific things, and also in the debugging printing of a compiled regex. We use a macro so that it can be defined close to the definitions of the opcodes themselves. As things have been extended, some of these are no longer fixed lenths, but are minima instead. For example, the length of a single-character repeat may vary in UTF-8 mode. The code that uses this table must know about such things. */ #define OP_LENGTHS \ 1, /* End */ \ 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \ 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \ 1, 1, 1, /* Any, AllAny, Anybyte */ \ 3, 3, /* \P, \p */ \ 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \ 1, /* \X */ \ 1, 1, 1, 1, 1, 1, /* \Z, \z, $, $M ^, ^M */ \ 2, /* Char - the minimum length */ \ 2, /* Chari - the minimum length */ \ 2, /* not */ \ 2, /* noti */ \ /* Positive single-char repeats ** These are */ \ 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto, minupto ** mode */ \ 2+IMM2_SIZE, /* exact */ \ 2, 2, 2, 2+IMM2_SIZE, /* *+, ++, ?+, upto+ */ \ 2, 2, 2, 2, 2, 2, /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8 */ \ 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto I, minupto I */ \ 2+IMM2_SIZE, /* exact I */ \ 2, 2, 2, 2+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ \ /* Negative single-char repeats - only for chars < 256 */ \ 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto, minupto */ \ 2+IMM2_SIZE, /* NOT exact */ \ 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *, +, ?, upto */ \ 2, 2, 2, 2, 2, 2, /* NOT *I, *?I, +I, +?I, ?I, ??I */ \ 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto I, minupto I */ \ 2+IMM2_SIZE, /* NOT exact I */ \ 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *I, +I, ?I, upto I */ \ /* Positive type repeats */ \ 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ 2+IMM2_SIZE, 2+IMM2_SIZE, /* Type upto, minupto */ \ 2+IMM2_SIZE, /* Type exact */ \ 2, 2, 2, 2+IMM2_SIZE, /* Possessive *+, ++, ?+, upto+ */ \ /* Character class & ref repeats */ \ 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ 1+2*IMM2_SIZE, 1+2*IMM2_SIZE, /* CRRANGE, CRMINRANGE */ \ 1, 1, 1, 1+2*IMM2_SIZE, /* Possessive *+, ++, ?+, CRPOSRANGE */ \ 1+(32/sizeof(pcre_uchar)), /* CLASS */ \ 1+(32/sizeof(pcre_uchar)), /* NCLASS */ \ 0, /* XCLASS - variable length */ \ 1+IMM2_SIZE, /* REF */ \ 1+IMM2_SIZE, /* REFI */ \ 1+2*IMM2_SIZE, /* DNREF */ \ 1+2*IMM2_SIZE, /* DNREFI */ \ 1+LINK_SIZE, /* RECURSE */ \ 2+2*LINK_SIZE, /* CALLOUT */ \ 1+LINK_SIZE, /* Alt */ \ 1+LINK_SIZE, /* Ket */ \ 1+LINK_SIZE, /* KetRmax */ \ 1+LINK_SIZE, /* KetRmin */ \ 1+LINK_SIZE, /* KetRpos */ \ 1+LINK_SIZE, /* Reverse */ \ 1+LINK_SIZE, /* Assert */ \ 1+LINK_SIZE, /* Assert not */ \ 1+LINK_SIZE, /* Assert behind */ \ 1+LINK_SIZE, /* Assert behind not */ \ 1+LINK_SIZE, /* ONCE */ \ 1+LINK_SIZE, /* ONCE_NC */ \ 1+LINK_SIZE, /* BRA */ \ 1+LINK_SIZE, /* BRAPOS */ \ 1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \ 1+LINK_SIZE+IMM2_SIZE, /* CBRAPOS */ \ 1+LINK_SIZE, /* COND */ \ 1+LINK_SIZE, /* SBRA */ \ 1+LINK_SIZE, /* SBRAPOS */ \ 1+LINK_SIZE+IMM2_SIZE, /* SCBRA */ \ 1+LINK_SIZE+IMM2_SIZE, /* SCBRAPOS */ \ 1+LINK_SIZE, /* SCOND */ \ 1+IMM2_SIZE, 1+2*IMM2_SIZE, /* CREF, DNCREF */ \ 1+IMM2_SIZE, 1+2*IMM2_SIZE, /* RREF, DNRREF */ \ 1, /* DEF */ \ 1, 1, 1, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ \ 3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \ 1, 3, /* SKIP, SKIP_ARG */ \ 1, 3, /* THEN, THEN_ARG */ \ 1, 1, 1, 1, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ \ 1+IMM2_SIZE, 1 /* CLOSE, SKIPZERO */ /* A magic value for OP_RREF to indicate the "any recursion" condition. */ #define RREF_ANY 0xffff /* Compile time error code numbers. They are given names so that they can more easily be tracked. When a new number is added, the table called eint in pcreposix.c must be updated. */ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERRCOUNT }; /* JIT compiling modes. The function list is indexed by them. */ enum { JIT_COMPILE, JIT_PARTIAL_SOFT_COMPILE, JIT_PARTIAL_HARD_COMPILE, JIT_NUMBER_OF_COMPILE_MODES }; /* The real format of the start of the pcre block; the index of names and the code vector run on as long as necessary after the end. We store an explicit offset to the name table so that if a regex is compiled on one host, saved, and then run on another where the size of pointers is different, all might still be well. The size of the structure must be a multiple of 8 bytes. For the case of compiled-on-4 and run-on-8, we include an extra pointer that is always NULL so that there are an even number of pointers which therefore are a multiple of 8 bytes. It is necessary to fork the struct for the 32 bit library, since it needs to use pcre_uint32 for first_char and req_char. We can't put an ifdef inside the typedef because pcretest needs access to the struct of the 8-, 16- and 32-bit variants. *** WARNING *** When new fields are added to these structures, remember to adjust the code in pcre_byte_order.c that is concerned with swapping the byte order of the fields when a compiled regex is reloaded on a host with different endianness. *** WARNING *** There is also similar byte-flipping code in pcretest.c, which is used for testing the byte-flipping features. It must also be kept in step. *** WARNING *** */ typedef struct real_pcre8_or_16 { pcre_uint32 magic_number; pcre_uint32 size; /* Total that was malloced */ pcre_uint32 options; /* Public options */ pcre_uint32 flags; /* Private flags */ pcre_uint32 limit_match; /* Limit set from regex */ pcre_uint32 limit_recursion; /* Limit set from regex */ pcre_uint16 first_char; /* Starting character */ pcre_uint16 req_char; /* This character must be seen */ pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */ pcre_uint16 top_bracket; /* Highest numbered group */ pcre_uint16 top_backref; /* Highest numbered back reference */ pcre_uint16 name_table_offset; /* Offset to name table that follows */ pcre_uint16 name_entry_size; /* Size of any name items */ pcre_uint16 name_count; /* Number of name items */ pcre_uint16 ref_count; /* Reference count */ pcre_uint16 dummy1; /* To ensure size is a multiple of 8 */ pcre_uint16 dummy2; /* To ensure size is a multiple of 8 */ pcre_uint16 dummy3; /* To ensure size is a multiple of 8 */ const pcre_uint8 *tables; /* Pointer to tables or NULL for std */ void *nullpad; /* NULL padding */ } real_pcre8_or_16; typedef struct real_pcre8_or_16 real_pcre; typedef struct real_pcre8_or_16 real_pcre16; typedef struct real_pcre32 { pcre_uint32 magic_number; pcre_uint32 size; /* Total that was malloced */ pcre_uint32 options; /* Public options */ pcre_uint32 flags; /* Private flags */ pcre_uint32 limit_match; /* Limit set from regex */ pcre_uint32 limit_recursion; /* Limit set from regex */ pcre_uint32 first_char; /* Starting character */ pcre_uint32 req_char; /* This character must be seen */ pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */ pcre_uint16 top_bracket; /* Highest numbered group */ pcre_uint16 top_backref; /* Highest numbered back reference */ pcre_uint16 name_table_offset; /* Offset to name table that follows */ pcre_uint16 name_entry_size; /* Size of any name items */ pcre_uint16 name_count; /* Number of name items */ pcre_uint16 ref_count; /* Reference count */ pcre_uint16 dummy; /* To ensure size is a multiple of 8 */ const pcre_uint8 *tables; /* Pointer to tables or NULL for std */ void *nullpad; /* NULL padding */ } real_pcre32; #if defined COMPILE_PCRE8 #define REAL_PCRE real_pcre #elif defined COMPILE_PCRE16 #define REAL_PCRE real_pcre16 #elif defined COMPILE_PCRE32 #define REAL_PCRE real_pcre32 #endif /* Assert that the size of REAL_PCRE is divisible by 8 */ typedef int __assert_real_pcre_size_divisible_8[(sizeof(REAL_PCRE) % 8) == 0 ? 1 : -1]; /* Needed in pcretest to access some fields in the real_pcre* structures * directly. They're unified for 8/16/32 bits since the structs only differ * after these fields; if that ever changes, need to fork those defines into * 8/16 and 32 bit versions. */ #define REAL_PCRE_MAGIC(re) (((REAL_PCRE*)re)->magic_number) #define REAL_PCRE_SIZE(re) (((REAL_PCRE*)re)->size) #define REAL_PCRE_OPTIONS(re) (((REAL_PCRE*)re)->options) #define REAL_PCRE_FLAGS(re) (((REAL_PCRE*)re)->flags) /* The format of the block used to store data from pcre_study(). The same remark (see NOTE above) about extending this structure applies. */ typedef struct pcre_study_data { pcre_uint32 size; /* Total that was malloced */ pcre_uint32 flags; /* Private flags */ pcre_uint8 start_bits[32]; /* Starting char bits */ pcre_uint32 minlength; /* Minimum subject length */ } pcre_study_data; /* Structure for building a chain of open capturing subpatterns during compiling, so that instructions to close them can be compiled when (*ACCEPT) is encountered. This is also used to identify subpatterns that contain recursive back references to themselves, so that they can be made atomic. */ typedef struct open_capitem { struct open_capitem *next; /* Chain link */ pcre_uint16 number; /* Capture number */ pcre_uint16 flag; /* Set TRUE if recursive back ref */ } open_capitem; /* Structure for building a list of named groups during the first pass of compiling. */ typedef struct named_group { const pcre_uchar *name; /* Points to the name in the pattern */ int length; /* Length of the name */ pcre_uint32 number; /* Group number */ } named_group; /* Structure for passing "static" information around between the functions doing the compiling, so that they are thread-safe. */ typedef struct compile_data { const pcre_uint8 *lcc; /* Points to lower casing table */ const pcre_uint8 *fcc; /* Points to case-flipping table */ const pcre_uint8 *cbits; /* Points to character type table */ const pcre_uint8 *ctypes; /* Points to table of type maps */ const pcre_uchar *start_workspace;/* The start of working space */ const pcre_uchar *start_code; /* The start of the compiled code */ const pcre_uchar *start_pattern; /* The start of the pattern */ const pcre_uchar *end_pattern; /* The end of the pattern */ pcre_uchar *hwm; /* High watermark of workspace */ open_capitem *open_caps; /* Chain of open capture items */ named_group *named_groups; /* Points to vector in pre-compile */ pcre_uchar *name_table; /* The name/number table */ int names_found; /* Number of entries so far */ int name_entry_size; /* Size of each entry */ int named_group_list_size; /* Number of entries in the list */ int workspace_size; /* Size of workspace */ unsigned int bracount; /* Count of capturing parens as we compile */ int final_bracount; /* Saved value after first pass */ int max_lookbehind; /* Maximum lookbehind (characters) */ int top_backref; /* Maximum back reference */ unsigned int backref_map; /* Bitmap of low back refs */ unsigned int namedrefcount; /* Number of backreferences by name */ int parens_depth; /* Depth of nested parentheses */ int assert_depth; /* Depth of nested assertions */ pcre_uint32 external_options; /* External (initial) options */ pcre_uint32 external_flags; /* External flag bits to be set */ int req_varyopt; /* "After variable item" flag for reqbyte */ BOOL had_accept; /* (*ACCEPT) encountered */ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL check_lookbehind; /* Lookbehinds need later checking */ BOOL dupnames; /* Duplicate names exist */ BOOL dupgroups; /* Duplicate groups exist: (?| found */ BOOL iscondassert; /* Next assert is a condition */ int nltype; /* Newline type */ int nllen; /* Newline string length */ pcre_uchar nl[4]; /* Newline string when fixed length */ } compile_data; /* Structure for maintaining a chain of pointers to the currently incomplete branches, for testing for left recursion while compiling. */ typedef struct branch_chain { struct branch_chain *outer; pcre_uchar *current_branch; } branch_chain; /* Structure for mutual recursion detection. */ typedef struct recurse_check { struct recurse_check *prev; const pcre_uchar *group; } recurse_check; /* Structure for items in a linked list that represents an explicit recursive call within the pattern; used by pcre_exec(). */ typedef struct recursion_info { struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ unsigned int group_num; /* Number of group that was called */ int *offset_save; /* Pointer to start of saved offsets */ int saved_max; /* Number of saved offsets */ int saved_capture_last; /* Last capture number */ PCRE_PUCHAR subject_position; /* Position at start of recursion */ } recursion_info; /* A similar structure for pcre_dfa_exec(). */ typedef struct dfa_recursion_info { struct dfa_recursion_info *prevrec; int group_num; PCRE_PUCHAR subject_position; } dfa_recursion_info; /* Structure for building a chain of data for holding the values of the subject pointer at the start of each subpattern, so as to detect when an empty string has been matched by a subpattern - to break infinite loops; used by pcre_exec(). */ typedef struct eptrblock { struct eptrblock *epb_prev; PCRE_PUCHAR epb_saved_eptr; } eptrblock; /* Structure for passing "static" information around between the functions doing traditional NFA matching, so that they are thread-safe. */ typedef struct match_data { unsigned long int match_call_count; /* As it says */ unsigned long int match_limit; /* As it says */ unsigned long int match_limit_recursion; /* As it says */ int *offset_vector; /* Offset vector */ int offset_end; /* One past the end */ int offset_max; /* The maximum usable for return data */ int nltype; /* Newline type */ int nllen; /* Newline string length */ int name_count; /* Number of names in name table */ int name_entry_size; /* Size of entry in names table */ unsigned int skip_arg_count; /* For counting SKIP_ARGs */ unsigned int ignore_skip_arg; /* For re-run when SKIP arg name not found */ pcre_uchar *name_table; /* Table of names */ pcre_uchar nl[4]; /* Newline string when fixed */ const pcre_uint8 *lcc; /* Points to lower casing table */ const pcre_uint8 *fcc; /* Points to case-flipping table */ const pcre_uint8 *ctypes; /* Points to table of type maps */ BOOL notbol; /* NOTBOL flag */ BOOL noteol; /* NOTEOL flag */ BOOL utf; /* UTF-8 / UTF-16 flag */ BOOL jscript_compat; /* JAVASCRIPT_COMPAT flag */ BOOL use_ucp; /* PCRE_UCP flag */ BOOL endonly; /* Dollar not before final \n */ BOOL notempty; /* Empty string match not wanted */ BOOL notempty_atstart; /* Empty string match at start not wanted */ BOOL hitend; /* Hit the end of the subject at some point */ BOOL bsr_anycrlf; /* \R is just any CRLF, not full Unicode */ BOOL hasthen; /* Pattern contains (*THEN) */ const pcre_uchar *start_code; /* For use when recursing */ PCRE_PUCHAR start_subject; /* Start of the subject string */ PCRE_PUCHAR end_subject; /* End of the subject string */ PCRE_PUCHAR start_match_ptr; /* Start of matched string */ PCRE_PUCHAR end_match_ptr; /* Subject position at end match */ PCRE_PUCHAR start_used_ptr; /* Earliest consulted character */ int partial; /* PARTIAL options */ int end_offset_top; /* Highwater mark at end of match */ pcre_int32 capture_last; /* Most recent capture number + overflow flag */ int start_offset; /* The start offset value */ int match_function_type; /* Set for certain special calls of MATCH() */ eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */ int eptrn; /* Next free eptrblock */ recursion_info *recursive; /* Linked list of recursion data */ void *callout_data; /* To pass back to callouts */ const pcre_uchar *mark; /* Mark pointer to pass back on success */ const pcre_uchar *nomatch_mark;/* Mark pointer to pass back on failure */ const pcre_uchar *once_target; /* Where to back up to for atomic groups */ #ifdef NO_RECURSE void *match_frames_base; /* For remembering malloc'd frames */ #endif } match_data; /* A similar structure is used for the same purpose by the DFA matching functions. */ typedef struct dfa_match_data { const pcre_uchar *start_code; /* Start of the compiled pattern */ const pcre_uchar *start_subject ; /* Start of the subject string */ const pcre_uchar *end_subject; /* End of subject string */ const pcre_uchar *start_used_ptr; /* Earliest consulted character */ const pcre_uint8 *tables; /* Character tables */ int start_offset; /* The start offset value */ int moptions; /* Match options */ int poptions; /* Pattern options */ int nltype; /* Newline type */ int nllen; /* Newline string length */ pcre_uchar nl[4]; /* Newline string when fixed */ void *callout_data; /* To pass back to callouts */ dfa_recursion_info *recursive; /* Linked list of recursion data */ } dfa_match_data; /* Bit definitions for entries in the pcre_ctypes table. */ #define ctype_space 0x01 #define ctype_letter 0x02 #define ctype_digit 0x04 #define ctype_xdigit 0x08 #define ctype_word 0x10 /* alphanumeric or '_' */ #define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ /* Offsets for the bitmap tables in pcre_cbits. Each table contains a set of bits for a class map. Some classes are built by combining these tables. */ #define cbit_space 0 /* [:space:] or \s */ #define cbit_xdigit 32 /* [:xdigit:] */ #define cbit_digit 64 /* [:digit:] or \d */ #define cbit_upper 96 /* [:upper:] */ #define cbit_lower 128 /* [:lower:] */ #define cbit_word 160 /* [:word:] or \w */ #define cbit_graph 192 /* [:graph:] */ #define cbit_print 224 /* [:print:] */ #define cbit_punct 256 /* [:punct:] */ #define cbit_cntrl 288 /* [:cntrl:] */ #define cbit_length 320 /* Length of the cbits table */ /* Offsets of the various tables from the base tables pointer, and total length. */ #define lcc_offset 0 #define fcc_offset 256 #define cbits_offset 512 #define ctypes_offset (cbits_offset + cbit_length) #define tables_length (ctypes_offset + 256) /* Internal function and data prefixes. */ #if defined COMPILE_PCRE8 #ifndef PUBL #define PUBL(name) pcre_##name #endif #ifndef PRIV #define PRIV(name) _pcre_##name #endif #elif defined COMPILE_PCRE16 #ifndef PUBL #define PUBL(name) pcre16_##name #endif #ifndef PRIV #define PRIV(name) _pcre16_##name #endif #elif defined COMPILE_PCRE32 #ifndef PUBL #define PUBL(name) pcre32_##name #endif #ifndef PRIV #define PRIV(name) _pcre32_##name #endif #else #error Unsupported compiling mode #endif /* COMPILE_PCRE[8|16|32] */ /* Layout of the UCP type table that translates property names into types and codes. Each entry used to point directly to a name, but to reduce the number of relocations in shared libraries, it now has an offset into a single string instead. */ typedef struct { pcre_uint16 name_offset; pcre_uint16 type; pcre_uint16 value; } ucp_type_table; /* Internal shared data tables. These are tables that are used by more than one of the exported public functions. They have to be "external" in the C sense, but are not part of the PCRE public API. The data for these tables is in the pcre_tables.c module. */ #ifdef COMPILE_PCRE8 extern const int PRIV(utf8_table1)[]; extern const int PRIV(utf8_table1_size); extern const int PRIV(utf8_table2)[]; extern const int PRIV(utf8_table3)[]; extern const pcre_uint8 PRIV(utf8_table4)[]; #endif /* COMPILE_PCRE8 */ extern const char PRIV(utt_names)[]; extern const ucp_type_table PRIV(utt)[]; extern const int PRIV(utt_size); extern const pcre_uint8 PRIV(OP_lengths)[]; extern const pcre_uint8 PRIV(default_tables)[]; extern const pcre_uint32 PRIV(hspace_list)[]; extern const pcre_uint32 PRIV(vspace_list)[]; /* Internal shared functions. These are functions that are used by more than one of the exported public functions. They have to be "external" in the C sense, but are not part of the PCRE public API. */ /* String comparison functions. */ #if defined COMPILE_PCRE8 #define STRCMP_UC_UC(str1, str2) \ strcmp((char *)(str1), (char *)(str2)) #define STRCMP_UC_C8(str1, str2) \ strcmp((char *)(str1), (str2)) #define STRNCMP_UC_UC(str1, str2, num) \ strncmp((char *)(str1), (char *)(str2), (num)) #define STRNCMP_UC_C8(str1, str2, num) \ strncmp((char *)(str1), (str2), (num)) #define STRLEN_UC(str) strlen((const char *)str) #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 extern int PRIV(strcmp_uc_uc)(const pcre_uchar *, const pcre_uchar *); extern int PRIV(strcmp_uc_c8)(const pcre_uchar *, const char *); extern int PRIV(strncmp_uc_uc)(const pcre_uchar *, const pcre_uchar *, unsigned int num); extern int PRIV(strncmp_uc_c8)(const pcre_uchar *, const char *, unsigned int num); extern unsigned int PRIV(strlen_uc)(const pcre_uchar *str); #define STRCMP_UC_UC(str1, str2) \ PRIV(strcmp_uc_uc)((str1), (str2)) #define STRCMP_UC_C8(str1, str2) \ PRIV(strcmp_uc_c8)((str1), (str2)) #define STRNCMP_UC_UC(str1, str2, num) \ PRIV(strncmp_uc_uc)((str1), (str2), (num)) #define STRNCMP_UC_C8(str1, str2, num) \ PRIV(strncmp_uc_c8)((str1), (str2), (num)) #define STRLEN_UC(str) PRIV(strlen_uc)(str) #endif /* COMPILE_PCRE[8|16|32] */ #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 #define STRCMP_UC_UC_TEST(str1, str2) STRCMP_UC_UC(str1, str2) #define STRCMP_UC_C8_TEST(str1, str2) STRCMP_UC_C8(str1, str2) #elif defined COMPILE_PCRE32 extern int PRIV(strcmp_uc_uc_utf)(const pcre_uchar *, const pcre_uchar *); extern int PRIV(strcmp_uc_c8_utf)(const pcre_uchar *, const char *); #define STRCMP_UC_UC_TEST(str1, str2) \ (utf ? PRIV(strcmp_uc_uc_utf)((str1), (str2)) : PRIV(strcmp_uc_uc)((str1), (str2))) #define STRCMP_UC_C8_TEST(str1, str2) \ (utf ? PRIV(strcmp_uc_c8_utf)((str1), (str2)) : PRIV(strcmp_uc_c8)((str1), (str2))) #endif /* COMPILE_PCRE[8|16|32] */ extern const pcre_uchar *PRIV(find_bracket)(const pcre_uchar *, BOOL, int); extern BOOL PRIV(is_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, int *, BOOL); extern unsigned int PRIV(ord2utf)(pcre_uint32, pcre_uchar *); extern int PRIV(valid_utf)(PCRE_PUCHAR, int, int *); extern BOOL PRIV(was_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, int *, BOOL); extern BOOL PRIV(xclass)(pcre_uint32, const pcre_uchar *, BOOL); #ifdef SUPPORT_JIT extern void PRIV(jit_compile)(const REAL_PCRE *, PUBL(extra) *, int); extern int PRIV(jit_exec)(const PUBL(extra) *, const pcre_uchar *, int, int, int, int *, int); extern void PRIV(jit_free)(void *); extern int PRIV(jit_get_size)(void *); extern const char* PRIV(jit_get_target)(void); #endif /* Unicode character database (UCD) */ typedef struct { pcre_uint8 script; /* ucp_Arabic, etc. */ pcre_uint8 chartype; /* ucp_Cc, etc. (general categories) */ pcre_uint8 gbprop; /* ucp_gbControl, etc. (grapheme break property) */ pcre_uint8 caseset; /* offset to multichar other cases or zero */ pcre_int32 other_case; /* offset to other case, or zero if none */ } ucd_record; extern const pcre_uint32 PRIV(ucd_caseless_sets)[]; extern const ucd_record PRIV(ucd_records)[]; extern const pcre_uint8 PRIV(ucd_stage1)[]; extern const pcre_uint16 PRIV(ucd_stage2)[]; extern const pcre_uint32 PRIV(ucp_gentype)[]; extern const pcre_uint32 PRIV(ucp_gbtable)[]; #ifdef COMPILE_PCRE32 extern const ucd_record PRIV(dummy_ucd_record)[]; #endif #ifdef SUPPORT_JIT extern const int PRIV(ucp_typerange)[]; #endif #ifdef SUPPORT_UCP /* UCD access macros */ #define UCD_BLOCK_SIZE 128 #define REAL_GET_UCD(ch) (PRIV(ucd_records) + \ PRIV(ucd_stage2)[PRIV(ucd_stage1)[(int)(ch) / UCD_BLOCK_SIZE] * \ UCD_BLOCK_SIZE + (int)(ch) % UCD_BLOCK_SIZE]) #ifdef COMPILE_PCRE32 #define GET_UCD(ch) ((ch > 0x10ffff)? PRIV(dummy_ucd_record) : REAL_GET_UCD(ch)) #else #define GET_UCD(ch) REAL_GET_UCD(ch) #endif #define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype #define UCD_SCRIPT(ch) GET_UCD(ch)->script #define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)] #define UCD_GRAPHBREAK(ch) GET_UCD(ch)->gbprop #define UCD_CASESET(ch) GET_UCD(ch)->caseset #define UCD_OTHERCASE(ch) ((pcre_uint32)((int)ch + (int)(GET_UCD(ch)->other_case))) #endif /* SUPPORT_UCP */ #endif /* End of pcre_internal.h */ ================================================ FILE: src/pcre/pcre_jit_compile.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2013 University of Cambridge The machine code generator part (this module) was written by Zoltan Herczeg Copyright (c) 2010-2013 ----------------------------------------------------------------------------- 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 the University of Cambridge 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 HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" #if defined SUPPORT_JIT /* All-in-one: Since we use the JIT compiler only from here, we just include it. This way we don't need to touch the build system files. */ #define SLJIT_MALLOC(size, allocator_data) (PUBL(malloc))(size) #define SLJIT_FREE(ptr, allocator_data) (PUBL(free))(ptr) #define SLJIT_CONFIG_AUTO 1 #define SLJIT_CONFIG_STATIC 1 #define SLJIT_VERBOSE 0 #define SLJIT_DEBUG 0 #include "sljit/sljitLir.c" #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED #error Unsupported architecture #endif /* Defines for debugging purposes. */ /* 1 - Use unoptimized capturing brackets. 2 - Enable capture_last_ptr (includes option 1). */ /* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */ /* 1 - Always have a control head. */ /* #define DEBUG_FORCE_CONTROL_HEAD 1 */ /* Allocate memory for the regex stack on the real machine stack. Fast, but limited size. */ #define MACHINE_STACK_SIZE 32768 /* Growth rate for stack allocated by the OS. Should be the multiply of page size. */ #define STACK_GROWTH_RATE 8192 /* Enable to check that the allocation could destroy temporaries. */ #if defined SLJIT_DEBUG && SLJIT_DEBUG #define DESTROY_REGISTERS 1 #endif /* Short summary about the backtracking mechanism empolyed by the jit code generator: The code generator follows the recursive nature of the PERL compatible regular expressions. The basic blocks of regular expressions are condition checkers whose execute different commands depending on the result of the condition check. The relationship between the operators can be horizontal (concatenation) and vertical (sub-expression) (See struct backtrack_common for more details). 'ab' - 'a' and 'b' regexps are concatenated 'a+' - 'a' is the sub-expression of the '+' operator The condition checkers are boolean (true/false) checkers. Machine code is generated for the checker itself and for the actions depending on the result of the checker. The 'true' case is called as the matching path (expected path), and the other is called as the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken branches on the matching path. Greedy star operator (*) : Matching path: match happens. Backtrack path: match failed. Non-greedy star operator (*?) : Matching path: no need to perform a match. Backtrack path: match is required. The following example shows how the code generated for a capturing bracket with two alternatives. Let A, B, C, D are arbirary regular expressions, and we have the following regular expression: A(B|C)D The generated code will be the following: A matching path '(' matching path (pushing arguments to the stack) B matching path ')' matching path (pushing arguments to the stack) D matching path return with successful match D backtrack path ')' backtrack path (If we arrived from "C" jump to the backtrack of "C") B backtrack path C expected path jump to D matching path C backtrack path A backtrack path Notice, that the order of backtrack code paths are the opposite of the fast code paths. In this way the topmost value on the stack is always belong to the current backtrack code path. The backtrack path must check whether there is a next alternative. If so, it needs to jump back to the matching path eventually. Otherwise it needs to clear out its own stack frame and continue the execution on the backtrack code paths. */ /* Saved stack frames: Atomic blocks and asserts require reloading the values of private data when the backtrack mechanism performed. Because of OP_RECURSE, the data are not necessarly known in compile time, thus we need a dynamic restore mechanism. The stack frames are stored in a chain list, and have the following format: ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ] Thus we can restore the private data to a particular point in the stack. */ typedef struct jit_arguments { /* Pointers first. */ struct sljit_stack *stack; const pcre_uchar *str; const pcre_uchar *begin; const pcre_uchar *end; int *offsets; pcre_uchar *mark_ptr; void *callout_data; /* Everything else after. */ sljit_u32 limit_match; int real_offset_count; int offset_count; sljit_u8 notbol; sljit_u8 noteol; sljit_u8 notempty; sljit_u8 notempty_atstart; } jit_arguments; typedef struct executable_functions { void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES]; sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; PUBL(jit_callback) callback; void *userdata; sljit_u32 top_bracket; sljit_u32 limit_match; } executable_functions; typedef struct jump_list { struct sljit_jump *jump; struct jump_list *next; } jump_list; typedef struct stub_list { struct sljit_jump *start; struct sljit_label *quit; struct stub_list *next; } stub_list; typedef struct label_addr_list { struct sljit_label *label; sljit_uw *update_addr; struct label_addr_list *next; } label_addr_list; enum frame_types { no_frame = -1, no_stack = -2 }; enum control_types { type_mark = 0, type_then_trap = 1 }; typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args); /* The following structure is the key data type for the recursive code generator. It is allocated by compile_matchingpath, and contains the arguments for compile_backtrackingpath. Must be the first member of its descendants. */ typedef struct backtrack_common { /* Concatenation stack. */ struct backtrack_common *prev; jump_list *nextbacktracks; /* Internal stack (for component operators). */ struct backtrack_common *top; jump_list *topbacktracks; /* Opcode pointer. */ pcre_uchar *cc; } backtrack_common; typedef struct assert_backtrack { backtrack_common common; jump_list *condfailed; /* Less than 0 if a frame is not needed. */ int framesize; /* Points to our private memory word on the stack. */ int private_data_ptr; /* For iterators. */ struct sljit_label *matchingpath; } assert_backtrack; typedef struct bracket_backtrack { backtrack_common common; /* Where to coninue if an alternative is successfully matched. */ struct sljit_label *alternative_matchingpath; /* For rmin and rmax iterators. */ struct sljit_label *recursive_matchingpath; /* For greedy ? operator. */ struct sljit_label *zero_matchingpath; /* Contains the branches of a failed condition. */ union { /* Both for OP_COND, OP_SCOND. */ jump_list *condfailed; assert_backtrack *assert; /* For OP_ONCE. Less than 0 if not needed. */ int framesize; } u; /* Points to our private memory word on the stack. */ int private_data_ptr; } bracket_backtrack; typedef struct bracketpos_backtrack { backtrack_common common; /* Points to our private memory word on the stack. */ int private_data_ptr; /* Reverting stack is needed. */ int framesize; /* Allocated stack size. */ int stacksize; } bracketpos_backtrack; typedef struct braminzero_backtrack { backtrack_common common; struct sljit_label *matchingpath; } braminzero_backtrack; typedef struct char_iterator_backtrack { backtrack_common common; /* Next iteration. */ struct sljit_label *matchingpath; union { jump_list *backtracks; struct { unsigned int othercasebit; pcre_uchar chr; BOOL enabled; } charpos; } u; } char_iterator_backtrack; typedef struct ref_iterator_backtrack { backtrack_common common; /* Next iteration. */ struct sljit_label *matchingpath; } ref_iterator_backtrack; typedef struct recurse_entry { struct recurse_entry *next; /* Contains the function entry. */ struct sljit_label *entry; /* Collects the calls until the function is not created. */ jump_list *calls; /* Points to the starting opcode. */ sljit_sw start; } recurse_entry; typedef struct recurse_backtrack { backtrack_common common; BOOL inlined_pattern; } recurse_backtrack; #define OP_THEN_TRAP OP_TABLE_LENGTH typedef struct then_trap_backtrack { backtrack_common common; /* If then_trap is not NULL, this structure contains the real then_trap for the backtracking path. */ struct then_trap_backtrack *then_trap; /* Points to the starting opcode. */ sljit_sw start; /* Exit point for the then opcodes of this alternative. */ jump_list *quit; /* Frame size of the current alternative. */ int framesize; } then_trap_backtrack; #define MAX_RANGE_SIZE 4 typedef struct compiler_common { /* The sljit ceneric compiler. */ struct sljit_compiler *compiler; /* First byte code. */ pcre_uchar *start; /* Maps private data offset to each opcode. */ sljit_s32 *private_data_ptrs; /* Chain list of read-only data ptrs. */ void *read_only_data_head; /* Tells whether the capturing bracket is optimized. */ sljit_u8 *optimized_cbracket; /* Tells whether the starting offset is a target of then. */ sljit_u8 *then_offsets; /* Current position where a THEN must jump. */ then_trap_backtrack *then_trap; /* Starting offset of private data for capturing brackets. */ sljit_s32 cbra_ptr; /* Output vector starting point. Must be divisible by 2. */ sljit_s32 ovector_start; /* Points to the starting character of the current match. */ sljit_s32 start_ptr; /* Last known position of the requested byte. */ sljit_s32 req_char_ptr; /* Head of the last recursion. */ sljit_s32 recursive_head_ptr; /* First inspected character for partial matching. (Needed for avoiding zero length partial matches.) */ sljit_s32 start_used_ptr; /* Starting pointer for partial soft matches. */ sljit_s32 hit_start; /* Pointer of the match end position. */ sljit_s32 match_end_ptr; /* Points to the marked string. */ sljit_s32 mark_ptr; /* Recursive control verb management chain. */ sljit_s32 control_head_ptr; /* Points to the last matched capture block index. */ sljit_s32 capture_last_ptr; /* Fast forward skipping byte code pointer. */ pcre_uchar *fast_forward_bc_ptr; /* Locals used by fast fail optimization. */ sljit_s32 fast_fail_start_ptr; sljit_s32 fast_fail_end_ptr; /* Flipped and lower case tables. */ const sljit_u8 *fcc; sljit_sw lcc; /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ int mode; /* TRUE, when minlength is greater than 0. */ BOOL might_be_empty; /* \K is found in the pattern. */ BOOL has_set_som; /* (*SKIP:arg) is found in the pattern. */ BOOL has_skip_arg; /* (*THEN) is found in the pattern. */ BOOL has_then; /* (*SKIP) or (*SKIP:arg) is found in lookbehind assertion. */ BOOL has_skip_in_assert_back; /* Currently in recurse or negative assert. */ BOOL local_exit; /* Currently in a positive assert. */ BOOL positive_assert; /* Newline control. */ int nltype; sljit_u32 nlmax; sljit_u32 nlmin; int newline; int bsr_nltype; sljit_u32 bsr_nlmax; sljit_u32 bsr_nlmin; /* Dollar endonly. */ int endonly; /* Tables. */ sljit_sw ctypes; /* Named capturing brackets. */ pcre_uchar *name_table; sljit_sw name_count; sljit_sw name_entry_size; /* Labels and jump lists. */ struct sljit_label *partialmatchlabel; struct sljit_label *quit_label; struct sljit_label *forced_quit_label; struct sljit_label *accept_label; struct sljit_label *ff_newline_shortcut; stub_list *stubs; label_addr_list *label_addrs; recurse_entry *entries; recurse_entry *currententry; jump_list *partialmatch; jump_list *quit; jump_list *positive_assert_quit; jump_list *forced_quit; jump_list *accept; jump_list *calllimit; jump_list *stackalloc; jump_list *revertframes; jump_list *wordboundary; jump_list *anynewline; jump_list *hspace; jump_list *vspace; jump_list *casefulcmp; jump_list *caselesscmp; jump_list *reset_match; BOOL jscript_compat; #ifdef SUPPORT_UTF BOOL utf; #ifdef SUPPORT_UCP BOOL use_ucp; jump_list *getucd; #endif #ifdef COMPILE_PCRE8 jump_list *utfreadchar; jump_list *utfreadchar16; jump_list *utfreadtype8; #endif #endif /* SUPPORT_UTF */ } compiler_common; /* For byte_sequence_compare. */ typedef struct compare_context { int length; int sourcereg; #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED int ucharptr; union { sljit_s32 asint; sljit_u16 asushort; #if defined COMPILE_PCRE8 sljit_u8 asbyte; sljit_u8 asuchars[4]; #elif defined COMPILE_PCRE16 sljit_u16 asuchars[2]; #elif defined COMPILE_PCRE32 sljit_u32 asuchars[1]; #endif } c; union { sljit_s32 asint; sljit_u16 asushort; #if defined COMPILE_PCRE8 sljit_u8 asbyte; sljit_u8 asuchars[4]; #elif defined COMPILE_PCRE16 sljit_u16 asuchars[2]; #elif defined COMPILE_PCRE32 sljit_u32 asuchars[1]; #endif } oc; #endif } compare_context; /* Undefine sljit macros. */ #undef CMP /* Used for accessing the elements of the stack. */ #define STACK(i) ((i) * (int)sizeof(sljit_sw)) #ifdef SLJIT_PREF_SHIFT_REG #if SLJIT_PREF_SHIFT_REG == SLJIT_R2 /* Nothing. */ #elif SLJIT_PREF_SHIFT_REG == SLJIT_R3 #define SHIFT_REG_IS_R3 #else #error "Unsupported shift register" #endif #endif #define TMP1 SLJIT_R0 #ifdef SHIFT_REG_IS_R3 #define TMP2 SLJIT_R3 #define TMP3 SLJIT_R2 #else #define TMP2 SLJIT_R2 #define TMP3 SLJIT_R3 #endif #define STR_PTR SLJIT_S0 #define STR_END SLJIT_S1 #define STACK_TOP SLJIT_R1 #define STACK_LIMIT SLJIT_S2 #define COUNT_MATCH SLJIT_S3 #define ARGUMENTS SLJIT_S4 #define RETURN_ADDR SLJIT_R4 /* Local space layout. */ /* These two locals can be used by the current opcode. */ #define LOCALS0 (0 * sizeof(sljit_sw)) #define LOCALS1 (1 * sizeof(sljit_sw)) /* Two local variables for possessive quantifiers (char1 cannot use them). */ #define POSSESSIVE0 (2 * sizeof(sljit_sw)) #define POSSESSIVE1 (3 * sizeof(sljit_sw)) /* Max limit of recursions. */ #define LIMIT_MATCH (4 * sizeof(sljit_sw)) /* The output vector is stored on the stack, and contains pointers to characters. The vector data is divided into two groups: the first group contains the start / end character pointers, and the second is the start pointers when the end of the capturing group has not yet reached. */ #define OVECTOR_START (common->ovector_start) #define OVECTOR(i) (OVECTOR_START + (i) * (sljit_sw)sizeof(sljit_sw)) #define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw)) #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) #if defined COMPILE_PCRE8 #define MOV_UCHAR SLJIT_MOV_U8 #elif defined COMPILE_PCRE16 #define MOV_UCHAR SLJIT_MOV_U16 #elif defined COMPILE_PCRE32 #define MOV_UCHAR SLJIT_MOV_U32 #else #error Unsupported compiling mode #endif /* Shortcuts. */ #define DEFINE_COMPILER \ struct sljit_compiler *compiler = common->compiler #define OP1(op, dst, dstw, src, srcw) \ sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw)) #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \ sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w)) #define LABEL() \ sljit_emit_label(compiler) #define JUMP(type) \ sljit_emit_jump(compiler, (type)) #define JUMPTO(type, label) \ sljit_set_label(sljit_emit_jump(compiler, (type)), (label)) #define JUMPHERE(jump) \ sljit_set_label((jump), sljit_emit_label(compiler)) #define SET_LABEL(jump, label) \ sljit_set_label((jump), (label)) #define CMP(type, src1, src1w, src2, src2w) \ sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)) #define CMPTO(type, src1, src1w, src2, src2w, label) \ sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) #define OP_FLAGS(op, dst, dstw, type) \ sljit_emit_op_flags(compiler, (op), (dst), (dstw), (type)) #define GET_LOCAL_BASE(dst, dstw, offset) \ sljit_get_local_base(compiler, (dst), (dstw), (offset)) #define READ_CHAR_MAX 0x7fffffff #define INVALID_UTF_CHAR 888 static pcre_uchar *bracketend(pcre_uchar *cc) { SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do cc += GET(cc, 1); while (*cc == OP_ALT); SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); cc += 1 + LINK_SIZE; return cc; } static int no_alternatives(pcre_uchar *cc) { int count = 0; SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do { cc += GET(cc, 1); count++; } while (*cc == OP_ALT); SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); return count; } /* Functions whose might need modification for all new supported opcodes: next_opcode check_opcode_types set_private_data_ptrs get_framesize init_frame get_private_data_copy_length copy_private_data compile_matchingpath compile_backtrackingpath */ static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) { SLJIT_UNUSED_ARG(common); switch(*cc) { case OP_SOD: case OP_SOM: case OP_SET_SOM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: case OP_ALLANY: case OP_NOTPROP: case OP_PROP: case OP_ANYNL: case OP_NOT_HSPACE: case OP_HSPACE: case OP_NOT_VSPACE: case OP_VSPACE: case OP_EXTUNI: case OP_EODN: case OP_EOD: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: case OP_CRPOSRANGE: case OP_CLASS: case OP_NCLASS: case OP_REF: case OP_REFI: case OP_DNREF: case OP_DNREFI: case OP_RECURSE: case OP_CALLOUT: case OP_ALT: case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_KETRPOS: case OP_REVERSE: case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_ONCE_NC: case OP_BRA: case OP_BRAPOS: case OP_CBRA: case OP_CBRAPOS: case OP_COND: case OP_SBRA: case OP_SBRAPOS: case OP_SCBRA: case OP_SCBRAPOS: case OP_SCOND: case OP_CREF: case OP_DNCREF: case OP_RREF: case OP_DNRREF: case OP_DEF: case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: case OP_PRUNE: case OP_SKIP: case OP_THEN: case OP_COMMIT: case OP_FAIL: case OP_ACCEPT: case OP_ASSERT_ACCEPT: case OP_CLOSE: case OP_SKIPZERO: return cc + PRIV(OP_lengths)[*cc]; case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_UPTO: case OP_MINUPTO: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_UPTOI: case OP_MINUPTOI: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: cc += PRIV(OP_lengths)[*cc]; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif return cc; /* Special cases. */ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEEXACT: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSUPTO: return cc + PRIV(OP_lengths)[*cc] - 1; case OP_ANYBYTE: #ifdef SUPPORT_UTF if (common->utf) return NULL; #endif return cc + 1; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: return cc + GET(cc, 1); #endif case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: return cc + 1 + 2 + cc[1]; default: /* All opcodes are supported now! */ SLJIT_UNREACHABLE(); return NULL; } } static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) { int count; pcre_uchar *slot; pcre_uchar *assert_back_end = cc - 1; /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ while (cc < ccend) { switch(*cc) { case OP_SET_SOM: common->has_set_som = TRUE; common->might_be_empty = TRUE; cc += 1; break; case OP_REF: case OP_REFI: common->optimized_cbracket[GET2(cc, 1)] = 0; cc += 1 + IMM2_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_COND: case OP_SCOND: /* Only AUTO_CALLOUT can insert this opcode. We do not intend to support this case. */ if (cc[1 + LINK_SIZE] == OP_CALLOUT) return FALSE; cc += 1 + LINK_SIZE; break; case OP_CREF: common->optimized_cbracket[GET2(cc, 1)] = 0; cc += 1 + IMM2_SIZE; break; case OP_DNREF: case OP_DNREFI: case OP_DNCREF: count = GET2(cc, 1 + IMM2_SIZE); slot = common->name_table + GET2(cc, 1) * common->name_entry_size; while (count-- > 0) { common->optimized_cbracket[GET2(slot, 0)] = 0; slot += common->name_entry_size; } cc += 1 + 2 * IMM2_SIZE; break; case OP_RECURSE: /* Set its value only once. */ if (common->recursive_head_ptr == 0) { common->recursive_head_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } cc += 1 + LINK_SIZE; break; case OP_CALLOUT: if (common->capture_last_ptr == 0) { common->capture_last_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } cc += 2 + 2 * LINK_SIZE; break; case OP_ASSERTBACK: slot = bracketend(cc); if (slot > assert_back_end) assert_back_end = slot; cc += 1 + LINK_SIZE; break; case OP_THEN_ARG: common->has_then = TRUE; common->control_head_ptr = 1; /* Fall through. */ case OP_PRUNE_ARG: case OP_MARK: if (common->mark_ptr == 0) { common->mark_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } cc += 1 + 2 + cc[1]; break; case OP_THEN: common->has_then = TRUE; common->control_head_ptr = 1; cc += 1; break; case OP_SKIP: if (cc < assert_back_end) common->has_skip_in_assert_back = TRUE; cc += 1; break; case OP_SKIP_ARG: common->control_head_ptr = 1; common->has_skip_arg = TRUE; if (cc < assert_back_end) common->has_skip_in_assert_back = TRUE; cc += 1 + 2 + cc[1]; break; default: cc = next_opcode(common, cc); if (cc == NULL) return FALSE; break; } } return TRUE; } static BOOL is_accelerated_repeat(pcre_uchar *cc) { switch(*cc) { case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: return (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI); case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_POSSTAR: case OP_POSPLUS: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_POSSTARI: case OP_POSPLUSI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: return TRUE; case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(pcre_uchar))); #else cc += (1 + (32 / sizeof(pcre_uchar))); #endif switch(*cc) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRPOSSTAR: case OP_CRPOSPLUS: return TRUE; } break; } return FALSE; } static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start) { pcre_uchar *cc = common->start; pcre_uchar *end; /* Skip not repeated brackets. */ while (TRUE) { switch(*cc) { case OP_SOD: case OP_SOM: case OP_SET_SOM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_EODN: case OP_EOD: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: /* Zero width assertions. */ cc++; continue; } if (*cc != OP_BRA && *cc != OP_CBRA) break; end = cc + GET(cc, 1); if (*end != OP_KET || PRIVATE_DATA(end) != 0) return FALSE; if (*cc == OP_CBRA) { if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) return FALSE; cc += IMM2_SIZE; } cc += 1 + LINK_SIZE; } if (is_accelerated_repeat(cc)) { common->fast_forward_bc_ptr = cc; common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; *private_data_start += sizeof(sljit_sw); return TRUE; } return FALSE; } static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *cc, int *private_data_start, sljit_s32 depth) { pcre_uchar *next_alt; SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA); if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) return; next_alt = bracketend(cc) - (1 + LINK_SIZE); if (*next_alt != OP_KET || PRIVATE_DATA(next_alt) != 0) return; do { next_alt = cc + GET(cc, 1); cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0); while (TRUE) { switch(*cc) { case OP_SOD: case OP_SOM: case OP_SET_SOM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_EODN: case OP_EOD: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: /* Zero width assertions. */ cc++; continue; } break; } if (depth > 0 && (*cc == OP_BRA || *cc == OP_CBRA)) detect_fast_fail(common, cc, private_data_start, depth - 1); if (is_accelerated_repeat(cc)) { common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; if (common->fast_fail_start_ptr == 0) common->fast_fail_start_ptr = *private_data_start; *private_data_start += sizeof(sljit_sw); common->fast_fail_end_ptr = *private_data_start; if (*private_data_start > SLJIT_MAX_LOCAL_SIZE) return; } cc = next_alt; } while (*cc == OP_ALT); } static int get_class_iterator_size(pcre_uchar *cc) { sljit_u32 min; sljit_u32 max; switch(*cc) { case OP_CRSTAR: case OP_CRPLUS: return 2; case OP_CRMINSTAR: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: return 1; case OP_CRRANGE: case OP_CRMINRANGE: min = GET2(cc, 1); max = GET2(cc, 1 + IMM2_SIZE); if (max == 0) return (*cc == OP_CRRANGE) ? 2 : 1; max -= min; if (max > 2) max = 2; return max; default: return 0; } } static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin) { pcre_uchar *end = bracketend(begin); pcre_uchar *next; pcre_uchar *next_end; pcre_uchar *max_end; pcre_uchar type; sljit_sw length = end - begin; int min, max, i; /* Detect fixed iterations first. */ if (end[-(1 + LINK_SIZE)] != OP_KET) return FALSE; /* Already detected repeat. */ if (common->private_data_ptrs[end - common->start - LINK_SIZE] != 0) return TRUE; next = end; min = 1; while (1) { if (*next != *begin) break; next_end = bracketend(next); if (next_end - next != length || memcmp(begin, next, IN_UCHARS(length)) != 0) break; next = next_end; min++; } if (min == 2) return FALSE; max = 0; max_end = next; if (*next == OP_BRAZERO || *next == OP_BRAMINZERO) { type = *next; while (1) { if (next[0] != type || next[1] != OP_BRA || next[2 + LINK_SIZE] != *begin) break; next_end = bracketend(next + 2 + LINK_SIZE); if (next_end - next != (length + 2 + LINK_SIZE) || memcmp(begin, next + 2 + LINK_SIZE, IN_UCHARS(length)) != 0) break; next = next_end; max++; } if (next[0] == type && next[1] == *begin && max >= 1) { next_end = bracketend(next + 1); if (next_end - next == (length + 1) && memcmp(begin, next + 1, IN_UCHARS(length)) == 0) { for (i = 0; i < max; i++, next_end += 1 + LINK_SIZE) if (*next_end != OP_KET) break; if (i == max) { common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end; common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO; /* +2 the original and the last. */ common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2; if (min == 1) return TRUE; min--; max_end -= (1 + LINK_SIZE) + GET(max_end, -LINK_SIZE); } } } } if (min >= 3) { common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end; common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT; common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min; return TRUE; } return FALSE; } #define CASE_ITERATOR_PRIVATE_DATA_1 \ case OP_MINSTAR: \ case OP_MINPLUS: \ case OP_QUERY: \ case OP_MINQUERY: \ case OP_MINSTARI: \ case OP_MINPLUSI: \ case OP_QUERYI: \ case OP_MINQUERYI: \ case OP_NOTMINSTAR: \ case OP_NOTMINPLUS: \ case OP_NOTQUERY: \ case OP_NOTMINQUERY: \ case OP_NOTMINSTARI: \ case OP_NOTMINPLUSI: \ case OP_NOTQUERYI: \ case OP_NOTMINQUERYI: #define CASE_ITERATOR_PRIVATE_DATA_2A \ case OP_STAR: \ case OP_PLUS: \ case OP_STARI: \ case OP_PLUSI: \ case OP_NOTSTAR: \ case OP_NOTPLUS: \ case OP_NOTSTARI: \ case OP_NOTPLUSI: #define CASE_ITERATOR_PRIVATE_DATA_2B \ case OP_UPTO: \ case OP_MINUPTO: \ case OP_UPTOI: \ case OP_MINUPTOI: \ case OP_NOTUPTO: \ case OP_NOTMINUPTO: \ case OP_NOTUPTOI: \ case OP_NOTMINUPTOI: #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \ case OP_TYPEMINSTAR: \ case OP_TYPEMINPLUS: \ case OP_TYPEQUERY: \ case OP_TYPEMINQUERY: #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \ case OP_TYPESTAR: \ case OP_TYPEPLUS: #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \ case OP_TYPEUPTO: \ case OP_TYPEMINUPTO: static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend) { pcre_uchar *cc = common->start; pcre_uchar *alternative; pcre_uchar *end = NULL; int private_data_ptr = *private_data_start; int space, size, bracketlen; BOOL repeat_check = TRUE; while (cc < ccend) { space = 0; size = 0; bracketlen = 0; if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) break; if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) { if (detect_repeat(common, cc)) { /* These brackets are converted to repeats, so no global based single character repeat is allowed. */ if (cc >= end) end = bracketend(cc); } } repeat_check = TRUE; switch(*cc) { case OP_KET: if (common->private_data_ptrs[cc + 1 - common->start] != 0) { common->private_data_ptrs[cc - common->start] = private_data_ptr; private_data_ptr += sizeof(sljit_sw); cc += common->private_data_ptrs[cc + 1 - common->start]; } cc += 1 + LINK_SIZE; break; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_ONCE_NC: case OP_BRAPOS: case OP_SBRA: case OP_SBRAPOS: case OP_SCOND: common->private_data_ptrs[cc - common->start] = private_data_ptr; private_data_ptr += sizeof(sljit_sw); bracketlen = 1 + LINK_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: common->private_data_ptrs[cc - common->start] = private_data_ptr; private_data_ptr += sizeof(sljit_sw); bracketlen = 1 + LINK_SIZE + IMM2_SIZE; break; case OP_COND: /* Might be a hidden SCOND. */ alternative = cc + GET(cc, 1); if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) { common->private_data_ptrs[cc - common->start] = private_data_ptr; private_data_ptr += sizeof(sljit_sw); } bracketlen = 1 + LINK_SIZE; break; case OP_BRA: bracketlen = 1 + LINK_SIZE; break; case OP_CBRA: case OP_SCBRA: bracketlen = 1 + LINK_SIZE + IMM2_SIZE; break; case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: repeat_check = FALSE; size = 1; break; CASE_ITERATOR_PRIVATE_DATA_1 space = 1; size = -2; break; CASE_ITERATOR_PRIVATE_DATA_2A space = 2; size = -2; break; CASE_ITERATOR_PRIVATE_DATA_2B space = 2; size = -(2 + IMM2_SIZE); break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 space = 1; size = 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI) space = 2; size = 1; break; case OP_TYPEUPTO: if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; size = 1 + IMM2_SIZE; break; case OP_TYPEMINUPTO: space = 2; size = 1 + IMM2_SIZE; break; case OP_CLASS: case OP_NCLASS: space = get_class_iterator_size(cc + size); size = 1 + 32 / sizeof(pcre_uchar); break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: space = get_class_iterator_size(cc + size); size = GET(cc, 1); break; #endif default: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); break; } /* Character iterators, which are not inside a repeated bracket, gets a private slot instead of allocating it on the stack. */ if (space > 0 && cc >= end) { common->private_data_ptrs[cc - common->start] = private_data_ptr; private_data_ptr += sizeof(sljit_sw) * space; } if (size != 0) { if (size < 0) { cc += -size; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif } else cc += size; } if (bracketlen > 0) { if (cc >= end) { end = bracketend(cc); if (end[-1 - LINK_SIZE] == OP_KET) end = NULL; } cc += bracketlen; } } *private_data_start = private_data_ptr; } /* Returns with a frame_types (always < 0) if no need for frame. */ static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL *needs_control_head) { int length = 0; int possessive = 0; BOOL stack_restore = FALSE; BOOL setsom_found = recursive; BOOL setmark_found = recursive; /* The last capture is a local variable even for recursions. */ BOOL capture_last_found = FALSE; #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD SLJIT_ASSERT(common->control_head_ptr != 0); *needs_control_head = TRUE; #else *needs_control_head = FALSE; #endif if (ccend == NULL) { ccend = bracketend(cc) - (1 + LINK_SIZE); if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) { possessive = length = (common->capture_last_ptr != 0) ? 5 : 3; /* This is correct regardless of common->capture_last_ptr. */ capture_last_found = TRUE; } cc = next_opcode(common, cc); } SLJIT_ASSERT(cc != NULL); while (cc < ccend) switch(*cc) { case OP_SET_SOM: SLJIT_ASSERT(common->has_set_som); stack_restore = TRUE; if (!setsom_found) { length += 2; setsom_found = TRUE; } cc += 1; break; case OP_MARK: case OP_PRUNE_ARG: case OP_THEN_ARG: SLJIT_ASSERT(common->mark_ptr != 0); stack_restore = TRUE; if (!setmark_found) { length += 2; setmark_found = TRUE; } if (common->control_head_ptr != 0) *needs_control_head = TRUE; cc += 1 + 2 + cc[1]; break; case OP_RECURSE: stack_restore = TRUE; if (common->has_set_som && !setsom_found) { length += 2; setsom_found = TRUE; } if (common->mark_ptr != 0 && !setmark_found) { length += 2; setmark_found = TRUE; } if (common->capture_last_ptr != 0 && !capture_last_found) { length += 2; capture_last_found = TRUE; } cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_CBRAPOS: case OP_SCBRA: case OP_SCBRAPOS: stack_restore = TRUE; if (common->capture_last_ptr != 0 && !capture_last_found) { length += 2; capture_last_found = TRUE; } length += 3; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_THEN: stack_restore = TRUE; if (common->control_head_ptr != 0) *needs_control_head = TRUE; cc ++; break; default: stack_restore = TRUE; /* Fall through. */ case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: case OP_ALLANY: case OP_ANYBYTE: case OP_NOTPROP: case OP_PROP: case OP_ANYNL: case OP_NOT_HSPACE: case OP_HSPACE: case OP_NOT_VSPACE: case OP_VSPACE: case OP_EXTUNI: case OP_EODN: case OP_EOD: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: case OP_TYPEEXACT: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSUPTO: case OP_CLASS: case OP_NCLASS: case OP_XCLASS: case OP_CALLOUT: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); break; } /* Possessive quantifiers can use a special case. */ if (SLJIT_UNLIKELY(possessive == length)) return stack_restore ? no_frame : no_stack; if (length > 0) return length + 1; return stack_restore ? no_frame : no_stack; } static void init_frame(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, int stackpos, int stacktop, BOOL recursive) { DEFINE_COMPILER; BOOL setsom_found = recursive; BOOL setmark_found = recursive; /* The last capture is a local variable even for recursions. */ BOOL capture_last_found = FALSE; int offset; /* >= 1 + shortest item size (2) */ SLJIT_UNUSED_ARG(stacktop); SLJIT_ASSERT(stackpos >= stacktop + 2); stackpos = STACK(stackpos); if (ccend == NULL) { ccend = bracketend(cc) - (1 + LINK_SIZE); if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) cc = next_opcode(common, cc); } SLJIT_ASSERT(cc != NULL); while (cc < ccend) switch(*cc) { case OP_SET_SOM: SLJIT_ASSERT(common->has_set_som); if (!setsom_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); setsom_found = TRUE; } cc += 1; break; case OP_MARK: case OP_PRUNE_ARG: case OP_THEN_ARG: SLJIT_ASSERT(common->mark_ptr != 0); if (!setmark_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); setmark_found = TRUE; } cc += 1 + 2 + cc[1]; break; case OP_RECURSE: if (common->has_set_som && !setsom_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); setsom_found = TRUE; } if (common->mark_ptr != 0 && !setmark_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); setmark_found = TRUE; } if (common->capture_last_ptr != 0 && !capture_last_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); capture_last_found = TRUE; } cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_CBRAPOS: case OP_SCBRA: case OP_SCBRAPOS: if (common->capture_last_ptr != 0 && !capture_last_found) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); capture_last_found = TRUE; } offset = (GET2(cc, 1 + LINK_SIZE)) << 1; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); stackpos -= (int)sizeof(sljit_sw); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); stackpos -= (int)sizeof(sljit_sw); cc += 1 + LINK_SIZE + IMM2_SIZE; break; default: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); break; } OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0); SLJIT_ASSERT(stackpos == STACK(stacktop)); } static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL needs_control_head) { int private_data_length = needs_control_head ? 3 : 2; int size; pcre_uchar *alternative; /* Calculate the sum of the private machine words. */ while (cc < ccend) { size = 0; switch(*cc) { case OP_KET: if (PRIVATE_DATA(cc) != 0) { private_data_length++; SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); cc += PRIVATE_DATA(cc + 1); } cc += 1 + LINK_SIZE; break; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_ONCE_NC: case OP_BRAPOS: case OP_SBRA: case OP_SBRAPOS: case OP_SCOND: private_data_length++; SLJIT_ASSERT(PRIVATE_DATA(cc) != 0); cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_SCBRA: if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) private_data_length++; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: private_data_length += 2; cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_COND: /* Might be a hidden SCOND. */ alternative = cc + GET(cc, 1); if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) private_data_length++; cc += 1 + LINK_SIZE; break; CASE_ITERATOR_PRIVATE_DATA_1 if (PRIVATE_DATA(cc)) private_data_length++; cc += 2; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; CASE_ITERATOR_PRIVATE_DATA_2A if (PRIVATE_DATA(cc)) private_data_length += 2; cc += 2; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; CASE_ITERATOR_PRIVATE_DATA_2B if (PRIVATE_DATA(cc)) private_data_length += 2; cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 if (PRIVATE_DATA(cc)) private_data_length++; cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A if (PRIVATE_DATA(cc)) private_data_length += 2; cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2B if (PRIVATE_DATA(cc)) private_data_length += 2; cc += 1 + IMM2_SIZE; break; case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar); #else size = 1 + 32 / (int)sizeof(pcre_uchar); #endif if (PRIVATE_DATA(cc)) private_data_length += get_class_iterator_size(cc + size); cc += size; break; default: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); break; } } SLJIT_ASSERT(cc == ccend); return private_data_length; } static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL save, int stackptr, int stacktop, BOOL needs_control_head) { DEFINE_COMPILER; int srcw[2]; int count, size; BOOL tmp1next = TRUE; BOOL tmp1empty = TRUE; BOOL tmp2empty = TRUE; pcre_uchar *alternative; enum { loop, end } status; status = loop; stackptr = STACK(stackptr); stacktop = STACK(stacktop - 1); if (!save) { stacktop -= (needs_control_head ? 2 : 1) * sizeof(sljit_sw); if (stackptr < stacktop) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); stackptr += sizeof(sljit_sw); tmp1empty = FALSE; } if (stackptr < stacktop) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); stackptr += sizeof(sljit_sw); tmp2empty = FALSE; } /* The tmp1next must be TRUE in either way. */ } SLJIT_ASSERT(common->recursive_head_ptr != 0); do { count = 0; if (cc >= ccend) { if (!save) break; count = 1; srcw[0] = common->recursive_head_ptr; if (needs_control_head) { SLJIT_ASSERT(common->control_head_ptr != 0); count = 2; srcw[0] = common->control_head_ptr; srcw[1] = common->recursive_head_ptr; } status = end; } else switch(*cc) { case OP_KET: if (PRIVATE_DATA(cc) != 0) { count = 1; srcw[0] = PRIVATE_DATA(cc); SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0); cc += PRIVATE_DATA(cc + 1); } cc += 1 + LINK_SIZE; break; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_ONCE_NC: case OP_BRAPOS: case OP_SBRA: case OP_SBRAPOS: case OP_SCOND: count = 1; srcw[0] = PRIVATE_DATA(cc); SLJIT_ASSERT(srcw[0] != 0); cc += 1 + LINK_SIZE; break; case OP_CBRA: case OP_SCBRA: if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) { count = 1; srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); } cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: count = 2; srcw[0] = PRIVATE_DATA(cc); srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); SLJIT_ASSERT(srcw[0] != 0 && srcw[1] != 0); cc += 1 + LINK_SIZE + IMM2_SIZE; break; case OP_COND: /* Might be a hidden SCOND. */ alternative = cc + GET(cc, 1); if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) { count = 1; srcw[0] = PRIVATE_DATA(cc); SLJIT_ASSERT(srcw[0] != 0); } cc += 1 + LINK_SIZE; break; CASE_ITERATOR_PRIVATE_DATA_1 if (PRIVATE_DATA(cc)) { count = 1; srcw[0] = PRIVATE_DATA(cc); } cc += 2; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; CASE_ITERATOR_PRIVATE_DATA_2A if (PRIVATE_DATA(cc)) { count = 2; srcw[0] = PRIVATE_DATA(cc); srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); } cc += 2; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; CASE_ITERATOR_PRIVATE_DATA_2B if (PRIVATE_DATA(cc)) { count = 2; srcw[0] = PRIVATE_DATA(cc); srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw); } cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 if (PRIVATE_DATA(cc)) { count = 1; srcw[0] = PRIVATE_DATA(cc); } cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A if (PRIVATE_DATA(cc)) { count = 2; srcw[0] = PRIVATE_DATA(cc); srcw[1] = srcw[0] + sizeof(sljit_sw); } cc += 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2B if (PRIVATE_DATA(cc)) { count = 2; srcw[0] = PRIVATE_DATA(cc); srcw[1] = srcw[0] + sizeof(sljit_sw); } cc += 1 + IMM2_SIZE; break; case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar); #else size = 1 + 32 / (int)sizeof(pcre_uchar); #endif if (PRIVATE_DATA(cc)) switch(get_class_iterator_size(cc + size)) { case 1: count = 1; srcw[0] = PRIVATE_DATA(cc); break; case 2: count = 2; srcw[0] = PRIVATE_DATA(cc); srcw[1] = srcw[0] + sizeof(sljit_sw); break; default: SLJIT_UNREACHABLE(); break; } cc += size; break; default: cc = next_opcode(common, cc); SLJIT_ASSERT(cc != NULL); break; } while (count > 0) { count--; if (save) { if (tmp1next) { if (!tmp1empty) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); stackptr += sizeof(sljit_sw); } OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); tmp1empty = FALSE; tmp1next = FALSE; } else { if (!tmp2empty) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); stackptr += sizeof(sljit_sw); } OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), srcw[count]); tmp2empty = FALSE; tmp1next = TRUE; } } else { if (tmp1next) { SLJIT_ASSERT(!tmp1empty); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP1, 0); tmp1empty = stackptr >= stacktop; if (!tmp1empty) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); stackptr += sizeof(sljit_sw); } tmp1next = FALSE; } else { SLJIT_ASSERT(!tmp2empty); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), srcw[count], TMP2, 0); tmp2empty = stackptr >= stacktop; if (!tmp2empty) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); stackptr += sizeof(sljit_sw); } tmp1next = TRUE; } } } } while (status != end); if (save) { if (tmp1next) { if (!tmp1empty) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); stackptr += sizeof(sljit_sw); } if (!tmp2empty) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); stackptr += sizeof(sljit_sw); } } else { if (!tmp2empty) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); stackptr += sizeof(sljit_sw); } if (!tmp1empty) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); stackptr += sizeof(sljit_sw); } } } SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); } static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, sljit_u8 *current_offset) { pcre_uchar *end = bracketend(cc); BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT; /* Assert captures then. */ if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) current_offset = NULL; /* Conditional block does not. */ if (*cc == OP_COND || *cc == OP_SCOND) has_alternatives = FALSE; cc = next_opcode(common, cc); if (has_alternatives) current_offset = common->then_offsets + (cc - common->start); while (cc < end) { if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)) cc = set_then_offsets(common, cc, current_offset); else { if (*cc == OP_ALT && has_alternatives) current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start); if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL) *current_offset = 1; cc = next_opcode(common, cc); } } return end; } #undef CASE_ITERATOR_PRIVATE_DATA_1 #undef CASE_ITERATOR_PRIVATE_DATA_2A #undef CASE_ITERATOR_PRIVATE_DATA_2B #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1 #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B static SLJIT_INLINE BOOL is_powerof2(unsigned int value) { return (value & (value - 1)) == 0; } static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label) { while (list) { /* sljit_set_label is clever enough to do nothing if either the jump or the label is NULL. */ SET_LABEL(list->jump, label); list = list->next; } } static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump *jump) { jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list)); if (list_item) { list_item->next = *list; list_item->jump = jump; *list = list_item; } } static void add_stub(compiler_common *common, struct sljit_jump *start) { DEFINE_COMPILER; stub_list *list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); if (list_item) { list_item->start = start; list_item->quit = LABEL(); list_item->next = common->stubs; common->stubs = list_item; } } static void flush_stubs(compiler_common *common) { DEFINE_COMPILER; stub_list *list_item = common->stubs; while (list_item) { JUMPHERE(list_item->start); add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); JUMPTO(SLJIT_JUMP, list_item->quit); list_item = list_item->next; } common->stubs = NULL; } static void add_label_addr(compiler_common *common, sljit_uw *update_addr) { DEFINE_COMPILER; label_addr_list *label_addr; label_addr = sljit_alloc_memory(compiler, sizeof(label_addr_list)); if (label_addr == NULL) return; label_addr->label = LABEL(); label_addr->update_addr = update_addr; label_addr->next = common->label_addrs; common->label_addrs = label_addr; } static SLJIT_INLINE void count_match(compiler_common *common) { DEFINE_COMPILER; OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1); add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO)); } static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) { /* May destroy all locals and registers except TMP2. */ DEFINE_COMPILER; SLJIT_ASSERT(size > 0); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); #ifdef DESTROY_REGISTERS OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); #endif add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0)); } static SLJIT_INLINE void free_stack(compiler_common *common, int size) { DEFINE_COMPILER; SLJIT_ASSERT(size > 0); OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); } static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size) { DEFINE_COMPILER; sljit_uw *result; if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data); if (SLJIT_UNLIKELY(result == NULL)) { sljit_set_compiler_memory_error(compiler); return NULL; } *(void**)result = common->read_only_data_head; common->read_only_data_head = (void *)result; return result + 1; } static void free_read_only_data(void *current, void *allocator_data) { void *next; SLJIT_UNUSED_ARG(allocator_data); while (current != NULL) { next = *(void**)current; SLJIT_FREE(current, allocator_data); current = next; } } static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) { DEFINE_COMPILER; struct sljit_label *loop; int i; /* At this point we can freely use all temporary registers. */ SLJIT_ASSERT(length > 1); /* TMP1 returns with begin - 1. */ OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_S0), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); if (length < 8) { for (i = 1; i < length; i++) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), SLJIT_R0, 0); } else { if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)) == SLJIT_SUCCESS) { GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); loop = LABEL(); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, SLJIT_R0, SLJIT_MEM1(SLJIT_R1), sizeof(sljit_sw)); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); } else { GET_LOCAL_BASE(SLJIT_R1, 0, OVECTOR_START + sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, length - 1); loop = LABEL(); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R0, 0); OP2(SLJIT_ADD, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, sizeof(sljit_sw)); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); } } } static SLJIT_INLINE void reset_fast_fail(compiler_common *common) { DEFINE_COMPILER; sljit_s32 i; SLJIT_ASSERT(common->fast_fail_start_ptr < common->fast_fail_end_ptr); OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); for (i = common->fast_fail_start_ptr; i < common->fast_fail_end_ptr; i += sizeof(sljit_sw)) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, TMP1, 0); } static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) { DEFINE_COMPILER; struct sljit_label *loop; int i; SLJIT_ASSERT(length > 1); /* OVECTOR(1) contains the "string begin - 1" constant. */ if (length > 2) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); if (length < 8) { for (i = 2; i < length; i++) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(i), TMP1, 0); } else { if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)) == SLJIT_SUCCESS) { GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); loop = LABEL(); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_STORE | SLJIT_MEM_PRE, TMP1, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); } else { GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + 2 * sizeof(sljit_sw)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); loop = LABEL(); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, TMP1, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(sljit_sw)); OP2(SLJIT_SUB | SLJIT_SET_Z, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); } } OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); if (common->mark_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0); if (common->control_head_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, end)); } static sljit_sw SLJIT_FUNC do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg) { while (current != NULL) { switch (current[1]) { case type_then_trap: break; case type_mark: if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[2]) == 0) return current[3]; break; default: SLJIT_UNREACHABLE(); break; } SLJIT_ASSERT(current[0] == 0 || current < (sljit_sw*)current[0]); current = (sljit_sw*)current[0]; } return 0; } static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) { DEFINE_COMPILER; struct sljit_label *loop; struct sljit_jump *early_quit; BOOL has_pre; /* At this point we can freely use all registers. */ OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); if (common->mark_ptr != 0) OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count)); if (common->mark_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0); OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin)); has_pre = sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)) == SLJIT_SUCCESS; GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START - (has_pre ? sizeof(sljit_sw) : 0)); /* Unlikely, but possible */ early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0); loop = LABEL(); if (has_pre) sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_S1, SLJIT_MEM1(SLJIT_S0), sizeof(sljit_sw)); else { OP1(SLJIT_MOV, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0); OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw)); } OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, sizeof(int)); OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_R0, 0); /* Copy the integer value to the output buffer */ #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R2), 0, SLJIT_S1, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, loop); JUMPHERE(early_quit); /* Calculate the return value, which is the maximum ovector value. */ if (topbracket > 1) { if (sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))) == SLJIT_SUCCESS) { GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); /* OVECTOR(0) is never equal to SLJIT_S2. */ loop = LABEL(); sljit_emit_mem(compiler, SLJIT_MOV | SLJIT_MEM_PRE, SLJIT_R2, SLJIT_MEM1(SLJIT_R0), -(2 * (sljit_sw)sizeof(sljit_sw))); OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); } else { GET_LOCAL_BASE(SLJIT_R0, 0, OVECTOR_START + (topbracket - 1) * 2 * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, topbracket + 1); /* OVECTOR(0) is never equal to SLJIT_S2. */ loop = LABEL(); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), 0); OP2(SLJIT_SUB, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 2 * (sljit_sw)sizeof(sljit_sw)); OP2(SLJIT_SUB, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1); CMPTO(SLJIT_EQUAL, SLJIT_R2, 0, SLJIT_S2, 0, loop); } OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_R1, 0); } else OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); } static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit) { DEFINE_COMPILER; struct sljit_jump *jump; SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2); SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count)); CMPTO(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 2, quit); /* Store match begin and end. */ OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin)); OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, offsets)); jump = CMP(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 3); OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_S0, 0); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0); JUMPHERE(jump); OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); OP2(SLJIT_SUB, SLJIT_S1, 0, STR_END, 0, SLJIT_S0, 0); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0); OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0); JUMPTO(SLJIT_JUMP, quit); } static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) { /* May destroy TMP1. */ DEFINE_COMPILER; struct sljit_jump *jump; if (common->mode == JIT_PARTIAL_SOFT_COMPILE) { /* The value of -1 must be kept for start_used_ptr! */ OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1); /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */ jump = CMP(SLJIT_LESS_EQUAL, TMP1, 0, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); JUMPHERE(jump); } else if (common->mode == JIT_PARTIAL_HARD_COMPILE) { jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); JUMPHERE(jump); } } static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar *cc) { /* Detects if the character has an othercase. */ unsigned int c; #ifdef SUPPORT_UTF if (common->utf) { GETCHAR(c, cc); if (c > 127) { #ifdef SUPPORT_UCP return c != UCD_OTHERCASE(c); #else return FALSE; #endif } #ifndef COMPILE_PCRE8 return common->fcc[c] != c; #endif } else #endif c = *cc; return MAX_255(c) ? common->fcc[c] != c : FALSE; } static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c) { /* Returns with the othercase. */ #ifdef SUPPORT_UTF if (common->utf && c > 127) { #ifdef SUPPORT_UCP return UCD_OTHERCASE(c); #else return c; #endif } #endif return TABLE_GET(c, common->fcc, c); } static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar *cc) { /* Detects if the character and its othercase has only 1 bit difference. */ unsigned int c, oc, bit; #if defined SUPPORT_UTF && defined COMPILE_PCRE8 int n; #endif #ifdef SUPPORT_UTF if (common->utf) { GETCHAR(c, cc); if (c <= 127) oc = common->fcc[c]; else { #ifdef SUPPORT_UCP oc = UCD_OTHERCASE(c); #else oc = c; #endif } } else { c = *cc; oc = TABLE_GET(c, common->fcc, c); } #else c = *cc; oc = TABLE_GET(c, common->fcc, c); #endif SLJIT_ASSERT(c != oc); bit = c ^ oc; /* Optimized for English alphabet. */ if (c <= 127 && bit == 0x20) return (0 << 8) | 0x20; /* Since c != oc, they must have at least 1 bit difference. */ if (!is_powerof2(bit)) return 0; #if defined COMPILE_PCRE8 #ifdef SUPPORT_UTF if (common->utf && c > 127) { n = GET_EXTRALEN(*cc); while ((bit & 0x3f) == 0) { n--; bit >>= 6; } return (n << 8) | bit; } #endif /* SUPPORT_UTF */ return (0 << 8) | bit; #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef SUPPORT_UTF if (common->utf && c > 65535) { if (bit >= (1 << 10)) bit >>= 10; else return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8)); } #endif /* SUPPORT_UTF */ return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8)); #endif /* COMPILE_PCRE[8|16|32] */ } static void check_partial(compiler_common *common, BOOL force) { /* Checks whether a partial matching is occurred. Does not modify registers. */ DEFINE_COMPILER; struct sljit_jump *jump = NULL; SLJIT_ASSERT(!force || common->mode != JIT_COMPILE); if (common->mode == JIT_COMPILE) return; if (!force) jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); else if (common->mode == JIT_PARTIAL_SOFT_COMPILE) jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1); if (common->mode == JIT_PARTIAL_SOFT_COMPILE) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); else { if (common->partialmatchlabel != NULL) JUMPTO(SLJIT_JUMP, common->partialmatchlabel); else add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); } if (jump != NULL) JUMPHERE(jump); } static void check_str_end(compiler_common *common, jump_list **end_reached) { /* Does not affect registers. Usually used in a tight spot. */ DEFINE_COMPILER; struct sljit_jump *jump; if (common->mode == JIT_COMPILE) { add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); return; } jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); if (common->mode == JIT_PARTIAL_SOFT_COMPILE) { add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); add_jump(compiler, end_reached, JUMP(SLJIT_JUMP)); } else { add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); if (common->partialmatchlabel != NULL) JUMPTO(SLJIT_JUMP, common->partialmatchlabel); else add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); } JUMPHERE(jump); } static void detect_partial_match(compiler_common *common, jump_list **backtracks) { DEFINE_COMPILER; struct sljit_jump *jump; if (common->mode == JIT_COMPILE) { add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); return; } /* Partial matching mode. */ jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0)); if (common->mode == JIT_PARTIAL_SOFT_COMPILE) { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); } else { if (common->partialmatchlabel != NULL) JUMPTO(SLJIT_JUMP, common->partialmatchlabel); else add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); } JUMPHERE(jump); } static void peek_char(compiler_common *common, sljit_u32 max) { /* Reads the character into TMP1, keeps STR_PTR. Does not check STR_END. TMP2 Destroyed. */ DEFINE_COMPILER; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 struct sljit_jump *jump; #endif SLJIT_UNUSED_ARG(max); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf) { if (max < 128) return; jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); JUMPHERE(jump); } #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */ #if defined SUPPORT_UTF && defined COMPILE_PCRE16 if (common->utf) { if (max < 0xd800) return; OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); /* TMP2 contains the high surrogate. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); JUMPHERE(jump); } #endif } #if defined SUPPORT_UTF && defined COMPILE_PCRE8 static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass) { /* Tells whether the character codes below 128 are enough to determine a match. */ const sljit_u8 value = nclass ? 0xff : 0; const sljit_u8 *end = bitset + 32; bitset += 16; do { if (*bitset++ != value) return FALSE; } while (bitset < end); return TRUE; } static void read_char7_type(compiler_common *common, BOOL full_read) { /* Reads the precise character type of a character into TMP1, if the character is less than 128. Otherwise it returns with zero. Does not check STR_END. The full_read argument tells whether characters above max are accepted or not. */ DEFINE_COMPILER; struct sljit_jump *jump; SLJIT_ASSERT(common->utf); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); if (full_read) { jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); JUMPHERE(jump); } } #endif /* SUPPORT_UTF && COMPILE_PCRE8 */ static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr) { /* Reads the precise value of a character into TMP1, if the character is between min and max (c >= min && c <= max). Otherwise it returns with a value outside the range. Does not check STR_END. */ DEFINE_COMPILER; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 struct sljit_jump *jump; #endif #if defined SUPPORT_UTF && defined COMPILE_PCRE8 struct sljit_jump *jump2; #endif SLJIT_UNUSED_ARG(update_str_ptr); SLJIT_UNUSED_ARG(min); SLJIT_UNUSED_ARG(max); SLJIT_ASSERT(min <= max); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf) { if (max < 128 && !update_str_ptr) return; jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); if (min >= 0x10000) { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf0); if (update_str_ptr) OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x7); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); if (!update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); JUMPHERE(jump2); if (update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0); } else if (min >= 0x800 && max <= 0xffff) { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xe0); if (update_str_ptr) OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xf); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); if (!update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); JUMPHERE(jump2); if (update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0); } else if (max >= 0x800) add_jump(compiler, (max < 0x10000) ? &common->utfreadchar16 : &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); else if (max < 128) { OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); } else { OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (!update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); else OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); if (update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, RETURN_ADDR, 0); } JUMPHERE(jump); } #endif #if defined SUPPORT_UTF && defined COMPILE_PCRE16 if (common->utf) { if (max >= 0x10000) { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); /* TMP2 contains the high surrogate. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x40); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); JUMPHERE(jump); return; } if (max < 0xd800 && !update_str_ptr) return; /* Skip low surrogate if necessary. */ OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800); jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); if (update_str_ptr) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); if (max >= 0xd800) OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000); JUMPHERE(jump); } #endif } static SLJIT_INLINE void read_char(compiler_common *common) { read_char_range(common, 0, READ_CHAR_MAX, TRUE); } static void read_char8_type(compiler_common *common, BOOL update_str_ptr) { /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ DEFINE_COMPILER; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 struct sljit_jump *jump; #endif #if defined SUPPORT_UTF && defined COMPILE_PCRE8 struct sljit_jump *jump2; #endif SLJIT_UNUSED_ARG(update_str_ptr); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf) { /* This can be an extra read in some situations, but hopefully it is needed in most cases. */ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); jump = CMP(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0xc0); if (!update_str_ptr) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); jump2 = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); JUMPHERE(jump2); } else add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL)); JUMPHERE(jump); return; } #endif /* SUPPORT_UTF && COMPILE_PCRE8 */ #if !defined COMPILE_PCRE8 /* The ctypes array contains only 256 values. */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255); #endif OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); #if !defined COMPILE_PCRE8 JUMPHERE(jump); #endif #if defined SUPPORT_UTF && defined COMPILE_PCRE16 if (common->utf && update_str_ptr) { /* Skip low surrogate if necessary. */ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xd800); jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0xdc00 - 0xd800 - 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPHERE(jump); } #endif /* SUPPORT_UTF && COMPILE_PCRE16 */ } static void skip_char_back(compiler_common *common) { /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */ DEFINE_COMPILER; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 #if defined COMPILE_PCRE8 struct sljit_label *label; if (common->utf) { label = LABEL(); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); return; } #elif defined COMPILE_PCRE16 if (common->utf) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); /* Skip low surrogate if necessary. */ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); return; } #endif /* COMPILE_PCRE[8|16] */ #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpifmatch) { /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */ DEFINE_COMPILER; struct sljit_jump *jump; if (nltype == NLTYPE_ANY) { add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(jumpifmatch ? SLJIT_NOT_ZERO : SLJIT_ZERO)); } else if (nltype == NLTYPE_ANYCRLF) { if (jumpifmatch) { add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR)); add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); } else { jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); JUMPHERE(jump); } } else { SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); add_jump(compiler, backtracks, CMP(jumpifmatch ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); } } #ifdef SUPPORT_UTF #if defined COMPILE_PCRE8 static void do_utfreadchar(compiler_common *common) { /* Fast decoding a UTF-8 character. TMP1 contains the first byte of the character (>= 0xc0). Return char value in TMP1, length in TMP2. */ DEFINE_COMPILER; struct sljit_jump *jump; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Searching for the first zero. */ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(jump); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000); jump = JUMP(SLJIT_NOT_ZERO); /* Three byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); /* Four byte sequence. */ JUMPHERE(jump); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(4)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } static void do_utfreadchar16(compiler_common *common) { /* Fast decoding a UTF-8 character. TMP1 contains the first byte of the character (>= 0xc0). Return value in TMP1. */ DEFINE_COMPILER; struct sljit_jump *jump; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Searching for the first zero. */ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(jump); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_NOT_ZERO); /* This code runs only in 8 bit mode. No need to shift the value. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x800); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); /* Three byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } static void do_utfreadtype8(compiler_common *common) { /* Fast decoding a UTF-8 character type. TMP2 contains the first byte of the character (>= 0xc0). Return value in TMP1. */ DEFINE_COMPILER; struct sljit_jump *jump; struct sljit_jump *compare; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); /* The upper 5 bits are known at this point. */ compare = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 0x3); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(compare); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); /* We only have types for characters less than 256. */ JUMPHERE(jump); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } #endif /* COMPILE_PCRE8 */ #endif /* SUPPORT_UTF */ #ifdef SUPPORT_UCP /* UCD_BLOCK_SIZE must be 128 (see the assert below). */ #define UCD_BLOCK_MASK 127 #define UCD_BLOCK_SHIFT 7 static void do_getucd(compiler_common *common) { /* Search the UCD record for the character comes in TMP1. Returns chartype in TMP1 and UCD offset in TMP2. */ DEFINE_COMPILER; #ifdef COMPILE_PCRE32 struct sljit_jump *jump; #endif #if defined SLJIT_DEBUG && SLJIT_DEBUG /* dummy_ucd_record */ const ucd_record *record = GET_UCD(INVALID_UTF_CHAR); SLJIT_ASSERT(record->script == ucp_Common && record->chartype == ucp_Cn && record->gbprop == ucp_gbOther); SLJIT_ASSERT(record->caseset == 0 && record->other_case == 0); #endif SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); #ifdef COMPILE_PCRE32 if (!common->utf) { jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); JUMPHERE(jump); } #endif OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } #endif static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf) { DEFINE_COMPILER; struct sljit_label *mainloop; struct sljit_label *newlinelabel = NULL; struct sljit_jump *start; struct sljit_jump *end = NULL; struct sljit_jump *end2 = NULL; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 struct sljit_jump *singlechar; #endif jump_list *newline = NULL; BOOL newlinecheck = FALSE; BOOL readuchar = FALSE; if (!(hascrorlf || (common->match_end_ptr != 0)) && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) newlinecheck = TRUE; if (common->match_end_ptr != 0) { /* Search for the end of the first line. */ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { mainloop = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); JUMPHERE(end); OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } else { end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); mainloop = LABEL(); /* Continual stores does not cause data dependency. */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0); read_char_range(common, common->nlmin, common->nlmax, TRUE); check_newlinechar(common, common->nltype, &newline, TRUE); CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, mainloop); JUMPHERE(end); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, STR_PTR, 0); set_jumps(newline, LABEL()); } OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); } start = JUMP(SLJIT_JUMP); if (newlinecheck) { newlinelabel = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); end2 = JUMP(SLJIT_JUMP); } mainloop = LABEL(); /* Increasing the STR_PTR here requires one less jump in the most common case. */ #ifdef SUPPORT_UTF if (common->utf) readuchar = TRUE; #endif if (newlinecheck) readuchar = TRUE; if (readuchar) OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); if (newlinecheck) CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 #if defined COMPILE_PCRE8 if (common->utf) { singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(singlechar); } #elif defined COMPILE_PCRE16 if (common->utf) { singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(singlechar); } #endif /* COMPILE_PCRE[8|16] */ #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */ JUMPHERE(start); if (newlinecheck) { JUMPHERE(end); JUMPHERE(end2); } return mainloop; } #define MAX_N_CHARS 16 #define MAX_DIFF_CHARS 6 static SLJIT_INLINE void add_prefix_char(pcre_uchar chr, pcre_uchar *chars) { pcre_uchar i, len; len = chars[0]; if (len == 255) return; if (len == 0) { chars[0] = 1; chars[1] = chr; return; } for (i = len; i > 0; i--) if (chars[i] == chr) return; if (len >= MAX_DIFF_CHARS - 1) { chars[0] = 255; return; } len++; chars[len] = chr; chars[0] = len; } static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uchar *chars, int max_chars, sljit_u32 *rec_count) { /* Recursive function, which scans prefix literals. */ BOOL last, any, class, caseless; int len, repeat, len_save, consumed = 0; sljit_u32 chr; /* Any unicode character. */ sljit_u8 *bytes, *bytes_end, byte; pcre_uchar *alternative, *cc_save, *oc; #if defined SUPPORT_UTF && defined COMPILE_PCRE8 pcre_uchar othercase[8]; #elif defined SUPPORT_UTF && defined COMPILE_PCRE16 pcre_uchar othercase[2]; #else pcre_uchar othercase[1]; #endif repeat = 1; while (TRUE) { if (*rec_count == 0) return 0; (*rec_count)--; last = TRUE; any = FALSE; class = FALSE; caseless = FALSE; switch (*cc) { case OP_CHARI: caseless = TRUE; case OP_CHAR: last = FALSE; cc++; break; case OP_SOD: case OP_SOM: case OP_SET_SOM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_EODN: case OP_EOD: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: /* Zero width assertions. */ cc++; continue; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: cc = bracketend(cc); continue; case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: caseless = TRUE; case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: cc++; break; case OP_EXACTI: caseless = TRUE; case OP_EXACT: repeat = GET2(cc, 1); last = FALSE; cc += 1 + IMM2_SIZE; break; case OP_QUERYI: case OP_MINQUERYI: case OP_POSQUERYI: caseless = TRUE; case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY: len = 1; cc++; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count); if (max_chars == 0) return consumed; last = FALSE; break; case OP_KET: cc += 1 + LINK_SIZE; continue; case OP_ALT: cc += GET(cc, 1); continue; case OP_ONCE: case OP_ONCE_NC: case OP_BRA: case OP_BRAPOS: case OP_CBRA: case OP_CBRAPOS: alternative = cc + GET(cc, 1); while (*alternative == OP_ALT) { max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, max_chars, rec_count); if (max_chars == 0) return consumed; alternative += GET(alternative, 1); } if (*cc == OP_CBRA || *cc == OP_CBRAPOS) cc += IMM2_SIZE; cc += 1 + LINK_SIZE; continue; case OP_CLASS: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE)) return consumed; #endif class = TRUE; break; case OP_NCLASS: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) return consumed; #endif class = TRUE; break; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) return consumed; #endif any = TRUE; cc += GET(cc, 1); break; #endif case OP_DIGIT: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) return consumed; #endif any = TRUE; cc++; break; case OP_WHITESPACE: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE)) return consumed; #endif any = TRUE; cc++; break; case OP_WORDCHAR: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE)) return consumed; #endif any = TRUE; cc++; break; case OP_NOT: case OP_NOTI: cc++; /* Fall through. */ case OP_NOT_DIGIT: case OP_NOT_WHITESPACE: case OP_NOT_WORDCHAR: case OP_ANY: case OP_ALLANY: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) return consumed; #endif any = TRUE; cc++; break; #ifdef SUPPORT_UTF case OP_NOTPROP: case OP_PROP: #ifndef COMPILE_PCRE32 if (common->utf) return consumed; #endif any = TRUE; cc += 1 + 2; break; #endif case OP_TYPEEXACT: repeat = GET2(cc, 1); cc += 1 + IMM2_SIZE; continue; case OP_NOTEXACT: case OP_NOTEXACTI: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) return consumed; #endif any = TRUE; repeat = GET2(cc, 1); cc += 1 + IMM2_SIZE + 1; break; default: return consumed; } if (any) { do { chars[0] = 255; consumed++; if (--max_chars == 0) return consumed; chars += MAX_DIFF_CHARS; } while (--repeat > 0); repeat = 1; continue; } if (class) { bytes = (sljit_u8*) (cc + 1); cc += 1 + 32 / sizeof(pcre_uchar); switch (*cc) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPOSSTAR: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSQUERY: max_chars = scan_prefix(common, cc + 1, chars, max_chars, rec_count); if (max_chars == 0) return consumed; break; default: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRPOSPLUS: break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: repeat = GET2(cc, 1); if (repeat <= 0) return consumed; break; } do { if (bytes[31] & 0x80) chars[0] = 255; else if (chars[0] != 255) { bytes_end = bytes + 32; chr = 0; do { byte = *bytes++; SLJIT_ASSERT((chr & 0x7) == 0); if (byte == 0) chr += 8; else { do { if ((byte & 0x1) != 0) add_prefix_char(chr, chars); byte >>= 1; chr++; } while (byte != 0); chr = (chr + 7) & ~7; } } while (chars[0] != 255 && bytes < bytes_end); bytes = bytes_end - 32; } consumed++; if (--max_chars == 0) return consumed; chars += MAX_DIFF_CHARS; } while (--repeat > 0); switch (*cc) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPOSSTAR: return consumed; case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSQUERY: cc++; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: if (GET2(cc, 1) != GET2(cc, 1 + IMM2_SIZE)) return consumed; cc += 1 + 2 * IMM2_SIZE; break; } repeat = 1; continue; } len = 1; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif if (caseless && char_has_othercase(common, cc)) { #ifdef SUPPORT_UTF if (common->utf) { GETCHAR(chr, cc); if ((int)PRIV(ord2utf)(char_othercase(common, chr), othercase) != len) return consumed; } else #endif { chr = *cc; othercase[0] = TABLE_GET(chr, common->fcc, chr); } } else { caseless = FALSE; othercase[0] = 0; /* Stops compiler warning - PH */ } len_save = len; cc_save = cc; while (TRUE) { oc = othercase; do { chr = *cc; add_prefix_char(*cc, chars); if (caseless) add_prefix_char(*oc, chars); len--; consumed++; if (--max_chars == 0) return consumed; chars += MAX_DIFF_CHARS; cc++; oc++; } while (len > 0); if (--repeat == 0) break; len = len_save; cc = cc_save; } repeat = 1; if (last) return consumed; } } #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) static sljit_s32 character_to_int32(pcre_uchar chr) { sljit_s32 value = (sljit_s32)chr; #if defined COMPILE_PCRE8 #define SSE2_COMPARE_TYPE_INDEX 0 return (value << 24) | (value << 16) | (value << 8) | value; #elif defined COMPILE_PCRE16 #define SSE2_COMPARE_TYPE_INDEX 1 return (value << 16) | value; #elif defined COMPILE_PCRE32 #define SSE2_COMPARE_TYPE_INDEX 2 return value; #else #error "Unsupported unit width" #endif } static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2) { DEFINE_COMPILER; struct sljit_label *start; struct sljit_jump *quit[3]; struct sljit_jump *nomatch; sljit_u8 instruction[8]; sljit_s32 tmp1_ind = sljit_get_register_index(TMP1); sljit_s32 tmp2_ind = sljit_get_register_index(TMP2); sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR); BOOL load_twice = FALSE; pcre_uchar bit; bit = char1 ^ char2; if (!is_powerof2(bit)) bit = 0; if ((char1 != char2) && bit == 0) load_twice = TRUE; quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); /* First part (unaligned start) */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); SLJIT_ASSERT(tmp1_ind < 8 && tmp2_ind == 1); /* MOVD xmm, r/m32 */ instruction[0] = 0x66; instruction[1] = 0x0f; instruction[2] = 0x6e; instruction[3] = 0xc0 | (2 << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 4); if (char1 != char2) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); /* MOVD xmm, r/m32 */ instruction[3] = 0xc0 | (3 << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 4); } /* PSHUFD xmm1, xmm2/m128, imm8 */ instruction[2] = 0x70; instruction[3] = 0xc0 | (2 << 3) | 2; instruction[4] = 0; sljit_emit_op_custom(compiler, instruction, 5); if (char1 != char2) { /* PSHUFD xmm1, xmm2/m128, imm8 */ instruction[3] = 0xc0 | (3 << 3) | 3; instruction[4] = 0; sljit_emit_op_custom(compiler, instruction, 5); } OP2(SLJIT_AND, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 0xf); OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf); /* MOVDQA xmm1, xmm2/m128 */ #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (str_ptr_ind < 8) { instruction[2] = 0x6f; instruction[3] = (0 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = (1 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); } } else { instruction[1] = 0x41; instruction[2] = 0x0f; instruction[3] = 0x6f; instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); sljit_emit_op_custom(compiler, instruction, 5); if (load_twice) { instruction[4] = (1 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 5); } instruction[1] = 0x0f; } #else instruction[2] = 0x6f; instruction[3] = (0 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = (1 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); } #endif if (bit != 0) { /* POR xmm1, xmm2/m128 */ instruction[2] = 0xeb; instruction[3] = 0xc0 | (0 << 3) | 3; sljit_emit_op_custom(compiler, instruction, 4); } /* PCMPEQB/W/D xmm1, xmm2/m128 */ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; instruction[3] = 0xc0 | (0 << 3) | 2; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = 0xc0 | (1 << 3) | 3; sljit_emit_op_custom(compiler, instruction, 4); } /* PMOVMSKB reg, xmm */ instruction[2] = 0xd7; instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0); instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; sljit_emit_op_custom(compiler, instruction, 4); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0); } OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0); /* BSF r32, r/m32 */ instruction[0] = 0x0f; instruction[1] = 0xbc; instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 3); sljit_set_current_flags(compiler, SLJIT_SET_Z); nomatch = JUMP(SLJIT_ZERO); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); quit[1] = JUMP(SLJIT_JUMP); JUMPHERE(nomatch); start = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); quit[2] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); /* Second part (aligned) */ instruction[0] = 0x66; instruction[1] = 0x0f; /* MOVDQA xmm1, xmm2/m128 */ #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (str_ptr_ind < 8) { instruction[2] = 0x6f; instruction[3] = (0 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = (1 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); } } else { instruction[1] = 0x41; instruction[2] = 0x0f; instruction[3] = 0x6f; instruction[4] = (0 << 3) | (str_ptr_ind & 0x7); sljit_emit_op_custom(compiler, instruction, 5); if (load_twice) { instruction[4] = (1 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 5); } instruction[1] = 0x0f; } #else instruction[2] = 0x6f; instruction[3] = (0 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = (1 << 3) | str_ptr_ind; sljit_emit_op_custom(compiler, instruction, 4); } #endif if (bit != 0) { /* POR xmm1, xmm2/m128 */ instruction[2] = 0xeb; instruction[3] = 0xc0 | (0 << 3) | 3; sljit_emit_op_custom(compiler, instruction, 4); } /* PCMPEQB/W/D xmm1, xmm2/m128 */ instruction[2] = 0x74 + SSE2_COMPARE_TYPE_INDEX; instruction[3] = 0xc0 | (0 << 3) | 2; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = 0xc0 | (1 << 3) | 3; sljit_emit_op_custom(compiler, instruction, 4); } /* PMOVMSKB reg, xmm */ instruction[2] = 0xd7; instruction[3] = 0xc0 | (tmp1_ind << 3) | 0; sljit_emit_op_custom(compiler, instruction, 4); if (load_twice) { instruction[3] = 0xc0 | (tmp2_ind << 3) | 1; sljit_emit_op_custom(compiler, instruction, 4); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); } /* BSF r32, r/m32 */ instruction[0] = 0x0f; instruction[1] = 0xbc; instruction[2] = 0xc0 | (tmp1_ind << 3) | tmp1_ind; sljit_emit_op_custom(compiler, instruction, 3); sljit_set_current_flags(compiler, SLJIT_SET_Z); JUMPTO(SLJIT_ZERO, start); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); start = LABEL(); SET_LABEL(quit[0], start); SET_LABEL(quit[1], start); SET_LABEL(quit[2], start); } #undef SSE2_COMPARE_TYPE_INDEX #endif static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_s32 offset) { DEFINE_COMPILER; struct sljit_label *start; struct sljit_jump *quit; struct sljit_jump *found; pcre_uchar mask; #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 struct sljit_label *utf_start = NULL; struct sljit_jump *utf_quit = NULL; #endif BOOL has_match_end = (common->match_end_ptr != 0); if (offset > 0) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); if (has_match_end) { OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); OP2(SLJIT_ADD, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, SLJIT_IMM, IN_UCHARS(offset + 1)); OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP3, 0); sljit_emit_cmov(compiler, SLJIT_GREATER, STR_END, TMP3, 0); } #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf && offset > 0) utf_start = LABEL(); #endif #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) && !(defined SUPPORT_VALGRIND) /* SSE2 accelerated first character search. */ if (sljit_has_cpu_feature(SLJIT_HAS_SSE2)) { fast_forward_first_char2_sse2(common, char1, char2); SLJIT_ASSERT(common->mode == JIT_COMPILE || offset == 0); if (common->mode == JIT_COMPILE) { /* In complete mode, we don't need to run a match when STR_PTR == STR_END. */ SLJIT_ASSERT(common->forced_quit_label == NULL); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf && offset > 0) { SLJIT_ASSERT(common->mode == JIT_COMPILE); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined COMPILE_PCRE8 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); #elif defined COMPILE_PCRE16 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); #else #error "Unknown code width" #endif OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } #endif if (offset > 0) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); } else { OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0); if (has_match_end) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, TMP1, 0); } else sljit_emit_cmov(compiler, SLJIT_GREATER_EQUAL, STR_PTR, STR_END, 0); } if (has_match_end) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); return; } #endif quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); start = LABEL(); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); if (char1 == char2) found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1); else { mask = char1 ^ char2; if (is_powerof2(mask)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); found = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, char1 | mask); } else { OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char1); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char2); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); found = JUMP(SLJIT_NOT_ZERO); } } OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf && offset > 0) utf_quit = JUMP(SLJIT_JUMP); #endif JUMPHERE(found); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf && offset > 0) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined COMPILE_PCRE8 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start); #elif defined COMPILE_PCRE16 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start); #else #error "Unknown code width" #endif OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPHERE(utf_quit); } #endif JUMPHERE(quit); if (has_match_end) { quit = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); if (offset > 0) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); JUMPHERE(quit); OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); } if (offset > 0) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offset)); } static SLJIT_INLINE BOOL fast_forward_first_n_chars(compiler_common *common) { DEFINE_COMPILER; struct sljit_label *start; struct sljit_jump *quit; struct sljit_jump *match; /* bytes[0] represent the number of characters between 0 and MAX_N_BYTES - 1, 255 represents any character. */ pcre_uchar chars[MAX_N_CHARS * MAX_DIFF_CHARS]; sljit_s32 offset; pcre_uchar mask; pcre_uchar *char_set, *char_set_end; int i, max, from; int range_right = -1, range_len; sljit_u8 *update_table = NULL; BOOL in_range; sljit_u32 rec_count; for (i = 0; i < MAX_N_CHARS; i++) chars[i * MAX_DIFF_CHARS] = 0; rec_count = 10000; max = scan_prefix(common, common->start, chars, MAX_N_CHARS, &rec_count); if (max < 1) return FALSE; in_range = FALSE; /* Prevent compiler "uninitialized" warning */ from = 0; range_len = 4 /* minimum length */ - 1; for (i = 0; i <= max; i++) { if (in_range && (i - from) > range_len && (chars[(i - 1) * MAX_DIFF_CHARS] < 255)) { range_len = i - from; range_right = i - 1; } if (i < max && chars[i * MAX_DIFF_CHARS] < 255) { SLJIT_ASSERT(chars[i * MAX_DIFF_CHARS] > 0); if (!in_range) { in_range = TRUE; from = i; } } else in_range = FALSE; } if (range_right >= 0) { update_table = (sljit_u8 *)allocate_read_only_data(common, 256); if (update_table == NULL) return TRUE; memset(update_table, IN_UCHARS(range_len), 256); for (i = 0; i < range_len; i++) { char_set = chars + ((range_right - i) * MAX_DIFF_CHARS); SLJIT_ASSERT(char_set[0] > 0 && char_set[0] < 255); char_set_end = char_set + char_set[0]; char_set++; while (char_set <= char_set_end) { if (update_table[(*char_set) & 0xff] > IN_UCHARS(i)) update_table[(*char_set) & 0xff] = IN_UCHARS(i); char_set++; } } } offset = -1; /* Scan forward. */ for (i = 0; i < max; i++) { if (offset == -1) { if (chars[i * MAX_DIFF_CHARS] <= 2) offset = i; } else if (chars[offset * MAX_DIFF_CHARS] == 2 && chars[i * MAX_DIFF_CHARS] <= 2) { if (chars[i * MAX_DIFF_CHARS] == 1) offset = i; else { mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; if (!is_powerof2(mask)) { mask = chars[i * MAX_DIFF_CHARS + 1] ^ chars[i * MAX_DIFF_CHARS + 2]; if (is_powerof2(mask)) offset = i; } } } } if (range_right < 0) { if (offset < 0) return FALSE; SLJIT_ASSERT(chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2); /* Works regardless the value is 1 or 2. */ mask = chars[offset * MAX_DIFF_CHARS + chars[offset * MAX_DIFF_CHARS]]; fast_forward_first_char2(common, chars[offset * MAX_DIFF_CHARS + 1], mask, offset); return TRUE; } if (range_right == offset) offset = -1; SLJIT_ASSERT(offset == -1 || (chars[offset * MAX_DIFF_CHARS] >= 1 && chars[offset * MAX_DIFF_CHARS] <= 2)); max -= 1; SLJIT_ASSERT(max > 0); if (common->match_end_ptr != 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); quit = CMP(SLJIT_LESS_EQUAL, STR_END, 0, TMP1, 0); OP1(SLJIT_MOV, STR_END, 0, TMP1, 0); JUMPHERE(quit); } else OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); SLJIT_ASSERT(range_right >= 0); #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table); #endif start = LABEL(); quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); #if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right)); #else OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1); #endif #if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(RETURN_ADDR, TMP1), 0); #else OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)update_table); #endif OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, start); if (offset >= 0) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(offset)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); if (chars[offset * MAX_DIFF_CHARS] == 1) CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1], start); else { mask = chars[offset * MAX_DIFF_CHARS + 1] ^ chars[offset * MAX_DIFF_CHARS + 2]; if (is_powerof2(mask)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, mask); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1] | mask, start); } else { match = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 1]); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, chars[offset * MAX_DIFF_CHARS + 2], start); JUMPHERE(match); } } } #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf && offset != 0) { if (offset < 0) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } else OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); #if defined COMPILE_PCRE8 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start); #elif defined COMPILE_PCRE16 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start); #else #error "Unknown code width" #endif if (offset < 0) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } #endif if (offset >= 0) OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPHERE(quit); if (common->match_end_ptr != 0) { if (range_right >= 0) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); if (range_right >= 0) { quit = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); JUMPHERE(quit); } } else OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max)); return TRUE; } #undef MAX_N_CHARS #undef MAX_DIFF_CHARS static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless) { pcre_uchar oc; oc = first_char; if (caseless) { oc = TABLE_GET(first_char, common->fcc, first_char); #if defined SUPPORT_UCP && !defined COMPILE_PCRE8 if (first_char > 127 && common->utf) oc = UCD_OTHERCASE(first_char); #endif } fast_forward_first_char2(common, first_char, oc, 0); } static SLJIT_INLINE void fast_forward_newline(compiler_common *common) { DEFINE_COMPILER; struct sljit_label *loop; struct sljit_jump *lastchar; struct sljit_jump *firstchar; struct sljit_jump *quit; struct sljit_jump *foundcr = NULL; struct sljit_jump *notfoundnl; jump_list *newline = NULL; if (common->match_end_ptr != 0) { OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); } if (common->nltype == NLTYPE_FIXED && common->newline > 255) { lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); loop = LABEL(); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); JUMPHERE(quit); JUMPHERE(firstchar); JUMPHERE(lastchar); if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); return; } OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); skip_char_back(common); loop = LABEL(); common->ff_newline_shortcut = loop; read_char_range(common, common->nlmin, common->nlmax, TRUE); lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); check_newlinechar(common, common->nltype, &newline, FALSE); set_jumps(newline, loop); if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) { quit = JUMP(SLJIT_JUMP); JUMPHERE(foundcr); notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); #endif OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(notfoundnl); JUMPHERE(quit); } JUMPHERE(lastchar); JUMPHERE(firstchar); if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); } static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks); static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, const sljit_u8 *start_bits) { DEFINE_COMPILER; struct sljit_label *start; struct sljit_jump *quit; struct sljit_jump *found = NULL; jump_list *matches = NULL; #ifndef COMPILE_PCRE8 struct sljit_jump *jump; #endif if (common->match_end_ptr != 0) { OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0); OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); } start = LABEL(); quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); #ifdef SUPPORT_UTF if (common->utf) OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); #endif if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches)) { #ifndef COMPILE_PCRE8 jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 255); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); JUMPHERE(jump); #endif OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)start_bits); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); found = JUMP(SLJIT_NOT_ZERO); } #ifdef SUPPORT_UTF if (common->utf) OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); #endif OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #ifdef SUPPORT_UTF #if defined COMPILE_PCRE8 if (common->utf) { CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); } #elif defined COMPILE_PCRE16 if (common->utf) { CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); } #endif /* COMPILE_PCRE[8|16] */ #endif /* SUPPORT_UTF */ JUMPTO(SLJIT_JUMP, start); if (found != NULL) JUMPHERE(found); if (matches != NULL) set_jumps(matches, LABEL()); JUMPHERE(quit); if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); } static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar) { DEFINE_COMPILER; struct sljit_label *loop; struct sljit_jump *toolong; struct sljit_jump *alreadyfound; struct sljit_jump *found; struct sljit_jump *foundoc = NULL; struct sljit_jump *notfound; sljit_u32 oc, bit; SLJIT_ASSERT(common->req_char_ptr != 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr); OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); toolong = CMP(SLJIT_LESS, TMP1, 0, STR_END, 0); alreadyfound = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0); if (has_firstchar) OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); else OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); loop = LABEL(); notfound = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); oc = req_char; if (caseless) { oc = TABLE_GET(req_char, common->fcc, req_char); #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) if (req_char > 127 && common->utf) oc = UCD_OTHERCASE(req_char); #endif } if (req_char == oc) found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); else { bit = req_char ^ oc; if (is_powerof2(bit)) { OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); } else { found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); foundoc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc); } } OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_JUMP, loop); JUMPHERE(found); if (foundoc) JUMPHERE(foundoc); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0); JUMPHERE(alreadyfound); JUMPHERE(toolong); return notfound; } static void do_revertframes(compiler_common *common) { DEFINE_COMPILER; struct sljit_jump *jump; struct sljit_label *mainloop; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP1(SLJIT_MOV, TMP3, 0, STACK_TOP, 0); GET_LOCAL_BASE(TMP1, 0, 0); /* Drop frames until we reach STACK_TOP. */ mainloop = LABEL(); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), -sizeof(sljit_sw)); jump = CMP(SLJIT_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(STACK_TOP), -3 * sizeof(sljit_sw)); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); JUMPTO(SLJIT_JUMP, mainloop); JUMPHERE(jump); jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0); /* End of reverting values. */ OP1(SLJIT_MOV, STACK_TOP, 0, TMP3, 0); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); JUMPHERE(jump); OP1(SLJIT_NEG, TMP2, 0, TMP2, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(STACK_TOP), -2 * sizeof(sljit_sw)); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); JUMPTO(SLJIT_JUMP, mainloop); } static void check_wordboundary(compiler_common *common) { DEFINE_COMPILER; struct sljit_jump *skipread; jump_list *skipread_list = NULL; #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF struct sljit_jump *jump; #endif SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); /* Get type of the previous char, and put it to LOCALS1. */ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, SLJIT_IMM, 0); skipread = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP1, 0); skip_char_back(common); check_start_used_ptr(common); read_char(common); /* Testing char type. */ #ifdef SUPPORT_UCP if (common->use_ucp) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); JUMPHERE(jump); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP2, 0); } else #endif { #ifndef COMPILE_PCRE8 jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #elif defined SUPPORT_UTF /* Here LOCALS1 has already been zeroed. */ jump = NULL; if (common->utf) jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #endif /* COMPILE_PCRE8 */ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0); #ifndef COMPILE_PCRE8 JUMPHERE(jump); #elif defined SUPPORT_UTF if (jump != NULL) JUMPHERE(jump); #endif /* COMPILE_PCRE8 */ } JUMPHERE(skipread); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); check_str_end(common, &skipread_list); peek_char(common, READ_CHAR_MAX); /* Testing char type. This is a code duplication. */ #ifdef SUPPORT_UCP if (common->use_ucp) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); JUMPHERE(jump); } else #endif { #ifndef COMPILE_PCRE8 /* TMP2 may be destroyed by peek_char. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #elif defined SUPPORT_UTF OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); jump = NULL; if (common->utf) jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); #endif OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); #ifndef COMPILE_PCRE8 JUMPHERE(jump); #elif defined SUPPORT_UTF if (jump != NULL) JUMPHERE(jump); #endif /* COMPILE_PCRE8 */ } set_jumps(skipread_list, LABEL()); OP2(SLJIT_XOR | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); } static BOOL check_class_ranges(compiler_common *common, const sljit_u8 *bits, BOOL nclass, BOOL invert, jump_list **backtracks) { /* May destroy TMP1. */ DEFINE_COMPILER; int ranges[MAX_RANGE_SIZE]; sljit_u8 bit, cbit, all; int i, byte, length = 0; bit = bits[0] & 0x1; /* All bits will be zero or one (since bit is zero or one). */ all = -bit; for (i = 0; i < 256; ) { byte = i >> 3; if ((i & 0x7) == 0 && bits[byte] == all) i += 8; else { cbit = (bits[byte] >> (i & 0x7)) & 0x1; if (cbit != bit) { if (length >= MAX_RANGE_SIZE) return FALSE; ranges[length] = i; length++; bit = cbit; all = -cbit; } i++; } } if (((bit == 0) && nclass) || ((bit == 1) && !nclass)) { if (length >= MAX_RANGE_SIZE) return FALSE; ranges[length] = 256; length++; } if (length < 0 || length > 4) return FALSE; bit = bits[0] & 0x1; if (invert) bit ^= 0x1; /* No character is accepted. */ if (length == 0 && bit == 0) add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); switch(length) { case 0: /* When bit != 0, all characters are accepted. */ return TRUE; case 1: add_jump(compiler, backtracks, CMP(bit == 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); return TRUE; case 2: if (ranges[0] + 1 != ranges[1]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); } else add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); return TRUE; case 3: if (bit != 0) { add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); if (ranges[0] + 1 != ranges[1]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); } else add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); return TRUE; } add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[0])); if (ranges[1] + 1 != ranges[2]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1]); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1])); } else add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1])); return TRUE; case 4: if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2]) && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2] && (ranges[1] & (ranges[2] - ranges[0])) == 0 && is_powerof2(ranges[2] - ranges[0])) { SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]); if (ranges[2] + 1 != ranges[3]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2]); add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_LESS : SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); } else add_jump(compiler, backtracks, CMP(bit != 0 ? SLJIT_EQUAL : SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2])); return TRUE; } if (bit != 0) { i = 0; if (ranges[0] + 1 != ranges[1]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); i = ranges[0]; } else add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[0])); if (ranges[2] + 1 != ranges[3]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - i); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[2])); } else add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[2] - i)); return TRUE; } OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[0]); add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, ranges[3] - ranges[0])); if (ranges[1] + 1 != ranges[2]) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0]); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[1])); } else add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, ranges[1] - ranges[0])); return TRUE; default: SLJIT_UNREACHABLE(); return FALSE; } } static void check_anynewline(compiler_common *common) { /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef COMPILE_PCRE8 if (common->utf) { #endif OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); #ifdef COMPILE_PCRE8 } #endif #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } static void check_hspace(compiler_common *common) { /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef COMPILE_PCRE8 if (common->utf) { #endif OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); #ifdef COMPILE_PCRE8 } #endif #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } static void check_vspace(compiler_common *common) { /* Check whether TMP1 contains a newline character. TMP2 destroyed. */ DEFINE_COMPILER; sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 #ifdef COMPILE_PCRE8 if (common->utf) { #endif OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); #ifdef COMPILE_PCRE8 } #endif #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); sljit_emit_fast_return(compiler, RETURN_ADDR, 0); } static void do_casefulcmp(compiler_common *common) { DEFINE_COMPILER; struct sljit_jump *jump; struct sljit_label *label; int char1_reg; int char2_reg; if (sljit_get_register_index(TMP3) < 0) { char1_reg = STR_END; char2_reg = STACK_TOP; } else { char1_reg = TMP3; char2_reg = RETURN_ADDR; } sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); if (char1_reg == STR_END) { OP1(SLJIT_MOV, TMP3, 0, char1_reg, 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, char2_reg, 0); } if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) { label = LABEL(); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); } else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); label = LABEL(); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } else { label = LABEL(); OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0); OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); } if (char1_reg == STR_END) { OP1(SLJIT_MOV, char1_reg, 0, TMP3, 0); OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0); } sljit_emit_fast_return(compiler, TMP1, 0); } static void do_caselesscmp(compiler_common *common) { DEFINE_COMPILER; struct sljit_jump *jump; struct sljit_label *label; int char1_reg = STR_END; int char2_reg; int lcc_table; int opt_type = 0; if (sljit_get_register_index(TMP3) < 0) { char2_reg = STACK_TOP; lcc_table = STACK_LIMIT; } else { char2_reg = RETURN_ADDR; lcc_table = TMP3; } if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) opt_type = 1; else if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)) == SLJIT_SUCCESS) opt_type = 2; sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, char1_reg, 0); if (char2_reg == STACK_TOP) { OP1(SLJIT_MOV, TMP3, 0, char2_reg, 0); OP1(SLJIT_MOV, RETURN_ADDR, 0, lcc_table, 0); } OP1(SLJIT_MOV, lcc_table, 0, SLJIT_IMM, common->lcc); if (opt_type == 1) { label = LABEL(); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); } else if (opt_type == 2) { OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); label = LABEL(); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char1_reg, SLJIT_MEM1(TMP1), IN_UCHARS(1)); sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_PRE, char2_reg, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); } else { label = LABEL(); OP1(MOV_UCHAR, char1_reg, 0, SLJIT_MEM1(TMP1), 0); OP1(MOV_UCHAR, char2_reg, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); } #ifndef COMPILE_PCRE8 jump = CMP(SLJIT_GREATER, char1_reg, 0, SLJIT_IMM, 255); #endif OP1(SLJIT_MOV_U8, char1_reg, 0, SLJIT_MEM2(lcc_table, char1_reg), 0); #ifndef COMPILE_PCRE8 JUMPHERE(jump); jump = CMP(SLJIT_GREATER, char2_reg, 0, SLJIT_IMM, 255); #endif OP1(SLJIT_MOV_U8, char2_reg, 0, SLJIT_MEM2(lcc_table, char2_reg), 0); #ifndef COMPILE_PCRE8 JUMPHERE(jump); #endif if (opt_type == 0) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump = CMP(SLJIT_NOT_EQUAL, char1_reg, 0, char2_reg, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); JUMPTO(SLJIT_NOT_ZERO, label); JUMPHERE(jump); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); if (opt_type == 2) OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); if (char2_reg == STACK_TOP) { OP1(SLJIT_MOV, char2_reg, 0, TMP3, 0); OP1(SLJIT_MOV, lcc_table, 0, RETURN_ADDR, 0); } OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); sljit_emit_fast_return(compiler, TMP1, 0); } #if defined SUPPORT_UTF && defined SUPPORT_UCP static const pcre_uchar * SLJIT_FUNC do_utf_caselesscmp(pcre_uchar *src1, pcre_uchar *src2, pcre_uchar *end1, pcre_uchar *end2) { /* This function would be ineffective to do in JIT level. */ sljit_u32 c1, c2; const ucd_record *ur; const sljit_u32 *pp; while (src1 < end1) { if (src2 >= end2) return (pcre_uchar*)1; GETCHARINC(c1, src1); GETCHARINC(c2, src2); ur = GET_UCD(c2); if (c1 != c2 && c1 != c2 + ur->other_case) { pp = PRIV(ucd_caseless_sets) + ur->caseset; for (;;) { if (c1 < *pp) return NULL; if (c1 == *pp++) break; } } } return src2; } #endif /* SUPPORT_UTF && SUPPORT_UCP */ static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, compare_context *context, jump_list **backtracks) { DEFINE_COMPILER; unsigned int othercasebit = 0; pcre_uchar *othercasechar = NULL; #ifdef SUPPORT_UTF int utflength; #endif if (caseless && char_has_othercase(common, cc)) { othercasebit = char_get_othercase_bit(common, cc); SLJIT_ASSERT(othercasebit); /* Extracting bit difference info. */ #if defined COMPILE_PCRE8 othercasechar = cc + (othercasebit >> 8); othercasebit &= 0xff; #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 /* Note that this code only handles characters in the BMP. If there ever are characters outside the BMP whose othercase differs in only one bit from itself (there currently are none), this code will need to be revised for COMPILE_PCRE32. */ othercasechar = cc + (othercasebit >> 9); if ((othercasebit & 0x100) != 0) othercasebit = (othercasebit & 0xff) << 8; else othercasebit &= 0xff; #endif /* COMPILE_PCRE[8|16|32] */ } if (context->sourcereg == -1) { #if defined COMPILE_PCRE8 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED if (context->length >= 4) OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); else if (context->length >= 2) OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); else #endif OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); #elif defined COMPILE_PCRE16 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED if (context->length >= 4) OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); else #endif OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); #elif defined COMPILE_PCRE32 OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); #endif /* COMPILE_PCRE[8|16|32] */ context->sourcereg = TMP2; } #ifdef SUPPORT_UTF utflength = 1; if (common->utf && HAS_EXTRALEN(*cc)) utflength += GET_EXTRALEN(*cc); do { #endif context->length -= IN_UCHARS(1); #if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16) /* Unaligned read is supported. */ if (othercasebit != 0 && othercasechar == cc) { context->c.asuchars[context->ucharptr] = *cc | othercasebit; context->oc.asuchars[context->ucharptr] = othercasebit; } else { context->c.asuchars[context->ucharptr] = *cc; context->oc.asuchars[context->ucharptr] = 0; } context->ucharptr++; #if defined COMPILE_PCRE8 if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) #else if (context->ucharptr >= 2 || context->length == 0) #endif { if (context->length >= 4) OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); else if (context->length >= 2) OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); #if defined COMPILE_PCRE8 else if (context->length >= 1) OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); #endif /* COMPILE_PCRE8 */ context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; switch(context->ucharptr) { case 4 / sizeof(pcre_uchar): if (context->oc.asint != 0) OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); break; case 2 / sizeof(pcre_uchar): if (context->oc.asushort != 0) OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); break; #ifdef COMPILE_PCRE8 case 1: if (context->oc.asbyte != 0) OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); break; #endif default: SLJIT_UNREACHABLE(); break; } context->ucharptr = 0; } #else /* Unaligned read is unsupported or in 32 bit mode. */ if (context->length >= 1) OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; if (othercasebit != 0 && othercasechar == cc) { OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); } else add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); #endif cc++; #ifdef SUPPORT_UTF utflength--; } while (utflength > 0); #endif return cc; } #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 #define SET_TYPE_OFFSET(value) \ if ((value) != typeoffset) \ { \ if ((value) < typeoffset) \ OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \ else \ OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \ } \ typeoffset = (value); #define SET_CHAR_OFFSET(value) \ if ((value) != charoffset) \ { \ if ((value) < charoffset) \ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(charoffset - (value))); \ else \ OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)((value) - charoffset)); \ } \ charoffset = (value); static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr); static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) { DEFINE_COMPILER; jump_list *found = NULL; jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks; sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX; struct sljit_jump *jump = NULL; pcre_uchar *ccbegin; int compares, invertcmp, numberofcmps; #if defined SUPPORT_UTF && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16) BOOL utf = common->utf; #endif #ifdef SUPPORT_UCP BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE; BOOL charsaved = FALSE; int typereg = TMP1; const sljit_u32 *other_cases; sljit_uw typeoffset; #endif /* Scanning the necessary info. */ cc++; ccbegin = cc; compares = 0; if (cc[-1] & XCL_MAP) { min = 0; cc += 32 / sizeof(pcre_uchar); } while (*cc != XCL_END) { compares++; if (*cc == XCL_SINGLE) { cc ++; GETCHARINCTEST(c, cc); if (c > max) max = c; if (c < min) min = c; #ifdef SUPPORT_UCP needschar = TRUE; #endif } else if (*cc == XCL_RANGE) { cc ++; GETCHARINCTEST(c, cc); if (c < min) min = c; GETCHARINCTEST(c, cc); if (c > max) max = c; #ifdef SUPPORT_UCP needschar = TRUE; #endif } #ifdef SUPPORT_UCP else { SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); cc++; if (*cc == PT_CLIST) { other_cases = PRIV(ucd_caseless_sets) + cc[1]; while (*other_cases != NOTACHAR) { if (*other_cases > max) max = *other_cases; if (*other_cases < min) min = *other_cases; other_cases++; } } else { max = READ_CHAR_MAX; min = 0; } switch(*cc) { case PT_ANY: /* Any either accepts everything or ignored. */ if (cc[-1] == XCL_PROP) { compile_char1_matchingpath(common, OP_ALLANY, cc, backtracks, FALSE); if (list == backtracks) add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); return; } break; case PT_LAMP: case PT_GC: case PT_PC: case PT_ALNUM: needstype = TRUE; break; case PT_SC: needsscript = TRUE; break; case PT_SPACE: case PT_PXSPACE: case PT_WORD: case PT_PXGRAPH: case PT_PXPRINT: case PT_PXPUNCT: needstype = TRUE; needschar = TRUE; break; case PT_CLIST: case PT_UCNC: needschar = TRUE; break; default: SLJIT_UNREACHABLE(); break; } cc += 2; } #endif } SLJIT_ASSERT(compares > 0); /* We are not necessary in utf mode even in 8 bit mode. */ cc = ccbegin; read_char_range(common, min, max, (cc[-1] & XCL_NOT) != 0); if ((cc[-1] & XCL_HASPROP) == 0) { if ((cc[-1] & XCL_MAP) != 0) { jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); if (!check_class_ranges(common, (const sljit_u8 *)cc, (((const sljit_u8 *)cc)[31] & 0x80) != 0, TRUE, &found)) { OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO)); } add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(jump); cc += 32 / sizeof(pcre_uchar); } else { OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, min); add_jump(compiler, (cc[-1] & XCL_NOT) == 0 ? backtracks : &found, CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, max - min)); } } else if ((cc[-1] & XCL_MAP) != 0) { OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); #ifdef SUPPORT_UCP charsaved = TRUE; #endif if (!check_class_ranges(common, (const sljit_u8 *)cc, FALSE, TRUE, list)) { #ifdef COMPILE_PCRE8 jump = NULL; if (common->utf) #endif jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO)); #ifdef COMPILE_PCRE8 if (common->utf) #endif JUMPHERE(jump); } OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); cc += 32 / sizeof(pcre_uchar); } #ifdef SUPPORT_UCP if (needstype || needsscript) { if (needschar && !charsaved) OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); #ifdef COMPILE_PCRE32 if (!common->utf) { jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x10ffff + 1); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); JUMPHERE(jump); } #endif OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1)); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); /* Before anything else, we deal with scripts. */ if (needsscript) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); ccbegin = cc; while (*cc != XCL_END) { if (*cc == XCL_SINGLE) { cc ++; GETCHARINCTEST(c, cc); } else if (*cc == XCL_RANGE) { cc ++; GETCHARINCTEST(c, cc); GETCHARINCTEST(c, cc); } else { SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); cc++; if (*cc == PT_SC) { compares--; invertcmp = (compares == 0 && list != backtracks); if (cc[-1] == XCL_NOTPROP) invertcmp ^= 0x1; jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]); add_jump(compiler, compares > 0 ? list : backtracks, jump); } cc += 2; } } cc = ccbegin; } if (needschar) { OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); } if (needstype) { if (!needschar) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); } else { OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); typereg = RETURN_ADDR; } } } #endif /* Generating code. */ charoffset = 0; numberofcmps = 0; #ifdef SUPPORT_UCP typeoffset = 0; #endif while (*cc != XCL_END) { compares--; invertcmp = (compares == 0 && list != backtracks); jump = NULL; if (*cc == XCL_SINGLE) { cc ++; GETCHARINCTEST(c, cc); if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) { OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL); numberofcmps++; } else if (numberofcmps > 0) { OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); numberofcmps = 0; } else { jump = CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); numberofcmps = 0; } } else if (*cc == XCL_RANGE) { cc ++; GETCHARINCTEST(c, cc); SET_CHAR_OFFSET(c); GETCHARINCTEST(c, cc); if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) { OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); numberofcmps++; } else if (numberofcmps > 0) { OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); numberofcmps = 0; } else { jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset)); numberofcmps = 0; } } #ifdef SUPPORT_UCP else { SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); if (*cc == XCL_NOTPROP) invertcmp ^= 0x1; cc++; switch(*cc) { case PT_ANY: if (!invertcmp) jump = JUMP(SLJIT_JUMP); break; case PT_LAMP: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_GC: c = PRIV(ucp_typerange)[(int)cc[1] * 2]; SET_TYPE_OFFSET(c); jump = CMP(SLJIT_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c); break; case PT_PC: jump = CMP(SLJIT_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset); break; case PT_SC: compares++; /* Do nothing. */ break; case PT_SPACE: case PT_PXSPACE: SET_CHAR_OFFSET(9); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); SET_TYPE_OFFSET(ucp_Zl); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_WORD: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset)); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); /* Fall through. */ case PT_ALNUM: SET_TYPE_OFFSET(ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Nd); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_CLIST: other_cases = PRIV(ucd_caseless_sets) + cc[1]; /* At least three characters are required. Otherwise this case would be handled by the normal code path. */ SLJIT_ASSERT(other_cases[0] != NOTACHAR && other_cases[1] != NOTACHAR && other_cases[2] != NOTACHAR); SLJIT_ASSERT(other_cases[0] < other_cases[1] && other_cases[1] < other_cases[2]); /* Optimizing character pairs, if their difference is power of 2. */ if (is_powerof2(other_cases[1] ^ other_cases[0])) { if (charoffset == 0) OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); else { OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); } OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); other_cases += 2; } else if (is_powerof2(other_cases[2] ^ other_cases[1])) { if (charoffset == 0) OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, other_cases[2] ^ other_cases[1]); else { OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); } OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset)); OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); other_cases += 3; } else { OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); } while (*other_cases != NOTACHAR) { OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset)); OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL); } jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_UCNC: OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset)); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset)); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset)); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); SET_CHAR_OFFSET(0xa0); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset)); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; case PT_PXGRAPH: /* C and Z groups are the farthest two groups. */ SET_TYPE_OFFSET(ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER); jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); /* In case of ucp_Cf, we overwrite the result. */ SET_CHAR_OFFSET(0x2066); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); JUMPHERE(jump); jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); break; case PT_PXPRINT: /* C and Z groups are the farthest two groups. */ SET_TYPE_OFFSET(ucp_Ll); OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll); OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL); jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll); /* In case of ucp_Cf, we overwrite the result. */ SET_CHAR_OFFSET(0x2066); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066); OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL); JUMPHERE(jump); jump = CMP(SLJIT_ZERO ^ invertcmp, TMP2, 0, SLJIT_IMM, 0); break; case PT_PXPUNCT: SET_TYPE_OFFSET(ucp_Sc); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f); OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Pc); OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL); jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp); break; default: SLJIT_UNREACHABLE(); break; } cc += 2; } #endif if (jump != NULL) add_jump(compiler, compares > 0 ? list : backtracks, jump); } if (found != NULL) set_jumps(found, LABEL()); } #undef SET_TYPE_OFFSET #undef SET_CHAR_OFFSET #endif static pcre_uchar *compile_simple_assertion_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks) { DEFINE_COMPILER; int length; struct sljit_jump *jump[4]; #ifdef SUPPORT_UTF struct sljit_label *label; #endif /* SUPPORT_UTF */ switch(type) { case OP_SOD: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); return cc; case OP_SOM: OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); return cc; case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; case OP_EODN: /* Requires rather complex checks. */ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (common->mode == JIT_COMPILE) add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); else { jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0); OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL); add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL)); check_partial(common, TRUE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(jump[1]); } OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); } else if (common->nltype == NLTYPE_FIXED) { OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); } else { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); jump[2] = JUMP(SLJIT_GREATER); add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */); /* Equal. */ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); jump[3] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(jump[1]); if (common->nltype == NLTYPE_ANYCRLF) { OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, STR_END, 0)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); } else { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STR_PTR, 0); read_char_range(common, common->nlmin, common->nlmax, TRUE); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); } JUMPHERE(jump[2]); JUMPHERE(jump[3]); } JUMPHERE(jump[0]); check_partial(common, FALSE); return cc; case OP_EOD: add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); check_partial(common, FALSE); return cc; case OP_DOLL: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); if (!common->endonly) compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks); else { add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0)); check_partial(common, FALSE); } return cc; case OP_DOLLM: jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); check_partial(common, FALSE); jump[0] = JUMP(SLJIT_JUMP); JUMPHERE(jump[1]); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (common->mode == JIT_COMPILE) add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0)); else { jump[1] = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0); /* STR_PTR = STR_END - IN_UCHARS(1) */ add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); check_partial(common, TRUE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(jump[1]); } OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); } else { peek_char(common, common->nlmax); check_newlinechar(common, common->nltype, backtracks, FALSE); } JUMPHERE(jump[0]); return cc; case OP_CIRC: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0)); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); return cc; case OP_CIRCM: OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); jump[0] = JUMP(SLJIT_JUMP); JUMPHERE(jump[1]); add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); add_jump(compiler, backtracks, CMP(SLJIT_LESS, TMP2, 0, TMP1, 0)); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); } else { skip_char_back(common); read_char_range(common, common->nlmin, common->nlmax, TRUE); check_newlinechar(common, common->nltype, backtracks, FALSE); } JUMPHERE(jump[0]); return cc; case OP_REVERSE: length = GET(cc, 0); if (length == 0) return cc + LINK_SIZE; OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); #ifdef SUPPORT_UTF if (common->utf) { OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); label = LABEL(); add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); skip_char_back(common); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else #endif { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); add_jump(compiler, backtracks, CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0)); } check_start_used_ptr(common); return cc + LINK_SIZE; } SLJIT_UNREACHABLE(); return cc; } static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr) { DEFINE_COMPILER; int length; unsigned int c, oc, bit; compare_context context; struct sljit_jump *jump[3]; jump_list *end_list; #ifdef SUPPORT_UTF struct sljit_label *label; #ifdef SUPPORT_UCP pcre_uchar propdata[5]; #endif #endif /* SUPPORT_UTF */ switch(type) { case OP_NOT_DIGIT: case OP_DIGIT: /* Digits are usually 0-9, so it is worth to optimize them. */ if (check_str_ptr) detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE)) read_char7_type(common, type == OP_NOT_DIGIT); else #endif read_char8_type(common, type == OP_NOT_DIGIT); /* Flip the starting bit in the negative case. */ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; case OP_NOT_WHITESPACE: case OP_WHITESPACE: if (check_str_ptr) detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE)) read_char7_type(common, type == OP_NOT_WHITESPACE); else #endif read_char8_type(common, type == OP_NOT_WHITESPACE); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; case OP_NOT_WORDCHAR: case OP_WORDCHAR: if (check_str_ptr) detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE)) read_char7_type(common, type == OP_NOT_WORDCHAR); else #endif read_char8_type(common, type == OP_NOT_WORDCHAR); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO)); return cc; case OP_ANY: if (check_str_ptr) detect_partial_match(common, backtracks); read_char_range(common, common->nlmin, common->nlmax, TRUE); if (common->nltype == NLTYPE_FIXED && common->newline > 255) { jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); end_list = NULL; if (common->mode != JIT_PARTIAL_HARD_COMPILE) add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); else check_str_end(common, &end_list); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); set_jumps(end_list, LABEL()); JUMPHERE(jump[0]); } else check_newlinechar(common, common->nltype, backtracks, TRUE); return cc; case OP_ALLANY: if (check_str_ptr) detect_partial_match(common, backtracks); #ifdef SUPPORT_UTF if (common->utf) { OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 #if defined COMPILE_PCRE8 jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); #elif defined COMPILE_PCRE16 jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); #endif JUMPHERE(jump[0]); #endif /* COMPILE_PCRE[8|16] */ return cc; } #endif OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); return cc; case OP_ANYBYTE: if (check_str_ptr) detect_partial_match(common, backtracks); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); return cc; #ifdef SUPPORT_UTF #ifdef SUPPORT_UCP case OP_NOTPROP: case OP_PROP: propdata[0] = XCL_HASPROP; propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP; propdata[2] = cc[0]; propdata[3] = cc[1]; propdata[4] = XCL_END; if (check_str_ptr) detect_partial_match(common, backtracks); compile_xclass_matchingpath(common, propdata, backtracks); return cc + 2; #endif #endif case OP_ANYNL: if (check_str_ptr) detect_partial_match(common, backtracks); read_char_range(common, common->bsr_nlmin, common->bsr_nlmax, FALSE); jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); /* We don't need to handle soft partial matching case. */ end_list = NULL; if (common->mode != JIT_PARTIAL_HARD_COMPILE) add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); else check_str_end(common, &end_list); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump[2] = JUMP(SLJIT_JUMP); JUMPHERE(jump[0]); check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); set_jumps(end_list, LABEL()); JUMPHERE(jump[1]); JUMPHERE(jump[2]); return cc; case OP_NOT_HSPACE: case OP_HSPACE: if (check_str_ptr) detect_partial_match(common, backtracks); read_char_range(common, 0x9, 0x3000, type == OP_NOT_HSPACE); add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; case OP_NOT_VSPACE: case OP_VSPACE: if (check_str_ptr) detect_partial_match(common, backtracks); read_char_range(common, 0xa, 0x2029, type == OP_NOT_VSPACE); add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); sljit_set_current_flags(compiler, SLJIT_SET_Z); add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO)); return cc; #ifdef SUPPORT_UCP case OP_EXTUNI: if (check_str_ptr) detect_partial_match(common, backtracks); read_char(common); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop)); /* Optimize register allocation: use a real register. */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); OP1(SLJIT_MOV_U8, STACK_TOP, 0, SLJIT_MEM2(TMP1, TMP2), 3); label = LABEL(); jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); read_char(common); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, gbprop)); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM2(TMP1, TMP2), 3); OP2(SLJIT_SHL, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 2); OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(STACK_TOP), (sljit_sw)PRIV(ucp_gbtable)); OP1(SLJIT_MOV, STACK_TOP, 0, TMP2, 0); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); JUMPTO(SLJIT_NOT_ZERO, label); OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); JUMPHERE(jump[0]); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); if (common->mode == JIT_PARTIAL_HARD_COMPILE) { jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0); /* Since we successfully read a char above, partial matching must occure. */ check_partial(common, TRUE); JUMPHERE(jump[0]); } return cc; #endif case OP_CHAR: case OP_CHARI: length = 1; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); #endif if (common->mode == JIT_COMPILE && check_str_ptr && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) { OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); context.length = IN_UCHARS(length); context.sourcereg = -1; #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED context.ucharptr = 0; #endif return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); } if (check_str_ptr) detect_partial_match(common, backtracks); #ifdef SUPPORT_UTF if (common->utf) { GETCHAR(c, cc); } else #endif c = *cc; if (type == OP_CHAR || !char_has_othercase(common, cc)) { read_char_range(common, c, c, FALSE); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); return cc + length; } oc = char_othercase(common, c); read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, FALSE); bit = c ^ oc; if (is_powerof2(bit)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); return cc + length; } jump[0] = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); JUMPHERE(jump[0]); return cc + length; case OP_NOT: case OP_NOTI: if (check_str_ptr) detect_partial_match(common, backtracks); length = 1; #ifdef SUPPORT_UTF if (common->utf) { #ifdef COMPILE_PCRE8 c = *cc; if (c < 128) { OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); if (type == OP_NOT || !char_has_othercase(common, cc)) add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); else { /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); } /* Skip the variable-length character. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); JUMPHERE(jump[0]); return cc + 1; } else #endif /* COMPILE_PCRE8 */ { GETCHARLEN(c, cc, length); } } else #endif /* SUPPORT_UTF */ c = *cc; if (type == OP_NOT || !char_has_othercase(common, cc)) { read_char_range(common, c, c, TRUE); add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); } else { oc = char_othercase(common, c); read_char_range(common, c < oc ? c : oc, c > oc ? c : oc, TRUE); bit = c ^ oc; if (is_powerof2(bit)) { OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); } else { add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, c)); add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, oc)); } } return cc + length; case OP_CLASS: case OP_NCLASS: if (check_str_ptr) detect_partial_match(common, backtracks); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255; read_char_range(common, 0, bit, type == OP_NCLASS); #else read_char_range(common, 0, 255, type == OP_NCLASS); #endif if (check_class_ranges(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks)) return cc + 32 / sizeof(pcre_uchar); #if defined SUPPORT_UTF && defined COMPILE_PCRE8 jump[0] = NULL; if (common->utf) { jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, bit); if (type == OP_CLASS) { add_jump(compiler, backtracks, jump[0]); jump[0] = NULL; } } #elif !defined COMPILE_PCRE8 jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); if (type == OP_CLASS) { add_jump(compiler, backtracks, jump[0]); jump[0] = NULL; } #endif /* SUPPORT_UTF && COMPILE_PCRE8 */ OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc); OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, backtracks, JUMP(SLJIT_ZERO)); #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 if (jump[0] != NULL) JUMPHERE(jump[0]); #endif return cc + 32 / sizeof(pcre_uchar); #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case OP_XCLASS: if (check_str_ptr) detect_partial_match(common, backtracks); compile_xclass_matchingpath(common, cc + LINK_SIZE, backtracks); return cc + GET(cc, 0) - 1; #endif } SLJIT_UNREACHABLE(); return cc; } static SLJIT_INLINE pcre_uchar *compile_charn_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks) { /* This function consumes at least one input character. */ /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ DEFINE_COMPILER; pcre_uchar *ccbegin = cc; compare_context context; int size; context.length = 0; do { if (cc >= ccend) break; if (*cc == OP_CHAR) { size = 1; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(cc[1])) size += GET_EXTRALEN(cc[1]); #endif } else if (*cc == OP_CHARI) { size = 1; #ifdef SUPPORT_UTF if (common->utf) { if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) size = 0; else if (HAS_EXTRALEN(cc[1])) size += GET_EXTRALEN(cc[1]); } else #endif if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) size = 0; } else size = 0; cc += 1 + size; context.length += IN_UCHARS(size); } while (size > 0 && context.length <= 128); cc = ccbegin; if (context.length > 0) { /* We have a fixed-length byte sequence. */ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0)); context.sourcereg = -1; #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED context.ucharptr = 0; #endif do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0); return cc; } /* A non-fixed length character will be checked if length == 0. */ return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE); } /* Forward definitions. */ static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *); static void compile_backtrackingpath(compiler_common *, struct backtrack_common *); #define PUSH_BACKTRACK(size, ccstart, error) \ do \ { \ backtrack = sljit_alloc_memory(compiler, (size)); \ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ return error; \ memset(backtrack, 0, size); \ backtrack->prev = parent->top; \ backtrack->cc = (ccstart); \ parent->top = backtrack; \ } \ while (0) #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \ do \ { \ backtrack = sljit_alloc_memory(compiler, (size)); \ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ return; \ memset(backtrack, 0, size); \ backtrack->prev = parent->top; \ backtrack->cc = (ccstart); \ parent->top = backtrack; \ } \ while (0) #define BACKTRACK_AS(type) ((type *)backtrack) static void compile_dnref_search(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) { /* The OVECTOR offset goes to TMP2. */ DEFINE_COMPILER; int count = GET2(cc, 1 + IMM2_SIZE); pcre_uchar *slot = common->name_table + GET2(cc, 1) * common->name_entry_size; unsigned int offset; jump_list *found = NULL; SLJIT_ASSERT(*cc == OP_DNREF || *cc == OP_DNREFI); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); count--; while (count-- > 0) { offset = GET2(slot, 0) << 1; GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset)); add_jump(compiler, &found, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0)); slot += common->name_entry_size; } offset = GET2(slot, 0) << 1; GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset)); if (backtracks != NULL && !common->jscript_compat) add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0)); set_jumps(found, LABEL()); } static void compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail) { DEFINE_COMPILER; BOOL ref = (*cc == OP_REF || *cc == OP_REFI); int offset = 0; struct sljit_jump *jump = NULL; struct sljit_jump *partial; struct sljit_jump *nopartial; if (ref) { offset = GET2(cc, 1) << 1; OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); /* OVECTOR(1) contains the "string begin - 1" constant. */ if (withchecks && !common->jscript_compat) add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); } else OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); #if defined SUPPORT_UTF && defined SUPPORT_UCP if (common->utf && *cc == OP_REFI) { SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1); if (ref) OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); if (withchecks) jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_R2, 0); /* No free saved registers so save data on stack. */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_R1, 0, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_R3, 0, STR_END, 0); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); if (common->mode == JIT_COMPILE) add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); else { OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); add_jump(compiler, backtracks, JUMP(SLJIT_LESS)); nopartial = JUMP(SLJIT_NOT_EQUAL); OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); check_partial(common, FALSE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(nopartial); } } else #endif /* SUPPORT_UTF && SUPPORT_UCP */ { if (ref) OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0); else OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); if (withchecks) jump = JUMP(SLJIT_ZERO); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0); if (common->mode == JIT_COMPILE) add_jump(compiler, backtracks, partial); add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); if (common->mode != JIT_COMPILE) { nopartial = JUMP(SLJIT_JUMP); JUMPHERE(partial); /* TMP2 -= STR_END - STR_PTR */ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0); partial = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); JUMPHERE(partial); check_partial(common, FALSE); add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); JUMPHERE(nopartial); } } if (jump != NULL) { if (emptyfail) add_jump(compiler, backtracks, jump); else JUMPHERE(jump); } } static SLJIT_INLINE pcre_uchar *compile_ref_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; BOOL ref = (*cc == OP_REF || *cc == OP_REFI); backtrack_common *backtrack; pcre_uchar type; int offset = 0; struct sljit_label *label; struct sljit_jump *zerolength; struct sljit_jump *jump = NULL; pcre_uchar *ccbegin = cc; int min = 0, max = 0; BOOL minimize; PUSH_BACKTRACK(sizeof(ref_iterator_backtrack), cc, NULL); if (ref) offset = GET2(cc, 1) << 1; else cc += IMM2_SIZE; type = cc[1 + IMM2_SIZE]; SLJIT_COMPILE_ASSERT((OP_CRSTAR & 0x1) == 0, crstar_opcode_must_be_even); minimize = (type & 0x1) != 0; switch(type) { case OP_CRSTAR: case OP_CRMINSTAR: min = 0; max = 0; cc += 1 + IMM2_SIZE + 1; break; case OP_CRPLUS: case OP_CRMINPLUS: min = 1; max = 0; cc += 1 + IMM2_SIZE + 1; break; case OP_CRQUERY: case OP_CRMINQUERY: min = 0; max = 1; cc += 1 + IMM2_SIZE + 1; break; case OP_CRRANGE: case OP_CRMINRANGE: min = GET2(cc, 1 + IMM2_SIZE + 1); max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE); cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE; break; default: SLJIT_UNREACHABLE(); break; } if (!minimize) { if (min == 0) { allocate_stack(common, 2); if (ref) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); /* Temporary release of STR_PTR. */ OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); /* Handles both invalid and empty cases. Since the minimum repeat, is zero the invalid case is basically the same as an empty case. */ if (ref) zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else { compile_dnref_search(common, ccbegin, NULL); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } /* Restore if not zero length. */ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); } else { allocate_stack(common, 1); if (ref) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); if (ref) { add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); } else { compile_dnref_search(common, ccbegin, &backtrack->topbacktracks); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, TMP2, 0); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } } if (min > 1 || max > 1) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, 0); label = LABEL(); if (!ref) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE); if (min > 1 || max > 1) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); if (min > 1) CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, label); if (max > 1) { jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); JUMPTO(SLJIT_JUMP, label); JUMPHERE(jump); } } if (max == 0) { /* Includes min > 1 case as well. */ allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); JUMPTO(SLJIT_JUMP, label); } JUMPHERE(zerolength); BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL(); count_match(common); return cc; } allocate_stack(common, ref ? 2 : 3); if (ref) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); if (type != OP_CRMINSTAR) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); if (min == 0) { /* Handles both invalid and empty cases. Since the minimum repeat, is zero the invalid case is basically the same as an empty case. */ if (ref) zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); else { compile_dnref_search(common, ccbegin, NULL); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } /* Length is non-zero, we can match real repeats. */ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); jump = JUMP(SLJIT_JUMP); } else { if (ref) { add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); } else { compile_dnref_search(common, ccbegin, &backtrack->topbacktracks); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0); zerolength = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(TMP2), sizeof(sljit_sw)); } } BACKTRACK_AS(ref_iterator_backtrack)->matchingpath = LABEL(); if (max > 0) add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); if (!ref) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); compile_ref_matchingpath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); if (min > 1) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(ref_iterator_backtrack)->matchingpath); } else if (max > 0) OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); if (jump != NULL) JUMPHERE(jump); JUMPHERE(zerolength); count_match(common); return cc; } static SLJIT_INLINE pcre_uchar *compile_recurse_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; recurse_entry *entry = common->entries; recurse_entry *prev = NULL; sljit_sw start = GET(cc, 1); pcre_uchar *start_cc; BOOL needs_control_head; PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); /* Inlining simple patterns. */ if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack) { start_cc = common->start + start; compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack); BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE; return cc + 1 + LINK_SIZE; } while (entry != NULL) { if (entry->start == start) break; prev = entry; entry = entry->next; } if (entry == NULL) { entry = sljit_alloc_memory(compiler, sizeof(recurse_entry)); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; entry->next = NULL; entry->entry = NULL; entry->calls = NULL; entry->start = start; if (prev != NULL) prev->next = entry; else common->entries = entry; } if (common->has_set_som && common->mark_ptr != 0) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); allocate_stack(common, 2); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); } else if (common->has_set_som || common->mark_ptr != 0) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } if (entry->entry == NULL) add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL)); else JUMPTO(SLJIT_FAST_CALL, entry->entry); /* Leave if the match is failed. */ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0)); return cc + 1 + LINK_SIZE; } static sljit_s32 SLJIT_FUNC do_callout(struct jit_arguments *arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector) { const pcre_uchar *begin = arguments->begin; int *offset_vector = arguments->offsets; int offset_count = arguments->offset_count; int i; if (PUBL(callout) == NULL) return 0; callout_block->version = 2; callout_block->callout_data = arguments->callout_data; /* Offsets in subject. */ callout_block->subject_length = arguments->end - arguments->begin; callout_block->start_match = (pcre_uchar*)callout_block->subject - arguments->begin; callout_block->current_position = (pcre_uchar*)callout_block->offset_vector - arguments->begin; #if defined COMPILE_PCRE8 callout_block->subject = (PCRE_SPTR)begin; #elif defined COMPILE_PCRE16 callout_block->subject = (PCRE_SPTR16)begin; #elif defined COMPILE_PCRE32 callout_block->subject = (PCRE_SPTR32)begin; #endif /* Convert and copy the JIT offset vector to the offset_vector array. */ callout_block->capture_top = 0; callout_block->offset_vector = offset_vector; for (i = 2; i < offset_count; i += 2) { offset_vector[i] = jit_ovector[i] - begin; offset_vector[i + 1] = jit_ovector[i + 1] - begin; if (jit_ovector[i] >= begin) callout_block->capture_top = i; } callout_block->capture_top = (callout_block->capture_top >> 1) + 1; if (offset_count > 0) offset_vector[0] = -1; if (offset_count > 1) offset_vector[1] = -1; return (*PUBL(callout))(callout_block); } /* Aligning to 8 byte. */ #define CALLOUT_ARG_SIZE \ (((int)sizeof(PUBL(callout_block)) + 7) & ~7) #define CALLOUT_ARG_OFFSET(arg) \ SLJIT_OFFSETOF(PUBL(callout_block), arg) static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); SLJIT_ASSERT(common->capture_last_ptr != 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]); OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); /* These pointer sized fields temporarly stores internal variables. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0); if (common->mark_ptr != 0) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr)); OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2)); OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0); /* Needed to save important temporary registers. */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); /* SLJIT_R0 = arguments */ OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0); GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); /* Check return value. */ OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER32)); if (common->forced_quit_label == NULL) add_jump(compiler, &common->forced_quit, JUMP(SLJIT_NOT_EQUAL32) /* SIG_LESS */); else JUMPTO(SLJIT_NOT_EQUAL32 /* SIG_LESS */, common->forced_quit_label); return cc + 2 + 2 * LINK_SIZE; } #undef CALLOUT_ARG_SIZE #undef CALLOUT_ARG_OFFSET static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(pcre_uchar *cc) { while (TRUE) { switch (*cc) { case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: case OP_CALLOUT: case OP_ALT: cc += PRIV(OP_lengths)[*cc]; break; case OP_KET: return FALSE; default: return TRUE; } } } static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) { DEFINE_COMPILER; int framesize; int extrasize; BOOL needs_control_head; int private_data_ptr; backtrack_common altbacktrack; pcre_uchar *ccbegin; pcre_uchar opcode; pcre_uchar bra = OP_BRA; jump_list *tmp = NULL; jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; jump_list **found; /* Saving previous accept variables. */ BOOL save_local_exit = common->local_exit; BOOL save_positive_assert = common->positive_assert; then_trap_backtrack *save_then_trap = common->then_trap; struct sljit_label *save_quit_label = common->quit_label; struct sljit_label *save_accept_label = common->accept_label; jump_list *save_quit = common->quit; jump_list *save_positive_assert_quit = common->positive_assert_quit; jump_list *save_accept = common->accept; struct sljit_jump *jump; struct sljit_jump *brajump = NULL; /* Assert captures then. */ common->then_trap = NULL; if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) { SLJIT_ASSERT(!conditional); bra = *cc; cc++; } private_data_ptr = PRIVATE_DATA(cc); SLJIT_ASSERT(private_data_ptr != 0); framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head); backtrack->framesize = framesize; backtrack->private_data_ptr = private_data_ptr; opcode = *cc; SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; ccbegin = cc; cc += GET(cc, 1); if (bra == OP_BRAMINZERO) { /* This is a braminzero backtrack path. */ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); } if (framesize < 0) { extrasize = 1; if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE)) extrasize = 0; if (needs_control_head) extrasize++; if (framesize == no_frame) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0); if (extrasize > 0) allocate_stack(common, extrasize); if (needs_control_head) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); if (extrasize > 0) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); if (needs_control_head) { SLJIT_ASSERT(extrasize == 2); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); } } else { extrasize = needs_control_head ? 3 : 2; allocate_stack(common, framesize + extrasize); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); if (needs_control_head) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); } else OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE); } memset(&altbacktrack, 0, sizeof(backtrack_common)); if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) { /* Negative assert is stronger than positive assert. */ common->local_exit = TRUE; common->quit_label = NULL; common->quit = NULL; common->positive_assert = FALSE; } else common->positive_assert = TRUE; common->positive_assert_quit = NULL; while (1) { common->accept_label = NULL; common->accept = NULL; altbacktrack.top = NULL; altbacktrack.topbacktracks = NULL; if (*ccbegin == OP_ALT && extrasize > 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); altbacktrack.cc = ccbegin; compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) { common->local_exit = save_local_exit; common->quit_label = save_quit_label; common->quit = save_quit; } common->positive_assert = save_positive_assert; common->then_trap = save_then_trap; common->accept_label = save_accept_label; common->positive_assert_quit = save_positive_assert_quit; common->accept = save_accept; return NULL; } common->accept_label = LABEL(); if (common->accept != NULL) set_jumps(common->accept, common->accept_label); /* Reset stack. */ if (framesize < 0) { if (framesize == no_frame) OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); else if (extrasize > 0) free_stack(common, extrasize); if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1)); } else { if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1)); } else { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 2)); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); } } if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) { /* We know that STR_PTR was stored on the top of the stack. */ if (conditional) { if (extrasize > 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? STACK(-2) : STACK(-1)); } else if (bra == OP_BRAZERO) { if (framesize < 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize)); else { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-framesize - extrasize)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else if (framesize >= 0) { /* For OP_BRA and OP_BRAMINZERO. */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1)); } } add_jump(compiler, found, JUMP(SLJIT_JUMP)); compile_backtrackingpath(common, altbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) { common->local_exit = save_local_exit; common->quit_label = save_quit_label; common->quit = save_quit; } common->positive_assert = save_positive_assert; common->then_trap = save_then_trap; common->accept_label = save_accept_label; common->positive_assert_quit = save_positive_assert_quit; common->accept = save_accept; return NULL; } set_jumps(altbacktrack.topbacktracks, LABEL()); if (*cc != OP_ALT) break; ccbegin = cc; cc += GET(cc, 1); } if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) { SLJIT_ASSERT(common->positive_assert_quit == NULL); /* Makes the check less complicated below. */ common->positive_assert_quit = common->quit; } /* None of them matched. */ if (common->positive_assert_quit != NULL) { jump = JUMP(SLJIT_JUMP); set_jumps(common->positive_assert_quit, LABEL()); SLJIT_ASSERT(framesize != no_stack); if (framesize < 0) OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); else { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); } JUMPHERE(jump); } if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1)); if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) { /* Assert is failed. */ if ((conditional && extrasize > 0) || bra == OP_BRAZERO) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (framesize < 0) { /* The topmost item should be 0. */ if (bra == OP_BRAZERO) { if (extrasize == 2) free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else if (extrasize > 0) free_stack(common, extrasize); } else { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1)); /* The topmost item should be 0. */ if (bra == OP_BRAZERO) { free_stack(common, framesize + extrasize - 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else free_stack(common, framesize + extrasize); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } jump = JUMP(SLJIT_JUMP); if (bra != OP_BRAZERO) add_jump(compiler, target, jump); /* Assert is successful. */ set_jumps(tmp, LABEL()); if (framesize < 0) { /* We know that STR_PTR was stored on the top of the stack. */ if (extrasize > 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize)); /* Keep the STR_PTR on the top of the stack. */ if (bra == OP_BRAZERO) { OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); if (extrasize == 2) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } else if (bra == OP_BRAMINZERO) { OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } } else { if (bra == OP_BRA) { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-extrasize + 1)); } else { /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); if (extrasize == 2) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (bra == OP_BRAMINZERO) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); } } } if (bra == OP_BRAZERO) { backtrack->matchingpath = LABEL(); SET_LABEL(jump, backtrack->matchingpath); } else if (bra == OP_BRAMINZERO) { JUMPTO(SLJIT_JUMP, backtrack->matchingpath); JUMPHERE(brajump); if (framesize >= 0) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-framesize - 1)); } set_jumps(backtrack->common.topbacktracks, LABEL()); } } else { /* AssertNot is successful. */ if (framesize < 0) { if (extrasize > 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (bra != OP_BRA) { if (extrasize == 2) free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else if (extrasize > 0) free_stack(common, extrasize); } else { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1)); /* The topmost item should be 0. */ if (bra != OP_BRA) { free_stack(common, framesize + extrasize - 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } else free_stack(common, framesize + extrasize); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } if (bra == OP_BRAZERO) backtrack->matchingpath = LABEL(); else if (bra == OP_BRAMINZERO) { JUMPTO(SLJIT_JUMP, backtrack->matchingpath); JUMPHERE(brajump); } if (bra != OP_BRA) { SLJIT_ASSERT(found == &backtrack->common.topbacktracks); set_jumps(backtrack->common.topbacktracks, LABEL()); backtrack->common.topbacktracks = NULL; } } if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) { common->local_exit = save_local_exit; common->quit_label = save_quit_label; common->quit = save_quit; } common->positive_assert = save_positive_assert; common->then_trap = save_then_trap; common->accept_label = save_accept_label; common->positive_assert_quit = save_positive_assert_quit; common->accept = save_accept; return cc + 1 + LINK_SIZE; } static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head) { DEFINE_COMPILER; int stacksize; if (framesize < 0) { if (framesize == no_frame) OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); else { stacksize = needs_control_head ? 1 : 0; if (ket != OP_KET || has_alternatives) stacksize++; if (stacksize > 0) free_stack(common, stacksize); } if (needs_control_head) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? STACK(-2) : STACK(-1)); /* TMP2 which is set here used by OP_KETRMAX below. */ if (ket == OP_KETRMAX) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-1)); else if (ket == OP_KETRMIN) { /* Move the STR_PTR to the private_data_ptr. */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-1)); } } else { stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1; OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); if (needs_control_head) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-1)); if (ket == OP_KETRMAX) { /* TMP2 which is set here used by OP_KETRMAX below. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); } } if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0); } static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr) { DEFINE_COMPILER; if (common->capture_last_ptr != 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); stacksize++; } if (common->optimized_cbracket[offset >> 1] == 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); stacksize += 2; } return stacksize; } /* Handling bracketed expressions is probably the most complex part. Stack layout naming characters: S - Push the current STR_PTR 0 - Push a 0 (NULL) A - Push the current STR_PTR. Needed for restoring the STR_PTR before the next alternative. Not pushed if there are no alternatives. M - Any values pushed by the current alternative. Can be empty, or anything. C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack. L - Push the previous local (pointed by localptr) to the stack () - opional values stored on the stack ()* - optonal, can be stored multiple times The following list shows the regular expression templates, their PCRE byte codes and stack layout supported by pcre-sljit. (?:) OP_BRA | OP_KET A M () OP_CBRA | OP_KET C M (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )* OP_SBRA | OP_KETRMAX 0 L M S ( L M S )* (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )* OP_SBRA | OP_KETRMIN 0 L M S ( L M S )* ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )* OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )* ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )* OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )* (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 ) (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 ) ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 ) ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 ) (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )* OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )* (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )* OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )* ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )* OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )* ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )* OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )* Stack layout naming characters: A - Push the alternative index (starting from 0) on the stack. Not pushed if there is no alternatives. M - Any values pushed by the current alternative. Can be empty, or anything. The next list shows the possible content of a bracket: (|) OP_*BRA | OP_ALT ... M A (?()|) OP_*COND | OP_ALT M A (?>|) OP_ONCE | OP_ALT ... [stack trace] M A (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A Or nothing, if trace is unnecessary */ static pcre_uchar *compile_bracket_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; pcre_uchar opcode; int private_data_ptr = 0; int offset = 0; int i, stacksize; int repeat_ptr = 0, repeat_length = 0; int repeat_type = 0, repeat_count = 0; pcre_uchar *ccbegin; pcre_uchar *matchingpath; pcre_uchar *slot; pcre_uchar bra = OP_BRA; pcre_uchar ket; assert_backtrack *assert; BOOL has_alternatives; BOOL needs_control_head = FALSE; struct sljit_jump *jump; struct sljit_jump *skip; struct sljit_label *rmax_label = NULL; struct sljit_jump *braminzero = NULL; PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) { bra = *cc; cc++; opcode = *cc; } opcode = *cc; ccbegin = cc; matchingpath = bracketend(cc) - 1 - LINK_SIZE; ket = *matchingpath; if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0) { repeat_ptr = PRIVATE_DATA(matchingpath); repeat_length = PRIVATE_DATA(matchingpath + 1); repeat_type = PRIVATE_DATA(matchingpath + 2); repeat_count = PRIVATE_DATA(matchingpath + 3); SLJIT_ASSERT(repeat_length != 0 && repeat_type != 0 && repeat_count != 0); if (repeat_type == OP_UPTO) ket = OP_KETRMAX; if (repeat_type == OP_MINUPTO) ket = OP_KETRMIN; } if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) { /* Drop this bracket_backtrack. */ parent->top = backtrack->prev; return matchingpath + 1 + LINK_SIZE + repeat_length; } matchingpath = ccbegin + 1 + LINK_SIZE; SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); cc += GET(cc, 1); has_alternatives = *cc == OP_ALT; if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND)) has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) ? FALSE : TRUE; if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) opcode = OP_SCOND; if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) opcode = OP_ONCE; if (opcode == OP_CBRA || opcode == OP_SCBRA) { /* Capturing brackets has a pre-allocated space. */ offset = GET2(ccbegin, 1 + LINK_SIZE); if (common->optimized_cbracket[offset] == 0) { private_data_ptr = OVECTOR_PRIV(offset); offset <<= 1; } else { offset <<= 1; private_data_ptr = OVECTOR(offset); } BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; matchingpath += IMM2_SIZE; } else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) { /* Other brackets simply allocate the next entry. */ private_data_ptr = PRIVATE_DATA(ccbegin); SLJIT_ASSERT(private_data_ptr != 0); BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; if (opcode == OP_ONCE) BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head); } /* Instructions before the first alternative. */ stacksize = 0; if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) stacksize++; if (bra == OP_BRAZERO) stacksize++; if (stacksize > 0) allocate_stack(common, stacksize); stacksize = 0; if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); stacksize++; } if (bra == OP_BRAZERO) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); if (bra == OP_BRAMINZERO) { /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */ OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (ket != OP_KETRMIN) { free_stack(common, 1); braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); } else { if (opcode == OP_ONCE || opcode >= OP_SBRA) { jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); /* Nothing stored during the first run. */ skip = JUMP(SLJIT_JUMP); JUMPHERE(jump); /* Checking zero-length iteration. */ if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) { /* When we come from outside, private_data_ptr contains the previous STR_PTR. */ braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); } else { /* Except when the whole stack frame must be saved. */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); braminzero = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-BACKTRACK_AS(bracket_backtrack)->u.framesize - 2)); } JUMPHERE(skip); } else { jump = CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); JUMPHERE(jump); } } } if (repeat_type != 0) { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, repeat_count); if (repeat_type == OP_EXACT) rmax_label = LABEL(); } if (ket == OP_KETRMIN) BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); if (ket == OP_KETRMAX) { rmax_label = LABEL(); if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA && repeat_type == 0) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = rmax_label; } /* Handling capturing brackets and alternatives. */ if (opcode == OP_ONCE) { stacksize = 0; if (needs_control_head) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); stacksize++; } if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) { /* Neither capturing brackets nor recursions are found in the block. */ if (ket == OP_KETRMIN) { stacksize += 2; if (!needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); } else { if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0); if (ket == OP_KETRMAX || has_alternatives) stacksize++; } if (stacksize > 0) allocate_stack(common, stacksize); stacksize = 0; if (needs_control_head) { stacksize++; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } if (ket == OP_KETRMIN) { if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); } else if (ket == OP_KETRMAX || has_alternatives) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); } else { if (ket != OP_KET || has_alternatives) stacksize++; stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1; allocate_stack(common, stacksize); if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP2(SLJIT_ADD, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); stacksize = needs_control_head ? 1 : 0; if (ket != OP_KET || has_alternatives) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); stacksize++; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); } else { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); } init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE); } } else if (opcode == OP_CBRA || opcode == OP_SCBRA) { /* Saving the previous values. */ if (common->optimized_cbracket[offset >> 1] != 0) { SLJIT_ASSERT(private_data_ptr == OVECTOR(offset)); allocate_stack(common, 2); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr + sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); } else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } } else if (opcode == OP_SBRA || opcode == OP_SCOND) { /* Saving the previous value. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } else if (has_alternatives) { /* Pushing the starting string pointer. */ allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } /* Generating code for the first alternative. */ if (opcode == OP_COND || opcode == OP_SCOND) { if (*matchingpath == OP_CREF) { SLJIT_ASSERT(has_alternatives); add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(matchingpath, 1) << 1), SLJIT_MEM1(SLJIT_SP), OVECTOR(1))); matchingpath += 1 + IMM2_SIZE; } else if (*matchingpath == OP_DNCREF) { SLJIT_ASSERT(has_alternatives); i = GET2(matchingpath, 1 + IMM2_SIZE); slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size; OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); slot += common->name_entry_size; i--; while (i-- > 0) { OP2(SLJIT_SUB, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(GET2(slot, 0) << 1), TMP1, 0); OP2(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, STR_PTR, 0); slot += common->name_entry_size; } OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO)); matchingpath += 1 + 2 * IMM2_SIZE; } else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) { /* Never has other case. */ BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL; SLJIT_ASSERT(!has_alternatives); if (*matchingpath == OP_FAIL) stacksize = 0; else if (*matchingpath == OP_RREF) { stacksize = GET2(matchingpath, 1); if (common->currententry == NULL) stacksize = 0; else if (stacksize == RREF_ANY) stacksize = 1; else if (common->currententry->start == 0) stacksize = stacksize == 0; else stacksize = stacksize == (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE); if (stacksize != 0) matchingpath += 1 + IMM2_SIZE; } else { if (common->currententry == NULL || common->currententry->start == 0) stacksize = 0; else { stacksize = GET2(matchingpath, 1 + IMM2_SIZE); slot = common->name_table + GET2(matchingpath, 1) * common->name_entry_size; i = (int)GET2(common->start, common->currententry->start + 1 + LINK_SIZE); while (stacksize > 0) { if ((int)GET2(slot, 0) == i) break; slot += common->name_entry_size; stacksize--; } } if (stacksize != 0) matchingpath += 1 + 2 * IMM2_SIZE; } /* The stacksize == 0 is a common "else" case. */ if (stacksize == 0) { if (*cc == OP_ALT) { matchingpath = cc + 1 + LINK_SIZE; cc += GET(cc, 1); } else matchingpath = cc; } } else { SLJIT_ASSERT(has_alternatives && *matchingpath >= OP_ASSERT && *matchingpath <= OP_ASSERTBACK_NOT); /* Similar code as PUSH_BACKTRACK macro. */ assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack)); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; memset(assert, 0, sizeof(assert_backtrack)); assert->common.cc = matchingpath; BACKTRACK_AS(bracket_backtrack)->u.assert = assert; matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE); } } compile_matchingpath(common, matchingpath, cc, backtrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; if (opcode == OP_ONCE) match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); stacksize = 0; if (repeat_type == OP_MINUPTO) { /* We need to preserve the counter. TMP2 will be used below. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr); stacksize++; } if (ket != OP_KET || bra != OP_BRA) stacksize++; if (offset != 0) { if (common->capture_last_ptr != 0) stacksize++; if (common->optimized_cbracket[offset >> 1] == 0) stacksize += 2; } if (has_alternatives && opcode != OP_ONCE) stacksize++; if (stacksize > 0) allocate_stack(common, stacksize); stacksize = 0; if (repeat_type == OP_MINUPTO) { /* TMP2 was set above. */ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1); stacksize++; } if (ket != OP_KET || bra != OP_BRA) { if (ket != OP_KET) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); else OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); stacksize++; } if (offset != 0) stacksize = match_capture_common(common, stacksize, offset, private_data_ptr); if (has_alternatives) { if (opcode != OP_ONCE) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); if (ket != OP_KETRMAX) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); } /* Must be after the matchingpath label. */ if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0) { SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); } if (ket == OP_KETRMAX) { if (repeat_type != 0) { if (has_alternatives) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, rmax_label); /* Drop STR_PTR for greedy plus quantifier. */ if (opcode != OP_ONCE) free_stack(common, 1); } else if (opcode == OP_ONCE || opcode >= OP_SBRA) { if (has_alternatives) BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL(); /* Checking zero-length iteration. */ if (opcode != OP_ONCE) { CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STR_PTR, 0, rmax_label); /* Drop STR_PTR for greedy plus quantifier. */ if (bra != OP_BRAZERO) free_stack(common, 1); } else /* TMP2 must contain the starting STR_PTR. */ CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmax_label); } else JUMPTO(SLJIT_JUMP, rmax_label); BACKTRACK_AS(bracket_backtrack)->recursive_matchingpath = LABEL(); } if (repeat_type == OP_EXACT) { count_match(common); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, rmax_label); } else if (repeat_type == OP_UPTO) { /* We need to preserve the counter. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } if (bra == OP_BRAZERO) BACKTRACK_AS(bracket_backtrack)->zero_matchingpath = LABEL(); if (bra == OP_BRAMINZERO) { /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */ JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->matchingpath); if (braminzero != NULL) { JUMPHERE(braminzero); /* We need to release the end pointer to perform the backtrack for the zero-length iteration. When framesize is < 0, OP_ONCE will do the release itself. */ if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); } else if (ket == OP_KETRMIN && opcode != OP_ONCE) free_stack(common, 1); } /* Continue to the normal backtrack. */ } if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) count_match(common); /* Skip the other alternatives. */ while (*cc == OP_ALT) cc += GET(cc, 1); cc += 1 + LINK_SIZE; if (opcode == OP_ONCE) { /* We temporarily encode the needs_control_head in the lowest bit. Note: on the target architectures of SLJIT the ((x << 1) >> 1) returns the same value for small signed numbers (including negative numbers). */ BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0); } return cc + repeat_length; } static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; pcre_uchar opcode; int private_data_ptr; int cbraprivptr = 0; BOOL needs_control_head; int framesize; int stacksize; int offset = 0; BOOL zero = FALSE; pcre_uchar *ccbegin = NULL; int stack; /* Also contains the offset of control head. */ struct sljit_label *loop = NULL; struct jump_list *emptymatch = NULL; PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL); if (*cc == OP_BRAPOSZERO) { zero = TRUE; cc++; } opcode = *cc; private_data_ptr = PRIVATE_DATA(cc); SLJIT_ASSERT(private_data_ptr != 0); BACKTRACK_AS(bracketpos_backtrack)->private_data_ptr = private_data_ptr; switch(opcode) { case OP_BRAPOS: case OP_SBRAPOS: ccbegin = cc + 1 + LINK_SIZE; break; case OP_CBRAPOS: case OP_SCBRAPOS: offset = GET2(cc, 1 + LINK_SIZE); /* This case cannot be optimized in the same was as normal capturing brackets. */ SLJIT_ASSERT(common->optimized_cbracket[offset] == 0); cbraprivptr = OVECTOR_PRIV(offset); offset <<= 1; ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE; break; default: SLJIT_UNREACHABLE(); break; } framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head); BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; if (framesize < 0) { if (offset != 0) { stacksize = 2; if (common->capture_last_ptr != 0) stacksize++; } else stacksize = 1; if (needs_control_head) stacksize++; if (!zero) stacksize++; BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; allocate_stack(common, stacksize); if (framesize == no_frame) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0); stack = 0; if (offset != 0) { stack = 2; OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); if (common->capture_last_ptr != 0) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); stack = 3; } } else { if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); stack = 1; } if (needs_control_head) stack++; if (!zero) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1); if (needs_control_head) { stack--; OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0); } } else { stacksize = framesize + 1; if (!zero) stacksize++; if (needs_control_head) stacksize++; if (offset == 0) stacksize++; BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; allocate_stack(common, stacksize); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (needs_control_head) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); stack = 0; if (!zero) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); stack = 1; } if (needs_control_head) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0); stack++; } if (offset == 0) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); stack++; } OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize, FALSE); stack -= 1 + (offset == 0); } if (offset != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); loop = LABEL(); while (*cc != OP_KETRPOS) { backtrack->top = NULL; backtrack->topbacktracks = NULL; cc += GET(cc, 1); compile_matchingpath(common, ccbegin, cc, backtrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; if (framesize < 0) { if (framesize == no_frame) OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); if (offset != 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); } else { if (opcode == OP_SBRAPOS) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } /* Even if the match is empty, we need to reset the control head. */ if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); if (!zero) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); } else { if (offset != 0) { OP2(SLJIT_SUB, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), cbraprivptr, STR_PTR, 0); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, offset >> 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); } else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP2(SLJIT_SUB, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); if (opcode == OP_SBRAPOS) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2)); OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(-framesize - 2), STR_PTR, 0); } /* Even if the match is empty, we need to reset the control head. */ if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); if (!zero) { if (framesize < 0) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); else OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); } } JUMPTO(SLJIT_JUMP, loop); flush_stubs(common); compile_backtrackingpath(common, backtrack->top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; set_jumps(backtrack->topbacktracks, LABEL()); if (framesize < 0) { if (offset != 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); } else { if (offset != 0) { /* Last alternative. */ if (*cc == OP_KETRPOS) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), cbraprivptr); } else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), STACK(-framesize - 2)); } } if (*cc == OP_KETRPOS) break; ccbegin = cc + 1 + LINK_SIZE; } /* We don't have to restore the control head in case of a failed match. */ backtrack->topbacktracks = NULL; if (!zero) { if (framesize < 0) add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); else /* TMP2 is set to [private_data_ptr] above. */ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(TMP2), STACK(-stacksize), SLJIT_IMM, 0)); } /* None of them matched. */ set_jumps(emptymatch, LABEL()); count_match(common); return cc + 1 + LINK_SIZE; } static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, sljit_u32 *max, sljit_u32 *exact, pcre_uchar **end) { int class_len; *opcode = *cc; *exact = 0; if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO) { cc++; *type = OP_CHAR; } else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI) { cc++; *type = OP_CHARI; *opcode -= OP_STARI - OP_STAR; } else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO) { cc++; *type = OP_NOT; *opcode -= OP_NOTSTAR - OP_STAR; } else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI) { cc++; *type = OP_NOTI; *opcode -= OP_NOTSTARI - OP_STAR; } else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO) { cc++; *opcode -= OP_TYPESTAR - OP_STAR; *type = OP_END; } else { SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS); *type = *opcode; cc++; class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); *opcode = cc[class_len - 1]; if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) { *opcode -= OP_CRSTAR - OP_STAR; *end = cc + class_len; if (*opcode == OP_PLUS || *opcode == OP_MINPLUS) { *exact = 1; *opcode -= OP_PLUS - OP_STAR; } } else if (*opcode >= OP_CRPOSSTAR && *opcode <= OP_CRPOSQUERY) { *opcode -= OP_CRPOSSTAR - OP_POSSTAR; *end = cc + class_len; if (*opcode == OP_POSPLUS) { *exact = 1; *opcode = OP_POSSTAR; } } else { SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE || *opcode == OP_CRPOSRANGE); *max = GET2(cc, (class_len + IMM2_SIZE)); *exact = GET2(cc, class_len); if (*max == 0) { if (*opcode == OP_CRPOSRANGE) *opcode = OP_POSSTAR; else *opcode -= OP_CRRANGE - OP_STAR; } else { *max -= *exact; if (*max == 0) *opcode = OP_EXACT; else if (*max == 1) { if (*opcode == OP_CRPOSRANGE) *opcode = OP_POSQUERY; else *opcode -= OP_CRRANGE - OP_QUERY; } else { if (*opcode == OP_CRPOSRANGE) *opcode = OP_POSUPTO; else *opcode -= OP_CRRANGE - OP_UPTO; } } *end = cc + class_len + 2 * IMM2_SIZE; } return cc; } switch(*opcode) { case OP_EXACT: *exact = GET2(cc, 0); cc += IMM2_SIZE; break; case OP_PLUS: case OP_MINPLUS: *exact = 1; *opcode -= OP_PLUS - OP_STAR; break; case OP_POSPLUS: *exact = 1; *opcode = OP_POSSTAR; break; case OP_UPTO: case OP_MINUPTO: case OP_POSUPTO: *max = GET2(cc, 0); cc += IMM2_SIZE; break; } if (*type == OP_END) { *type = *cc; *end = next_opcode(common, cc); cc++; return cc; } *end = cc + 1; #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); #endif return cc; } static pcre_uchar *compile_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; pcre_uchar opcode; pcre_uchar type; sljit_u32 max = 0, exact; BOOL fast_fail; sljit_s32 fast_str_ptr; BOOL charpos_enabled; pcre_uchar charpos_char; unsigned int charpos_othercasebit; pcre_uchar *end; jump_list *no_match = NULL; jump_list *no_char1_match = NULL; struct sljit_jump *jump = NULL; struct sljit_label *label; int private_data_ptr = PRIVATE_DATA(cc); int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP); int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); int tmp_base, tmp_offset; PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL); fast_str_ptr = PRIVATE_DATA(cc + 1); fast_fail = TRUE; SLJIT_ASSERT(common->fast_forward_bc_ptr == NULL || fast_str_ptr == 0 || cc == common->fast_forward_bc_ptr); if (cc == common->fast_forward_bc_ptr) fast_fail = FALSE; else if (common->fast_fail_start_ptr == 0) fast_str_ptr = 0; SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || fast_str_ptr == 0 || (fast_str_ptr >= common->fast_fail_start_ptr && fast_str_ptr <= common->fast_fail_end_ptr)); cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); if (type != OP_EXTUNI) { tmp_base = TMP3; tmp_offset = 0; } else { tmp_base = SLJIT_MEM1(SLJIT_SP); tmp_offset = POSSESSIVE0; } if (fast_fail && fast_str_ptr != 0) add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), fast_str_ptr)); /* Handle fixed part first. */ if (exact > 1) { SLJIT_ASSERT(fast_str_ptr == 0); if (common->mode == JIT_COMPILE #ifdef SUPPORT_UTF && !common->utf #endif && type != OP_ANYNL && type != OP_EXTUNI) { OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(exact)); add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_GREATER, TMP1, 0, STR_END, 0)); OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); label = LABEL(); compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else { OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, exact); label = LABEL(); compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } } else if (exact == 1) compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); switch(opcode) { case OP_STAR: case OP_UPTO: SLJIT_ASSERT(fast_str_ptr == 0 || opcode == OP_STAR); if (type == OP_ANYNL || type == OP_EXTUNI) { SLJIT_ASSERT(private_data_ptr == 0); SLJIT_ASSERT(fast_str_ptr == 0); allocate_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); if (opcode == OP_UPTO) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, SLJIT_IMM, max); label = LABEL(); compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE); if (opcode == OP_UPTO) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); jump = JUMP(SLJIT_ZERO); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); } /* We cannot use TMP3 because of this allocate_stack. */ allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); JUMPTO(SLJIT_JUMP, label); if (jump != NULL) JUMPHERE(jump); } else { charpos_enabled = FALSE; charpos_char = 0; charpos_othercasebit = 0; if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI)) { charpos_enabled = TRUE; #ifdef SUPPORT_UTF charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]); #endif if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1)) { charpos_othercasebit = char_get_othercase_bit(common, end + 1); if (charpos_othercasebit == 0) charpos_enabled = FALSE; } if (charpos_enabled) { charpos_char = end[1]; /* Consumpe the OP_CHAR opcode. */ end += 2; #if defined COMPILE_PCRE8 SLJIT_ASSERT((charpos_othercasebit >> 8) == 0); #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SLJIT_ASSERT((charpos_othercasebit >> 9) == 0); if ((charpos_othercasebit & 0x100) != 0) charpos_othercasebit = (charpos_othercasebit & 0xff) << 8; #endif if (charpos_othercasebit != 0) charpos_char |= charpos_othercasebit; BACKTRACK_AS(char_iterator_backtrack)->u.charpos.enabled = TRUE; BACKTRACK_AS(char_iterator_backtrack)->u.charpos.chr = charpos_char; BACKTRACK_AS(char_iterator_backtrack)->u.charpos.othercasebit = charpos_othercasebit; } } if (charpos_enabled) { if (opcode == OP_UPTO) OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max + 1); /* Search the first instance of charpos_char. */ jump = JUMP(SLJIT_JUMP); label = LABEL(); if (opcode == OP_UPTO) { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO)); } compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); JUMPHERE(jump); detect_partial_match(common, &backtrack->topbacktracks); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (charpos_othercasebit != 0) OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); if (private_data_ptr == 0) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); if (opcode == OP_UPTO) { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); } /* Search the last instance of charpos_char. */ label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, FALSE); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); detect_partial_match(common, &no_match); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (charpos_othercasebit != 0) OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); if (opcode == OP_STAR) { CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } else { jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPHERE(jump); } if (opcode == OP_UPTO) { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else JUMPTO(SLJIT_JUMP, label); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 else if (common->utf) { if (private_data_ptr == 0) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); if (opcode == OP_UPTO) OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); if (opcode == OP_UPTO) { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } else JUMPTO(SLJIT_JUMP, label); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); } #endif else { if (private_data_ptr == 0) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); if (opcode == OP_UPTO) OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); label = LABEL(); detect_partial_match(common, &no_match); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); if (opcode == OP_UPTO) { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); } else JUMPTO(SLJIT_JUMP, label); set_jumps(no_char1_match, LABEL()); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); } } BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_MINSTAR: if (private_data_ptr == 0) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); break; case OP_MINUPTO: SLJIT_ASSERT(fast_str_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, SLJIT_IMM, max + 1); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_QUERY: case OP_MINQUERY: SLJIT_ASSERT(fast_str_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); if (opcode == OP_QUERY) compile_char1_matchingpath(common, type, cc, &BACKTRACK_AS(char_iterator_backtrack)->u.backtracks, TRUE); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; case OP_EXACT: break; case OP_POSSTAR: #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) { OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); JUMPTO(SLJIT_JUMP, label); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); break; } #endif label = LABEL(); detect_partial_match(common, &no_match); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); JUMPTO(SLJIT_JUMP, label); set_jumps(no_char1_match, LABEL()); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_match, LABEL()); if (fast_str_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); break; case OP_POSUPTO: SLJIT_ASSERT(fast_str_ptr == 0); #if defined SUPPORT_UTF && !defined COMPILE_PCRE32 if (common->utf) { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0); OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1); break; } #endif OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); label = LABEL(); detect_partial_match(common, &no_match); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_char1_match, LABEL()); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_match, LABEL()); break; case OP_POSQUERY: SLJIT_ASSERT(fast_str_ptr == 0); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); break; default: SLJIT_UNREACHABLE(); break; } count_match(common); return end; } static SLJIT_INLINE pcre_uchar *compile_fail_accept_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); if (*cc == OP_FAIL) { add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); return cc + 1; } if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL || !common->might_be_empty) { /* No need to check notempty conditions. */ if (common->accept_label == NULL) add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); else JUMPTO(SLJIT_JUMP, common->accept_label); return cc + 1; } if (common->accept_label == NULL) add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0))); else CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); if (common->accept_label == NULL) add_jump(compiler, &common->accept, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); else CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); if (common->accept_label == NULL) add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); else CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label); add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); return cc + 1; } static SLJIT_INLINE pcre_uchar *compile_close_matchingpath(compiler_common *common, pcre_uchar *cc) { DEFINE_COMPILER; int offset = GET2(cc, 1); BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0; /* Data will be discarded anyway... */ if (common->currententry != NULL) return cc + 1 + IMM2_SIZE; if (!optimized_cbracket) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR_PRIV(offset)); offset <<= 1; OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); if (!optimized_cbracket) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); return cc + 1 + IMM2_SIZE; } static SLJIT_INLINE pcre_uchar *compile_control_verb_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; pcre_uchar opcode = *cc; pcre_uchar *ccend = cc + 1; if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) ccend += 2 + cc[1]; PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); if (opcode == OP_SKIP) { allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); return ccend; } if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG) { OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); } return ccend; } static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP }; static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; BOOL needs_control_head; int size; PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); common->then_trap = BACKTRACK_AS(then_trap_backtrack); BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start); BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head); size = BACKTRACK_AS(then_trap_backtrack)->framesize; size = 3 + (size < 0 ? 0 : size); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); allocate_stack(common, size); if (size > 3) OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); else OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0); size = BACKTRACK_AS(then_trap_backtrack)->framesize; if (size >= 0) init_frame(common, cc, ccend, size - 1, 0, FALSE); } static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) { DEFINE_COMPILER; backtrack_common *backtrack; BOOL has_then_trap = FALSE; then_trap_backtrack *save_then_trap = NULL; SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS)); if (common->has_then && common->then_offsets[cc - common->start] != 0) { SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0); has_then_trap = TRUE; save_then_trap = common->then_trap; /* Tail item on backtrack. */ compile_then_trap_matchingpath(common, cc, ccend, parent); } while (cc < ccend) { switch(*cc) { case OP_SOD: case OP_SOM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: case OP_EODN: case OP_EOD: case OP_DOLL: case OP_DOLLM: case OP_CIRC: case OP_CIRCM: case OP_REVERSE: cc = compile_simple_assertion_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); break; case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: case OP_ALLANY: case OP_ANYBYTE: case OP_NOTPROP: case OP_PROP: case OP_ANYNL: case OP_NOT_HSPACE: case OP_HSPACE: case OP_NOT_VSPACE: case OP_VSPACE: case OP_EXTUNI: case OP_NOT: case OP_NOTI: cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; case OP_SET_SOM: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); cc++; break; case OP_CHAR: case OP_CHARI: if (common->mode == JIT_COMPILE) cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); else cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_UPTO: case OP_MINUPTO: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_UPTOI: case OP_MINUPTOI: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEEXACT: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSUPTO: cc = compile_iterator_matchingpath(common, cc, parent); break; case OP_CLASS: case OP_NCLASS: if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRPOSRANGE) cc = compile_iterator_matchingpath(common, cc, parent); else cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case OP_XCLASS: if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE) cc = compile_iterator_matchingpath(common, cc, parent); else cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE); break; #endif case OP_REF: case OP_REFI: if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRPOSRANGE) cc = compile_ref_iterator_matchingpath(common, cc, parent); else { compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE); cc += 1 + IMM2_SIZE; } break; case OP_DNREF: case OP_DNREFI: if (cc[1 + 2 * IMM2_SIZE] >= OP_CRSTAR && cc[1 + 2 * IMM2_SIZE] <= OP_CRPOSRANGE) cc = compile_ref_iterator_matchingpath(common, cc, parent); else { compile_dnref_search(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); compile_ref_matchingpath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE); cc += 1 + 2 * IMM2_SIZE; } break; case OP_RECURSE: cc = compile_recurse_matchingpath(common, cc, parent); break; case OP_CALLOUT: cc = compile_callout_matchingpath(common, cc, parent); break; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); break; case OP_BRAMINZERO: PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc); cc = bracketend(cc + 1); if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) { allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } else { allocate_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); } BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL(); count_match(common); break; case OP_ONCE: case OP_ONCE_NC: case OP_BRA: case OP_CBRA: case OP_COND: case OP_SBRA: case OP_SCBRA: case OP_SCOND: cc = compile_bracket_matchingpath(common, cc, parent); break; case OP_BRAZERO: if (cc[1] > OP_ASSERTBACK_NOT) cc = compile_bracket_matchingpath(common, cc, parent); else { PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); cc = compile_assert_matchingpath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); } break; case OP_BRAPOS: case OP_CBRAPOS: case OP_SBRAPOS: case OP_SCBRAPOS: case OP_BRAPOSZERO: cc = compile_bracketpos_matchingpath(common, cc, parent); break; case OP_MARK: PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); SLJIT_ASSERT(common->mark_ptr != 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr); allocate_stack(common, common->has_skip_arg ? 5 : 1); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); if (common->has_skip_arg) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); } cc += 1 + 2 + cc[1]; break; case OP_PRUNE: case OP_PRUNE_ARG: case OP_SKIP: case OP_SKIP_ARG: case OP_THEN: case OP_THEN_ARG: case OP_COMMIT: cc = compile_control_verb_matchingpath(common, cc, parent); break; case OP_FAIL: case OP_ACCEPT: case OP_ASSERT_ACCEPT: cc = compile_fail_accept_matchingpath(common, cc, parent); break; case OP_CLOSE: cc = compile_close_matchingpath(common, cc); break; case OP_SKIPZERO: cc = bracketend(cc + 1); break; default: SLJIT_UNREACHABLE(); return; } if (cc == NULL) return; } if (has_then_trap) { /* Head item on backtrack. */ PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap; common->then_trap = save_then_trap; } SLJIT_ASSERT(cc == ccend); } #undef PUSH_BACKTRACK #undef PUSH_BACKTRACK_NOVALUE #undef BACKTRACK_AS #define COMPILE_BACKTRACKINGPATH(current) \ do \ { \ compile_backtrackingpath(common, (current)); \ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ return; \ } \ while (0) #define CURRENT_AS(type) ((type *)current) static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; pcre_uchar *cc = current->cc; pcre_uchar opcode; pcre_uchar type; sljit_u32 max = 0, exact; struct sljit_label *label = NULL; struct sljit_jump *jump = NULL; jump_list *jumplist = NULL; pcre_uchar *end; int private_data_ptr = PRIVATE_DATA(cc); int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP); int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); switch(opcode) { case OP_STAR: case OP_UPTO: if (type == OP_ANYNL || type == OP_EXTUNI) { SLJIT_ASSERT(private_data_ptr == 0); set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); } else { if (CURRENT_AS(char_iterator_backtrack)->u.charpos.enabled) { OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, TMP2, 0, base, offset1); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); label = LABEL(); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); if (CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit != 0) OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.othercasebit); CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CURRENT_AS(char_iterator_backtrack)->u.charpos.chr, CURRENT_AS(char_iterator_backtrack)->matchingpath); skip_char_back(common); CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP2, 0, label); } else { OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); jump = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, base, offset1); skip_char_back(common); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); } JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 2); } break; case OP_MINSTAR: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); set_jumps(jumplist, LABEL()); if (private_data_ptr == 0) free_stack(common, 1); break; case OP_MINUPTO: OP1(SLJIT_MOV, TMP1, 0, base, offset1); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP2(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); add_jump(compiler, &jumplist, JUMP(SLJIT_ZERO)); OP1(SLJIT_MOV, base, offset1, TMP1, 0); compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); set_jumps(jumplist, LABEL()); if (private_data_ptr == 0) free_stack(common, 2); break; case OP_QUERY: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(char_iterator_backtrack)->matchingpath); jump = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(char_iterator_backtrack)->u.backtracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 1); break; case OP_MINQUERY: OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); OP1(SLJIT_MOV, base, offset0, SLJIT_IMM, 0); jump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); compile_char1_matchingpath(common, type, cc, &jumplist, TRUE); JUMPTO(SLJIT_JUMP, CURRENT_AS(char_iterator_backtrack)->matchingpath); set_jumps(jumplist, LABEL()); JUMPHERE(jump); if (private_data_ptr == 0) free_stack(common, 1); break; case OP_EXACT: case OP_POSSTAR: case OP_POSQUERY: case OP_POSUPTO: break; default: SLJIT_UNREACHABLE(); break; } set_jumps(current->topbacktracks, LABEL()); } static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; pcre_uchar *cc = current->cc; BOOL ref = (*cc == OP_REF || *cc == OP_REFI); pcre_uchar type; type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE]; if ((type & 0x1) == 0) { /* Maximize case. */ set_jumps(current->topbacktracks, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath); return; } OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(ref_iterator_backtrack)->matchingpath); set_jumps(current->topbacktracks, LABEL()); free_stack(common, ref ? 2 : 3); } static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; if (CURRENT_AS(recurse_backtrack)->inlined_pattern) compile_backtrackingpath(common, current->top); set_jumps(current->topbacktracks, LABEL()); if (CURRENT_AS(recurse_backtrack)->inlined_pattern) return; if (common->has_set_som && common->mark_ptr != 0) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); free_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0); } else if (common->has_set_som || common->mark_ptr != 0) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); } } static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; pcre_uchar *cc = current->cc; pcre_uchar bra = OP_BRA; struct sljit_jump *brajump = NULL; SLJIT_ASSERT(*cc != OP_BRAMINZERO); if (*cc == OP_BRAZERO) { bra = *cc; cc++; } if (bra == OP_BRAZERO) { SLJIT_ASSERT(current->topbacktracks == NULL); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); } if (CURRENT_AS(assert_backtrack)->framesize < 0) { set_jumps(current->topbacktracks, LABEL()); if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath); free_stack(common, 1); } return; } if (bra == OP_BRAZERO) { if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT) { OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->matchingpath); free_stack(common, 1); return; } free_stack(common, 1); brajump = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); } if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(assert_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(assert_backtrack)->framesize - 1)); set_jumps(current->topbacktracks, LABEL()); } else set_jumps(current->topbacktracks, LABEL()); if (bra == OP_BRAZERO) { /* We know there is enough place on the stack. */ OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->matchingpath); JUMPHERE(brajump); } } static void compile_bracket_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; int opcode, stacksize, alt_count, alt_max; int offset = 0; int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr; int repeat_ptr = 0, repeat_type = 0, repeat_count = 0; pcre_uchar *cc = current->cc; pcre_uchar *ccbegin; pcre_uchar *ccprev; pcre_uchar bra = OP_BRA; pcre_uchar ket; assert_backtrack *assert; sljit_uw *next_update_addr = NULL; BOOL has_alternatives; BOOL needs_control_head = FALSE; struct sljit_jump *brazero = NULL; struct sljit_jump *alt1 = NULL; struct sljit_jump *alt2 = NULL; struct sljit_jump *once = NULL; struct sljit_jump *cond = NULL; struct sljit_label *rmin_label = NULL; struct sljit_label *exact_label = NULL; if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) { bra = *cc; cc++; } opcode = *cc; ccbegin = bracketend(cc) - 1 - LINK_SIZE; ket = *ccbegin; if (ket == OP_KET && PRIVATE_DATA(ccbegin) != 0) { repeat_ptr = PRIVATE_DATA(ccbegin); repeat_type = PRIVATE_DATA(ccbegin + 2); repeat_count = PRIVATE_DATA(ccbegin + 3); SLJIT_ASSERT(repeat_type != 0 && repeat_count != 0); if (repeat_type == OP_UPTO) ket = OP_KETRMAX; if (repeat_type == OP_MINUPTO) ket = OP_KETRMIN; } ccbegin = cc; cc += GET(cc, 1); has_alternatives = *cc == OP_ALT; if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL; if (opcode == OP_CBRA || opcode == OP_SCBRA) offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) opcode = OP_SCOND; if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) opcode = OP_ONCE; alt_max = has_alternatives ? no_alternatives(ccbegin) : 0; /* Decoding the needs_control_head in framesize. */ if (opcode == OP_ONCE) { needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0; CURRENT_AS(bracket_backtrack)->u.framesize >>= 1; } if (ket != OP_KET && repeat_type != 0) { /* TMP1 is used in OP_KETRMIN below. */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); if (repeat_type == OP_UPTO) OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0, SLJIT_IMM, 1); else OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0); } if (ket == OP_KETRMAX) { if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); brazero = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0); } } else if (ket == OP_KETRMIN) { if (bra != OP_BRAMINZERO) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (repeat_type != 0) { /* TMP1 was set a few lines above. */ CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); /* Drop STR_PTR for non-greedy plus quantifier. */ if (opcode != OP_ONCE) free_stack(common, 1); } else if (opcode >= OP_SBRA || opcode == OP_ONCE) { /* Checking zero-length iteration. */ if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); else { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 2), CURRENT_AS(bracket_backtrack)->recursive_matchingpath); } /* Drop STR_PTR for non-greedy plus quantifier. */ if (opcode != OP_ONCE) free_stack(common, 1); } else JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); } rmin_label = LABEL(); if (repeat_type != 0) OP2(SLJIT_ADD, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); } else if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); brazero = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); } else if (repeat_type == OP_EXACT) { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); exact_label = LABEL(); } if (offset != 0) { if (common->capture_last_ptr != 0) { SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); free_stack(common, 3); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0); } else if (common->optimized_cbracket[offset >> 1] == 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); free_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); } } if (SLJIT_UNLIKELY(opcode == OP_ONCE)) { if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); } once = JUMP(SLJIT_JUMP); } else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) { if (has_alternatives) { /* Always exactly one alternative. */ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); alt_max = 2; alt1 = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); } } else if (has_alternatives) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); if (alt_max > 4) { /* Table jump if alt_max is greater than 4. */ next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw)); if (SLJIT_UNLIKELY(next_update_addr == NULL)) return; sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr); add_label_addr(common, next_update_addr++); } else { if (alt_max == 4) alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, sizeof(sljit_uw)); } } COMPILE_BACKTRACKINGPATH(current->top); if (current->topbacktracks) set_jumps(current->topbacktracks, LABEL()); if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) { /* Conditional block always has at most one alternative. */ if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) { SLJIT_ASSERT(has_alternatives); assert = CURRENT_AS(bracket_backtrack)->u.assert; if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1)); } cond = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL()); } else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL) { SLJIT_ASSERT(has_alternatives); cond = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL()); } else SLJIT_ASSERT(!has_alternatives); } if (has_alternatives) { alt_count = sizeof(sljit_uw); do { current->top = NULL; current->topbacktracks = NULL; current->nextbacktracks = NULL; /* Conditional blocks always have an additional alternative, even if it is empty. */ if (*cc == OP_ALT) { ccprev = cc + 1 + LINK_SIZE; cc += GET(cc, 1); if (opcode != OP_COND && opcode != OP_SCOND) { if (opcode != OP_ONCE) { if (private_data_ptr != 0) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); } else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0)); } compile_matchingpath(common, ccprev, cc, current); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return; } /* Instructions after the current alternative is successfully matched. */ /* There is a similar code in compile_bracket_matchingpath. */ if (opcode == OP_ONCE) match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); stacksize = 0; if (repeat_type == OP_MINUPTO) { /* We need to preserve the counter. TMP2 will be used below. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr); stacksize++; } if (ket != OP_KET || bra != OP_BRA) stacksize++; if (offset != 0) { if (common->capture_last_ptr != 0) stacksize++; if (common->optimized_cbracket[offset >> 1] == 0) stacksize += 2; } if (opcode != OP_ONCE) stacksize++; if (stacksize > 0) allocate_stack(common, stacksize); stacksize = 0; if (repeat_type == OP_MINUPTO) { /* TMP2 was set above. */ OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP2, 0, SLJIT_IMM, 1); stacksize++; } if (ket != OP_KET || bra != OP_BRA) { if (ket != OP_KET) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); else OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); stacksize++; } if (offset != 0) stacksize = match_capture_common(common, stacksize, offset, private_data_ptr); if (opcode != OP_ONCE) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count); if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0) { /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */ SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0); } JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath); if (opcode != OP_ONCE) { if (alt_max > 4) add_label_addr(common, next_update_addr++); else { if (alt_count != 2 * sizeof(sljit_uw)) { JUMPHERE(alt1); if (alt_max == 3 && alt_count == sizeof(sljit_uw)) alt2 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_uw)); } else { JUMPHERE(alt2); if (alt_max == 4) alt1 = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_uw)); } } alt_count += sizeof(sljit_uw); } COMPILE_BACKTRACKINGPATH(current->top); if (current->topbacktracks) set_jumps(current->topbacktracks, LABEL()); SLJIT_ASSERT(!current->nextbacktracks); } while (*cc == OP_ALT); if (cond != NULL) { SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); assert = CURRENT_AS(bracket_backtrack)->u.assert; if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) { OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), assert->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-assert->framesize - 1)); } JUMPHERE(cond); } /* Free the STR_PTR. */ if (private_data_ptr == 0) free_stack(common, 1); } if (offset != 0) { /* Using both tmp register is better for instruction scheduling. */ if (common->optimized_cbracket[offset >> 1] != 0) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); free_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); } else { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } } else if (opcode == OP_SBRA || opcode == OP_SCOND) { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); } else if (opcode == OP_ONCE) { cc = ccbegin + GET(ccbegin, 1); stacksize = needs_control_head ? 1 : 0; if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) { /* Reset head and drop saved frame. */ stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1); } else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) { /* The STR_PTR must be released. */ stacksize++; } if (stacksize > 0) free_stack(common, stacksize); JUMPHERE(once); /* Restore previous private_data_ptr */ if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracket_backtrack)->u.framesize - 1)); else if (ket == OP_KETRMIN) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); /* See the comment below. */ free_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } } if (repeat_type == OP_EXACT) { OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), repeat_ptr, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), repeat_ptr, TMP1, 0); CMPTO(SLJIT_LESS_EQUAL, TMP1, 0, SLJIT_IMM, repeat_count, exact_label); } else if (ket == OP_KETRMAX) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); if (bra != OP_BRAZERO) free_stack(common, 1); CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursive_matchingpath); if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath); JUMPHERE(brazero); free_stack(common, 1); } } else if (ket == OP_KETRMIN) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); /* OP_ONCE removes everything in case of a backtrack, so we don't need to explicitly release the STR_PTR. The extra release would affect badly the free_stack(2) above. */ if (opcode != OP_ONCE) free_stack(common, 1); CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rmin_label); if (opcode == OP_ONCE) free_stack(common, bra == OP_BRAMINZERO ? 2 : 1); else if (bra == OP_BRAMINZERO) free_stack(common, 1); } else if (bra == OP_BRAZERO) { OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zero_matchingpath); JUMPHERE(brazero); } } static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; int offset; struct sljit_jump *jump; if (CURRENT_AS(bracketpos_backtrack)->framesize < 0) { if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS) { offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1; OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP2, 0); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0); } set_jumps(current->topbacktracks, LABEL()); free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); return; } OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); if (current->topbacktracks) { jump = JUMP(SLJIT_JUMP); set_jumps(current->topbacktracks, LABEL()); /* Drop the stack frame. */ free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); JUMPHERE(jump); } OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), CURRENT_AS(bracketpos_backtrack)->private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(-CURRENT_AS(bracketpos_backtrack)->framesize - 1)); } static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) { assert_backtrack backtrack; current->top = NULL; current->topbacktracks = NULL; current->nextbacktracks = NULL; if (current->cc[1] > OP_ASSERTBACK_NOT) { /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */ compile_bracket_matchingpath(common, current->cc, current); compile_bracket_backtrackingpath(common, current->top); } else { memset(&backtrack, 0, sizeof(backtrack)); backtrack.common.cc = current->cc; backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath; /* Manual call of compile_assert_matchingpath. */ compile_assert_matchingpath(common, current->cc, &backtrack, FALSE); } SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); } static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; pcre_uchar opcode = *current->cc; struct sljit_label *loop; struct sljit_jump *jump; if (opcode == OP_THEN || opcode == OP_THEN_ARG) { if (common->then_trap != NULL) { SLJIT_ASSERT(common->control_head_ptr != 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start); jump = JUMP(SLJIT_JUMP); loop = LABEL(); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); JUMPHERE(jump); CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, loop); CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(2), TMP2, 0, loop); add_jump(compiler, &common->then_trap->quit, JUMP(SLJIT_JUMP)); return; } else if (common->positive_assert) { add_jump(compiler, &common->positive_assert_quit, JUMP(SLJIT_JUMP)); return; } } if (common->local_exit) { if (common->quit_label == NULL) add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); else JUMPTO(SLJIT_JUMP, common->quit_label); return; } if (opcode == OP_SKIP_ARG) { SLJIT_ASSERT(common->control_head_ptr != 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0)); return; } if (opcode == OP_SKIP) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); else OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_IMM, 0); add_jump(compiler, &common->reset_match, JUMP(SLJIT_JUMP)); } static SLJIT_INLINE void compile_then_trap_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; struct sljit_jump *jump; int size; if (CURRENT_AS(then_trap_backtrack)->then_trap) { common->then_trap = CURRENT_AS(then_trap_backtrack)->then_trap; return; } size = CURRENT_AS(then_trap_backtrack)->framesize; size = 3 + (size < 0 ? 0 : size); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(size - 3)); free_stack(common, size); jump = JUMP(SLJIT_JUMP); set_jumps(CURRENT_AS(then_trap_backtrack)->quit, LABEL()); /* STACK_TOP is set by THEN. */ if (CURRENT_AS(then_trap_backtrack)->framesize >= 0) add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 3); JUMPHERE(jump); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP1, 0); } static void compile_backtrackingpath(compiler_common *common, struct backtrack_common *current) { DEFINE_COMPILER; then_trap_backtrack *save_then_trap = common->then_trap; while (current) { if (current->nextbacktracks != NULL) set_jumps(current->nextbacktracks, LABEL()); switch(*current->cc) { case OP_SET_SOM: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), TMP1, 0); break; case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_UPTO: case OP_MINUPTO: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_UPTOI: case OP_MINUPTOI: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEEXACT: case OP_TYPEPOSSTAR: case OP_TYPEPOSPLUS: case OP_TYPEPOSQUERY: case OP_TYPEPOSUPTO: case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: #endif compile_iterator_backtrackingpath(common, current); break; case OP_REF: case OP_REFI: case OP_DNREF: case OP_DNREFI: compile_ref_iterator_backtrackingpath(common, current); break; case OP_RECURSE: compile_recurse_backtrackingpath(common, current); break; case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: compile_assert_backtrackingpath(common, current); break; case OP_ONCE: case OP_ONCE_NC: case OP_BRA: case OP_CBRA: case OP_COND: case OP_SBRA: case OP_SCBRA: case OP_SCOND: compile_bracket_backtrackingpath(common, current); break; case OP_BRAZERO: if (current->cc[1] > OP_ASSERTBACK_NOT) compile_bracket_backtrackingpath(common, current); else compile_assert_backtrackingpath(common, current); break; case OP_BRAPOS: case OP_CBRAPOS: case OP_SBRAPOS: case OP_SCBRAPOS: case OP_BRAPOSZERO: compile_bracketpos_backtrackingpath(common, current); break; case OP_BRAMINZERO: compile_braminzero_backtrackingpath(common, current); break; case OP_MARK: OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0)); if (common->has_skip_arg) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, common->has_skip_arg ? 5 : 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, TMP1, 0); if (common->has_skip_arg) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0); break; case OP_THEN: case OP_THEN_ARG: case OP_PRUNE: case OP_PRUNE_ARG: case OP_SKIP: case OP_SKIP_ARG: compile_control_verb_backtrackingpath(common, current); break; case OP_COMMIT: if (!common->local_exit) OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); if (common->quit_label == NULL) add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); else JUMPTO(SLJIT_JUMP, common->quit_label); break; case OP_CALLOUT: case OP_FAIL: case OP_ACCEPT: case OP_ASSERT_ACCEPT: set_jumps(current->topbacktracks, LABEL()); break; case OP_THEN_TRAP: /* A virtual opcode for then traps. */ compile_then_trap_backtrackingpath(common, current); break; default: SLJIT_UNREACHABLE(); break; } current = current->prev; } common->then_trap = save_then_trap; } static SLJIT_INLINE void compile_recurse(compiler_common *common) { DEFINE_COMPILER; pcre_uchar *cc = common->start + common->currententry->start; pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); pcre_uchar *ccend = bracketend(cc) - (1 + LINK_SIZE); BOOL needs_control_head; int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head); int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head); int alternativesize; BOOL needs_frame; backtrack_common altbacktrack; struct sljit_jump *jump; /* Recurse captures then. */ common->then_trap = NULL; SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); needs_frame = framesize >= 0; if (!needs_frame) framesize = 0; alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0; SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head_ptr != 0); common->currententry->entry = LABEL(); set_jumps(common->currententry->calls, common->currententry->entry); sljit_emit_fast_enter(compiler, TMP2, 0); count_match(common); allocate_stack(common, private_data_size + framesize + alternativesize); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); copy_private_data(common, ccbegin, ccend, TRUE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head); if (needs_control_head) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0); if (needs_frame) init_frame(common, cc, NULL, framesize + alternativesize - 1, alternativesize, TRUE); if (alternativesize > 0) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); memset(&altbacktrack, 0, sizeof(backtrack_common)); common->quit_label = NULL; common->accept_label = NULL; common->quit = NULL; common->accept = NULL; altbacktrack.cc = ccbegin; cc += GET(cc, 1); while (1) { altbacktrack.top = NULL; altbacktrack.topbacktracks = NULL; if (altbacktrack.cc != ccbegin) OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); compile_matchingpath(common, altbacktrack.cc, cc, &altbacktrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return; add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); compile_backtrackingpath(common, altbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return; set_jumps(altbacktrack.topbacktracks, LABEL()); if (*cc != OP_ALT) break; altbacktrack.cc = cc + 1 + LINK_SIZE; cc += GET(cc, 1); } /* None of them matched. */ OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); jump = JUMP(SLJIT_JUMP); if (common->quit != NULL) { set_jumps(common->quit, LABEL()); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); if (needs_frame) { OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); } OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); common->quit = NULL; add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP)); } set_jumps(common->accept, LABEL()); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr); if (needs_frame) { OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_sw)); } OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); JUMPHERE(jump); if (common->quit != NULL) set_jumps(common->quit, LABEL()); copy_private_data(common, ccbegin, ccend, FALSE, framesize + alternativesize, private_data_size + framesize + alternativesize, needs_control_head); free_stack(common, private_data_size + framesize + alternativesize); if (needs_control_head) { OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(-3)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP1, 0); OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, TMP2, 0); } else { OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(-2)); OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, TMP2, 0); } sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), STACK(-1)); } #undef COMPILE_BACKTRACKINGPATH #undef CURRENT_AS void PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode) { struct sljit_compiler *compiler; backtrack_common rootbacktrack; compiler_common common_data; compiler_common *common = &common_data; const sljit_u8 *tables = re->tables; pcre_study_data *study; int private_data_size; pcre_uchar *ccend; executable_functions *functions; void *executable_func; sljit_uw executable_size; sljit_uw total_length; label_addr_list *label_addr; struct sljit_label *mainloop_label = NULL; struct sljit_label *continue_match_label; struct sljit_label *empty_match_found_label = NULL; struct sljit_label *empty_match_backtrack_label = NULL; struct sljit_label *reset_match_label; struct sljit_label *quit_label; struct sljit_jump *jump; struct sljit_jump *minlength_check_failed = NULL; struct sljit_jump *reqbyte_notfound = NULL; struct sljit_jump *empty_match = NULL; SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0); study = extra->study_data; if (!tables) tables = PRIV(default_tables); memset(&rootbacktrack, 0, sizeof(backtrack_common)); memset(common, 0, sizeof(compiler_common)); rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size; common->start = rootbacktrack.cc; common->read_only_data_head = NULL; common->fcc = tables + fcc_offset; common->lcc = (sljit_sw)(tables + lcc_offset); common->mode = mode; common->might_be_empty = study->minlength == 0; common->nltype = NLTYPE_FIXED; switch(re->options & PCRE_NEWLINE_BITS) { case 0: /* Compile-time default */ switch(NEWLINE) { case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break; case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break; default: common->newline = NEWLINE; break; } break; case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break; case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break; case PCRE_NEWLINE_CR+ PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break; case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break; case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break; default: return; } common->nlmax = READ_CHAR_MAX; common->nlmin = 0; if ((re->options & PCRE_BSR_ANYCRLF) != 0) common->bsr_nltype = NLTYPE_ANYCRLF; else if ((re->options & PCRE_BSR_UNICODE) != 0) common->bsr_nltype = NLTYPE_ANY; else { #ifdef BSR_ANYCRLF common->bsr_nltype = NLTYPE_ANYCRLF; #else common->bsr_nltype = NLTYPE_ANY; #endif } common->bsr_nlmax = READ_CHAR_MAX; common->bsr_nlmin = 0; common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; common->ctypes = (sljit_sw)(tables + ctypes_offset); common->name_table = ((pcre_uchar *)re) + re->name_table_offset; common->name_count = re->name_count; common->name_entry_size = re->name_entry_size; common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; #ifdef SUPPORT_UTF /* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */ common->utf = (re->options & PCRE_UTF8) != 0; #ifdef SUPPORT_UCP common->use_ucp = (re->options & PCRE_UCP) != 0; #endif if (common->utf) { if (common->nltype == NLTYPE_ANY) common->nlmax = 0x2029; else if (common->nltype == NLTYPE_ANYCRLF) common->nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL; else { /* We only care about the first newline character. */ common->nlmax = common->newline & 0xff; } if (common->nltype == NLTYPE_FIXED) common->nlmin = common->newline & 0xff; else common->nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL; if (common->bsr_nltype == NLTYPE_ANY) common->bsr_nlmax = 0x2029; else common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL; common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL; } #endif /* SUPPORT_UTF */ ccend = bracketend(common->start); /* Calculate the local space size on the stack. */ common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw); common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, compiler->allocator_data); if (!common->optimized_cbracket) return; #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1 memset(common->optimized_cbracket, 0, re->top_bracket + 1); #else memset(common->optimized_cbracket, 1, re->top_bracket + 1); #endif SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET); #if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2 common->capture_last_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); #endif if (!check_opcode_types(common, common->start, ccend)) { SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); return; } /* Checking flags and updating ovector_start. */ if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) { common->req_char_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } if (mode != JIT_COMPILE) { common->start_used_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); if (mode == JIT_PARTIAL_SOFT_COMPILE) { common->hit_start = common->ovector_start; common->ovector_start += 2 * sizeof(sljit_sw); } } if ((re->options & PCRE_FIRSTLINE) != 0) { common->match_end_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD common->control_head_ptr = 1; #endif if (common->control_head_ptr != 0) { common->control_head_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } if (common->has_set_som) { /* Saving the real start pointer is necessary. */ common->start_ptr = common->ovector_start; common->ovector_start += sizeof(sljit_sw); } /* Aligning ovector to even number of sljit words. */ if ((common->ovector_start & sizeof(sljit_sw)) != 0) common->ovector_start += sizeof(sljit_sw); if (common->start_ptr == 0) common->start_ptr = OVECTOR(0); /* Capturing brackets cannot be optimized if callouts are allowed. */ if (common->capture_last_ptr != 0) memset(common->optimized_cbracket, 0, re->top_bracket + 1); SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw); total_length = ccend - common->start; common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), compiler->allocator_data); if (!common->private_data_ptrs) { SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); return; } memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32)); private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); set_private_data_ptrs(common, &private_data_size, ccend); if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) { if (!detect_fast_forward_skip(common, &private_data_size) && !common->has_skip_in_assert_back) detect_fast_fail(common, common->start, &private_data_size, 4); } SLJIT_ASSERT(common->fast_fail_start_ptr <= common->fast_fail_end_ptr); if (private_data_size > SLJIT_MAX_LOCAL_SIZE) { SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); return; } if (common->has_then) { common->then_offsets = (sljit_u8 *)(common->private_data_ptrs + total_length); memset(common->then_offsets, 0, total_length); set_then_offsets(common, common->start, NULL); } compiler = sljit_create_compiler(NULL); if (!compiler) { SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); return; } common->compiler = compiler; /* Main pcre_jit_exec entry. */ sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size); /* Register init. */ reset_ovector(common, (re->top_bracket + 1) * 2); if (common->req_char_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, SLJIT_R0, 0); OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_S0, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_S0, 0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, end)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, start)); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); if (common->fast_fail_start_ptr < common->fast_fail_end_ptr) reset_fast_fail(common); if (mode == JIT_PARTIAL_SOFT_COMPILE) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1); if (common->mark_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0); if (common->control_head_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0); /* Main part of the matching */ if ((re->options & PCRE_ANCHORED) == 0) { mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0); continue_match_label = LABEL(); /* Forward search if possible. */ if ((re->options & PCRE_NO_START_OPTIMIZE) == 0) { if (mode == JIT_COMPILE && fast_forward_first_n_chars(common)) ; else if ((re->flags & PCRE_FIRSTSET) != 0) fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0); else if ((re->flags & PCRE_STARTLINE) != 0) fast_forward_newline(common); else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) fast_forward_start_bits(common, study->start_bits); } } else continue_match_label = LABEL(); if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) { OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0); } if (common->req_char_ptr != 0) reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0); /* Store the current STR_PTR in OVECTOR(0). */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0); /* Copy the limit of allowed recursions. */ OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1); if (common->fast_forward_bc_ptr != NULL) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1), STR_PTR, 0); if (common->start_ptr != OVECTOR(0)) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0); /* Copy the beginning of the string. */ if (mode == JIT_PARTIAL_SOFT_COMPILE) { jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start + sizeof(sljit_sw), STR_PTR, 0); JUMPHERE(jump); } else if (mode == JIT_PARTIAL_HARD_COMPILE) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0); compile_matchingpath(common, common->start, ccend, &rootbacktrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } if (common->might_be_empty) { empty_match = CMP(SLJIT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0)); empty_match_found_label = LABEL(); } common->accept_label = LABEL(); if (common->accept != NULL) set_jumps(common->accept, common->accept_label); /* This means we have a match. Update the ovector. */ copy_ovector(common, re->top_bracket + 1); common->quit_label = common->forced_quit_label = LABEL(); if (common->quit != NULL) set_jumps(common->quit, common->quit_label); if (common->forced_quit != NULL) set_jumps(common->forced_quit, common->forced_quit_label); if (minlength_check_failed != NULL) SET_LABEL(minlength_check_failed, common->forced_quit_label); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); if (mode != JIT_COMPILE) { common->partialmatchlabel = LABEL(); set_jumps(common->partialmatch, common->partialmatchlabel); return_with_partial_match(common, common->quit_label); } if (common->might_be_empty) empty_match_backtrack_label = LABEL(); compile_backtrackingpath(common, rootbacktrack.top); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } SLJIT_ASSERT(rootbacktrack.prev == NULL); reset_match_label = LABEL(); if (mode == JIT_PARTIAL_SOFT_COMPILE) { /* Update hit_start only in the first time. */ jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0); JUMPHERE(jump); } /* Check we have remaining characters. */ if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_FIRSTLINE) != 0) { SLJIT_ASSERT(common->match_end_ptr != 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr); } OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1)) : common->start_ptr); if ((re->options & PCRE_ANCHORED) == 0) { if (common->ff_newline_shortcut != NULL) { if ((re->options & PCRE_FIRSTLINE) == 0) CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut); /* There cannot be more newlines here. */ } else CMPTO(SLJIT_LESS, STR_PTR, 0, ((re->options & PCRE_FIRSTLINE) == 0) ? STR_END : TMP1, 0, mainloop_label); } /* No more remaining characters. */ if (reqbyte_notfound != NULL) JUMPHERE(reqbyte_notfound); if (mode == JIT_PARTIAL_SOFT_COMPILE) CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); JUMPTO(SLJIT_JUMP, common->quit_label); flush_stubs(common); if (common->might_be_empty) { JUMPHERE(empty_match); OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label); OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label); JUMPTO(SLJIT_JUMP, empty_match_backtrack_label); } common->fast_forward_bc_ptr = NULL; common->fast_fail_start_ptr = 0; common->fast_fail_end_ptr = 0; common->currententry = common->entries; common->local_exit = TRUE; quit_label = common->quit_label; while (common->currententry != NULL) { /* Might add new entries. */ compile_recurse(common); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) { sljit_free_compiler(compiler); SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } flush_stubs(common); common->currententry = common->currententry->next; } common->local_exit = FALSE; common->quit_label = quit_label; /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ /* This is a (really) rare case. */ set_jumps(common->stackalloc, LABEL()); /* RETURN_ADDR is not a saved register. */ sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0); SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, STACK_TOP, 0); OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0); OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE); OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); sljit_emit_fast_return(compiler, TMP1, 0); /* Allocation failed. */ JUMPHERE(jump); /* We break the return address cache here, but this is a really rare case. */ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT); JUMPTO(SLJIT_JUMP, common->quit_label); /* Call limit reached. */ set_jumps(common->calllimit, LABEL()); OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT); JUMPTO(SLJIT_JUMP, common->quit_label); if (common->revertframes != NULL) { set_jumps(common->revertframes, LABEL()); do_revertframes(common); } if (common->wordboundary != NULL) { set_jumps(common->wordboundary, LABEL()); check_wordboundary(common); } if (common->anynewline != NULL) { set_jumps(common->anynewline, LABEL()); check_anynewline(common); } if (common->hspace != NULL) { set_jumps(common->hspace, LABEL()); check_hspace(common); } if (common->vspace != NULL) { set_jumps(common->vspace, LABEL()); check_vspace(common); } if (common->casefulcmp != NULL) { set_jumps(common->casefulcmp, LABEL()); do_casefulcmp(common); } if (common->caselesscmp != NULL) { set_jumps(common->caselesscmp, LABEL()); do_caselesscmp(common); } if (common->reset_match != NULL) { set_jumps(common->reset_match, LABEL()); do_reset_match(common, (re->top_bracket + 1) * 2); CMPTO(SLJIT_GREATER, STR_PTR, 0, TMP1, 0, continue_match_label); OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0); JUMPTO(SLJIT_JUMP, reset_match_label); } #ifdef SUPPORT_UTF #ifdef COMPILE_PCRE8 if (common->utfreadchar != NULL) { set_jumps(common->utfreadchar, LABEL()); do_utfreadchar(common); } if (common->utfreadchar16 != NULL) { set_jumps(common->utfreadchar16, LABEL()); do_utfreadchar16(common); } if (common->utfreadtype8 != NULL) { set_jumps(common->utfreadtype8, LABEL()); do_utfreadtype8(common); } #endif /* COMPILE_PCRE8 */ #endif /* SUPPORT_UTF */ #ifdef SUPPORT_UCP if (common->getucd != NULL) { set_jumps(common->getucd, LABEL()); do_getucd(common); } #endif SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data); SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data); executable_func = sljit_generate_code(compiler); executable_size = sljit_get_generated_code_size(compiler); label_addr = common->label_addrs; while (label_addr != NULL) { *label_addr->update_addr = sljit_get_label_addr(label_addr->label); label_addr = label_addr->next; } sljit_free_compiler(compiler); if (executable_func == NULL) { free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } /* Reuse the function descriptor if possible. */ if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL) functions = (executable_functions *)extra->executable_jit; else { /* Note: If your memory-checker has flagged the allocation below as a * memory leak, it is probably because you either forgot to call * pcre_free_study() (or pcre16_free_study()) on the pcre_extra (or * pcre16_extra) object, or you called said function after having * cleared the PCRE_EXTRA_EXECUTABLE_JIT bit from the "flags" field * of the object. (The function will only free the JIT data if the * bit remains set, as the bit indicates that the pointer to the data * is valid.) */ functions = SLJIT_MALLOC(sizeof(executable_functions), compiler->allocator_data); if (functions == NULL) { /* This case is highly unlikely since we just recently freed a lot of memory. Not impossible though. */ sljit_free_code(executable_func); free_read_only_data(common->read_only_data_head, compiler->allocator_data); return; } memset(functions, 0, sizeof(executable_functions)); functions->top_bracket = (re->top_bracket + 1) * 2; functions->limit_match = (re->flags & PCRE_MLSET) != 0 ? re->limit_match : 0; extra->executable_jit = functions; extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT; } functions->executable_funcs[mode] = executable_func; functions->read_only_data_heads[mode] = common->read_only_data_head; functions->executable_sizes[mode] = executable_size; } static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, void *executable_func) { union { void *executable_func; jit_function call_executable_func; } convert_executable_func; sljit_u8 local_space[MACHINE_STACK_SIZE]; struct sljit_stack local_stack; local_stack.min_start = local_space; local_stack.start = local_space; local_stack.end = local_space + MACHINE_STACK_SIZE; local_stack.top = local_space + MACHINE_STACK_SIZE; arguments->stack = &local_stack; convert_executable_func.executable_func = executable_func; return convert_executable_func.call_executable_func(arguments); } int PRIV(jit_exec)(const PUBL(extra) *extra_data, const pcre_uchar *subject, int length, int start_offset, int options, int *offsets, int offset_count) { executable_functions *functions = (executable_functions *)extra_data->executable_jit; union { void *executable_func; jit_function call_executable_func; } convert_executable_func; jit_arguments arguments; int max_offset_count; int retval; int mode = JIT_COMPILE; if ((options & PCRE_PARTIAL_HARD) != 0) mode = JIT_PARTIAL_HARD_COMPILE; else if ((options & PCRE_PARTIAL_SOFT) != 0) mode = JIT_PARTIAL_SOFT_COMPILE; if (functions->executable_funcs[mode] == NULL) return PCRE_ERROR_JIT_BADOPTION; /* Sanity checks should be handled by pcre_exec. */ arguments.str = subject + start_offset; arguments.begin = subject; arguments.end = subject + length; arguments.mark_ptr = NULL; /* JIT decreases this value less frequently than the interpreter. */ arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit); if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match) arguments.limit_match = functions->limit_match; arguments.notbol = (options & PCRE_NOTBOL) != 0; arguments.noteol = (options & PCRE_NOTEOL) != 0; arguments.notempty = (options & PCRE_NOTEMPTY) != 0; arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; arguments.offsets = offsets; arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL; arguments.real_offset_count = offset_count; /* pcre_exec() rounds offset_count to a multiple of 3, and then uses only 2/3 of the output vector for storing captured strings, with the remainder used as workspace. We don't need the workspace here. For compatibility, we limit the number of captured strings in the same way as pcre_exec(), so that the user gets the same result with and without JIT. */ if (offset_count != 2) offset_count = ((offset_count - (offset_count % 3)) * 2) / 3; max_offset_count = functions->top_bracket; if (offset_count > max_offset_count) offset_count = max_offset_count; arguments.offset_count = offset_count; if (functions->callback) arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata); else arguments.stack = (struct sljit_stack *)functions->userdata; if (arguments.stack == NULL) retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]); else { convert_executable_func.executable_func = functions->executable_funcs[mode]; retval = convert_executable_func.call_executable_func(&arguments); } if (retval * 2 > offset_count) retval = 0; if ((extra_data->flags & PCRE_EXTRA_MARK) != 0) *(extra_data->mark) = arguments.mark_ptr; return retval; } #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_jit_exec(const pcre *argument_re, const pcre_extra *extra_data, PCRE_SPTR subject, int length, int start_offset, int options, int *offsets, int offset_count, pcre_jit_stack *stack) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_jit_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, int offset_count, pcre16_jit_stack *stack) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_jit_exec(const pcre32 *argument_re, const pcre32_extra *extra_data, PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets, int offset_count, pcre32_jit_stack *stack) #endif { pcre_uchar *subject_ptr = (pcre_uchar *)subject; executable_functions *functions = (executable_functions *)extra_data->executable_jit; union { void *executable_func; jit_function call_executable_func; } convert_executable_func; jit_arguments arguments; int max_offset_count; int retval; int mode = JIT_COMPILE; SLJIT_UNUSED_ARG(argument_re); /* Plausibility checks */ if ((options & ~PUBLIC_JIT_EXEC_OPTIONS) != 0) return PCRE_ERROR_JIT_BADOPTION; if ((options & PCRE_PARTIAL_HARD) != 0) mode = JIT_PARTIAL_HARD_COMPILE; else if ((options & PCRE_PARTIAL_SOFT) != 0) mode = JIT_PARTIAL_SOFT_COMPILE; if (functions == NULL || functions->executable_funcs[mode] == NULL) return PCRE_ERROR_JIT_BADOPTION; /* Sanity checks should be handled by pcre_exec. */ arguments.stack = (struct sljit_stack *)stack; arguments.str = subject_ptr + start_offset; arguments.begin = subject_ptr; arguments.end = subject_ptr + length; arguments.mark_ptr = NULL; /* JIT decreases this value less frequently than the interpreter. */ arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit); if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match) arguments.limit_match = functions->limit_match; arguments.notbol = (options & PCRE_NOTBOL) != 0; arguments.noteol = (options & PCRE_NOTEOL) != 0; arguments.notempty = (options & PCRE_NOTEMPTY) != 0; arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; arguments.offsets = offsets; arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL; arguments.real_offset_count = offset_count; /* pcre_exec() rounds offset_count to a multiple of 3, and then uses only 2/3 of the output vector for storing captured strings, with the remainder used as workspace. We don't need the workspace here. For compatibility, we limit the number of captured strings in the same way as pcre_exec(), so that the user gets the same result with and without JIT. */ if (offset_count != 2) offset_count = ((offset_count - (offset_count % 3)) * 2) / 3; max_offset_count = functions->top_bracket; if (offset_count > max_offset_count) offset_count = max_offset_count; arguments.offset_count = offset_count; convert_executable_func.executable_func = functions->executable_funcs[mode]; retval = convert_executable_func.call_executable_func(&arguments); if (retval * 2 > offset_count) retval = 0; if ((extra_data->flags & PCRE_EXTRA_MARK) != 0) *(extra_data->mark) = arguments.mark_ptr; return retval; } void PRIV(jit_free)(void *executable_funcs) { int i; executable_functions *functions = (executable_functions *)executable_funcs; for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) { if (functions->executable_funcs[i] != NULL) sljit_free_code(functions->executable_funcs[i]); free_read_only_data(functions->read_only_data_heads[i], NULL); } SLJIT_FREE(functions, compiler->allocator_data); } int PRIV(jit_get_size)(void *executable_funcs) { int i; sljit_uw size = 0; sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes; for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) size += executable_sizes[i]; return (int)size; } const char* PRIV(jit_get_target)(void) { return sljit_get_platform_name(); } #if defined COMPILE_PCRE8 PCRE_EXP_DECL pcre_jit_stack * pcre_jit_stack_alloc(int startsize, int maxsize) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL pcre16_jit_stack * pcre16_jit_stack_alloc(int startsize, int maxsize) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL pcre32_jit_stack * pcre32_jit_stack_alloc(int startsize, int maxsize) #endif { if (startsize < 1 || maxsize < 1) return NULL; if (startsize > maxsize) startsize = maxsize; startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize, NULL); } #if defined COMPILE_PCRE8 PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *stack) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *stack) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *stack) #endif { sljit_free_stack((struct sljit_stack *)stack, NULL); } #if defined COMPILE_PCRE8 PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata) #endif { executable_functions *functions; if (extra != NULL && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL) { functions = (executable_functions *)extra->executable_jit; functions->callback = callback; functions->userdata = userdata; } } #if defined COMPILE_PCRE8 PCRE_EXP_DECL void pcre_jit_free_unused_memory(void) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void) #endif { sljit_free_unused_memory_exec(); } #else /* SUPPORT_JIT */ /* These are dummy functions to avoid linking errors when JIT support is not being compiled. */ #if defined COMPILE_PCRE8 PCRE_EXP_DECL pcre_jit_stack * pcre_jit_stack_alloc(int startsize, int maxsize) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL pcre16_jit_stack * pcre16_jit_stack_alloc(int startsize, int maxsize) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL pcre32_jit_stack * pcre32_jit_stack_alloc(int startsize, int maxsize) #endif { (void)startsize; (void)maxsize; return NULL; } #if defined COMPILE_PCRE8 PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *stack) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *stack) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *stack) #endif { (void)stack; } #if defined COMPILE_PCRE8 PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata) #endif { (void)extra; (void)callback; (void)userdata; } #if defined COMPILE_PCRE8 PCRE_EXP_DECL void pcre_jit_free_unused_memory(void) #elif defined COMPILE_PCRE16 PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void) #elif defined COMPILE_PCRE32 PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void) #endif { } #endif /* End of pcre_jit_compile.c */ ================================================ FILE: src/pcre/pcre_jit_test.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Main Library written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge This JIT compiler regression test program was written by Zoltan Herczeg Copyright (c) 2010-2012 ----------------------------------------------------------------------------- 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 the University of Cambridge 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 HAVE_CONFIG_H #include "config.h" #endif #include #include #include "pcre.h" #include "pcre_internal.h" /* Letter characters: \xe6\x92\xad = 0x64ad = 25773 (kanji) Non-letter characters: \xc2\xa1 = 0xa1 = (Inverted Exclamation Mark) \xf3\xa9\xb7\x80 = 0xe9dc0 = 957888 \xed\xa0\x80 = 55296 = 0xd800 (Invalid UTF character) \xed\xb0\x80 = 56320 = 0xdc00 (Invalid UTF character) Newlines: \xc2\x85 = 0x85 = 133 (NExt Line = NEL) \xe2\x80\xa8 = 0x2028 = 8232 (Line Separator) Othercase pairs: \xc3\xa9 = 0xe9 = 233 (e') \xc3\x89 = 0xc9 = 201 (E') \xc3\xa1 = 0xe1 = 225 (a') \xc3\x81 = 0xc1 = 193 (A') \x53 = 0x53 = S \x73 = 0x73 = s \xc5\xbf = 0x17f = 383 (long S) \xc8\xba = 0x23a = 570 \xe2\xb1\xa5 = 0x2c65 = 11365 \xe1\xbd\xb8 = 0x1f78 = 8056 \xe1\xbf\xb8 = 0x1ff8 = 8184 \xf0\x90\x90\x80 = 0x10400 = 66560 \xf0\x90\x90\xa8 = 0x10428 = 66600 \xc7\x84 = 0x1c4 = 452 \xc7\x85 = 0x1c5 = 453 \xc7\x86 = 0x1c6 = 454 Caseless sets: ucp_Armenian - \x{531}-\x{556} -> \x{561}-\x{586} ucp_Coptic - \x{2c80}-\x{2ce3} -> caseless: XOR 0x1 ucp_Latin - \x{ff21}-\x{ff3a} -> \x{ff41]-\x{ff5a} Mark property: \xcc\x8d = 0x30d = 781 Special: \xc2\x80 = 0x80 = 128 (lowest 2 byte character) \xdf\xbf = 0x7ff = 2047 (highest 2 byte character) \xe0\xa0\x80 = 0x800 = 2048 (lowest 2 byte character) \xef\xbf\xbf = 0xffff = 65535 (highest 3 byte character) \xf0\x90\x80\x80 = 0x10000 = 65536 (lowest 4 byte character) \xf4\x8f\xbf\xbf = 0x10ffff = 1114111 (highest allowed utf character) */ static int regression_tests(void); int main(void) { int jit = 0; #if defined SUPPORT_PCRE8 pcre_config(PCRE_CONFIG_JIT, &jit); #elif defined SUPPORT_PCRE16 pcre16_config(PCRE_CONFIG_JIT, &jit); #elif defined SUPPORT_PCRE32 pcre32_config(PCRE_CONFIG_JIT, &jit); #endif if (!jit) { printf("JIT must be enabled to run pcre_jit_test\n"); return 1; } return regression_tests(); } /* --------------------------------------------------------------------------------------- */ #if !(defined SUPPORT_PCRE8) && !(defined SUPPORT_PCRE16) && !(defined SUPPORT_PCRE32) #error SUPPORT_PCRE8 or SUPPORT_PCRE16 or SUPPORT_PCRE32 must be defined #endif #define MUA (PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANYCRLF) #define MUAP (PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANYCRLF | PCRE_UCP) #define CMUA (PCRE_CASELESS | PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANYCRLF) #define CMUAP (PCRE_CASELESS | PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANYCRLF | PCRE_UCP) #define MA (PCRE_MULTILINE | PCRE_NEWLINE_ANYCRLF) #define MAP (PCRE_MULTILINE | PCRE_NEWLINE_ANYCRLF | PCRE_UCP) #define CMA (PCRE_CASELESS | PCRE_MULTILINE | PCRE_NEWLINE_ANYCRLF) #define OFFSET_MASK 0x00ffff #define F_NO8 0x010000 #define F_NO16 0x020000 #define F_NO32 0x020000 #define F_NOMATCH 0x040000 #define F_DIFF 0x080000 #define F_FORCECONV 0x100000 #define F_PROPERTY 0x200000 #define F_STUDY 0x400000 struct regression_test_case { int flags; int start_offset; const char *pattern; const char *input; }; static struct regression_test_case regression_test_cases[] = { /* Constant strings. */ { MUA, 0, "AbC", "AbAbC" }, { MUA, 0, "ACCEPT", "AACACCACCEACCEPACCEPTACCEPTT" }, { CMUA, 0, "aA#\xc3\xa9\xc3\x81", "aA#Aa#\xc3\x89\xc3\xa1" }, { MA, 0, "[^a]", "aAbB" }, { CMA, 0, "[^m]", "mMnN" }, { MA, 0, "a[^b][^#]", "abacd" }, { CMA, 0, "A[^B][^E]", "abacd" }, { CMUA, 0, "[^x][^#]", "XxBll" }, { MUA, 0, "[^a]", "aaa\xc3\xa1#Ab" }, { CMUA, 0, "[^A]", "aA\xe6\x92\xad" }, { MUA, 0, "\\W(\\W)?\\w", "\r\n+bc" }, { MUA, 0, "\\W(\\W)?\\w", "\n\r+bc" }, { MUA, 0, "\\W(\\W)?\\w", "\r\r+bc" }, { MUA, 0, "\\W(\\W)?\\w", "\n\n+bc" }, { MUA, 0, "[axd]", "sAXd" }, { CMUA, 0, "[axd]", "sAXd" }, { CMUA, 0 | F_NOMATCH, "[^axd]", "DxA" }, { MUA, 0, "[a-dA-C]", "\xe6\x92\xad\xc3\xa9.B" }, { MUA, 0, "[^a-dA-C]", "\xe6\x92\xad\xc3\xa9" }, { CMUA, 0, "[^\xc3\xa9]", "\xc3\xa9\xc3\x89." }, { MUA, 0, "[^\xc3\xa9]", "\xc3\xa9\xc3\x89." }, { MUA, 0, "[^a]", "\xc2\x80[]" }, { CMUA, 0, "\xf0\x90\x90\xa7", "\xf0\x90\x91\x8f" }, { CMA, 0, "1a2b3c4", "1a2B3c51A2B3C4" }, { PCRE_CASELESS, 0, "\xff#a", "\xff#\xff\xfe##\xff#A" }, { PCRE_CASELESS, 0, "\xfe", "\xff\xfc#\xfe\xfe" }, { PCRE_CASELESS, 0, "a1", "Aa1" }, { MA, 0, "\\Ca", "cda" }, { CMA, 0, "\\Ca", "CDA" }, { MA, 0 | F_NOMATCH, "\\Cx", "cda" }, { CMA, 0 | F_NOMATCH, "\\Cx", "CDA" }, { CMUAP, 0, "\xf0\x90\x90\x80\xf0\x90\x90\xa8", "\xf0\x90\x90\xa8\xf0\x90\x90\x80" }, { CMUAP, 0, "\xf0\x90\x90\x80{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" }, { CMUAP, 0, "\xf0\x90\x90\xa8{2}", "\xf0\x90\x90\x80#\xf0\x90\x90\xa8\xf0\x90\x90\x80" }, { CMUAP, 0, "\xe1\xbd\xb8\xe1\xbf\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" }, { MA, 0, "[3-57-9]", "5" }, /* Assertions. */ { MUA, 0, "\\b[^A]", "A_B#" }, { MA, 0 | F_NOMATCH, "\\b\\W", "\n*" }, { MUA, 0, "\\B[^,]\\b[^s]\\b", "#X" }, { MAP, 0, "\\B", "_\xa1" }, { MAP, 0, "\\b_\\b[,A]\\B", "_," }, { MUAP, 0, "\\b", "\xe6\x92\xad!" }, { MUAP, 0, "\\B", "_\xc2\xa1\xc3\xa1\xc2\x85" }, { MUAP, 0, "\\b[^A]\\B[^c]\\b[^_]\\B", "_\xc3\xa1\xe2\x80\xa8" }, { MUAP, 0, "\\b\\w+\\B", "\xc3\x89\xc2\xa1\xe6\x92\xad\xc3\x81\xc3\xa1" }, { MUA, 0 | F_NOMATCH, "\\b.", "\xcd\xbe" }, { CMUAP, 0, "\\By", "\xf0\x90\x90\xa8y" }, { MA, 0 | F_NOMATCH, "\\R^", "\n" }, { MA, 1 | F_NOMATCH, "^", "\n" }, { 0, 0, "^ab", "ab" }, { 0, 0 | F_NOMATCH, "^ab", "aab" }, { PCRE_MULTILINE | PCRE_NEWLINE_CRLF, 0, "^a", "\r\raa\n\naa\r\naa" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANYCRLF, 0, "^-", "\xe2\x80\xa8--\xc2\x85-\r\n-" }, { PCRE_MULTILINE | PCRE_NEWLINE_ANY, 0, "^-", "a--b--\x85--" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANY, 0, "^-", "a--\xe2\x80\xa8--" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANY, 0, "^-", "a--\xc2\x85--" }, { 0, 0, "ab$", "ab" }, { 0, 0 | F_NOMATCH, "ab$", "abab\n\n" }, { PCRE_DOLLAR_ENDONLY, 0 | F_NOMATCH, "ab$", "abab\r\n" }, { PCRE_MULTILINE | PCRE_NEWLINE_CRLF, 0, "a$", "\r\raa\n\naa\r\naa" }, { PCRE_MULTILINE | PCRE_NEWLINE_ANY, 0, "a$", "aaa" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANYCRLF, 0, "#$", "#\xc2\x85###\r#" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANY, 0, "#$", "#\xe2\x80\xa9" }, { PCRE_NOTBOL | PCRE_NEWLINE_ANY, 0 | F_NOMATCH, "^a", "aa\naa" }, { PCRE_NOTBOL | PCRE_MULTILINE | PCRE_NEWLINE_ANY, 0, "^a", "aa\naa" }, { PCRE_NOTEOL | PCRE_NEWLINE_ANY, 0 | F_NOMATCH, "a$", "aa\naa" }, { PCRE_NOTEOL | PCRE_NEWLINE_ANY, 0 | F_NOMATCH, "a$", "aa\r\n" }, { PCRE_UTF8 | PCRE_DOLLAR_ENDONLY | PCRE_NEWLINE_ANY, 0 | F_PROPERTY, "\\p{Any}{2,}$", "aa\r\n" }, { PCRE_NOTEOL | PCRE_MULTILINE | PCRE_NEWLINE_ANY, 0, "a$", "aa\naa" }, { PCRE_NEWLINE_CR, 0, ".\\Z", "aaa" }, { PCRE_NEWLINE_CR | PCRE_UTF8, 0, "a\\Z", "aaa\r" }, { PCRE_NEWLINE_CR, 0, ".\\Z", "aaa\n" }, { PCRE_NEWLINE_CRLF, 0, ".\\Z", "aaa\r" }, { PCRE_NEWLINE_CRLF | PCRE_UTF8, 0, ".\\Z", "aaa\n" }, { PCRE_NEWLINE_CRLF, 0, ".\\Z", "aaa\r\n" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\r" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\n" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\r\n" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\xe2\x80\xa8" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\r" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\n" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".\\Z", "aaa\r\n" }, { PCRE_NEWLINE_ANY | PCRE_UTF8, 0, ".\\Z", "aaa\xc2\x85" }, { PCRE_NEWLINE_ANY | PCRE_UTF8, 0, ".\\Z", "aaa\xe2\x80\xa8" }, { MA, 0, "\\Aa", "aaa" }, { MA, 1 | F_NOMATCH, "\\Aa", "aaa" }, { MA, 1, "\\Ga", "aaa" }, { MA, 1 | F_NOMATCH, "\\Ga", "aba" }, { MA, 0, "a\\z", "aaa" }, { MA, 0 | F_NOMATCH, "a\\z", "aab" }, /* Brackets and alternatives. */ { MUA, 0, "(ab|bb|cd)", "bacde" }, { MUA, 0, "(?:ab|a)(bc|c)", "ababc" }, { MUA, 0, "((ab|(cc))|(bb)|(?:cd|efg))", "abac" }, { CMUA, 0, "((aB|(Cc))|(bB)|(?:cd|EFg))", "AcCe" }, { MUA, 0, "((ab|(cc))|(bb)|(?:cd|ebg))", "acebebg" }, { MUA, 0, "(?:(a)|(?:b))(cc|(?:d|e))(a|b)k", "accabdbbccbk" }, { MUA, 0, "\xc7\x82|\xc6\x82", "\xf1\x83\x82\x82\xc7\x82\xc7\x83" }, { MUA, 0, "=\xc7\x82|#\xc6\x82", "\xf1\x83\x82\x82=\xc7\x82\xc7\x83" }, { MUA, 0, "\xc7\x82\xc7\x83|\xc6\x82\xc6\x82", "\xf1\x83\x82\x82\xc7\x82\xc7\x83" }, { MUA, 0, "\xc6\x82\xc6\x82|\xc7\x83\xc7\x83|\xc8\x84\xc8\x84", "\xf1\x83\x82\x82\xc8\x84\xc8\x84" }, /* Greedy and non-greedy ? operators. */ { MUA, 0, "(?:a)?a", "laab" }, { CMUA, 0, "(A)?A", "llaab" }, { MUA, 0, "(a)?\?a", "aab" }, /* ?? is the prefix of trygraphs in GCC. */ { MUA, 0, "(a)?a", "manm" }, { CMUA, 0, "(a|b)?\?d((?:e)?)", "ABABdx" }, { MUA, 0, "(a|b)?\?d((?:e)?)", "abcde" }, { MUA, 0, "((?:ab)?\?g|b(?:g(nn|d)?\?)?)?\?(?:n)?m", "abgnbgnnbgdnmm" }, /* Greedy and non-greedy + operators */ { MUA, 0, "(aa)+aa", "aaaaaaa" }, { MUA, 0, "(aa)+?aa", "aaaaaaa" }, { MUA, 0, "(?:aba|ab|a)+l", "ababamababal" }, { MUA, 0, "(?:aba|ab|a)+?l", "ababamababal" }, { MUA, 0, "(a(?:bc|cb|b|c)+?|ss)+e", "accssabccbcacbccbbXaccssabccbcacbccbbe" }, { MUA, 0, "(a(?:bc|cb|b|c)+|ss)+?e", "accssabccbcacbccbbXaccssabccbcacbccbbe" }, { MUA, 0, "(?:(b(c)+?)+)?\?(?:(bc)+|(cb)+)+(?:m)+", "bccbcccbcbccbcbPbccbcccbcbccbcbmmn" }, /* Greedy and non-greedy * operators */ { CMUA, 0, "(?:AA)*AB", "aaaaaaamaaaaaaab" }, { MUA, 0, "(?:aa)*?ab", "aaaaaaamaaaaaaab" }, { MUA, 0, "(aa|ab)*ab", "aaabaaab" }, { CMUA, 0, "(aa|Ab)*?aB", "aaabaaab" }, { MUA, 0, "(a|b)*(?:a)*(?:b)*m", "abbbaaababanabbbaaababamm" }, { MUA, 0, "(a|b)*?(?:a)*?(?:b)*?m", "abbbaaababanabbbaaababamm" }, { MA, 0, "a(a(\\1*)a|(b)b+){0}a", "aa" }, { MA, 0, "((?:a|)*){0}a", "a" }, /* Combining ? + * operators */ { MUA, 0, "((bm)+)?\?(?:a)*(bm)+n|((am)+?)?(?:a)+(am)*n", "bmbmabmamaaamambmaman" }, { MUA, 0, "(((ab)?cd)*ef)+g", "abcdcdefcdefefmabcdcdefcdefefgg" }, { MUA, 0, "(((ab)?\?cd)*?ef)+?g", "abcdcdefcdefefmabcdcdefcdefefgg" }, { MUA, 0, "(?:(ab)?c|(?:ab)+?d)*g", "ababcdccababddg" }, { MUA, 0, "(?:(?:ab)?\?c|(ab)+d)*?g", "ababcdccababddg" }, /* Single character iterators. */ { MUA, 0, "(a+aab)+aaaab", "aaaabcaaaabaabcaabcaaabaaaab" }, { MUA, 0, "(a*a*aab)+x", "aaaaabaabaaabmaabx" }, { MUA, 0, "(a*?(b|ab)a*?)+x", "aaaabcxbbaabaacbaaabaabax" }, { MUA, 0, "(a+(ab|ad)a+)+x", "aaabaaaadaabaaabaaaadaaax" }, { MUA, 0, "(a?(a)a?)+(aaa)", "abaaabaaaaaaaa" }, { MUA, 0, "(a?\?(a)a?\?)+(b)", "aaaacaaacaacacbaaab" }, { MUA, 0, "(a{0,4}(b))+d", "aaaaaabaabcaaaaabaaaaabd" }, { MUA, 0, "(a{0,4}?[^b])+d+(a{0,4}[^b])d+", "aaaaadaaaacaadddaaddd" }, { MUA, 0, "(ba{2})+c", "baabaaabacbaabaac" }, { MUA, 0, "(a*+bc++)+", "aaabbcaaabcccab" }, { MUA, 0, "(a?+[^b])+", "babaacacb" }, { MUA, 0, "(a{0,3}+b)(a{0,3}+b)(a{0,3}+)[^c]", "abaabaaacbaabaaaac" }, { CMUA, 0, "([a-c]+[d-f]+?)+?g", "aBdacdehAbDaFgA" }, { CMUA, 0, "[c-f]+k", "DemmFke" }, { MUA, 0, "([DGH]{0,4}M)+", "GGDGHDGMMHMDHHGHM" }, { MUA, 0, "([a-c]{4,}s)+", "abasabbasbbaabsbba" }, { CMUA, 0, "[ace]{3,7}", "AcbDAcEEcEd" }, { CMUA, 0, "[ace]{3,7}?", "AcbDAcEEcEd" }, { CMUA, 0, "[ace]{3,}", "AcbDAcEEcEd" }, { CMUA, 0, "[ace]{3,}?", "AcbDAcEEcEd" }, { MUA, 0, "[ckl]{2,}?g", "cdkkmlglglkcg" }, { CMUA, 0, "[ace]{5}?", "AcCebDAcEEcEd" }, { MUA, 0, "([AbC]{3,5}?d)+", "BACaAbbAEAACCbdCCbdCCAAbb" }, { MUA, 0, "([^ab]{0,}s){2}", "abaabcdsABamsDDs" }, { MUA, 0, "\\b\\w+\\B", "x,a_cd" }, { MUAP, 0, "\\b[^\xc2\xa1]+\\B", "\xc3\x89\xc2\xa1\xe6\x92\xad\xc3\x81\xc3\xa1" }, { CMUA, 0, "[^b]+(a*)([^c]?d{3})", "aaaaddd" }, { CMUAP, 0, "\xe1\xbd\xb8{2}", "\xe1\xbf\xb8#\xe1\xbf\xb8\xe1\xbd\xb8" }, { CMUA, 0, "[^\xf0\x90\x90\x80]{2,4}@", "\xf0\x90\x90\xa8\xf0\x90\x90\x80###\xf0\x90\x90\x80@@@" }, { CMUA, 0, "[^\xe1\xbd\xb8][^\xc3\xa9]", "\xe1\xbd\xb8\xe1\xbf\xb8\xc3\xa9\xc3\x89#" }, { MUA, 0, "[^\xe1\xbd\xb8][^\xc3\xa9]", "\xe1\xbd\xb8\xe1\xbf\xb8\xc3\xa9\xc3\x89#" }, { MUA, 0, "[^\xe1\xbd\xb8]{3,}?", "##\xe1\xbd\xb8#\xe1\xbd\xb8#\xc3\x89#\xe1\xbd\xb8" }, { MUA, 0, "\\d+123", "987654321,01234" }, { MUA, 0, "abcd*|\\w+xy", "aaaaa,abxyz" }, { MUA, 0, "(?:abc|((?:amc|\\b\\w*xy)))", "aaaaa,abxyz" }, { MUA, 0, "a(?R)|([a-z]++)#", ".abcd.abcd#."}, { MUA, 0, "a(?R)|([a-z]++)#", ".abcd.mbcd#."}, { MUA, 0, ".[ab]*.", "xx" }, { MUA, 0, ".[ab]*a", "xxa" }, { MUA, 0, ".[ab]?.", "xx" }, /* Bracket repeats with limit. */ { MUA, 0, "(?:(ab){2}){5}M", "abababababababababababM" }, { MUA, 0, "(?:ab|abab){1,5}M", "abababababababababababM" }, { MUA, 0, "(?>ab|abab){1,5}M", "abababababababababababM" }, { MUA, 0, "(?:ab|abab){1,5}?M", "abababababababababababM" }, { MUA, 0, "(?>ab|abab){1,5}?M", "abababababababababababM" }, { MUA, 0, "(?:(ab){1,4}?){1,3}?M", "abababababababababababababM" }, { MUA, 0, "(?:(ab){1,4}){1,3}abababababababababababM", "ababababababababababababM" }, { MUA, 0 | F_NOMATCH, "(?:(ab){1,4}){1,3}abababababababababababM", "abababababababababababM" }, { MUA, 0, "(ab){4,6}?M", "abababababababM" }, /* Basic character sets. */ { MUA, 0, "(?:\\s)+(?:\\S)+", "ab \t\xc3\xa9\xe6\x92\xad " }, { MUA, 0, "(\\w)*(k)(\\W)?\?", "abcdef abck11" }, { MUA, 0, "\\((\\d)+\\)\\D", "a() (83 (8)2 (9)ab" }, { MUA, 0, "\\w(\\s|(?:\\d)*,)+\\w\\wb", "a 5, 4,, bb 5, 4,, aab" }, { MUA, 0, "(\\v+)(\\V+)", "\x0e\xc2\x85\xe2\x80\xa8\x0b\x09\xe2\x80\xa9" }, { MUA, 0, "(\\h+)(\\H+)", "\xe2\x80\xa8\xe2\x80\x80\x20\xe2\x80\x8a\xe2\x81\x9f\xe3\x80\x80\x09\x20\xc2\xa0\x0a" }, { MUA, 0, "x[bcef]+", "xaxdxecbfg" }, { MUA, 0, "x[bcdghij]+", "xaxexfxdgbjk" }, { MUA, 0, "x[^befg]+", "xbxexacdhg" }, { MUA, 0, "x[^bcdl]+", "xlxbxaekmd" }, { MUA, 0, "x[^bcdghi]+", "xbxdxgxaefji" }, { MUA, 0, "x[B-Fb-f]+", "xaxAxgxbfBFG" }, { CMUA, 0, "\\x{e9}+", "#\xf0\x90\x90\xa8\xc3\xa8\xc3\xa9\xc3\x89\xc3\x88" }, { CMUA, 0, "[^\\x{e9}]+", "\xc3\xa9#\xf0\x90\x90\xa8\xc3\xa8\xc3\x88\xc3\x89" }, { MUA, 0, "[\\x02\\x7e]+", "\xc3\x81\xe1\xbf\xb8\xf0\x90\x90\xa8\x01\x02\x7e\x7f" }, { MUA, 0, "[^\\x02\\x7e]+", "\x02\xc3\x81\xe1\xbf\xb8\xf0\x90\x90\xa8\x01\x7f\x7e" }, { MUA, 0, "[\\x{81}-\\x{7fe}]+", "#\xe1\xbf\xb8\xf0\x90\x90\xa8\xc2\x80\xc2\x81\xdf\xbe\xdf\xbf" }, { MUA, 0, "[^\\x{81}-\\x{7fe}]+", "\xc2\x81#\xe1\xbf\xb8\xf0\x90\x90\xa8\xc2\x80\xdf\xbf\xdf\xbe" }, { MUA, 0, "[\\x{801}-\\x{fffe}]+", "#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xe0\xa0\x81\xef\xbf\xbe\xef\xbf\xbf" }, { MUA, 0, "[^\\x{801}-\\x{fffe}]+", "\xe0\xa0\x81#\xc3\xa9\xf0\x90\x90\x80\xe0\xa0\x80\xef\xbf\xbf\xef\xbf\xbe" }, { MUA, 0, "[\\x{10001}-\\x{10fffe}]+", "#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf0\x90\x80\x81\xf4\x8f\xbf\xbe\xf4\x8f\xbf\xbf" }, { MUA, 0, "[^\\x{10001}-\\x{10fffe}]+", "\xf0\x90\x80\x81#\xc3\xa9\xe2\xb1\xa5\xf0\x90\x80\x80\xf4\x8f\xbf\xbf\xf4\x8f\xbf\xbe" }, /* Unicode properties. */ { MUAP, 0, "[1-5\xc3\xa9\\w]", "\xc3\xa1_" }, { MUAP, 0 | F_PROPERTY, "[\xc3\x81\\p{Ll}]", "A_\xc3\x89\xc3\xa1" }, { MUAP, 0, "[\\Wd-h_x-z]+", "a\xc2\xa1#_yhzdxi" }, { MUAP, 0 | F_NOMATCH | F_PROPERTY, "[\\P{Any}]", "abc" }, { MUAP, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Any}]", "abc" }, { MUAP, 0 | F_NOMATCH | F_PROPERTY, "[\\P{Any}\xc3\xa1-\xc3\xa8]", "abc" }, { MUAP, 0 | F_NOMATCH | F_PROPERTY, "[^\\p{Any}\xc3\xa1-\xc3\xa8]", "abc" }, { MUAP, 0 | F_NOMATCH | F_PROPERTY, "[\xc3\xa1-\xc3\xa8\\P{Any}]", "abc" }, { MUAP, 0 | F_NOMATCH | F_PROPERTY, "[^\xc3\xa1-\xc3\xa8\\p{Any}]", "abc" }, { MUAP, 0 | F_PROPERTY, "[\xc3\xa1-\xc3\xa8\\p{Any}]", "abc" }, { MUAP, 0 | F_PROPERTY, "[^\xc3\xa1-\xc3\xa8\\P{Any}]", "abc" }, { MUAP, 0, "[b-\xc3\xa9\\s]", "a\xc\xe6\x92\xad" }, { CMUAP, 0, "[\xc2\x85-\xc2\x89\xc3\x89]", "\xc2\x84\xc3\xa9" }, { MUAP, 0, "[^b-d^&\\s]{3,}", "db^ !a\xe2\x80\xa8_ae" }, { MUAP, 0 | F_PROPERTY, "[^\\S\\P{Any}][\\sN]{1,3}[\\P{N}]{4}", "\xe2\x80\xaa\xa N\x9\xc3\xa9_0" }, { MUA, 0 | F_PROPERTY, "[^\\P{L}\x9!D-F\xa]{2,3}", "\x9,.DF\xa.CG\xc3\x81" }, { CMUAP, 0, "[\xc3\xa1-\xc3\xa9_\xe2\x80\xa0-\xe2\x80\xaf]{1,5}[^\xe2\x80\xa0-\xe2\x80\xaf]", "\xc2\xa1\xc3\x89\xc3\x89\xe2\x80\xaf_\xe2\x80\xa0" }, { MUAP, 0 | F_PROPERTY, "[\xc3\xa2-\xc3\xa6\xc3\x81-\xc3\x84\xe2\x80\xa8-\xe2\x80\xa9\xe6\x92\xad\\p{Zs}]{2,}", "\xe2\x80\xa7\xe2\x80\xa9\xe6\x92\xad \xe6\x92\xae" }, { MUAP, 0 | F_PROPERTY, "[\\P{L&}]{2}[^\xc2\x85-\xc2\x89\\p{Ll}\\p{Lu}]{2}", "\xc3\xa9\xe6\x92\xad.a\xe6\x92\xad|\xc2\x8a#" }, { PCRE_UCP, 0, "[a-b\\s]{2,5}[^a]", "AB baaa" }, /* Possible empty brackets. */ { MUA, 0, "(?:|ab||bc|a)+d", "abcxabcabd" }, { MUA, 0, "(|ab||bc|a)+d", "abcxabcabd" }, { MUA, 0, "(?:|ab||bc|a)*d", "abcxabcabd" }, { MUA, 0, "(|ab||bc|a)*d", "abcxabcabd" }, { MUA, 0, "(?:|ab||bc|a)+?d", "abcxabcabd" }, { MUA, 0, "(|ab||bc|a)+?d", "abcxabcabd" }, { MUA, 0, "(?:|ab||bc|a)*?d", "abcxabcabd" }, { MUA, 0, "(|ab||bc|a)*?d", "abcxabcabd" }, { MUA, 0, "(((a)*?|(?:ba)+)+?|(?:|c|ca)*)*m", "abaacaccabacabalabaacaccabacabamm" }, { MUA, 0, "(?:((?:a)*|(ba)+?)+|(|c|ca)*?)*?m", "abaacaccabacabalabaacaccabacabamm" }, /* Start offset. */ { MUA, 3, "(\\d|(?:\\w)*\\w)+", "0ac01Hb" }, { MUA, 4 | F_NOMATCH, "(\\w\\W\\w)+", "ab#d" }, { MUA, 2 | F_NOMATCH, "(\\w\\W\\w)+", "ab#d" }, { MUA, 1, "(\\w\\W\\w)+", "ab#d" }, /* Newline. */ { PCRE_MULTILINE | PCRE_NEWLINE_CRLF, 0, "\\W{0,2}[^#]{3}", "\r\n#....." }, { PCRE_MULTILINE | PCRE_NEWLINE_CR, 0, "\\W{0,2}[^#]{3}", "\r\n#....." }, { PCRE_MULTILINE | PCRE_NEWLINE_CRLF, 0, "\\W{1,3}[^#]", "\r\n##...." }, { MUA | PCRE_NO_UTF8_CHECK, 1, "^.a", "\n\x80\nxa" }, { MUA, 1, "^", "\r\n" }, { PCRE_MULTILINE | PCRE_NEWLINE_CRLF, 1 | F_NOMATCH, "^", "\r\n" }, { PCRE_MULTILINE | PCRE_NEWLINE_CRLF, 1, "^", "\r\na" }, /* Any character except newline or any newline. */ { PCRE_NEWLINE_CRLF, 0, ".", "\r" }, { PCRE_NEWLINE_CRLF | PCRE_UTF8, 0, ".(.).", "a\xc3\xa1\r\n\n\r\r" }, { PCRE_NEWLINE_ANYCRLF, 0, ".(.)", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa8" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0, ".(.)", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa8" }, { PCRE_NEWLINE_ANY | PCRE_UTF8, 0, "(.).", "a\rb\nc\r\n\xc2\x85\xe2\x80\xa9$de" }, { PCRE_NEWLINE_ANYCRLF | PCRE_UTF8, 0 | F_NOMATCH, ".(.).", "\xe2\x80\xa8\nb\r" }, { PCRE_NEWLINE_ANY, 0, "(.)(.)", "#\x85#\r#\n#\r\n#\x84" }, { PCRE_NEWLINE_ANY | PCRE_UTF8, 0, "(.+)#", "#\rMn\xc2\x85#\n###" }, { PCRE_BSR_ANYCRLF, 0, "\\R", "\r" }, { PCRE_BSR_ANYCRLF, 0, "\\R", "\x85#\r\n#" }, { PCRE_BSR_UNICODE | PCRE_UTF8, 0, "\\R", "ab\xe2\x80\xa8#c" }, { PCRE_BSR_UNICODE | PCRE_UTF8, 0, "\\R", "ab\r\nc" }, { PCRE_NEWLINE_CRLF | PCRE_BSR_UNICODE | PCRE_UTF8, 0, "(\\R.)+", "\xc2\x85\r\n#\xe2\x80\xa8\n\r\n\r" }, { MUA, 0 | F_NOMATCH, "\\R+", "ab" }, { MUA, 0, "\\R+", "ab\r\n\r" }, { MUA, 0, "\\R*", "ab\r\n\r" }, { MUA, 0, "\\R*", "\r\n\r" }, { MUA, 0, "\\R{2,4}", "\r\nab\r\r" }, { MUA, 0, "\\R{2,4}", "\r\nab\n\n\n\r\r\r" }, { MUA, 0, "\\R{2,}", "\r\nab\n\n\n\r\r\r" }, { MUA, 0, "\\R{0,3}", "\r\n\r\n\r\n\r\n\r\n" }, { MUA, 0 | F_NOMATCH, "\\R+\\R\\R", "\r\n\r\n" }, { MUA, 0, "\\R+\\R\\R", "\r\r\r" }, { MUA, 0, "\\R*\\R\\R", "\n\r" }, { MUA, 0 | F_NOMATCH, "\\R{2,4}\\R\\R", "\r\r\r" }, { MUA, 0, "\\R{2,4}\\R\\R", "\r\r\r\r" }, /* Atomic groups (no fallback from "next" direction). */ { MUA, 0 | F_NOMATCH, "(?>ab)ab", "bab" }, { MUA, 0 | F_NOMATCH, "(?>(ab))ab", "bab" }, { MUA, 0, "(?>ab)+abc(?>de)*def(?>gh)?ghe(?>ij)+?k(?>lm)*?n(?>op)?\?op", "bababcdedefgheijijklmlmnop" }, { MUA, 0, "(?>a(b)+a|(ab)?\?(b))an", "abban" }, { MUA, 0, "(?>ab+a|(?:ab)?\?b)an", "abban" }, { MUA, 0, "((?>ab|ad|)*?)(?>|c)*abad", "abababcababad" }, { MUA, 0, "(?>(aa|b|)*+(?>(##)|###)*d|(aa)(?>(baa)?)m)", "aabaa#####da" }, { MUA, 0, "((?>a|)+?)b", "aaacaaab" }, { MUA, 0, "(?>x|)*$", "aaa" }, { MUA, 0, "(?>(x)|)*$", "aaa" }, { MUA, 0, "(?>x|())*$", "aaa" }, { MUA, 0, "((?>[cxy]a|[a-d])*?)b", "aaa+ aaab" }, { MUA, 0, "((?>[cxy](a)|[a-d])*?)b", "aaa+ aaab" }, { MUA, 0, "(?>((?>(a+))))bab|(?>((?>(a+))))bb", "aaaabaaabaabab" }, { MUA, 0, "(?>(?>a+))bab|(?>(?>a+))bb", "aaaabaaabaabab" }, { MUA, 0, "(?>(a)c|(?>(c)|(a))a)b*?bab", "aaaabaaabaabab" }, { MUA, 0, "(?>ac|(?>c|a)a)b*?bab", "aaaabaaabaabab" }, { MUA, 0, "(?>(b)b|(a))*b(?>(c)|d)?x", "ababcaaabdbx" }, { MUA, 0, "(?>bb|a)*b(?>c|d)?x", "ababcaaabdbx" }, { MUA, 0, "(?>(bb)|a)*b(?>c|(d))?x", "ababcaaabdbx" }, { MUA, 0, "(?>(a))*?(?>(a))+?(?>(a))??x", "aaaaaacccaaaaabax" }, { MUA, 0, "(?>a)*?(?>a)+?(?>a)??x", "aaaaaacccaaaaabax" }, { MUA, 0, "(?>(a)|)*?(?>(a)|)+?(?>(a)|)??x", "aaaaaacccaaaaabax" }, { MUA, 0, "(?>a|)*?(?>a|)+?(?>a|)??x", "aaaaaacccaaaaabax" }, { MUA, 0, "(?>a(?>(a{0,2}))*?b|aac)+b", "aaaaaaacaaaabaaaaacaaaabaacaaabb" }, { CMA, 0, "(?>((?>a{32}|b+|(a*))?(?>c+|d*)?\?)+e)+?f", "aaccebbdde bbdaaaccebbdee bbdaaaccebbdeef" }, { MUA, 0, "(?>(?:(?>aa|a||x)+?b|(?>aa|a||(x))+?c)?(?>[ad]{0,2})*?d)+d", "aaacdbaabdcabdbaaacd aacaabdbdcdcaaaadaabcbaadd" }, { MUA, 0, "(?>(?:(?>aa|a||(x))+?b|(?>aa|a||x)+?c)?(?>[ad]{0,2})*?d)+d", "aaacdbaabdcabdbaaacd aacaabdbdcdcaaaadaabcbaadd" }, { MUA, 0 | F_PROPERTY, "\\X", "\xcc\x8d\xcc\x8d" }, { MUA, 0 | F_PROPERTY, "\\X", "\xcc\x8d\xcc\x8d#\xcc\x8d\xcc\x8d" }, { MUA, 0 | F_PROPERTY, "\\X+..", "\xcc\x8d#\xcc\x8d#\xcc\x8d\xcc\x8d" }, { MUA, 0 | F_PROPERTY, "\\X{2,4}", "abcdef" }, { MUA, 0 | F_PROPERTY, "\\X{2,4}?", "abcdef" }, { MUA, 0 | F_NOMATCH | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d##" }, { MUA, 0 | F_PROPERTY, "\\X{2,4}..", "#\xcc\x8d#\xcc\x8d##" }, { MUA, 0, "(c(ab)?+ab)+", "cabcababcab" }, { MUA, 0, "(?>(a+)b)+aabab", "aaaabaaabaabab" }, /* Possessive quantifiers. */ { MUA, 0, "(?:a|b)++m", "mababbaaxababbaam" }, { MUA, 0, "(?:a|b)*+m", "mababbaaxababbaam" }, { MUA, 0, "(?:a|b)*+m", "ababbaaxababbaam" }, { MUA, 0, "(a|b)++m", "mababbaaxababbaam" }, { MUA, 0, "(a|b)*+m", "mababbaaxababbaam" }, { MUA, 0, "(a|b)*+m", "ababbaaxababbaam" }, { MUA, 0, "(a|b(*ACCEPT))++m", "maaxab" }, { MUA, 0, "(?:b*)++m", "bxbbxbbbxm" }, { MUA, 0, "(?:b*)++m", "bxbbxbbbxbbm" }, { MUA, 0, "(?:b*)*+m", "bxbbxbbbxm" }, { MUA, 0, "(?:b*)*+m", "bxbbxbbbxbbm" }, { MUA, 0, "(b*)++m", "bxbbxbbbxm" }, { MUA, 0, "(b*)++m", "bxbbxbbbxbbm" }, { MUA, 0, "(b*)*+m", "bxbbxbbbxm" }, { MUA, 0, "(b*)*+m", "bxbbxbbbxbbm" }, { MUA, 0, "(?:a|(b))++m", "mababbaaxababbaam" }, { MUA, 0, "(?:(a)|b)*+m", "mababbaaxababbaam" }, { MUA, 0, "(?:(a)|(b))*+m", "ababbaaxababbaam" }, { MUA, 0, "(a|(b))++m", "mababbaaxababbaam" }, { MUA, 0, "((a)|b)*+m", "mababbaaxababbaam" }, { MUA, 0, "((a)|(b))*+m", "ababbaaxababbaam" }, { MUA, 0, "(a|(b)(*ACCEPT))++m", "maaxab" }, { MUA, 0, "(?:(b*))++m", "bxbbxbbbxm" }, { MUA, 0, "(?:(b*))++m", "bxbbxbbbxbbm" }, { MUA, 0, "(?:(b*))*+m", "bxbbxbbbxm" }, { MUA, 0, "(?:(b*))*+m", "bxbbxbbbxbbm" }, { MUA, 0, "((b*))++m", "bxbbxbbbxm" }, { MUA, 0, "((b*))++m", "bxbbxbbbxbbm" }, { MUA, 0, "((b*))*+m", "bxbbxbbbxm" }, { MUA, 0, "((b*))*+m", "bxbbxbbbxbbm" }, { MUA, 0 | F_NOMATCH, "(?>(b{2,4}))(?:(?:(aa|c))++m|(?:(aa|c))+n)", "bbaacaaccaaaacxbbbmbn" }, { MUA, 0, "((?:b)++a)+(cd)*+m", "bbababbacdcdnbbababbacdcdm" }, { MUA, 0, "((?:(b))++a)+((c)d)*+m", "bbababbacdcdnbbababbacdcdm" }, { MUA, 0, "(?:(?:(?:ab)*+k)++(?:n(?:cd)++)*+)*+m", "ababkkXababkkabkncXababkkabkncdcdncdXababkkabkncdcdncdkkabkncdXababkkabkncdcdncdkkabkncdm" }, { MUA, 0, "(?:((ab)*+(k))++(n(?:c(d))++)*+)*+m", "ababkkXababkkabkncXababkkabkncdcdncdXababkkabkncdcdncdkkabkncdXababkkabkncdcdncdkkabkncdm" }, /* Back references. */ { MUA, 0, "(aa|bb)(\\1*)(ll|)(\\3*)bbbbbbc", "aaaaaabbbbbbbbc" }, { CMUA, 0, "(aa|bb)(\\1+)(ll|)(\\3+)bbbbbbc", "bBbbBbCbBbbbBbbcbbBbbbBBbbC" }, { CMA, 0, "(a{2,4})\\1", "AaAaaAaA" }, { MUA, 0, "(aa|bb)(\\1?)aa(\\1?)(ll|)(\\4+)bbc", "aaaaaaaabbaabbbbaabbbbc" }, { MUA, 0, "(aa|bb)(\\1{0,5})(ll|)(\\3{0,5})cc", "bbxxbbbbxxaaaaaaaaaaaaaaaacc" }, { MUA, 0, "(aa|bb)(\\1{3,5})(ll|)(\\3{3,5})cc", "bbbbbbbbbbbbaaaaaaccbbbbbbbbbbbbbbcc" }, { MUA, 0, "(aa|bb)(\\1{3,})(ll|)(\\3{3,})cc", "bbbbbbbbbbbbaaaaaaccbbbbbbbbbbbbbbcc" }, { MUA, 0, "(\\w+)b(\\1+)c", "GabGaGaDbGaDGaDc" }, { MUA, 0, "(?:(aa)|b)\\1?b", "bb" }, { CMUA, 0, "(aa|bb)(\\1*?)aa(\\1+?)", "bBBbaaAAaaAAaa" }, { MUA, 0, "(aa|bb)(\\1*?)(dd|)cc(\\3+?)", "aaaaaccdd" }, { CMUA, 0, "(?:(aa|bb)(\\1?\?)cc){2}(\\1?\?)", "aAaABBbbAAaAcCaAcCaA" }, { MUA, 0, "(?:(aa|bb)(\\1{3,5}?)){2}(dd|)(\\3{3,5}?)", "aaaaaabbbbbbbbbbaaaaaaaaaaaaaa" }, { CMA, 0, "(?:(aa|bb)(\\1{3,}?)){2}(dd|)(\\3{3,}?)", "aaaaaabbbbbbbbbbaaaaaaaaaaaaaa" }, { MUA, 0, "(?:(aa|bb)(\\1{0,3}?)){2}(dd|)(\\3{0,3}?)b(\\1{0,3}?)(\\1{0,3})", "aaaaaaaaaaaaaaabaaaaa" }, { MUA, 0, "(a(?:\\1|)a){3}b", "aaaaaaaaaaab" }, { MA, 0, "(a?)b(\\1\\1*\\1+\\1?\\1*?\\1+?\\1??\\1*+\\1++\\1?+\\1{4}\\1{3,5}\\1{4,}\\1{0,5}\\1{3,5}?\\1{4,}?\\1{0,5}?\\1{3,5}+\\1{4,}+\\1{0,5}+#){2}d", "bb#b##d" }, { MUAP, 0 | F_PROPERTY, "(\\P{N})\\1{2,}", ".www." }, { MUAP, 0 | F_PROPERTY, "(\\P{N})\\1{0,2}", "wwwww." }, { MUAP, 0 | F_PROPERTY, "(\\P{N})\\1{1,2}ww", "wwww" }, { MUAP, 0 | F_PROPERTY, "(\\P{N})\\1{1,2}ww", "wwwww" }, { PCRE_UCP, 0 | F_PROPERTY, "(\\P{N})\\1{2,}", ".www." }, { CMUAP, 0, "(\xf0\x90\x90\x80)\\1", "\xf0\x90\x90\xa8\xf0\x90\x90\xa8" }, { MUA | PCRE_DUPNAMES, 0 | F_NOMATCH, "\\k{1,3}(?aa)(?bb)", "aabb" }, { MUA | PCRE_DUPNAMES | PCRE_JAVASCRIPT_COMPAT, 0, "\\k{1,3}(?aa)(?bb)", "aabb" }, { MUA | PCRE_DUPNAMES | PCRE_JAVASCRIPT_COMPAT, 0, "\\k*(?aa)(?bb)", "aabb" }, { MUA | PCRE_DUPNAMES, 0, "(?aa)(?bb)\\k{0,3}aaaaaa", "aabbaaaaaa" }, { MUA | PCRE_DUPNAMES, 0, "(?aa)(?bb)\\k{2,5}bb", "aabbaaaabb" }, { MUA | PCRE_DUPNAMES, 0, "(?:(?aa)|(?bb))\\k{0,3}m", "aaaaaaaabbbbaabbbbm" }, { MUA | PCRE_DUPNAMES, 0 | F_NOMATCH, "\\k{1,3}?(?aa)(?bb)", "aabb" }, { MUA | PCRE_DUPNAMES | PCRE_JAVASCRIPT_COMPAT, 0, "\\k{1,3}?(?aa)(?bb)", "aabb" }, { MUA | PCRE_DUPNAMES, 0, "\\k*?(?aa)(?bb)", "aabb" }, { MUA | PCRE_DUPNAMES, 0, "(?:(?aa)|(?bb))\\k{0,3}?m", "aaaaaabbbbbbaabbbbbbbbbbm" }, { MUA | PCRE_DUPNAMES, 0, "(?:(?aa)|(?bb))\\k*?m", "aaaaaabbbbbbaabbbbbbbbbbm" }, { MUA | PCRE_DUPNAMES, 0, "(?:(?aa)|(?bb))\\k{2,3}?", "aaaabbbbaaaabbbbbbbbbb" }, { CMUA | PCRE_DUPNAMES, 0, "(?:(?AA)|(?BB))\\k{0,3}M", "aaaaaaaabbbbaabbbbm" }, { CMUA | PCRE_DUPNAMES, 0, "(?:(?AA)|(?BB))\\k{1,3}M", "aaaaaaaabbbbaabbbbm" }, { CMUA | PCRE_DUPNAMES, 0, "(?:(?AA)|(?BB))\\k{0,3}?M", "aaaaaabbbbbbaabbbbbbbbbbm" }, { CMUA | PCRE_DUPNAMES, 0, "(?:(?AA)|(?BB))\\k{2,3}?", "aaaabbbbaaaabbbbbbbbbb" }, /* Assertions. */ { MUA, 0, "(?=xx|yy|zz)\\w{4}", "abczzdefg" }, { MUA, 0, "(?=((\\w+)b){3}|ab)", "dbbbb ab" }, { MUA, 0, "(?!ab|bc|cd)[a-z]{2}", "Xabcdef" }, { MUA, 0, "(?<=aaa|aa|a)a", "aaa" }, { MUA, 2, "(?<=aaa|aa|a)a", "aaa" }, { MA, 0, "(?<=aaa|aa|a)a", "aaa" }, { MA, 2, "(?<=aaa|aa|a)a", "aaa" }, { MUA, 0, "(\\d{2})(?!\\w+c|(((\\w?)m){2}n)+|\\1)", "x5656" }, { MUA, 0, "((?=((\\d{2,6}\\w){2,}))\\w{5,20}K){2,}", "567v09708K12l00M00 567v09708K12l00M00K45K" }, { MUA, 0, "(?=(?:(?=\\S+a)\\w*(b)){3})\\w+\\d", "bba bbab nbbkba nbbkba0kl" }, { MUA, 0, "(?>a(?>(b+))a(?=(..)))*?k", "acabbcabbaabacabaabbakk" }, { MUA, 0, "((?(?=(a))a)+k)", "bbak" }, { MUA, 0, "((?(?=a)a)+k)", "bbak" }, { MUA, 0 | F_NOMATCH, "(?=(?>(a))m)amk", "a k" }, { MUA, 0 | F_NOMATCH, "(?!(?>(a))m)amk", "a k" }, { MUA, 0 | F_NOMATCH, "(?>(?=(a))am)amk", "a k" }, { MUA, 0, "(?=(?>a|(?=(?>(b+))a|c)[a-c]+)*?m)[a-cm]+k", "aaam bbam baaambaam abbabba baaambaamk" }, { MUA, 0, "(?> ?\?\\b(?(?=\\w{1,4}(a))m)\\w{0,8}bc){2,}?", "bca ssbc mabd ssbc mabc" }, { MUA, 0, "(?:(?=ab)?[^n][^n])+m", "ababcdabcdcdabnababcdabcdcdabm" }, { MUA, 0, "(?:(?=a(b))?[^n][^n])+m", "ababcdabcdcdabnababcdabcdcdabm" }, { MUA, 0, "(?:(?=.(.))??\\1.)+m", "aabbbcbacccanaabbbcbacccam" }, { MUA, 0, "(?:(?=.)??[a-c])+m", "abacdcbacacdcaccam" }, { MUA, 0, "((?!a)?(?!([^a]))?)+$", "acbab" }, { MUA, 0, "((?!a)?\?(?!([^a]))?\?)+$", "acbab" }, { MUA, 0, "a(?=(?C)\\B)b", "ab" }, { MUA, 0, "a(?!(?C)\\B)bb|ab", "abb" }, { MUA, 0, "a(?=\\b|(?C)\\B)b", "ab" }, { MUA, 0, "a(?!\\b|(?C)\\B)bb|ab", "abb" }, { MUA, 0, "c(?(?=(?C)\\B)ab|a)", "cab" }, { MUA, 0, "c(?(?!(?C)\\B)ab|a)", "cab" }, { MUA, 0, "c(?(?=\\b|(?C)\\B)ab|a)", "cab" }, { MUA, 0, "c(?(?!\\b|(?C)\\B)ab|a)", "cab" }, { MUA, 0, "a(?=)b", "ab" }, { MUA, 0 | F_NOMATCH, "a(?!)b", "ab" }, /* Not empty, ACCEPT, FAIL */ { MUA | PCRE_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" }, { MUA | PCRE_NOTEMPTY, 0, "a*", "bcaad" }, { MUA | PCRE_NOTEMPTY, 0, "a*?", "bcaad" }, { MUA | PCRE_NOTEMPTY_ATSTART, 0, "a*", "bcaad" }, { MUA, 0, "a(*ACCEPT)b", "ab" }, { MUA | PCRE_NOTEMPTY, 0 | F_NOMATCH, "a*(*ACCEPT)b", "bcx" }, { MUA | PCRE_NOTEMPTY, 0, "a*(*ACCEPT)b", "bcaad" }, { MUA | PCRE_NOTEMPTY, 0, "a*?(*ACCEPT)b", "bcaad" }, { MUA | PCRE_NOTEMPTY, 0 | F_NOMATCH, "(?:z|a*(*ACCEPT)b)", "bcx" }, { MUA | PCRE_NOTEMPTY, 0, "(?:z|a*(*ACCEPT)b)", "bcaad" }, { MUA | PCRE_NOTEMPTY, 0, "(?:z|a*?(*ACCEPT)b)", "bcaad" }, { MUA | PCRE_NOTEMPTY_ATSTART, 0, "a*(*ACCEPT)b", "bcx" }, { MUA | PCRE_NOTEMPTY_ATSTART, 0 | F_NOMATCH, "a*(*ACCEPT)b", "" }, { MUA, 0, "((a(*ACCEPT)b))", "ab" }, { MUA, 0, "(a(*FAIL)a|a)", "aaa" }, { MUA, 0, "(?=ab(*ACCEPT)b)a", "ab" }, { MUA, 0, "(?=(?:x|ab(*ACCEPT)b))", "ab" }, { MUA, 0, "(?=(a(b(*ACCEPT)b)))a", "ab" }, { MUA | PCRE_NOTEMPTY, 0, "(?=a*(*ACCEPT))c", "c" }, /* Conditional blocks. */ { MUA, 0, "(?(?=(a))a|b)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?!(b))a|b)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?=a)a|b)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?!b)a|b)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?=(a))a*|b*)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?!(b))a*|b*)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?!(b))(?:aaaaaa|a)|(?:bbbbbb|b))+aaaak", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb aaaaaaak" }, { MUA, 0, "(?(?!b)(?:aaaaaa|a)|(?:bbbbbb|b))+aaaak", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb aaaaaaak" }, { MUA, 0 | F_DIFF, "(?(?!(b))(?:aaaaaa|a)|(?:bbbbbb|b))+bbbbk", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb bbbbbbbk" }, { MUA, 0, "(?(?!b)(?:aaaaaa|a)|(?:bbbbbb|b))+bbbbk", "aaaaaaaaaaaaaa bbbbbbbbbbbbbbb bbbbbbbk" }, { MUA, 0, "(?(?=a)a*|b*)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?!b)a*|b*)+k", "ababbalbbadabak" }, { MUA, 0, "(?(?=a)ab)", "a" }, { MUA, 0, "(?(?a)?(?Pb)?(?(Name)c|d)*l", "bc ddd abccabccl" }, { MUA, 0, "(?Pa)?(?Pb)?(?(Name)c|d)+?dd", "bcabcacdb bdddd" }, { MUA, 0, "(?Pa)?(?Pb)?(?(Name)c|d)+l", "ababccddabdbccd abcccl" }, { MUA, 0, "((?:a|aa)(?(1)aaa))x", "aax" }, { MUA, 0, "(?(?!)a|b)", "ab" }, { MUA, 0, "(?(?!)a)", "ab" }, { MUA, 0 | F_NOMATCH, "(?(?!)a|b)", "ac" }, /* Set start of match. */ { MUA, 0, "(?:\\Ka)*aaaab", "aaaaaaaa aaaaaaabb" }, { MUA, 0, "(?>\\Ka\\Ka)*aaaab", "aaaaaaaa aaaaaaaaaabb" }, { MUA, 0, "a+\\K(?<=\\Gaa)a", "aaaaaa" }, { MUA | PCRE_NOTEMPTY, 0 | F_NOMATCH, "a\\K(*ACCEPT)b", "aa" }, { MUA | PCRE_NOTEMPTY_ATSTART, 0, "a\\K(*ACCEPT)b", "aa" }, /* First line. */ { MUA | PCRE_FIRSTLINE, 0 | F_PROPERTY, "\\p{Any}a", "bb\naaa" }, { MUA | PCRE_FIRSTLINE, 0 | F_NOMATCH | F_PROPERTY, "\\p{Any}a", "bb\r\naaa" }, { MUA | PCRE_FIRSTLINE, 0, "(?<=a)", "a" }, { MUA | PCRE_FIRSTLINE, 0 | F_NOMATCH, "[^a][^b]", "ab" }, { MUA | PCRE_FIRSTLINE, 0 | F_NOMATCH, "a", "\na" }, { MUA | PCRE_FIRSTLINE, 0 | F_NOMATCH, "[abc]", "\na" }, { MUA | PCRE_FIRSTLINE, 0 | F_NOMATCH, "^a", "\na" }, { MUA | PCRE_FIRSTLINE, 0 | F_NOMATCH, "^(?<=\n)", "\na" }, { MUA | PCRE_FIRSTLINE, 0, "\xf0\x90\x90\x80", "\xf0\x90\x90\x80" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANY | PCRE_FIRSTLINE, 0 | F_NOMATCH, "#", "\xc2\x85#" }, { PCRE_MULTILINE | PCRE_NEWLINE_ANY | PCRE_FIRSTLINE, 0 | F_NOMATCH, "#", "\x85#" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_ANY | PCRE_FIRSTLINE, 0 | F_NOMATCH, "^#", "\xe2\x80\xa8#" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_CRLF | PCRE_FIRSTLINE, 0 | F_PROPERTY, "\\p{Any}", "\r\na" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_CRLF | PCRE_FIRSTLINE, 0, ".", "\r" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_CRLF | PCRE_FIRSTLINE, 0, "a", "\ra" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_CRLF | PCRE_FIRSTLINE, 0 | F_NOMATCH, "ba", "bbb\r\nba" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_CRLF | PCRE_FIRSTLINE, 0 | F_NOMATCH | F_PROPERTY, "\\p{Any}{4}|a", "\r\na" }, { PCRE_MULTILINE | PCRE_UTF8 | PCRE_NEWLINE_CRLF | PCRE_FIRSTLINE, 1, ".", "\r\n" }, { PCRE_FIRSTLINE | PCRE_NEWLINE_LF | PCRE_DOTALL, 0 | F_NOMATCH, "ab.", "ab" }, { MUA | PCRE_FIRSTLINE, 1 | F_NOMATCH, "^[a-d0-9]", "\nxx\nd" }, { PCRE_NEWLINE_ANY | PCRE_FIRSTLINE | PCRE_DOTALL, 0, "....a", "012\n0a" }, { MUA | PCRE_FIRSTLINE, 0, "[aC]", "a" }, /* Recurse. */ { MUA, 0, "(a)(?1)", "aa" }, { MUA, 0, "((a))(?1)", "aa" }, { MUA, 0, "(b|a)(?1)", "aa" }, { MUA, 0, "(b|(a))(?1)", "aa" }, { MUA, 0 | F_NOMATCH, "((a)(b)(?:a*))(?1)", "aba" }, { MUA, 0, "((a)(b)(?:a*))(?1)", "abab" }, { MUA, 0, "((a+)c(?2))b(?1)", "aacaabaca" }, { MUA, 0, "((?2)b|(a)){2}(?1)", "aabab" }, { MUA, 0, "(?1)(a)*+(?2)(b(?1))", "aababa" }, { MUA, 0, "(?1)(((a(*ACCEPT)))b)", "axaa" }, { MUA, 0, "(?1)(?(DEFINE) (((ac(*ACCEPT)))b) )", "akaac" }, { MUA, 0, "(a+)b(?1)b\\1", "abaaabaaaaa" }, { MUA, 0 | F_NOMATCH, "(?(DEFINE)(aa|a))(?1)ab", "aab" }, { MUA, 0, "(?(DEFINE)(a\\Kb))(?1)+ababc", "abababxabababc" }, { MUA, 0, "(a\\Kb)(?1)+ababc", "abababxababababc" }, { MUA, 0 | F_NOMATCH, "(a\\Kb)(?1)+ababc", "abababxababababxc" }, { MUA, 0, "b|<(?R)*>", "<" }, { MUA, 0, "(a\\K){0}(?:(?1)b|ac)", "ac" }, { MUA, 0, "(?(DEFINE)(a(?2)|b)(b(?1)|(a)))(?:(?1)|(?2))m", "ababababnababababaam" }, { MUA, 0, "(a)((?(R)a|b))(?2)", "aabbabaa" }, { MUA, 0, "(a)((?(R2)a|b))(?2)", "aabbabaa" }, { MUA, 0, "(a)((?(R1)a|b))(?2)", "ababba" }, { MUA, 0, "(?(R0)aa|bb(?R))", "abba aabb bbaa" }, { MUA, 0, "((?(R)(?:aaaa|a)|(?:(aaaa)|(a)))+)(?1)$", "aaaaaaaaaa aaaa" }, { MUA, 0, "(?Pa(?(R&Name)a|b))(?1)", "aab abb abaa" }, { MUA, 0, "((?(R)a|(?1)){3})", "XaaaaaaaaaX" }, { MUA, 0, "((?:(?(R)a|(?1))){3})", "XaaaaaaaaaX" }, { MUA, 0, "((?(R)a|(?1)){1,3})aaaaaa", "aaaaaaaaXaaaaaaaaa" }, { MUA, 0, "((?(R)a|(?1)){1,3}?)M", "aaaM" }, /* 16 bit specific tests. */ { CMA, 0 | F_FORCECONV, "\xc3\xa1", "\xc3\x81\xc3\xa1" }, { CMA, 0 | F_FORCECONV, "\xe1\xbd\xb8", "\xe1\xbf\xb8\xe1\xbd\xb8" }, { CMA, 0 | F_FORCECONV, "[\xc3\xa1]", "\xc3\x81\xc3\xa1" }, { CMA, 0 | F_FORCECONV, "[\xe1\xbd\xb8]", "\xe1\xbf\xb8\xe1\xbd\xb8" }, { CMA, 0 | F_FORCECONV, "[a-\xed\xb0\x80]", "A" }, { CMA, 0 | F_NO8 | F_FORCECONV, "[a-\\x{dc00}]", "B" }, { CMA, 0 | F_NO8 | F_NOMATCH | F_FORCECONV, "[b-\\x{dc00}]", "a" }, { CMA, 0 | F_NO8 | F_FORCECONV, "\xed\xa0\x80\\x{d800}\xed\xb0\x80\\x{dc00}", "\xed\xa0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80" }, { CMA, 0 | F_NO8 | F_FORCECONV, "[\xed\xa0\x80\\x{d800}]{1,2}?[\xed\xb0\x80\\x{dc00}]{1,2}?#", "\xed\xa0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80#" }, { CMA, 0 | F_FORCECONV, "[\xed\xa0\x80\xed\xb0\x80#]{0,3}(?<=\xed\xb0\x80.)", "\xed\xa0\x80#\xed\xa0\x80##\xed\xb0\x80\xed\xa0\x80" }, { CMA, 0 | F_FORCECONV, "[\xed\xa0\x80-\xed\xb3\xbf]", "\xed\x9f\xbf\xed\xa0\x83" }, { CMA, 0 | F_FORCECONV, "[\xed\xa0\x80-\xed\xb3\xbf]", "\xed\xb4\x80\xed\xb3\xb0" }, { CMA, 0 | F_NO8 | F_FORCECONV, "[\\x{d800}-\\x{dcff}]", "\xed\x9f\xbf\xed\xa0\x83" }, { CMA, 0 | F_NO8 | F_FORCECONV, "[\\x{d800}-\\x{dcff}]", "\xed\xb4\x80\xed\xb3\xb0" }, { CMA, 0 | F_FORCECONV, "[\xed\xa0\x80-\xef\xbf\xbf]+[\x1-\xed\xb0\x80]+#", "\xed\xa0\x85\xc3\x81\xed\xa0\x85\xef\xbf\xb0\xc2\x85\xed\xa9\x89#" }, { CMA, 0 | F_FORCECONV, "[\xed\xa0\x80][\xed\xb0\x80]{2,}", "\xed\xa0\x80\xed\xb0\x80\xed\xa0\x80\xed\xb0\x80\xed\xb0\x80\xed\xb0\x80" }, { MA, 0 | F_FORCECONV, "[^\xed\xb0\x80]{3,}?", "##\xed\xb0\x80#\xed\xb0\x80#\xc3\x89#\xed\xb0\x80" }, { MA, 0 | F_NO8 | F_FORCECONV, "[^\\x{dc00}]{3,}?", "##\xed\xb0\x80#\xed\xb0\x80#\xc3\x89#\xed\xb0\x80" }, { CMA, 0 | F_FORCECONV, ".\\B.", "\xed\xa0\x80\xed\xb0\x80" }, { CMA, 0 | F_FORCECONV, "\\D+(?:\\d+|.)\\S+(?:\\s+|.)\\W+(?:\\w+|.)\xed\xa0\x80\xed\xa0\x80", "\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80" }, { CMA, 0 | F_FORCECONV, "\\d*\\s*\\w*\xed\xa0\x80\xed\xa0\x80", "\xed\xa0\x80\xed\xa0\x80" }, { CMA, 0 | F_FORCECONV | F_NOMATCH, "\\d*?\\D*?\\s*?\\S*?\\w*?\\W*?##", "\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80\xed\xa0\x80#" }, { CMA | PCRE_EXTENDED, 0 | F_FORCECONV, "\xed\xa0\x80 \xed\xb0\x80 !", "\xed\xa0\x80\xed\xb0\x80!" }, { CMA, 0 | F_FORCECONV, "\xed\xa0\x80+#[^#]+\xed\xa0\x80", "\xed\xa0\x80#a\xed\xa0\x80" }, { CMA, 0 | F_FORCECONV, "(\xed\xa0\x80+)#\\1", "\xed\xa0\x80\xed\xa0\x80#\xed\xa0\x80\xed\xa0\x80" }, { PCRE_MULTILINE | PCRE_NEWLINE_ANY, 0 | F_NO8 | F_FORCECONV, "^-", "a--\xe2\x80\xa8--" }, { PCRE_BSR_UNICODE, 0 | F_NO8 | F_FORCECONV, "\\R", "ab\xe2\x80\xa8" }, { 0, 0 | F_NO8 | F_FORCECONV, "\\v", "ab\xe2\x80\xa9" }, { 0, 0 | F_NO8 | F_FORCECONV, "\\h", "ab\xe1\xa0\x8e" }, { 0, 0 | F_NO8 | F_FORCECONV, "\\v+?\\V+?#", "\xe2\x80\xa9\xe2\x80\xa9\xef\xbf\xbf\xef\xbf\xbf#" }, { 0, 0 | F_NO8 | F_FORCECONV, "\\h+?\\H+?#", "\xe1\xa0\x8e\xe1\xa0\x8e\xef\xbf\xbf\xef\xbf\xbf#" }, /* Partial matching. */ { MUA | PCRE_PARTIAL_SOFT, 0, "ab", "a" }, { MUA | PCRE_PARTIAL_SOFT, 0, "ab|a", "a" }, { MUA | PCRE_PARTIAL_HARD, 0, "ab|a", "a" }, { MUA | PCRE_PARTIAL_SOFT, 0, "\\b#", "a" }, { MUA | PCRE_PARTIAL_SOFT, 0, "(?<=a)b", "a" }, { MUA | PCRE_PARTIAL_SOFT, 0, "abc|(?<=xxa)bc", "xxab" }, { MUA | PCRE_PARTIAL_SOFT, 0, "a\\B", "a" }, { MUA | PCRE_PARTIAL_HARD, 0, "a\\b", "a" }, /* (*MARK) verb. */ { MUA, 0, "a(*MARK:aa)a", "ababaa" }, { MUA, 0 | F_NOMATCH, "a(*:aa)a", "abab" }, { MUA, 0, "a(*:aa)(b(*:bb)b|bc)", "abc" }, { MUA, 0 | F_NOMATCH, "a(*:1)x|b(*:2)y", "abc" }, { MUA, 0, "(?>a(*:aa))b|ac", "ac" }, { MUA, 0, "(?(DEFINE)(a(*:aa)))(?1)", "a" }, { MUA, 0 | F_NOMATCH, "(?(DEFINE)((a)(*:aa)))(?1)b", "aa" }, { MUA, 0, "(?(DEFINE)(a(*:aa)))a(?1)b|aac", "aac" }, { MUA, 0, "(a(*:aa)){0}(?:b(?1)b|c)+c", "babbab cc" }, { MUA, 0, "(a(*:aa)){0}(?:b(?1)b)+", "babba" }, { MUA, 0 | F_NOMATCH | F_STUDY, "(a(*:aa)){0}(?:b(?1)b)+", "ba" }, { MUA, 0, "(a\\K(*:aa)){0}(?:b(?1)b|c)+c", "babbab cc" }, { MUA, 0, "(a\\K(*:aa)){0}(?:b(?1)b)+", "babba" }, { MUA, 0 | F_NOMATCH | F_STUDY, "(a\\K(*:aa)){0}(?:b(?1)b)+", "ba" }, { MUA, 0 | F_NOMATCH | F_STUDY, "(*:mark)m", "a" }, /* (*COMMIT) verb. */ { MUA, 0 | F_NOMATCH, "a(*COMMIT)b", "ac" }, { MUA, 0, "aa(*COMMIT)b", "xaxaab" }, { MUA, 0 | F_NOMATCH, "a(*COMMIT)(*:msg)b|ac", "ac" }, { MUA, 0 | F_NOMATCH, "(a(*COMMIT)b)++", "abac" }, { MUA, 0 | F_NOMATCH, "((a)(*COMMIT)b)++", "abac" }, { MUA, 0 | F_NOMATCH, "(?=a(*COMMIT)b)ab|ad", "ad" }, /* (*PRUNE) verb. */ { MUA, 0, "aa\\K(*PRUNE)b", "aaab" }, { MUA, 0, "aa(*PRUNE:bb)b|a", "aa" }, { MUA, 0, "(a)(a)(*PRUNE)b|(a)", "aa" }, { MUA, 0, "(a)(a)(a)(a)(a)(a)(a)(a)(*PRUNE)b|(a)", "aaaaaaaa" }, { MUA | PCRE_PARTIAL_SOFT, 0, "a(*PRUNE)a|", "a" }, { MUA | PCRE_PARTIAL_SOFT, 0, "a(*PRUNE)a|m", "a" }, { MUA, 0 | F_NOMATCH, "(?=a(*PRUNE)b)ab|ad", "ad" }, { MUA, 0, "a(*COMMIT)(*PRUNE)d|bc", "abc" }, { MUA, 0, "(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?=a(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, { MUA, 0, "(?=(a)(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?=(a)(*COMMIT)b)a(*PRUNE)c|bc", "abc" }, { MUA, 0, "(a(*COMMIT)b){0}a(?1)(*PRUNE)c|bc", "abc" }, { MUA, 0 | F_NOMATCH, "(a(*COMMIT)b){0}a(*COMMIT)(?1)(*PRUNE)c|bc", "abc" }, { MUA, 0, "(a(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(a(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, { MUA, 0, "((a)(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)((a)(*COMMIT)b)++(*PRUNE)d|c", "ababc" }, { MUA, 0, "(?>a(*COMMIT)b)*abab(*PRUNE)d|ba", "ababab" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)*abab(*PRUNE)d|ba", "ababab" }, { MUA, 0, "(?>a(*COMMIT)b)+abab(*PRUNE)d|ba", "ababab" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)+abab(*PRUNE)d|ba", "ababab" }, { MUA, 0, "(?>a(*COMMIT)b)?ab(*PRUNE)d|ba", "aba" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)?ab(*PRUNE)d|ba", "aba" }, { MUA, 0, "(?>a(*COMMIT)b)*?n(*PRUNE)d|ba", "abababn" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)*?n(*PRUNE)d|ba", "abababn" }, { MUA, 0, "(?>a(*COMMIT)b)+?n(*PRUNE)d|ba", "abababn" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)+?n(*PRUNE)d|ba", "abababn" }, { MUA, 0, "(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" }, { MUA, 0 | F_NOMATCH, "(*COMMIT)(?>a(*COMMIT)b)??n(*PRUNE)d|bn", "abn" }, /* (*SKIP) verb. */ { MUA, 0 | F_NOMATCH, "(?=a(*SKIP)b)ab|ad", "ad" }, { MUA, 0, "(\\w+(*SKIP)#)", "abcd,xyz#," }, { MUA, 0, "\\w+(*SKIP)#|mm", "abcd,xyz#," }, { MUA, 0 | F_NOMATCH, "b+(?<=(*SKIP)#c)|b+", "#bbb" }, /* (*THEN) verb. */ { MUA, 0, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcaabcaabcaabcnacm" }, { MUA, 0 | F_NOMATCH, "((?:a(*THEN)|aab)(*THEN)c|a+)+m", "aabcm" }, { MUA, 0, "((?:a(*THEN)|aab)c|a+)+m", "aabcaabcnmaabcaabcm" }, { MUA, 0, "((?:a|aab)(*THEN)c|a+)+m", "aam" }, { MUA, 0, "((?:a(*COMMIT)|aab)(*THEN)c|a+)+m", "aam" }, { MUA, 0, "(?(?=a(*THEN)b)ab|ad)", "ad" }, { MUA, 0, "(?(?!a(*THEN)b)ad|add)", "add" }, { MUA, 0 | F_NOMATCH, "(?(?=a)a(*THEN)b|ad)", "ad" }, { MUA, 0, "(?!(?(?=a)ab|b(*THEN)d))bn|bnn", "bnn" }, /* Deep recursion. */ { MUA, 0, "((((?:(?:(?:\\w)+)?)*|(?>\\w)+?)+|(?>\\w)?\?)*)?\\s", "aaaaa+ " }, { MUA, 0, "(?:((?:(?:(?:\\w*?)+)??|(?>\\w)?|\\w*+)*)+)+?\\s", "aa+ " }, { MUA, 0, "((a?)+)+b", "aaaaaaaaaaaa b" }, /* Deep recursion: Stack limit reached. */ { MA, 0 | F_NOMATCH, "a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaa" }, { MA, 0 | F_NOMATCH, "(?:a+)+b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, { MA, 0 | F_NOMATCH, "(?:a+?)+?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, { MA, 0 | F_NOMATCH, "(?:a*)*b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, { MA, 0 | F_NOMATCH, "(?:a*?)*?b", "aaaaaaaaaaaaaaaaaaaaaaaa b" }, { 0, 0, NULL, NULL } }; static const unsigned char *tables(int mode) { /* The purpose of this function to allow valgrind for reporting invalid reads and writes. */ static unsigned char *tables_copy; const char *errorptr; int erroroffset; unsigned char *default_tables; #if defined SUPPORT_PCRE8 pcre *regex; char null_str[1] = { 0 }; #elif defined SUPPORT_PCRE16 pcre16 *regex; PCRE_UCHAR16 null_str[1] = { 0 }; #elif defined SUPPORT_PCRE32 pcre32 *regex; PCRE_UCHAR32 null_str[1] = { 0 }; #endif if (mode) { if (tables_copy) free(tables_copy); tables_copy = NULL; return NULL; } if (tables_copy) return tables_copy; default_tables = NULL; #if defined SUPPORT_PCRE8 regex = pcre_compile(null_str, 0, &errorptr, &erroroffset, NULL); if (regex) { pcre_fullinfo(regex, NULL, PCRE_INFO_DEFAULT_TABLES, &default_tables); pcre_free(regex); } #elif defined SUPPORT_PCRE16 regex = pcre16_compile(null_str, 0, &errorptr, &erroroffset, NULL); if (regex) { pcre16_fullinfo(regex, NULL, PCRE_INFO_DEFAULT_TABLES, &default_tables); pcre16_free(regex); } #elif defined SUPPORT_PCRE32 regex = pcre32_compile(null_str, 0, &errorptr, &erroroffset, NULL); if (regex) { pcre32_fullinfo(regex, NULL, PCRE_INFO_DEFAULT_TABLES, &default_tables); pcre32_free(regex); } #endif /* Shouldn't ever happen. */ if (!default_tables) return NULL; /* Unfortunately this value cannot get from pcre_fullinfo. Since this is a test program, this is acceptable at the moment. */ tables_copy = (unsigned char *)malloc(1088); if (!tables_copy) return NULL; memcpy(tables_copy, default_tables, 1088); return tables_copy; } #ifdef SUPPORT_PCRE8 static pcre_jit_stack* callback8(void *arg) { return (pcre_jit_stack *)arg; } #endif #ifdef SUPPORT_PCRE16 static pcre16_jit_stack* callback16(void *arg) { return (pcre16_jit_stack *)arg; } #endif #ifdef SUPPORT_PCRE32 static pcre32_jit_stack* callback32(void *arg) { return (pcre32_jit_stack *)arg; } #endif #ifdef SUPPORT_PCRE8 static pcre_jit_stack *stack8; static pcre_jit_stack *getstack8(void) { if (!stack8) stack8 = pcre_jit_stack_alloc(1, 1024 * 1024); return stack8; } static void setstack8(pcre_extra *extra) { if (!extra) { if (stack8) pcre_jit_stack_free(stack8); stack8 = NULL; return; } pcre_assign_jit_stack(extra, callback8, getstack8()); } #endif /* SUPPORT_PCRE8 */ #ifdef SUPPORT_PCRE16 static pcre16_jit_stack *stack16; static pcre16_jit_stack *getstack16(void) { if (!stack16) stack16 = pcre16_jit_stack_alloc(1, 1024 * 1024); return stack16; } static void setstack16(pcre16_extra *extra) { if (!extra) { if (stack16) pcre16_jit_stack_free(stack16); stack16 = NULL; return; } pcre16_assign_jit_stack(extra, callback16, getstack16()); } #endif /* SUPPORT_PCRE16 */ #ifdef SUPPORT_PCRE32 static pcre32_jit_stack *stack32; static pcre32_jit_stack *getstack32(void) { if (!stack32) stack32 = pcre32_jit_stack_alloc(1, 1024 * 1024); return stack32; } static void setstack32(pcre32_extra *extra) { if (!extra) { if (stack32) pcre32_jit_stack_free(stack32); stack32 = NULL; return; } pcre32_assign_jit_stack(extra, callback32, getstack32()); } #endif /* SUPPORT_PCRE32 */ #ifdef SUPPORT_PCRE16 static int convert_utf8_to_utf16(const char *input, PCRE_UCHAR16 *output, int *offsetmap, int max_length) { unsigned char *iptr = (unsigned char*)input; PCRE_UCHAR16 *optr = output; unsigned int c; if (max_length == 0) return 0; while (*iptr && max_length > 1) { c = 0; if (offsetmap) *offsetmap++ = (int)(iptr - (unsigned char*)input); if (*iptr < 0xc0) c = *iptr++; else if (!(*iptr & 0x20)) { c = ((iptr[0] & 0x1f) << 6) | (iptr[1] & 0x3f); iptr += 2; } else if (!(*iptr & 0x10)) { c = ((iptr[0] & 0x0f) << 12) | ((iptr[1] & 0x3f) << 6) | (iptr[2] & 0x3f); iptr += 3; } else if (!(*iptr & 0x08)) { c = ((iptr[0] & 0x07) << 18) | ((iptr[1] & 0x3f) << 12) | ((iptr[2] & 0x3f) << 6) | (iptr[3] & 0x3f); iptr += 4; } if (c < 65536) { *optr++ = c; max_length--; } else if (max_length <= 2) { *optr = '\0'; return (int)(optr - output); } else { c -= 0x10000; *optr++ = 0xd800 | ((c >> 10) & 0x3ff); *optr++ = 0xdc00 | (c & 0x3ff); max_length -= 2; if (offsetmap) offsetmap++; } } if (offsetmap) *offsetmap = (int)(iptr - (unsigned char*)input); *optr = '\0'; return (int)(optr - output); } static int copy_char8_to_char16(const char *input, PCRE_UCHAR16 *output, int max_length) { unsigned char *iptr = (unsigned char*)input; PCRE_UCHAR16 *optr = output; if (max_length == 0) return 0; while (*iptr && max_length > 1) { *optr++ = *iptr++; max_length--; } *optr = '\0'; return (int)(optr - output); } #define REGTEST_MAX_LENGTH16 4096 static PCRE_UCHAR16 regtest_buf16[REGTEST_MAX_LENGTH16]; static int regtest_offsetmap16[REGTEST_MAX_LENGTH16]; #endif /* SUPPORT_PCRE16 */ #ifdef SUPPORT_PCRE32 static int convert_utf8_to_utf32(const char *input, PCRE_UCHAR32 *output, int *offsetmap, int max_length) { unsigned char *iptr = (unsigned char*)input; PCRE_UCHAR32 *optr = output; unsigned int c; if (max_length == 0) return 0; while (*iptr && max_length > 1) { c = 0; if (offsetmap) *offsetmap++ = (int)(iptr - (unsigned char*)input); if (*iptr < 0xc0) c = *iptr++; else if (!(*iptr & 0x20)) { c = ((iptr[0] & 0x1f) << 6) | (iptr[1] & 0x3f); iptr += 2; } else if (!(*iptr & 0x10)) { c = ((iptr[0] & 0x0f) << 12) | ((iptr[1] & 0x3f) << 6) | (iptr[2] & 0x3f); iptr += 3; } else if (!(*iptr & 0x08)) { c = ((iptr[0] & 0x07) << 18) | ((iptr[1] & 0x3f) << 12) | ((iptr[2] & 0x3f) << 6) | (iptr[3] & 0x3f); iptr += 4; } *optr++ = c; max_length--; } if (offsetmap) *offsetmap = (int)(iptr - (unsigned char*)input); *optr = 0; return (int)(optr - output); } static int copy_char8_to_char32(const char *input, PCRE_UCHAR32 *output, int max_length) { unsigned char *iptr = (unsigned char*)input; PCRE_UCHAR32 *optr = output; if (max_length == 0) return 0; while (*iptr && max_length > 1) { *optr++ = *iptr++; max_length--; } *optr = '\0'; return (int)(optr - output); } #define REGTEST_MAX_LENGTH32 4096 static PCRE_UCHAR32 regtest_buf32[REGTEST_MAX_LENGTH32]; static int regtest_offsetmap32[REGTEST_MAX_LENGTH32]; #endif /* SUPPORT_PCRE32 */ static int check_ascii(const char *input) { const unsigned char *ptr = (unsigned char *)input; while (*ptr) { if (*ptr > 127) return 0; ptr++; } return 1; } static int regression_tests(void) { struct regression_test_case *current = regression_test_cases; const char *error; char *cpu_info; int i, err_offs; int is_successful, is_ascii; int total = 0; int successful = 0; int successful_row = 0; int counter = 0; int study_mode; int utf = 0, ucp = 0; int disabled_flags = 0; #ifdef SUPPORT_PCRE8 pcre *re8; pcre_extra *extra8; pcre_extra dummy_extra8; int ovector8_1[32]; int ovector8_2[32]; int return_value8[2]; unsigned char *mark8_1, *mark8_2; #endif #ifdef SUPPORT_PCRE16 pcre16 *re16; pcre16_extra *extra16; pcre16_extra dummy_extra16; int ovector16_1[32]; int ovector16_2[32]; int return_value16[2]; PCRE_UCHAR16 *mark16_1, *mark16_2; int length16; #endif #ifdef SUPPORT_PCRE32 pcre32 *re32; pcre32_extra *extra32; pcre32_extra dummy_extra32; int ovector32_1[32]; int ovector32_2[32]; int return_value32[2]; PCRE_UCHAR32 *mark32_1, *mark32_2; int length32; #endif /* This test compares the behaviour of interpreter and JIT. Although disabling utf or ucp may make tests fail, if the pcre_exec result is the SAME, it is still considered successful from pcre_jit_test point of view. */ #if defined SUPPORT_PCRE8 pcre_config(PCRE_CONFIG_JITTARGET, &cpu_info); #elif defined SUPPORT_PCRE16 pcre16_config(PCRE_CONFIG_JITTARGET, &cpu_info); #elif defined SUPPORT_PCRE32 pcre32_config(PCRE_CONFIG_JITTARGET, &cpu_info); #endif printf("Running JIT regression tests\n"); printf(" target CPU of SLJIT compiler: %s\n", cpu_info); #if defined SUPPORT_PCRE8 pcre_config(PCRE_CONFIG_UTF8, &utf); pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &ucp); #elif defined SUPPORT_PCRE16 pcre16_config(PCRE_CONFIG_UTF16, &utf); pcre16_config(PCRE_CONFIG_UNICODE_PROPERTIES, &ucp); #elif defined SUPPORT_PCRE32 pcre32_config(PCRE_CONFIG_UTF32, &utf); pcre32_config(PCRE_CONFIG_UNICODE_PROPERTIES, &ucp); #endif if (!utf) disabled_flags |= PCRE_UTF8 | PCRE_UTF16 | PCRE_UTF32; if (!ucp) disabled_flags |= PCRE_UCP; #ifdef SUPPORT_PCRE8 printf(" in 8 bit mode with UTF-8 %s and ucp %s:\n", utf ? "enabled" : "disabled", ucp ? "enabled" : "disabled"); #endif #ifdef SUPPORT_PCRE16 printf(" in 16 bit mode with UTF-16 %s and ucp %s:\n", utf ? "enabled" : "disabled", ucp ? "enabled" : "disabled"); #endif #ifdef SUPPORT_PCRE32 printf(" in 32 bit mode with UTF-32 %s and ucp %s:\n", utf ? "enabled" : "disabled", ucp ? "enabled" : "disabled"); #endif while (current->pattern) { /* printf("\nPattern: %s :\n", current->pattern); */ total++; is_ascii = 0; if (!(current->start_offset & F_PROPERTY)) is_ascii = check_ascii(current->pattern) && check_ascii(current->input); if (current->flags & PCRE_PARTIAL_SOFT) study_mode = PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE; else if (current->flags & PCRE_PARTIAL_HARD) study_mode = PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE; else study_mode = PCRE_STUDY_JIT_COMPILE; error = NULL; #ifdef SUPPORT_PCRE8 re8 = NULL; if (!(current->start_offset & F_NO8)) re8 = pcre_compile(current->pattern, current->flags & ~(PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | disabled_flags), &error, &err_offs, tables(0)); extra8 = NULL; if (re8) { error = NULL; extra8 = pcre_study(re8, study_mode, &error); if (!extra8) { printf("\n8 bit: Cannot study pattern: %s\n", current->pattern); pcre_free(re8); re8 = NULL; } else if (!(extra8->flags & PCRE_EXTRA_EXECUTABLE_JIT)) { printf("\n8 bit: JIT compiler does not support: %s\n", current->pattern); pcre_free_study(extra8); pcre_free(re8); re8 = NULL; } extra8->flags |= PCRE_EXTRA_MARK; } else if (((utf && ucp) || is_ascii) && !(current->start_offset & F_NO8)) printf("\n8 bit: Cannot compile pattern \"%s\": %s\n", current->pattern, error); #endif #ifdef SUPPORT_PCRE16 if ((current->flags & PCRE_UTF16) || (current->start_offset & F_FORCECONV)) convert_utf8_to_utf16(current->pattern, regtest_buf16, NULL, REGTEST_MAX_LENGTH16); else copy_char8_to_char16(current->pattern, regtest_buf16, REGTEST_MAX_LENGTH16); re16 = NULL; if (!(current->start_offset & F_NO16)) re16 = pcre16_compile(regtest_buf16, current->flags & ~(PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | disabled_flags), &error, &err_offs, tables(0)); extra16 = NULL; if (re16) { error = NULL; extra16 = pcre16_study(re16, study_mode, &error); if (!extra16) { printf("\n16 bit: Cannot study pattern: %s\n", current->pattern); pcre16_free(re16); re16 = NULL; } else if (!(extra16->flags & PCRE_EXTRA_EXECUTABLE_JIT)) { printf("\n16 bit: JIT compiler does not support: %s\n", current->pattern); pcre16_free_study(extra16); pcre16_free(re16); re16 = NULL; } extra16->flags |= PCRE_EXTRA_MARK; } else if (((utf && ucp) || is_ascii) && !(current->start_offset & F_NO16)) printf("\n16 bit: Cannot compile pattern \"%s\": %s\n", current->pattern, error); #endif #ifdef SUPPORT_PCRE32 if ((current->flags & PCRE_UTF32) || (current->start_offset & F_FORCECONV)) convert_utf8_to_utf32(current->pattern, regtest_buf32, NULL, REGTEST_MAX_LENGTH32); else copy_char8_to_char32(current->pattern, regtest_buf32, REGTEST_MAX_LENGTH32); re32 = NULL; if (!(current->start_offset & F_NO32)) re32 = pcre32_compile(regtest_buf32, current->flags & ~(PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | disabled_flags), &error, &err_offs, tables(0)); extra32 = NULL; if (re32) { error = NULL; extra32 = pcre32_study(re32, study_mode, &error); if (!extra32) { printf("\n32 bit: Cannot study pattern: %s\n", current->pattern); pcre32_free(re32); re32 = NULL; } if (!(extra32->flags & PCRE_EXTRA_EXECUTABLE_JIT)) { printf("\n32 bit: JIT compiler does not support: %s\n", current->pattern); pcre32_free_study(extra32); pcre32_free(re32); re32 = NULL; } extra32->flags |= PCRE_EXTRA_MARK; } else if (((utf && ucp) || is_ascii) && !(current->start_offset & F_NO32)) printf("\n32 bit: Cannot compile pattern \"%s\": %s\n", current->pattern, error); #endif counter++; if ((counter & 0x3) != 0) { #ifdef SUPPORT_PCRE8 setstack8(NULL); #endif #ifdef SUPPORT_PCRE16 setstack16(NULL); #endif #ifdef SUPPORT_PCRE32 setstack32(NULL); #endif } #ifdef SUPPORT_PCRE8 return_value8[0] = -1000; return_value8[1] = -1000; for (i = 0; i < 32; ++i) ovector8_1[i] = -2; for (i = 0; i < 32; ++i) ovector8_2[i] = -2; if (re8) { mark8_1 = NULL; mark8_2 = NULL; extra8->mark = &mark8_1; if ((counter & 0x1) != 0) { setstack8(extra8); return_value8[0] = pcre_exec(re8, extra8, current->input, strlen(current->input), current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector8_1, 32); } else return_value8[0] = pcre_jit_exec(re8, extra8, current->input, strlen(current->input), current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector8_1, 32, getstack8()); memset(&dummy_extra8, 0, sizeof(pcre_extra)); dummy_extra8.flags = PCRE_EXTRA_MARK; if (current->start_offset & F_STUDY) { dummy_extra8.flags |= PCRE_EXTRA_STUDY_DATA; dummy_extra8.study_data = extra8->study_data; } dummy_extra8.mark = &mark8_2; return_value8[1] = pcre_exec(re8, &dummy_extra8, current->input, strlen(current->input), current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector8_2, 32); } #endif #ifdef SUPPORT_PCRE16 return_value16[0] = -1000; return_value16[1] = -1000; for (i = 0; i < 32; ++i) ovector16_1[i] = -2; for (i = 0; i < 32; ++i) ovector16_2[i] = -2; if (re16) { mark16_1 = NULL; mark16_2 = NULL; if ((current->flags & PCRE_UTF16) || (current->start_offset & F_FORCECONV)) length16 = convert_utf8_to_utf16(current->input, regtest_buf16, regtest_offsetmap16, REGTEST_MAX_LENGTH16); else length16 = copy_char8_to_char16(current->input, regtest_buf16, REGTEST_MAX_LENGTH16); extra16->mark = &mark16_1; if ((counter & 0x1) != 0) { setstack16(extra16); return_value16[0] = pcre16_exec(re16, extra16, regtest_buf16, length16, current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector16_1, 32); } else return_value16[0] = pcre16_jit_exec(re16, extra16, regtest_buf16, length16, current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector16_1, 32, getstack16()); memset(&dummy_extra16, 0, sizeof(pcre16_extra)); dummy_extra16.flags = PCRE_EXTRA_MARK; if (current->start_offset & F_STUDY) { dummy_extra16.flags |= PCRE_EXTRA_STUDY_DATA; dummy_extra16.study_data = extra16->study_data; } dummy_extra16.mark = &mark16_2; return_value16[1] = pcre16_exec(re16, &dummy_extra16, regtest_buf16, length16, current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector16_2, 32); } #endif #ifdef SUPPORT_PCRE32 return_value32[0] = -1000; return_value32[1] = -1000; for (i = 0; i < 32; ++i) ovector32_1[i] = -2; for (i = 0; i < 32; ++i) ovector32_2[i] = -2; if (re32) { mark32_1 = NULL; mark32_2 = NULL; if ((current->flags & PCRE_UTF32) || (current->start_offset & F_FORCECONV)) length32 = convert_utf8_to_utf32(current->input, regtest_buf32, regtest_offsetmap32, REGTEST_MAX_LENGTH32); else length32 = copy_char8_to_char32(current->input, regtest_buf32, REGTEST_MAX_LENGTH32); extra32->mark = &mark32_1; if ((counter & 0x1) != 0) { setstack32(extra32); return_value32[0] = pcre32_exec(re32, extra32, regtest_buf32, length32, current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector32_1, 32); } else return_value32[0] = pcre32_jit_exec(re32, extra32, regtest_buf32, length32, current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector32_1, 32, getstack32()); memset(&dummy_extra32, 0, sizeof(pcre32_extra)); dummy_extra32.flags = PCRE_EXTRA_MARK; if (current->start_offset & F_STUDY) { dummy_extra32.flags |= PCRE_EXTRA_STUDY_DATA; dummy_extra32.study_data = extra32->study_data; } dummy_extra32.mark = &mark32_2; return_value32[1] = pcre32_exec(re32, &dummy_extra32, regtest_buf32, length32, current->start_offset & OFFSET_MASK, current->flags & (PCRE_NOTBOL | PCRE_NOTEOL | PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD | PCRE_NO_UTF8_CHECK), ovector32_2, 32); } #endif /* printf("[%d-%d-%d|%d-%d|%d-%d|%d-%d]%s", return_value8[0], return_value16[0], return_value32[0], ovector8_1[0], ovector8_1[1], ovector16_1[0], ovector16_1[1], ovector32_1[0], ovector32_1[1], (current->flags & PCRE_CASELESS) ? "C" : ""); */ /* If F_DIFF is set, just run the test, but do not compare the results. Segfaults can still be captured. */ is_successful = 1; if (!(current->start_offset & F_DIFF)) { #if defined SUPPORT_UTF && ((defined(SUPPORT_PCRE8) + defined(SUPPORT_PCRE16) + defined(SUPPORT_PCRE32)) >= 2) if (!(current->start_offset & F_FORCECONV)) { int return_value; /* All results must be the same. */ #ifdef SUPPORT_PCRE8 if ((return_value = return_value8[0]) != return_value8[1]) { printf("\n8 bit: Return value differs(J8:%d,I8:%d): [%d] '%s' @ '%s'\n", return_value8[0], return_value8[1], total, current->pattern, current->input); is_successful = 0; } else #endif #ifdef SUPPORT_PCRE16 if ((return_value = return_value16[0]) != return_value16[1]) { printf("\n16 bit: Return value differs(J16:%d,I16:%d): [%d] '%s' @ '%s'\n", return_value16[0], return_value16[1], total, current->pattern, current->input); is_successful = 0; } else #endif #ifdef SUPPORT_PCRE32 if ((return_value = return_value32[0]) != return_value32[1]) { printf("\n32 bit: Return value differs(J32:%d,I32:%d): [%d] '%s' @ '%s'\n", return_value32[0], return_value32[1], total, current->pattern, current->input); is_successful = 0; } else #endif #if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16 if (return_value8[0] != return_value16[0]) { printf("\n8 and 16 bit: Return value differs(J8:%d,J16:%d): [%d] '%s' @ '%s'\n", return_value8[0], return_value16[0], total, current->pattern, current->input); is_successful = 0; } else #endif #if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE32 if (return_value8[0] != return_value32[0]) { printf("\n8 and 32 bit: Return value differs(J8:%d,J32:%d): [%d] '%s' @ '%s'\n", return_value8[0], return_value32[0], total, current->pattern, current->input); is_successful = 0; } else #endif #if defined SUPPORT_PCRE16 && defined SUPPORT_PCRE32 if (return_value16[0] != return_value32[0]) { printf("\n16 and 32 bit: Return value differs(J16:%d,J32:%d): [%d] '%s' @ '%s'\n", return_value16[0], return_value32[0], total, current->pattern, current->input); is_successful = 0; } else #endif if (return_value >= 0 || return_value == PCRE_ERROR_PARTIAL) { if (return_value == PCRE_ERROR_PARTIAL) { return_value = 2; } else { return_value *= 2; } #ifdef SUPPORT_PCRE8 return_value8[0] = return_value; #endif #ifdef SUPPORT_PCRE16 return_value16[0] = return_value; #endif #ifdef SUPPORT_PCRE32 return_value32[0] = return_value; #endif /* Transform back the results. */ if (current->flags & PCRE_UTF8) { #ifdef SUPPORT_PCRE16 for (i = 0; i < return_value; ++i) { if (ovector16_1[i] >= 0) ovector16_1[i] = regtest_offsetmap16[ovector16_1[i]]; if (ovector16_2[i] >= 0) ovector16_2[i] = regtest_offsetmap16[ovector16_2[i]]; } #endif #ifdef SUPPORT_PCRE32 for (i = 0; i < return_value; ++i) { if (ovector32_1[i] >= 0) ovector32_1[i] = regtest_offsetmap32[ovector32_1[i]]; if (ovector32_2[i] >= 0) ovector32_2[i] = regtest_offsetmap32[ovector32_2[i]]; } #endif } for (i = 0; i < return_value; ++i) { #if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE16 if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector16_1[i] || ovector8_1[i] != ovector16_2[i]) { printf("\n8 and 16 bit: Ovector[%d] value differs(J8:%d,I8:%d,J16:%d,I16:%d): [%d] '%s' @ '%s' \n", i, ovector8_1[i], ovector8_2[i], ovector16_1[i], ovector16_2[i], total, current->pattern, current->input); is_successful = 0; } #endif #if defined SUPPORT_PCRE8 && defined SUPPORT_PCRE32 if (ovector8_1[i] != ovector8_2[i] || ovector8_1[i] != ovector32_1[i] || ovector8_1[i] != ovector32_2[i]) { printf("\n8 and 32 bit: Ovector[%d] value differs(J8:%d,I8:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n", i, ovector8_1[i], ovector8_2[i], ovector32_1[i], ovector32_2[i], total, current->pattern, current->input); is_successful = 0; } #endif #if defined SUPPORT_PCRE16 && defined SUPPORT_PCRE32 if (ovector16_1[i] != ovector16_2[i] || ovector16_1[i] != ovector32_1[i] || ovector16_1[i] != ovector32_2[i]) { printf("\n16 and 32 bit: Ovector[%d] value differs(J16:%d,I16:%d,J32:%d,I32:%d): [%d] '%s' @ '%s' \n", i, ovector16_1[i], ovector16_2[i], ovector32_1[i], ovector32_2[i], total, current->pattern, current->input); is_successful = 0; } #endif } } } else #endif /* more than one of SUPPORT_PCRE8, SUPPORT_PCRE16 and SUPPORT_PCRE32 */ { /* Only the 8 bit and 16 bit results must be equal. */ #ifdef SUPPORT_PCRE8 if (return_value8[0] != return_value8[1]) { printf("\n8 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n", return_value8[0], return_value8[1], total, current->pattern, current->input); is_successful = 0; } else if (return_value8[0] >= 0 || return_value8[0] == PCRE_ERROR_PARTIAL) { if (return_value8[0] == PCRE_ERROR_PARTIAL) return_value8[0] = 2; else return_value8[0] *= 2; for (i = 0; i < return_value8[0]; ++i) if (ovector8_1[i] != ovector8_2[i]) { printf("\n8 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n", i, ovector8_1[i], ovector8_2[i], total, current->pattern, current->input); is_successful = 0; } } #endif #ifdef SUPPORT_PCRE16 if (return_value16[0] != return_value16[1]) { printf("\n16 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n", return_value16[0], return_value16[1], total, current->pattern, current->input); is_successful = 0; } else if (return_value16[0] >= 0 || return_value16[0] == PCRE_ERROR_PARTIAL) { if (return_value16[0] == PCRE_ERROR_PARTIAL) return_value16[0] = 2; else return_value16[0] *= 2; for (i = 0; i < return_value16[0]; ++i) if (ovector16_1[i] != ovector16_2[i]) { printf("\n16 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n", i, ovector16_1[i], ovector16_2[i], total, current->pattern, current->input); is_successful = 0; } } #endif #ifdef SUPPORT_PCRE32 if (return_value32[0] != return_value32[1]) { printf("\n32 bit: Return value differs(%d:%d): [%d] '%s' @ '%s'\n", return_value32[0], return_value32[1], total, current->pattern, current->input); is_successful = 0; } else if (return_value32[0] >= 0 || return_value32[0] == PCRE_ERROR_PARTIAL) { if (return_value32[0] == PCRE_ERROR_PARTIAL) return_value32[0] = 2; else return_value32[0] *= 2; for (i = 0; i < return_value32[0]; ++i) if (ovector32_1[i] != ovector32_2[i]) { printf("\n32 bit: Ovector[%d] value differs(%d:%d): [%d] '%s' @ '%s'\n", i, ovector32_1[i], ovector32_2[i], total, current->pattern, current->input); is_successful = 0; } } #endif } } if (is_successful) { #ifdef SUPPORT_PCRE8 if (!(current->start_offset & F_NO8) && ((utf && ucp) || is_ascii)) { if (return_value8[0] < 0 && !(current->start_offset & F_NOMATCH)) { printf("8 bit: Test should match: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } if (return_value8[0] >= 0 && (current->start_offset & F_NOMATCH)) { printf("8 bit: Test should not match: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } } #endif #ifdef SUPPORT_PCRE16 if (!(current->start_offset & F_NO16) && ((utf && ucp) || is_ascii)) { if (return_value16[0] < 0 && !(current->start_offset & F_NOMATCH)) { printf("16 bit: Test should match: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } if (return_value16[0] >= 0 && (current->start_offset & F_NOMATCH)) { printf("16 bit: Test should not match: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } } #endif #ifdef SUPPORT_PCRE32 if (!(current->start_offset & F_NO32) && ((utf && ucp) || is_ascii)) { if (return_value32[0] < 0 && !(current->start_offset & F_NOMATCH)) { printf("32 bit: Test should match: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } if (return_value32[0] >= 0 && (current->start_offset & F_NOMATCH)) { printf("32 bit: Test should not match: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } } #endif } if (is_successful) { #ifdef SUPPORT_PCRE8 if (mark8_1 != mark8_2) { printf("8 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } #endif #ifdef SUPPORT_PCRE16 if (mark16_1 != mark16_2) { printf("16 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } #endif #ifdef SUPPORT_PCRE32 if (mark32_1 != mark32_2) { printf("32 bit: Mark value mismatch: [%d] '%s' @ '%s'\n", total, current->pattern, current->input); is_successful = 0; } #endif } #ifdef SUPPORT_PCRE8 if (re8) { pcre_free_study(extra8); pcre_free(re8); } #endif #ifdef SUPPORT_PCRE16 if (re16) { pcre16_free_study(extra16); pcre16_free(re16); } #endif #ifdef SUPPORT_PCRE32 if (re32) { pcre32_free_study(extra32); pcre32_free(re32); } #endif if (is_successful) { successful++; successful_row++; printf("."); if (successful_row >= 60) { successful_row = 0; printf("\n"); } } else successful_row = 0; fflush(stdout); current++; } tables(1); #ifdef SUPPORT_PCRE8 setstack8(NULL); #endif #ifdef SUPPORT_PCRE16 setstack16(NULL); #endif #ifdef SUPPORT_PCRE32 setstack32(NULL); #endif if (total == successful) { printf("\nAll JIT regression tests are successfully passed.\n"); return 0; } else { printf("\nSuccessful test ratio: %d%% (%d failed)\n", successful * 100 / total, total - successful); return 1; } } /* End of pcre_jit_test.c */ ================================================ FILE: src/pcre/pcre_maketables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_maketables(), which builds character tables for PCRE in the current locale. The file is compiled on its own as part of the PCRE library. However, it is also included in the compilation of dftables.c, in which case the macro DFTABLES is defined. */ #ifndef DFTABLES # ifdef HAVE_CONFIG_H # include "config.h" # endif # include "pcre_internal.h" #endif /************************************************* * Create PCRE character tables * *************************************************/ /* This function builds a set of character tables for use by PCRE and returns a pointer to them. They are build using the ctype functions, and consequently their contents will depend upon the current locale setting. When compiled as part of the library, the store is obtained via PUBL(malloc)(), but when compiled inside dftables, use malloc(). Arguments: none Returns: pointer to the contiguous block of data */ #if defined COMPILE_PCRE8 const unsigned char * pcre_maketables(void) #elif defined COMPILE_PCRE16 const unsigned char * pcre16_maketables(void) #elif defined COMPILE_PCRE32 const unsigned char * pcre32_maketables(void) #endif { unsigned char *yield, *p; int i; #ifndef DFTABLES yield = (unsigned char*)(PUBL(malloc))(tables_length); #else yield = (unsigned char*)malloc(tables_length); #endif if (yield == NULL) return NULL; p = yield; /* First comes the lower casing table */ for (i = 0; i < 256; i++) *p++ = tolower(i); /* Next the case-flipping table */ for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i); /* Then the character class tables. Don't try to be clever and save effort on exclusive ones - in some locales things may be different. Note that the table for "space" includes everything "isspace" gives, including VT in the default locale. This makes it work for the POSIX class [:space:]. From release 8.34 is is also correct for Perl space, because Perl added VT at release 5.18. Note also that it is possible for a character to be alnum or alpha without being lower or upper, such as "male and female ordinals" (\xAA and \xBA) in the fr_FR locale (at least under Debian Linux's locales as of 12/2005). So we must test for alnum specially. */ memset(p, 0, cbit_length); for (i = 0; i < 256; i++) { if (isdigit(i)) p[cbit_digit + i/8] |= 1 << (i&7); if (isupper(i)) p[cbit_upper + i/8] |= 1 << (i&7); if (islower(i)) p[cbit_lower + i/8] |= 1 << (i&7); if (isalnum(i)) p[cbit_word + i/8] |= 1 << (i&7); if (i == '_') p[cbit_word + i/8] |= 1 << (i&7); if (isspace(i)) p[cbit_space + i/8] |= 1 << (i&7); if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7); if (isgraph(i)) p[cbit_graph + i/8] |= 1 << (i&7); if (isprint(i)) p[cbit_print + i/8] |= 1 << (i&7); if (ispunct(i)) p[cbit_punct + i/8] |= 1 << (i&7); if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1 << (i&7); } p += cbit_length; /* Finally, the character type table. In this, we used to exclude VT from the white space chars, because Perl didn't recognize it as such for \s and for comments within regexes. However, Perl changed at release 5.18, so PCRE changed at release 8.34. */ for (i = 0; i < 256; i++) { int x = 0; if (isspace(i)) x += ctype_space; if (isalpha(i)) x += ctype_letter; if (isdigit(i)) x += ctype_digit; if (isxdigit(i)) x += ctype_xdigit; if (isalnum(i) || i == '_') x += ctype_word; /* Note: strchr includes the terminating zero in the characters it considers. In this instance, that is ok because we want binary zero to be flagged as a meta-character, which in this sense is any character that terminates a run of data characters. */ if (strchr("\\*+?{^.$|()[", i) != 0) x += ctype_meta; *p++ = x; } return yield; } /* End of pcre_maketables.c */ ================================================ FILE: src/pcre/pcre_newline.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains internal functions for testing newlines when more than one kind of newline is to be recognized. When a newline is found, its length is returned. In principle, we could implement several newline "types", each referring to a different set of newline characters. At present, PCRE supports only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF, and NLTYPE_ANY. The full list of Unicode newline characters is taken from http://unicode.org/unicode/reports/tr18/. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Check for newline at given position * *************************************************/ /* It is guaranteed that the initial value of ptr is less than the end of the string that is being processed. Arguments: ptr pointer to possible newline type the newline type endptr pointer to the end of the string lenptr where to return the length utf TRUE if in utf mode Returns: TRUE or FALSE */ BOOL PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr, BOOL utf) { pcre_uint32 c; (void)utf; #ifdef SUPPORT_UTF if (utf) { GETCHAR(c, ptr); } else #endif /* SUPPORT_UTF */ c = *ptr; /* Note that this function is called only for ANY or ANYCRLF. */ if (type == NLTYPE_ANYCRLF) switch(c) { case CHAR_LF: *lenptr = 1; return TRUE; case CHAR_CR: *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1; return TRUE; default: return FALSE; } /* NLTYPE_ANY */ else switch(c) { #ifdef EBCDIC case CHAR_NEL: #endif case CHAR_LF: case CHAR_VT: case CHAR_FF: *lenptr = 1; return TRUE; case CHAR_CR: *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1; return TRUE; #ifndef EBCDIC #ifdef COMPILE_PCRE8 case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE; case 0x2028: /* LS */ case 0x2029: *lenptr = 3; return TRUE; /* PS */ #else /* COMPILE_PCRE16 || COMPILE_PCRE32 */ case CHAR_NEL: case 0x2028: /* LS */ case 0x2029: *lenptr = 1; return TRUE; /* PS */ #endif /* COMPILE_PCRE8 */ #endif /* Not EBCDIC */ default: return FALSE; } } /************************************************* * Check for newline at previous position * *************************************************/ /* It is guaranteed that the initial value of ptr is greater than the start of the string that is being processed. Arguments: ptr pointer to possible newline type the newline type startptr pointer to the start of the string lenptr where to return the length utf TRUE if in utf mode Returns: TRUE or FALSE */ BOOL PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr, BOOL utf) { pcre_uint32 c; (void)utf; ptr--; #ifdef SUPPORT_UTF if (utf) { BACKCHAR(ptr); GETCHAR(c, ptr); } else #endif /* SUPPORT_UTF */ c = *ptr; /* Note that this function is called only for ANY or ANYCRLF. */ if (type == NLTYPE_ANYCRLF) switch(c) { case CHAR_LF: *lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1; return TRUE; case CHAR_CR: *lenptr = 1; return TRUE; default: return FALSE; } /* NLTYPE_ANY */ else switch(c) { case CHAR_LF: *lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1; return TRUE; #ifdef EBCDIC case CHAR_NEL: #endif case CHAR_VT: case CHAR_FF: case CHAR_CR: *lenptr = 1; return TRUE; #ifndef EBCDIC #ifdef COMPILE_PCRE8 case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE; case 0x2028: /* LS */ case 0x2029: *lenptr = 3; return TRUE; /* PS */ #else /* COMPILE_PCRE16 || COMPILE_PCRE32 */ case CHAR_NEL: case 0x2028: /* LS */ case 0x2029: *lenptr = 1; return TRUE; /* PS */ #endif /* COMPILE_PCRE8 */ #endif /* NotEBCDIC */ default: return FALSE; } } /* End of pcre_newline.c */ ================================================ FILE: src/pcre/pcre_ord2utf8.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This file contains a private PCRE function that converts an ordinal character value into a UTF8 string. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define COMPILE_PCRE8 #include "pcre_internal.h" /************************************************* * Convert character value to UTF-8 * *************************************************/ /* This function takes an integer value in the range 0 - 0x10ffff and encodes it as a UTF-8 character in 1 to 4 pcre_uchars. Arguments: cvalue the character value buffer pointer to buffer for result - at least 6 pcre_uchars long Returns: number of characters placed in the buffer */ unsigned int PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer) { #ifdef SUPPORT_UTF register int i, j; for (i = 0; i < PRIV(utf8_table1_size); i++) if ((int)cvalue <= PRIV(utf8_table1)[i]) break; buffer += i; for (j = i; j > 0; j--) { *buffer-- = 0x80 | (cvalue & 0x3f); cvalue >>= 6; } *buffer = PRIV(utf8_table2)[i] | cvalue; return i + 1; #else (void)(cvalue); /* Keep compiler happy; this function won't ever be */ (void)(buffer); /* called when SUPPORT_UTF is not defined. */ return 0; #endif } /* End of pcre_ord2utf8.c */ ================================================ FILE: src/pcre/pcre_printint.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains a PCRE private debugging function for printing out the internal form of a compiled regular expression, along with some supporting local functions. This source file is used in two places: (1) It is #included by pcre_compile.c when it is compiled in debugging mode (PCRE_DEBUG defined in pcre_internal.h). It is not included in production compiles. In this case PCRE_INCLUDED is defined. (2) It is also compiled separately and linked with pcretest.c, which can be asked to print out a compiled regex for debugging purposes. */ #ifndef PCRE_INCLUDED #ifdef HAVE_CONFIG_H #include "config.h" #endif /* For pcretest program. */ #define PRIV(name) name /* We have to include pcre_internal.h because we need the internal info for displaying the results of pcre_study() and we also need to know about the internal macros, structures, and other internal data values; pcretest has "inside information" compared to a program that strictly follows the PCRE API. Although pcre_internal.h does itself include pcre.h, we explicitly include it here before pcre_internal.h so that the PCRE_EXP_xxx macros get set appropriately for an application, not for building PCRE. */ #include "pcre.h" #include "pcre_internal.h" /* These are the funtions that are contained within. It doesn't seem worth having a separate .h file just for this. */ #endif /* PCRE_INCLUDED */ #ifdef PCRE_INCLUDED static /* Keep the following function as private. */ #endif #if defined COMPILE_PCRE8 void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths); #elif defined COMPILE_PCRE16 void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths); #elif defined COMPILE_PCRE32 void pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths); #endif /* Macro that decides whether a character should be output as a literal or in hexadecimal. We don't use isprint() because that can vary from system to system (even without the use of locales) and we want the output always to be the same, for testing purposes. */ #ifdef EBCDIC #define PRINTABLE(c) ((c) >= 64 && (c) < 255) #else #define PRINTABLE(c) ((c) >= 32 && (c) < 127) #endif /* The table of operator names. */ static const char *priv_OP_names[] = { OP_NAME_LIST }; /* This table of operator lengths is not actually used by the working code, but its size is needed for a check that ensures it is the correct size for the number of opcodes (thus catching update omissions). */ static const pcre_uint8 priv_OP_lengths[] = { OP_LENGTHS }; /************************************************* * Print single- or multi-byte character * *************************************************/ static unsigned int print_char(FILE *f, pcre_uchar *ptr, BOOL utf) { pcre_uint32 c = *ptr; #ifndef SUPPORT_UTF (void)utf; /* Avoid compiler warning */ if (PRINTABLE(c)) fprintf(f, "%c", (char)c); else if (c <= 0x80) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c); return 0; #else #if defined COMPILE_PCRE8 if (!utf || (c & 0xc0) != 0xc0) { if (PRINTABLE(c)) fprintf(f, "%c", (char)c); else if (c < 0x80) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%02x}", c); return 0; } else { int i; int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */ int s = 6*a; c = (c & PRIV(utf8_table3)[a]) << s; for (i = 1; i <= a; i++) { /* This is a check for malformed UTF-8; it should only occur if the sanity check has been turned off. Rather than swallow random bytes, just stop if we hit a bad one. Print it with \X instead of \x as an indication. */ if ((ptr[i] & 0xc0) != 0x80) { fprintf(f, "\\X{%x}", c); return i - 1; } /* The byte is OK */ s -= 6; c |= (ptr[i] & 0x3f) << s; } fprintf(f, "\\x{%x}", c); return a; } #elif defined COMPILE_PCRE16 if (!utf || (c & 0xfc00) != 0xd800) { if (PRINTABLE(c)) fprintf(f, "%c", (char)c); else if (c <= 0x80) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%02x}", c); return 0; } else { /* This is a check for malformed UTF-16; it should only occur if the sanity check has been turned off. Rather than swallow a low surrogate, just stop if we hit a bad one. Print it with \X instead of \x as an indication. */ if ((ptr[1] & 0xfc00) != 0xdc00) { fprintf(f, "\\X{%x}", c); return 0; } c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000; fprintf(f, "\\x{%x}", c); return 1; } #elif defined COMPILE_PCRE32 if (!utf || (c & 0xfffff800u) != 0xd800u) { if (PRINTABLE(c)) fprintf(f, "%c", (char)c); else if (c <= 0x80) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c); return 0; } else { /* This is a check for malformed UTF-32; it should only occur if the sanity check has been turned off. Rather than swallow a surrogate, just stop if we hit one. Print it with \X instead of \x as an indication. */ fprintf(f, "\\X{%x}", c); return 0; } #endif /* COMPILE_PCRE[8|16|32] */ #endif /* SUPPORT_UTF */ } /************************************************* * Print uchar string (regardless of utf) * *************************************************/ static void print_puchar(FILE *f, PCRE_PUCHAR ptr) { while (*ptr != '\0') { register pcre_uint32 c = *ptr++; if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c); } } /************************************************* * Find Unicode property name * *************************************************/ static const char * get_ucpname(unsigned int ptype, unsigned int pvalue) { #ifdef SUPPORT_UCP int i; for (i = PRIV(utt_size) - 1; i >= 0; i--) { if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break; } return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??"; #else /* It gets harder and harder to shut off unwanted compiler warnings. */ ptype = ptype * pvalue; return (ptype == pvalue)? "??" : "??"; #endif } /************************************************* * Print Unicode property value * *************************************************/ /* "Normal" properties can be printed from tables. The PT_CLIST property is a pseudo-property that contains a pointer to a list of case-equivalent characters. This is used only when UCP support is available and UTF mode is selected. It should never occur otherwise, but just in case it does, have something ready to print. */ static void print_prop(FILE *f, pcre_uchar *code, const char *before, const char *after) { if (code[1] != PT_CLIST) { fprintf(f, "%s%s %s%s", before, priv_OP_names[*code], get_ucpname(code[1], code[2]), after); } else { const char *not = (*code == OP_PROP)? "" : "not "; #ifndef SUPPORT_UCP fprintf(f, "%s%sclist %d%s", before, not, code[2], after); #else const pcre_uint32 *p = PRIV(ucd_caseless_sets) + code[2]; fprintf (f, "%s%sclist", before, not); while (*p < NOTACHAR) fprintf(f, " %04x", *p++); fprintf(f, "%s", after); #endif } } /************************************************* * Print compiled regex * *************************************************/ /* Make this function work for a regex with integers either byte order. However, we assume that what we are passed is a compiled regex. The print_lengths flag controls whether offsets and lengths of items are printed. They can be turned off from pcretest so that automatic tests on bytecode can be written that do not depend on the value of LINK_SIZE. */ #ifdef PCRE_INCLUDED static /* Keep the following function as private. */ #endif #if defined COMPILE_PCRE8 void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths) #elif defined COMPILE_PCRE16 void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths) #elif defined COMPILE_PCRE32 void pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths) #endif { REAL_PCRE *re = (REAL_PCRE *)external_re; pcre_uchar *codestart, *code; BOOL utf; unsigned int options = re->options; int offset = re->name_table_offset; int count = re->name_count; int size = re->name_entry_size; if (re->magic_number != MAGIC_NUMBER) { offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff); count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff); size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff); options = ((options << 24) & 0xff000000) | ((options << 8) & 0x00ff0000) | ((options >> 8) & 0x0000ff00) | ((options >> 24) & 0x000000ff); } code = codestart = (pcre_uchar *)re + offset + count * size; /* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */ utf = (options & PCRE_UTF8) != 0; for(;;) { pcre_uchar *ccode; const char *flag = " "; pcre_uint32 c; unsigned int extra = 0; if (print_lengths) fprintf(f, "%3d ", (int)(code - codestart)); else fprintf(f, " "); switch(*code) { /* ========================================================================== */ /* These cases are never obeyed. This is a fudge that causes a compile- time error if the vectors OP_names or OP_lengths, which are indexed by opcode, are not the correct length. It seems to be the only way to do such a check at compile time, as the sizeof() operator does not work in the C preprocessor. */ case OP_TABLE_LENGTH: case OP_TABLE_LENGTH + ((sizeof(priv_OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) && (sizeof(priv_OP_lengths) == OP_TABLE_LENGTH)): break; /* ========================================================================== */ case OP_END: fprintf(f, " %s\n", priv_OP_names[*code]); fprintf(f, "------------------------------------------------------------------\n"); return; case OP_CHAR: fprintf(f, " "); do { code++; code += 1 + print_char(f, code, utf); } while (*code == OP_CHAR); fprintf(f, "\n"); continue; case OP_CHARI: fprintf(f, " /i "); do { code++; code += 1 + print_char(f, code, utf); } while (*code == OP_CHARI); fprintf(f, "\n"); continue; case OP_CBRA: case OP_CBRAPOS: case OP_SCBRA: case OP_SCBRAPOS: if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); else fprintf(f, " "); fprintf(f, "%s %d", priv_OP_names[*code], GET2(code, 1+LINK_SIZE)); break; case OP_BRA: case OP_BRAPOS: case OP_SBRA: case OP_SBRAPOS: case OP_KETRMAX: case OP_KETRMIN: case OP_KETRPOS: case OP_ALT: case OP_KET: case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: case OP_ONCE: case OP_ONCE_NC: case OP_COND: case OP_SCOND: case OP_REVERSE: if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); else fprintf(f, " "); fprintf(f, "%s", priv_OP_names[*code]); break; case OP_CLOSE: fprintf(f, " %s %d", priv_OP_names[*code], GET2(code, 1)); break; case OP_CREF: fprintf(f, "%3d %s", GET2(code,1), priv_OP_names[*code]); break; case OP_DNCREF: { pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) + IMM2_SIZE; fprintf(f, " %s Cond ref <", flag); print_puchar(f, entry); fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); } break; case OP_RREF: c = GET2(code, 1); if (c == RREF_ANY) fprintf(f, " Cond recurse any"); else fprintf(f, " Cond recurse %d", c); break; case OP_DNRREF: { pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) + IMM2_SIZE; fprintf(f, " %s Cond recurse <", flag); print_puchar(f, entry); fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); } break; case OP_DEF: fprintf(f, " Cond def"); break; case OP_STARI: case OP_MINSTARI: case OP_POSSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_POSQUERYI: flag = "/i"; /* Fall through */ case OP_STAR: case OP_MINSTAR: case OP_POSSTAR: case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY: case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPOSSTAR: case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEPOSPLUS: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSQUERY: fprintf(f, " %s ", flag); if (*code >= OP_TYPESTAR) { if (code[1] == OP_PROP || code[1] == OP_NOTPROP) { print_prop(f, code + 1, "", " "); extra = 2; } else fprintf(f, "%s", priv_OP_names[code[1]]); } else extra = print_char(f, code+1, utf); fprintf(f, "%s", priv_OP_names[*code]); break; case OP_EXACTI: case OP_UPTOI: case OP_MINUPTOI: case OP_POSUPTOI: flag = "/i"; /* Fall through */ case OP_EXACT: case OP_UPTO: case OP_MINUPTO: case OP_POSUPTO: fprintf(f, " %s ", flag); extra = print_char(f, code + 1 + IMM2_SIZE, utf); fprintf(f, "{"); if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,"); fprintf(f, "%d}", GET2(code,1)); if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?"); else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+"); break; case OP_TYPEEXACT: case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO: if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP) { print_prop(f, code + IMM2_SIZE + 1, " ", " "); extra = 2; } else fprintf(f, " %s", priv_OP_names[code[1 + IMM2_SIZE]]); fprintf(f, "{"); if (*code != OP_TYPEEXACT) fprintf(f, "0,"); fprintf(f, "%d}", GET2(code,1)); if (*code == OP_TYPEMINUPTO) fprintf(f, "?"); else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+"); break; case OP_NOTI: flag = "/i"; /* Fall through */ case OP_NOT: fprintf(f, " %s [^", flag); extra = print_char(f, code + 1, utf); fprintf(f, "]"); break; case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPOSSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTPOSPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTPOSQUERYI: flag = "/i"; /* Fall through */ case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPOSSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTPOSPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTPOSQUERY: fprintf(f, " %s [^", flag); extra = print_char(f, code + 1, utf); fprintf(f, "]%s", priv_OP_names[*code]); break; case OP_NOTEXACTI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTPOSUPTOI: flag = "/i"; /* Fall through */ case OP_NOTEXACT: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTPOSUPTO: fprintf(f, " %s [^", flag); extra = print_char(f, code + 1 + IMM2_SIZE, utf); fprintf(f, "]{"); if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,"); fprintf(f, "%d}", GET2(code,1)); if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?"); else if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+"); break; case OP_RECURSE: if (print_lengths) fprintf(f, "%3d ", GET(code, 1)); else fprintf(f, " "); fprintf(f, "%s", priv_OP_names[*code]); break; case OP_REFI: flag = "/i"; /* Fall through */ case OP_REF: fprintf(f, " %s \\%d", flag, GET2(code,1)); ccode = code + priv_OP_lengths[*code]; goto CLASS_REF_REPEAT; case OP_DNREFI: flag = "/i"; /* Fall through */ case OP_DNREF: { pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) + IMM2_SIZE; fprintf(f, " %s \\k<", flag); print_puchar(f, entry); fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE)); } ccode = code + priv_OP_lengths[*code]; goto CLASS_REF_REPEAT; case OP_CALLOUT: fprintf(f, " %s %d %d %d", priv_OP_names[*code], code[1], GET(code,2), GET(code, 2 + LINK_SIZE)); break; case OP_PROP: case OP_NOTPROP: print_prop(f, code, " ", ""); break; /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm in having this code always here, and it makes it less messy without all those #ifdefs. */ case OP_CLASS: case OP_NCLASS: case OP_XCLASS: { int i; unsigned int min, max; BOOL printmap; BOOL invertmap = FALSE; pcre_uint8 *map; pcre_uint8 inverted_map[32]; fprintf(f, " ["); if (*code == OP_XCLASS) { extra = GET(code, 1); ccode = code + LINK_SIZE + 1; printmap = (*ccode & XCL_MAP) != 0; if ((*ccode & XCL_NOT) != 0) { invertmap = (*ccode & XCL_HASPROP) == 0; fprintf(f, "^"); } ccode++; } else { printmap = TRUE; ccode = code + 1; } /* Print a bit map */ if (printmap) { map = (pcre_uint8 *)ccode; if (invertmap) { for (i = 0; i < 32; i++) inverted_map[i] = ~map[i]; map = inverted_map; } for (i = 0; i < 256; i++) { if ((map[i/8] & (1 << (i&7))) != 0) { int j; for (j = i+1; j < 256; j++) if ((map[j/8] & (1 << (j&7))) == 0) break; if (i == '-' || i == ']') fprintf(f, "\\"); if (PRINTABLE(i)) fprintf(f, "%c", i); else fprintf(f, "\\x%02x", i); if (--j > i) { if (j != i + 1) fprintf(f, "-"); if (j == '-' || j == ']') fprintf(f, "\\"); if (PRINTABLE(j)) fprintf(f, "%c", j); else fprintf(f, "\\x%02x", j); } i = j; } } ccode += 32 / sizeof(pcre_uchar); } /* For an XCLASS there is always some additional data */ if (*code == OP_XCLASS) { pcre_uchar ch; while ((ch = *ccode++) != XCL_END) { BOOL not = FALSE; const char *notch = ""; switch(ch) { case XCL_NOTPROP: not = TRUE; notch = "^"; /* Fall through */ case XCL_PROP: { unsigned int ptype = *ccode++; unsigned int pvalue = *ccode++; switch(ptype) { case PT_PXGRAPH: fprintf(f, "[:%sgraph:]", notch); break; case PT_PXPRINT: fprintf(f, "[:%sprint:]", notch); break; case PT_PXPUNCT: fprintf(f, "[:%spunct:]", notch); break; default: fprintf(f, "\\%c{%s}", (not? 'P':'p'), get_ucpname(ptype, pvalue)); break; } } break; default: ccode += 1 + print_char(f, ccode, utf); if (ch == XCL_RANGE) { fprintf(f, "-"); ccode += 1 + print_char(f, ccode, utf); } break; } } } /* Indicate a non-UTF class which was created by negation */ fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : ""); /* Handle repeats after a class or a back reference */ CLASS_REF_REPEAT: switch(*ccode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSPLUS: case OP_CRPOSQUERY: fprintf(f, "%s", priv_OP_names[*ccode]); extra += priv_OP_lengths[*ccode]; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: min = GET2(ccode,1); max = GET2(ccode,1 + IMM2_SIZE); if (max == 0) fprintf(f, "{%u,}", min); else fprintf(f, "{%u,%u}", min, max); if (*ccode == OP_CRMINRANGE) fprintf(f, "?"); else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+"); extra += priv_OP_lengths[*ccode]; break; /* Do nothing if it's not a repeat; this code stops picky compilers warning about the lack of a default code path. */ default: break; } } break; case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: fprintf(f, " %s ", priv_OP_names[*code]); print_puchar(f, code + 2); extra += code[1]; break; case OP_THEN: fprintf(f, " %s", priv_OP_names[*code]); break; case OP_CIRCM: case OP_DOLLM: flag = "/m"; /* Fall through */ /* Anything else is just an item with no data, but possibly a flag. */ default: fprintf(f, " %s %s", flag, priv_OP_names[*code]); break; } code += priv_OP_lengths[*code] + extra; fprintf(f, "\n"); } } /* End of pcre_printint.src */ ================================================ FILE: src/pcre/pcre_refcount.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_refcount(), which is an auxiliary function that can be used to maintain a reference count in a compiled pattern data block. This might be helpful in applications where the block is shared by different users. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Maintain reference count * *************************************************/ /* The reference count is a 16-bit field, initialized to zero. It is not possible to transfer a non-zero count from one host to a different host that has a different byte order - though I can't see why anyone in their right mind would ever want to do that! Arguments: argument_re points to compiled code adjust value to add to the count Returns: the (possibly updated) count value (a non-negative number), or a negative error number */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre_refcount(pcre *argument_re, int adjust) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre16_refcount(pcre16 *argument_re, int adjust) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN int PCRE_CALL_CONVENTION pcre32_refcount(pcre32 *argument_re, int adjust) #endif { REAL_PCRE *re = (REAL_PCRE *)argument_re; if (re == NULL) return PCRE_ERROR_NULL; if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; re->ref_count = (-adjust > re->ref_count)? 0 : (adjust + re->ref_count > 65535)? 65535 : re->ref_count + adjust; return re->ref_count; } /* End of pcre_refcount.c */ ================================================ FILE: src/pcre/pcre_scanner.cc ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "pcrecpp_internal.h" #include "pcre_scanner.h" using std::vector; namespace pcrecpp { Scanner::Scanner() : data_(), input_(data_), skip_(NULL), should_skip_(false), skip_repeat_(false), save_comments_(false), comments_(NULL), comments_offset_(0) { } Scanner::Scanner(const string& in) : data_(in), input_(data_), skip_(NULL), should_skip_(false), skip_repeat_(false), save_comments_(false), comments_(NULL), comments_offset_(0) { } Scanner::~Scanner() { delete skip_; delete comments_; } void Scanner::SetSkipExpression(const char* re) { delete skip_; if (re != NULL) { skip_ = new RE(re); should_skip_ = true; skip_repeat_ = true; ConsumeSkip(); } else { skip_ = NULL; should_skip_ = false; skip_repeat_ = false; } } void Scanner::Skip(const char* re) { delete skip_; if (re != NULL) { skip_ = new RE(re); should_skip_ = true; skip_repeat_ = false; ConsumeSkip(); } else { skip_ = NULL; should_skip_ = false; skip_repeat_ = false; } } void Scanner::DisableSkip() { assert(skip_ != NULL); should_skip_ = false; } void Scanner::EnableSkip() { assert(skip_ != NULL); should_skip_ = true; ConsumeSkip(); } int Scanner::LineNumber() const { // TODO: Make it more efficient by keeping track of the last point // where we computed line numbers and counting newlines since then. // We could use std:count, but not all systems have it. :-( int count = 1; for (const char* p = data_.data(); p < input_.data(); ++p) if (*p == '\n') ++count; return count; } int Scanner::Offset() const { return (int)(input_.data() - data_.c_str()); } bool Scanner::LookingAt(const RE& re) const { int consumed; return re.DoMatch(input_, RE::ANCHOR_START, &consumed, 0, 0); } bool Scanner::Consume(const RE& re, const Arg& arg0, const Arg& arg1, const Arg& arg2) { const bool result = re.Consume(&input_, arg0, arg1, arg2); if (result && should_skip_) ConsumeSkip(); return result; } // helper function to consume *skip_ and honour save_comments_ void Scanner::ConsumeSkip() { const char* start_data = input_.data(); while (skip_->Consume(&input_)) { if (!skip_repeat_) { // Only one skip allowed. break; } } if (save_comments_) { if (comments_ == NULL) { comments_ = new vector; } // already pointing one past end, so no need to +1 int length = (int)(input_.data() - start_data); if (length > 0) { comments_->push_back(StringPiece(start_data, length)); } } } void Scanner::GetComments(int start, int end, vector *ranges) { // short circuit out if we've not yet initialized comments_ // (e.g., when save_comments is false) if (!comments_) { return; } // TODO: if we guarantee that comments_ will contain StringPieces // that are ordered by their start, then we can do a binary search // for the first StringPiece at or past start and then scan for the // ones contained in the range, quit early (use equal_range or // lower_bound) for (vector::const_iterator it = comments_->begin(); it != comments_->end(); ++it) { if ((it->data() >= data_.c_str() + start && it->data() + it->size() <= data_.c_str() + end)) { ranges->push_back(*it); } } } void Scanner::GetNextComments(vector *ranges) { // short circuit out if we've not yet initialized comments_ // (e.g., when save_comments is false) if (!comments_) { return; } for (vector::const_iterator it = comments_->begin() + comments_offset_; it != comments_->end(); ++it) { ranges->push_back(*it); ++comments_offset_; } } } // namespace pcrecpp ================================================ FILE: src/pcre/pcre_scanner.h ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat // // Regular-expression based scanner for parsing an input stream. // // Example 1: parse a sequence of "var = number" entries from input: // // Scanner scanner(input); // string var; // int number; // scanner.SetSkipExpression("\\s+"); // Skip any white space we encounter // while (scanner.Consume("(\\w+) = (\\d+)", &var, &number)) { // ...; // } #ifndef _PCRE_SCANNER_H #define _PCRE_SCANNER_H #include #include #include #include #include namespace pcrecpp { class PCRECPP_EXP_DEFN Scanner { public: Scanner(); explicit Scanner(const std::string& input); ~Scanner(); // Return current line number. The returned line-number is // one-based. I.e. it returns 1 + the number of consumed newlines. // // Note: this method may be slow. It may take time proportional to // the size of the input. int LineNumber() const; // Return the byte-offset that the scanner is looking in the // input data; int Offset() const; // Return true iff the start of the remaining input matches "re" bool LookingAt(const RE& re) const; // Return true iff all of the following are true // a. the start of the remaining input matches "re", // b. if any arguments are supplied, matched sub-patterns can be // parsed and stored into the arguments. // If it returns true, it skips over the matched input and any // following input that matches the "skip" regular expression. bool Consume(const RE& re, const Arg& arg0 = RE::no_arg, const Arg& arg1 = RE::no_arg, const Arg& arg2 = RE::no_arg // TODO: Allow more arguments? ); // Set the "skip" regular expression. If after consuming some data, // a prefix of the input matches this RE, it is automatically // skipped. For example, a programming language scanner would use // a skip RE that matches white space and comments. // // scanner.SetSkipExpression("\\s+|//.*|/[*](.|\n)*?[*]/"); // // Skipping repeats as long as it succeeds. We used to let people do // this by writing "(...)*" in the regular expression, but that added // up to lots of recursive calls within the pcre library, so now we // control repetition explicitly via the function call API. // // You can pass NULL for "re" if you do not want any data to be skipped. void Skip(const char* re); // DEPRECATED; does *not* repeat void SetSkipExpression(const char* re); // Temporarily pause "skip"ing. This // Skip("Foo"); code ; DisableSkip(); code; EnableSkip() // is similar to // Skip("Foo"); code ; Skip(NULL); code ; Skip("Foo"); // but avoids creating/deleting new RE objects. void DisableSkip(); // Reenable previously paused skipping. Any prefix of the input // that matches the skip pattern is immediately dropped. void EnableSkip(); /***** Special wrappers around SetSkip() for some common idioms *****/ // Arranges to skip whitespace, C comments, C++ comments. // The overall RE is a disjunction of the following REs: // \\s whitespace // //.*\n C++ comment // /[*](.|\n)*?[*]/ C comment (x*? means minimal repetitions of x) // We get repetition via the semantics of SetSkipExpression, not by using * void SkipCXXComments() { SetSkipExpression("\\s|//.*\n|/[*](?:\n|.)*?[*]/"); } void set_save_comments(bool comments) { save_comments_ = comments; } bool save_comments() { return save_comments_; } // Append to vector ranges the comments found in the // byte range [start,end] (inclusive) of the input data. // Only comments that were extracted entirely within that // range are returned: no range splitting of atomically-extracted // comments is performed. void GetComments(int start, int end, std::vector *ranges); // Append to vector ranges the comments added // since the last time this was called. This // functionality is provided for efficiency when // interleaving scanning with parsing. void GetNextComments(std::vector *ranges); private: std::string data_; // All the input data StringPiece input_; // Unprocessed input RE* skip_; // If non-NULL, RE for skipping input bool should_skip_; // If true, use skip_ bool skip_repeat_; // If true, repeat skip_ as long as it works bool save_comments_; // If true, aggregate the skip expression // the skipped comments // TODO: later consider requiring that the StringPieces be added // in order by their start position std::vector *comments_; // the offset into comments_ that has been returned by GetNextComments int comments_offset_; // helper function to consume *skip_ and honour // save_comments_ void ConsumeSkip(); }; } // namespace pcrecpp #endif /* _PCRE_SCANNER_H */ ================================================ FILE: src/pcre/pcre_scanner_unittest.cc ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: Greg J. Badros // // Unittest for scanner, especially GetNextComments and GetComments() // functionality. #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include /* for strchr */ #include #include #include "pcrecpp.h" #include "pcre_stringpiece.h" #include "pcre_scanner.h" #define FLAGS_unittest_stack_size 49152 // Dies with a fatal error if the two values are not equal. #define CHECK_EQ(a, b) do { \ if ( (a) != (b) ) { \ fprintf(stderr, "%s:%d: Check failed because %s != %s\n", \ __FILE__, __LINE__, #a, #b); \ exit(1); \ } \ } while (0) using std::vector; using std::string; using pcrecpp::StringPiece; using pcrecpp::Scanner; static void TestScanner() { const char input[] = "\n" "alpha = 1; // this sets alpha\n" "bravo = 2; // bravo is set here\n" "gamma = 33; /* and here is gamma */\n"; const char *re = "(\\w+) = (\\d+);"; Scanner s(input); string var; int number; s.SkipCXXComments(); s.set_save_comments(true); vector comments; s.Consume(re, &var, &number); CHECK_EQ(var, "alpha"); CHECK_EQ(number, 1); CHECK_EQ(s.LineNumber(), 3); s.GetNextComments(&comments); CHECK_EQ(comments.size(), 1); CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); comments.resize(0); s.Consume(re, &var, &number); CHECK_EQ(var, "bravo"); CHECK_EQ(number, 2); s.GetNextComments(&comments); CHECK_EQ(comments.size(), 1); CHECK_EQ(comments[0].as_string(), " // bravo is set here\n"); comments.resize(0); s.Consume(re, &var, &number); CHECK_EQ(var, "gamma"); CHECK_EQ(number, 33); s.GetNextComments(&comments); CHECK_EQ(comments.size(), 1); CHECK_EQ(comments[0].as_string(), " /* and here is gamma */\n"); comments.resize(0); s.GetComments(0, sizeof(input), &comments); CHECK_EQ(comments.size(), 3); CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); CHECK_EQ(comments[1].as_string(), " // bravo is set here\n"); CHECK_EQ(comments[2].as_string(), " /* and here is gamma */\n"); comments.resize(0); s.GetComments(0, (int)(strchr(input, '/') - input), &comments); CHECK_EQ(comments.size(), 0); comments.resize(0); s.GetComments((int)(strchr(input, '/') - input - 1), sizeof(input), &comments); CHECK_EQ(comments.size(), 3); CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); CHECK_EQ(comments[1].as_string(), " // bravo is set here\n"); CHECK_EQ(comments[2].as_string(), " /* and here is gamma */\n"); comments.resize(0); s.GetComments((int)(strchr(input, '/') - input - 1), (int)(strchr(input + 1, '\n') - input + 1), &comments); CHECK_EQ(comments.size(), 1); CHECK_EQ(comments[0].as_string(), " // this sets alpha\n"); comments.resize(0); } static void TestBigComment() { string input; for (int i = 0; i < 1024; ++i) { char buf[1024]; // definitely big enough sprintf(buf, " # Comment %d\n", i); input += buf; } input += "name = value;\n"; Scanner s(input.c_str()); s.SetSkipExpression("\\s+|#.*\n"); string name; string value; s.Consume("(\\w+) = (\\w+);", &name, &value); CHECK_EQ(name, "name"); CHECK_EQ(value, "value"); } // TODO: also test scanner and big-comment in a thread with a // small stack size int main(int argc, char** argv) { (void)argc; (void)argv; TestScanner(); TestBigComment(); // Done printf("OK\n"); return 0; } ================================================ FILE: src/pcre/pcre_string_utils.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2014 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains internal functions for comparing and finding the length of strings for different data item sizes. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" #ifndef COMPILE_PCRE8 /************************************************* * Compare string utilities * *************************************************/ /* The following two functions compares two strings. Basically a strcmp for non 8 bit characters. Arguments: str1 first string str2 second string Returns: 0 if both string are equal (like strcmp), 1 otherwise */ int PRIV(strcmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2) { pcre_uchar c1; pcre_uchar c2; while (*str1 != '\0' || *str2 != '\0') { c1 = *str1++; c2 = *str2++; if (c1 != c2) return ((c1 > c2) << 1) - 1; } /* Both length and characters must be equal. */ return 0; } #ifdef COMPILE_PCRE32 int PRIV(strcmp_uc_uc_utf)(const pcre_uchar *str1, const pcre_uchar *str2) { pcre_uchar c1; pcre_uchar c2; while (*str1 != '\0' || *str2 != '\0') { c1 = UCHAR21INC(str1); c2 = UCHAR21INC(str2); if (c1 != c2) return ((c1 > c2) << 1) - 1; } /* Both length and characters must be equal. */ return 0; } #endif /* COMPILE_PCRE32 */ int PRIV(strcmp_uc_c8)(const pcre_uchar *str1, const char *str2) { const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; pcre_uchar c1; pcre_uchar c2; while (*str1 != '\0' || *ustr2 != '\0') { c1 = *str1++; c2 = (pcre_uchar)*ustr2++; if (c1 != c2) return ((c1 > c2) << 1) - 1; } /* Both length and characters must be equal. */ return 0; } #ifdef COMPILE_PCRE32 int PRIV(strcmp_uc_c8_utf)(const pcre_uchar *str1, const char *str2) { const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; pcre_uchar c1; pcre_uchar c2; while (*str1 != '\0' || *ustr2 != '\0') { c1 = UCHAR21INC(str1); c2 = (pcre_uchar)*ustr2++; if (c1 != c2) return ((c1 > c2) << 1) - 1; } /* Both length and characters must be equal. */ return 0; } #endif /* COMPILE_PCRE32 */ /* The following two functions compares two, fixed length strings. Basically an strncmp for non 8 bit characters. Arguments: str1 first string str2 second string num size of the string Returns: 0 if both string are equal (like strcmp), 1 otherwise */ int PRIV(strncmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2, unsigned int num) { pcre_uchar c1; pcre_uchar c2; while (num-- > 0) { c1 = *str1++; c2 = *str2++; if (c1 != c2) return ((c1 > c2) << 1) - 1; } /* Both length and characters must be equal. */ return 0; } int PRIV(strncmp_uc_c8)(const pcre_uchar *str1, const char *str2, unsigned int num) { const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; pcre_uchar c1; pcre_uchar c2; while (num-- > 0) { c1 = *str1++; c2 = (pcre_uchar)*ustr2++; if (c1 != c2) return ((c1 > c2) << 1) - 1; } /* Both length and characters must be equal. */ return 0; } /* The following function returns with the length of a zero terminated string. Basically an strlen for non 8 bit characters. Arguments: str string Returns: length of the string */ unsigned int PRIV(strlen_uc)(const pcre_uchar *str) { unsigned int len = 0; while (*str++ != 0) len++; return len; } #endif /* !COMPILE_PCRE8 */ /* End of pcre_string_utils.c */ ================================================ FILE: src/pcre/pcre_stringpiece.cc ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: wilsonh@google.com (Wilson Hsieh) // #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "pcrecpp_internal.h" #include "pcre_stringpiece.h" std::ostream& operator<<(std::ostream& o, const pcrecpp::StringPiece& piece) { return (o << piece.as_string()); } ================================================ FILE: src/pcre/pcre_stringpiece.h.in ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat // // A string like object that points into another piece of memory. // Useful for providing an interface that allows clients to easily // pass in either a "const char*" or a "string". // // Arghh! I wish C++ literals were automatically of type "string". #ifndef _PCRE_STRINGPIECE_H #define _PCRE_STRINGPIECE_H #include #include #include // for ostream forward-declaration #if @pcre_have_type_traits@ #define HAVE_TYPE_TRAITS #include #elif @pcre_have_bits_type_traits@ #define HAVE_TYPE_TRAITS #include #endif #include namespace pcrecpp { using std::memcmp; using std::strlen; using std::string; class PCRECPP_EXP_DEFN StringPiece { private: const char* ptr_; int length_; public: // We provide non-explicit singleton constructors so users can pass // in a "const char*" or a "string" wherever a "StringPiece" is // expected. StringPiece() : ptr_(NULL), length_(0) { } StringPiece(const char* str) : ptr_(str), length_(static_cast(strlen(ptr_))) { } StringPiece(const unsigned char* str) : ptr_(reinterpret_cast(str)), length_(static_cast(strlen(ptr_))) { } StringPiece(const string& str) : ptr_(str.data()), length_(static_cast(str.size())) { } StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { } // data() may return a pointer to a buffer with embedded NULs, and the // returned buffer may or may not be null terminated. Therefore it is // typically a mistake to pass data() to a routine that expects a NUL // terminated string. Use "as_string().c_str()" if you really need to do // this. Or better yet, change your routine so it does not rely on NUL // termination. const char* data() const { return ptr_; } int size() const { return length_; } bool empty() const { return length_ == 0; } void clear() { ptr_ = NULL; length_ = 0; } void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; } void set(const char* str) { ptr_ = str; length_ = static_cast(strlen(str)); } void set(const void* buffer, int len) { ptr_ = reinterpret_cast(buffer); length_ = len; } char operator[](int i) const { return ptr_[i]; } void remove_prefix(int n) { ptr_ += n; length_ -= n; } void remove_suffix(int n) { length_ -= n; } bool operator==(const StringPiece& x) const { return ((length_ == x.length_) && (memcmp(ptr_, x.ptr_, length_) == 0)); } bool operator!=(const StringPiece& x) const { return !(*this == x); } #define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp) \ bool operator cmp (const StringPiece& x) const { \ int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \ return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_))); \ } STRINGPIECE_BINARY_PREDICATE(<, <); STRINGPIECE_BINARY_PREDICATE(<=, <); STRINGPIECE_BINARY_PREDICATE(>=, >); STRINGPIECE_BINARY_PREDICATE(>, >); #undef STRINGPIECE_BINARY_PREDICATE int compare(const StringPiece& x) const { int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); if (r == 0) { if (length_ < x.length_) r = -1; else if (length_ > x.length_) r = +1; } return r; } string as_string() const { return string(data(), size()); } void CopyToString(string* target) const { target->assign(ptr_, length_); } // Does "this" start with "x" bool starts_with(const StringPiece& x) const { return ((length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0)); } }; } // namespace pcrecpp // ------------------------------------------------------------------ // Functions used to create STL containers that use StringPiece // Remember that a StringPiece's lifetime had better be less than // that of the underlying string or char*. If it is not, then you // cannot safely store a StringPiece into an STL container // ------------------------------------------------------------------ #ifdef HAVE_TYPE_TRAITS // This makes vector really fast for some STL implementations template<> struct __type_traits { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type; }; #endif // allow StringPiece to be logged PCRECPP_EXP_DECL std::ostream& operator<<(std::ostream& o, const pcrecpp::StringPiece& piece); #endif /* _PCRE_STRINGPIECE_H */ ================================================ FILE: src/pcre/pcre_stringpiece_unittest.cc ================================================ // Copyright 2003 and onwards Google Inc. // Author: Sanjay Ghemawat #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include // for make_pair #include "pcrecpp.h" #include "pcre_stringpiece.h" // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. Therefore, it is safe to do things like: // CHECK(fp->Write(x) == 4) #define CHECK(condition) do { \ if (!(condition)) { \ fprintf(stderr, "%s:%d: Check failed: %s\n", \ __FILE__, __LINE__, #condition); \ exit(1); \ } \ } while (0) using std::string; using pcrecpp::StringPiece; static void CheckSTLComparator() { string s1("foo"); string s2("bar"); string s3("baz"); StringPiece p1(s1); StringPiece p2(s2); StringPiece p3(s3); typedef std::map TestMap; TestMap map; map.insert(std::make_pair(p1, 0)); map.insert(std::make_pair(p2, 1)); map.insert(std::make_pair(p3, 2)); CHECK(map.size() == 3); TestMap::const_iterator iter = map.begin(); CHECK(iter->second == 1); ++iter; CHECK(iter->second == 2); ++iter; CHECK(iter->second == 0); ++iter; CHECK(iter == map.end()); TestMap::iterator new_iter = map.find("zot"); CHECK(new_iter == map.end()); new_iter = map.find("bar"); CHECK(new_iter != map.end()); map.erase(new_iter); CHECK(map.size() == 2); iter = map.begin(); CHECK(iter->second == 2); ++iter; CHECK(iter->second == 0); ++iter; CHECK(iter == map.end()); } static void CheckComparisonOperators() { #define CMP_Y(op, x, y) \ CHECK( (StringPiece((x)) op StringPiece((y)))); \ CHECK( (StringPiece((x)).compare(StringPiece((y))) op 0)) #define CMP_N(op, x, y) \ CHECK(!(StringPiece((x)) op StringPiece((y)))); \ CHECK(!(StringPiece((x)).compare(StringPiece((y))) op 0)) CMP_Y(==, "", ""); CMP_Y(==, "a", "a"); CMP_Y(==, "aa", "aa"); CMP_N(==, "a", ""); CMP_N(==, "", "a"); CMP_N(==, "a", "b"); CMP_N(==, "a", "aa"); CMP_N(==, "aa", "a"); CMP_N(!=, "", ""); CMP_N(!=, "a", "a"); CMP_N(!=, "aa", "aa"); CMP_Y(!=, "a", ""); CMP_Y(!=, "", "a"); CMP_Y(!=, "a", "b"); CMP_Y(!=, "a", "aa"); CMP_Y(!=, "aa", "a"); CMP_Y(<, "a", "b"); CMP_Y(<, "a", "aa"); CMP_Y(<, "aa", "b"); CMP_Y(<, "aa", "bb"); CMP_N(<, "a", "a"); CMP_N(<, "b", "a"); CMP_N(<, "aa", "a"); CMP_N(<, "b", "aa"); CMP_N(<, "bb", "aa"); CMP_Y(<=, "a", "a"); CMP_Y(<=, "a", "b"); CMP_Y(<=, "a", "aa"); CMP_Y(<=, "aa", "b"); CMP_Y(<=, "aa", "bb"); CMP_N(<=, "b", "a"); CMP_N(<=, "aa", "a"); CMP_N(<=, "b", "aa"); CMP_N(<=, "bb", "aa"); CMP_N(>=, "a", "b"); CMP_N(>=, "a", "aa"); CMP_N(>=, "aa", "b"); CMP_N(>=, "aa", "bb"); CMP_Y(>=, "a", "a"); CMP_Y(>=, "b", "a"); CMP_Y(>=, "aa", "a"); CMP_Y(>=, "b", "aa"); CMP_Y(>=, "bb", "aa"); CMP_N(>, "a", "a"); CMP_N(>, "a", "b"); CMP_N(>, "a", "aa"); CMP_N(>, "aa", "b"); CMP_N(>, "aa", "bb"); CMP_Y(>, "b", "a"); CMP_Y(>, "aa", "a"); CMP_Y(>, "b", "aa"); CMP_Y(>, "bb", "aa"); #undef CMP_Y #undef CMP_N } int main(int argc, char** argv) { (void)argc; (void)argv; CheckComparisonOperators(); CheckSTLComparator(); printf("OK\n"); return 0; } ================================================ FILE: src/pcre/pcre_study.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_study(), along with local supporting functions. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" #define SET_BIT(c) start_bits[c/8] |= (1 << (c&7)) /* Returns from set_start_bits() */ enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN }; /************************************************* * Find the minimum subject length for a group * *************************************************/ /* Scan a parenthesized group and compute the minimum length of subject that is needed to match it. This is a lower bound; it does not mean there is a string of that length that matches. In UTF8 mode, the result is in characters rather than bytes. Arguments: re compiled pattern block code pointer to start of group (the bracket) startcode pointer to start of the whole pattern's code options the compiling options recurses chain of recurse_check to catch mutual recursion countptr pointer to call count (to catch over complexity) Returns: the minimum length -1 if \C in UTF-8 mode or (*ACCEPT) was encountered -2 internal error (missing capturing bracket) -3 internal error (opcode not listed) */ static int find_minlength(const REAL_PCRE *re, const pcre_uchar *code, const pcre_uchar *startcode, int options, recurse_check *recurses, int *countptr) { int length = -1; /* PCRE_UTF16 has the same value as PCRE_UTF8. */ BOOL utf = (options & PCRE_UTF8) != 0; BOOL had_recurse = FALSE; recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; if ((*countptr)++ > 1000) return -1; /* too complex */ if (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; /* Scan along the opcodes for this branch. If we get to the end of the branch, check the length against that of the other branches. */ for (;;) { int d, min; pcre_uchar *cs, *ce; register pcre_uchar op = *cc; switch (op) { case OP_COND: case OP_SCOND: /* If there is only one branch in a condition, the implied branch has zero length, so we don't add anything. This covers the DEFINE "condition" automatically. */ cs = cc + GET(cc, 1); if (*cs != OP_ALT) { cc = cs + 1 + LINK_SIZE; break; } /* Otherwise we can fall through and treat it the same as any other subpattern. */ case OP_CBRA: case OP_SCBRA: case OP_BRA: case OP_SBRA: case OP_CBRAPOS: case OP_SCBRAPOS: case OP_BRAPOS: case OP_SBRAPOS: case OP_ONCE: case OP_ONCE_NC: d = find_minlength(re, cc, startcode, options, recurses, countptr); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); cc += 1 + LINK_SIZE; break; /* ACCEPT makes things far too complicated; we have to give up. */ case OP_ACCEPT: case OP_ASSERT_ACCEPT: return -1; /* Reached end of a branch; if it's a ket it is the end of a nested call. If it's ALT it is an alternation in a nested call. If it is END it's the end of the outer call. All can be handled by the same code. If an ACCEPT was previously encountered, use the length that was in force at that time, and pass back the shortest ACCEPT length. */ case OP_ALT: case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_KETRPOS: case OP_END: if (length < 0 || (!had_recurse && branchlength < length)) length = branchlength; if (op != OP_ALT) return length; cc += 1 + LINK_SIZE; branchlength = 0; had_recurse = FALSE; break; /* Skip over assertive subpatterns */ case OP_ASSERT: case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += GET(cc, 1); while (*cc == OP_ALT); /* Fall through */ /* Skip over things that don't match chars */ case OP_REVERSE: case OP_CREF: case OP_DNCREF: case OP_RREF: case OP_DNRREF: case OP_DEF: case OP_CALLOUT: case OP_SOD: case OP_SOM: case OP_EOD: case OP_EODN: case OP_CIRC: case OP_CIRCM: case OP_DOLL: case OP_DOLLM: case OP_NOT_WORD_BOUNDARY: case OP_WORD_BOUNDARY: cc += PRIV(OP_lengths)[*cc]; break; /* Skip over a subpattern that has a {0} or {0,x} quantifier */ case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: case OP_SKIPZERO: cc += PRIV(OP_lengths)[*cc]; do cc += GET(cc, 1); while (*cc == OP_ALT); cc += 1 + LINK_SIZE; break; /* Handle literal characters and + repetitions */ case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_PLUS: case OP_PLUSI: case OP_MINPLUS: case OP_MINPLUSI: case OP_POSPLUS: case OP_POSPLUSI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: branchlength++; cc += 2; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEPOSPLUS: branchlength++; cc += (cc[1] == OP_PROP || cc[1] == OP_NOTPROP)? 4 : 2; break; /* Handle exact repetitions. The count is already in characters, but we need to skip over a multibyte character in UTF8 mode. */ case OP_EXACT: case OP_EXACTI: case OP_NOTEXACT: case OP_NOTEXACTI: branchlength += GET2(cc,1); cc += 2 + IMM2_SIZE; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; case OP_TYPEEXACT: branchlength += GET2(cc,1); cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0); break; /* Handle single-char non-literal matchers */ case OP_PROP: case OP_NOTPROP: cc += 2; /* Fall through */ case OP_NOT_DIGIT: case OP_DIGIT: case OP_NOT_WHITESPACE: case OP_WHITESPACE: case OP_NOT_WORDCHAR: case OP_WORDCHAR: case OP_ANY: case OP_ALLANY: case OP_EXTUNI: case OP_HSPACE: case OP_NOT_HSPACE: case OP_VSPACE: case OP_NOT_VSPACE: branchlength++; cc++; break; /* "Any newline" might match two characters, but it also might match just one. */ case OP_ANYNL: branchlength += 1; cc++; break; /* The single-byte matcher means we can't proceed in UTF-8 mode. (In non-UTF-8 mode \C will actually be turned into OP_ALLANY, so won't ever appear, but leave the code, just in case.) */ case OP_ANYBYTE: #ifdef SUPPORT_UTF if (utf) return -1; #endif branchlength++; cc++; break; /* For repeated character types, we have to test for \p and \P, which have an extra two bytes of parameters. */ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSSTAR: case OP_TYPEPOSQUERY: if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2; cc += PRIV(OP_lengths)[op]; break; case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO: if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2; cc += PRIV(OP_lengths)[op]; break; /* Check a class for variable quantification */ case OP_CLASS: case OP_NCLASS: #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 case OP_XCLASS: /* The original code caused an unsigned overflow in 64 bit systems, so now we use a conditional statement. */ if (op == OP_XCLASS) cc += GET(cc, 1); else cc += PRIV(OP_lengths)[OP_CLASS]; #else cc += PRIV(OP_lengths)[OP_CLASS]; #endif switch (*cc) { case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRPOSPLUS: branchlength++; /* Fall through */ case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSQUERY: cc++; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: branchlength += GET2(cc,1); cc += 1 + 2 * IMM2_SIZE; break; default: branchlength++; break; } break; /* Backreferences and subroutine calls are treated in the same way: we find the minimum length for the subpattern. A recursion, however, causes an a flag to be set that causes the length of this branch to be ignored. The logic is that a recursion can only make sense if there is another alternation that stops the recursing. That will provide the minimum length (when no recursion happens). A backreference within the group that it is referencing behaves in the same way. If PCRE_JAVASCRIPT_COMPAT is set, a backreference to an unset bracket matches an empty string (by default it causes a matching failure), so in that case we must set the minimum length to zero. */ case OP_DNREF: /* Duplicate named pattern back reference */ case OP_DNREFI: if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) { int count = GET2(cc, 1+IMM2_SIZE); pcre_uchar *slot = (pcre_uchar *)re + re->name_table_offset + GET2(cc, 1) * re->name_entry_size; d = INT_MAX; while (count-- > 0) { ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0)); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); if (cc > cs && cc < ce) /* Simple recursion */ { d = 0; had_recurse = TRUE; break; } else { recurse_check *r = recurses; for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; if (r != NULL) /* Mutual recursion */ { d = 0; had_recurse = TRUE; break; } else { int dd; this_recurse.prev = recurses; this_recurse.group = cs; dd = find_minlength(re, cs, startcode, options, &this_recurse, countptr); if (dd < d) d = dd; } } slot += re->name_entry_size; } } else d = 0; cc += 1 + 2*IMM2_SIZE; goto REPEAT_BACK_REFERENCE; case OP_REF: /* Single back reference */ case OP_REFI: if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) { ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1)); if (cs == NULL) return -2; do ce += GET(ce, 1); while (*ce == OP_ALT); if (cc > cs && cc < ce) /* Simple recursion */ { d = 0; had_recurse = TRUE; } else { recurse_check *r = recurses; for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; if (r != NULL) /* Mutual recursion */ { d = 0; had_recurse = TRUE; } else { this_recurse.prev = recurses; this_recurse.group = cs; d = find_minlength(re, cs, startcode, options, &this_recurse, countptr); } } } else d = 0; cc += 1 + IMM2_SIZE; /* Handle repeated back references */ REPEAT_BACK_REFERENCE: switch (*cc) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSQUERY: min = 0; cc++; break; case OP_CRPLUS: case OP_CRMINPLUS: case OP_CRPOSPLUS: min = 1; cc++; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: min = GET2(cc, 1); cc += 1 + 2 * IMM2_SIZE; break; default: min = 1; break; } branchlength += min * d; break; /* We can easily detect direct recursion, but not mutual recursion. This is caught by a recursion depth count. */ case OP_RECURSE: cs = ce = (pcre_uchar *)startcode + GET(cc, 1); do ce += GET(ce, 1); while (*ce == OP_ALT); if (cc > cs && cc < ce) /* Simple recursion */ had_recurse = TRUE; else { recurse_check *r = recurses; for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break; if (r != NULL) /* Mutual recursion */ had_recurse = TRUE; else { this_recurse.prev = recurses; this_recurse.group = cs; branchlength += find_minlength(re, cs, startcode, options, &this_recurse, countptr); } } cc += 1 + LINK_SIZE; break; /* Anything else does not or need not match a character. We can get the item's length from the table, but for those that can match zero occurrences of a character, we must take special action for UTF-8 characters. As it happens, the "NOT" versions of these opcodes are used at present only for ASCII characters, so they could be omitted from this list. However, in future that may change, so we include them here so as not to leave a gotcha for a future maintainer. */ case OP_UPTO: case OP_UPTOI: case OP_NOTUPTO: case OP_NOTUPTOI: case OP_MINUPTO: case OP_MINUPTOI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: case OP_POSUPTO: case OP_POSUPTOI: case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: case OP_STAR: case OP_STARI: case OP_NOTSTAR: case OP_NOTSTARI: case OP_MINSTAR: case OP_MINSTARI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_POSSTAR: case OP_POSSTARI: case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: case OP_QUERY: case OP_QUERYI: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_MINQUERY: case OP_MINQUERYI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: case OP_POSQUERY: case OP_POSQUERYI: case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: cc += PRIV(OP_lengths)[op]; #ifdef SUPPORT_UTF if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif break; /* Skip these, but we need to add in the name length. */ case OP_MARK: case OP_PRUNE_ARG: case OP_SKIP_ARG: case OP_THEN_ARG: cc += PRIV(OP_lengths)[op] + cc[1]; break; /* The remaining opcodes are just skipped over. */ case OP_CLOSE: case OP_COMMIT: case OP_FAIL: case OP_PRUNE: case OP_SET_SOM: case OP_SKIP: case OP_THEN: cc += PRIV(OP_lengths)[op]; break; /* This should not occur: we list all opcodes explicitly so that when new ones get added they are properly considered. */ default: return -3; } } /* Control never gets here */ } /************************************************* * Set a bit and maybe its alternate case * *************************************************/ /* Given a character, set its first byte's bit in the table, and also the corresponding bit for the other version of a letter if we are caseless. In UTF-8 mode, for characters greater than 127, we can only do the caseless thing when Unicode property support is available. Arguments: start_bits points to the bit map p points to the character caseless the caseless flag cd the block with char table pointers utf TRUE for UTF-8 / UTF-16 / UTF-32 mode Returns: pointer after the character */ static const pcre_uchar * set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless, compile_data *cd, BOOL utf) { pcre_uint32 c = *p; #ifdef COMPILE_PCRE8 SET_BIT(c); #ifdef SUPPORT_UTF if (utf && c > 127) { GETCHARINC(c, p); #ifdef SUPPORT_UCP if (caseless) { pcre_uchar buff[6]; c = UCD_OTHERCASE(c); (void)PRIV(ord2utf)(c, buff); SET_BIT(buff[0]); } #endif /* Not SUPPORT_UCP */ return p; } #else /* Not SUPPORT_UTF */ (void)(utf); /* Stops warning for unused parameter */ #endif /* SUPPORT_UTF */ /* Not UTF-8 mode, or character is less than 127. */ if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]); return p + 1; #endif /* COMPILE_PCRE8 */ #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 if (c > 0xff) { c = 0xff; caseless = FALSE; } SET_BIT(c); #ifdef SUPPORT_UTF if (utf && c > 127) { GETCHARINC(c, p); #ifdef SUPPORT_UCP if (caseless) { c = UCD_OTHERCASE(c); if (c > 0xff) c = 0xff; SET_BIT(c); } #endif /* SUPPORT_UCP */ return p; } #else /* Not SUPPORT_UTF */ (void)(utf); /* Stops warning for unused parameter */ #endif /* SUPPORT_UTF */ if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]); return p + 1; #endif } /************************************************* * Set bits for a positive character type * *************************************************/ /* This function sets starting bits for a character type. In UTF-8 mode, we can only do a direct setting for bytes less than 128, as otherwise there can be confusion with bytes in the middle of UTF-8 characters. In a "traditional" environment, the tables will only recognize ASCII characters anyway, but in at least one Windows environment, some higher bytes bits were set in the tables. So we deal with that case by considering the UTF-8 encoding. Arguments: start_bits the starting bitmap cbit type the type of character wanted table_limit 32 for non-UTF-8; 16 for UTF-8 cd the block with char table pointers Returns: nothing */ static void set_type_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit, compile_data *cd) { register pcre_uint32 c; for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type]; #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (table_limit == 32) return; for (c = 128; c < 256; c++) { if ((cd->cbits[c/8] & (1 << (c&7))) != 0) { pcre_uchar buff[6]; (void)PRIV(ord2utf)(c, buff); SET_BIT(buff[0]); } } #endif } /************************************************* * Set bits for a negative character type * *************************************************/ /* This function sets starting bits for a negative character type such as \D. In UTF-8 mode, we can only do a direct setting for bytes less than 128, as otherwise there can be confusion with bytes in the middle of UTF-8 characters. Unlike in the positive case, where we can set appropriate starting bits for specific high-valued UTF-8 characters, in this case we have to set the bits for all high-valued characters. The lowest is 0xc2, but we overkill by starting at 0xc0 (192) for simplicity. Arguments: start_bits the starting bitmap cbit type the type of character wanted table_limit 32 for non-UTF-8; 16 for UTF-8 cd the block with char table pointers Returns: nothing */ static void set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit, compile_data *cd) { register pcre_uint32 c; for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type]; #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff; #endif } /************************************************* * Create bitmap of starting bytes * *************************************************/ /* This function scans a compiled unanchored expression recursively and attempts to build a bitmap of the set of possible starting bytes. As time goes by, we may be able to get more clever at doing this. The SSB_CONTINUE return is useful for parenthesized groups in patterns such as (a*)b where the group provides some optional starting bytes but scanning must continue at the outer level to find at least one mandatory byte. At the outermost level, this function fails unless the result is SSB_DONE. Arguments: code points to an expression start_bits points to a 32-byte table, initialized to 0 utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode cd the block with char table pointers Returns: SSB_FAIL => Failed to find any starting bytes SSB_DONE => Found mandatory starting bytes SSB_CONTINUE => Found optional starting bytes SSB_UNKNOWN => Hit an unrecognized opcode */ static int set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf, compile_data *cd) { register pcre_uint32 c; int yield = SSB_DONE; #if defined SUPPORT_UTF && defined COMPILE_PCRE8 int table_limit = utf? 16:32; #else int table_limit = 32; #endif #if 0 /* ========================================================================= */ /* The following comment and code was inserted in January 1999. In May 2006, when it was observed to cause compiler warnings about unused values, I took it out again. If anybody is still using OS/2, they will have to put it back manually. */ /* This next statement and the later reference to dummy are here in order to trick the optimizer of the IBM C compiler for OS/2 into generating correct code. Apparently IBM isn't going to fix the problem, and we would rather not disable optimization (in this module it actually makes a big difference, and the pcre module can use all the optimization it can get). */ volatile int dummy; /* ========================================================================= */ #endif do { BOOL try_next = TRUE; const pcre_uchar *tcode = code + 1 + LINK_SIZE; if (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE; while (try_next) /* Loop for items in this branch */ { int rc; switch(*tcode) { /* If we reach something we don't understand, it means a new opcode has been created that hasn't been added to this code. Hopefully this problem will be discovered during testing. */ default: return SSB_UNKNOWN; /* Fail for a valid opcode that implies no starting bits. */ case OP_ACCEPT: case OP_ASSERT_ACCEPT: case OP_ALLANY: case OP_ANY: case OP_ANYBYTE: case OP_CIRC: case OP_CIRCM: case OP_CLOSE: case OP_COMMIT: case OP_COND: case OP_CREF: case OP_DEF: case OP_DNCREF: case OP_DNREF: case OP_DNREFI: case OP_DNRREF: case OP_DOLL: case OP_DOLLM: case OP_END: case OP_EOD: case OP_EODN: case OP_EXTUNI: case OP_FAIL: case OP_MARK: case OP_NOT: case OP_NOTEXACT: case OP_NOTEXACTI: case OP_NOTI: case OP_NOTMINPLUS: case OP_NOTMINPLUSI: case OP_NOTMINQUERY: case OP_NOTMINQUERYI: case OP_NOTMINSTAR: case OP_NOTMINSTARI: case OP_NOTMINUPTO: case OP_NOTMINUPTOI: case OP_NOTPLUS: case OP_NOTPLUSI: case OP_NOTPOSPLUS: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERY: case OP_NOTPOSQUERYI: case OP_NOTPOSSTAR: case OP_NOTPOSSTARI: case OP_NOTPOSUPTO: case OP_NOTPOSUPTOI: case OP_NOTPROP: case OP_NOTQUERY: case OP_NOTQUERYI: case OP_NOTSTAR: case OP_NOTSTARI: case OP_NOTUPTO: case OP_NOTUPTOI: case OP_NOT_HSPACE: case OP_NOT_VSPACE: case OP_PRUNE: case OP_PRUNE_ARG: case OP_RECURSE: case OP_REF: case OP_REFI: case OP_REVERSE: case OP_RREF: case OP_SCOND: case OP_SET_SOM: case OP_SKIP: case OP_SKIP_ARG: case OP_SOD: case OP_SOM: case OP_THEN: case OP_THEN_ARG: return SSB_FAIL; /* A "real" property test implies no starting bits, but the fake property PT_CLIST identifies a list of characters. These lists are short, as they are used for characters with more than one "other case", so there is no point in recognizing them for OP_NOTPROP. */ case OP_PROP: if (tcode[1] != PT_CLIST) return SSB_FAIL; { const pcre_uint32 *p = PRIV(ucd_caseless_sets) + tcode[2]; while ((c = *p++) < NOTACHAR) { #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (utf) { pcre_uchar buff[6]; (void)PRIV(ord2utf)(c, buff); c = buff[0]; } #endif if (c > 0xff) SET_BIT(0xff); else SET_BIT(c); } } try_next = FALSE; break; /* We can ignore word boundary tests. */ case OP_WORD_BOUNDARY: case OP_NOT_WORD_BOUNDARY: tcode++; break; /* If we hit a bracket or a positive lookahead assertion, recurse to set bits from within the subpattern. If it can't find anything, we have to give up. If it finds some mandatory character(s), we are done for this branch. Otherwise, carry on scanning after the subpattern. */ case OP_BRA: case OP_SBRA: case OP_CBRA: case OP_SCBRA: case OP_BRAPOS: case OP_SBRAPOS: case OP_CBRAPOS: case OP_SCBRAPOS: case OP_ONCE: case OP_ONCE_NC: case OP_ASSERT: rc = set_start_bits(tcode, start_bits, utf, cd); if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; if (rc == SSB_DONE) try_next = FALSE; else { do tcode += GET(tcode, 1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; } break; /* If we hit ALT or KET, it means we haven't found anything mandatory in this branch, though we might have found something optional. For ALT, we continue with the next alternative, but we have to arrange that the final result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET, return SSB_CONTINUE: if this is the top level, that indicates failure, but after a nested subpattern, it causes scanning to continue. */ case OP_ALT: yield = SSB_CONTINUE; try_next = FALSE; break; case OP_KET: case OP_KETRMAX: case OP_KETRMIN: case OP_KETRPOS: return SSB_CONTINUE; /* Skip over callout */ case OP_CALLOUT: tcode += 2 + 2*LINK_SIZE; break; /* Skip over lookbehind and negative lookahead assertions */ case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do tcode += GET(tcode, 1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; break; /* BRAZERO does the bracket, but carries on. */ case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: rc = set_start_bits(++tcode, start_bits, utf, cd); if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; /* ========================================================================= See the comment at the head of this function concerning the next line, which was an old fudge for the benefit of OS/2. dummy = 1; ========================================================================= */ do tcode += GET(tcode,1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; break; /* SKIPZERO skips the bracket. */ case OP_SKIPZERO: tcode++; do tcode += GET(tcode,1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; break; /* Single-char * or ? sets the bit and tries the next item */ case OP_STAR: case OP_MINSTAR: case OP_POSSTAR: case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY: tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf); break; case OP_STARI: case OP_MINSTARI: case OP_POSSTARI: case OP_QUERYI: case OP_MINQUERYI: case OP_POSQUERYI: tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf); break; /* Single-char upto sets the bit and tries the next */ case OP_UPTO: case OP_MINUPTO: case OP_POSUPTO: tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf); break; case OP_UPTOI: case OP_MINUPTOI: case OP_POSUPTOI: tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf); break; /* At least one single char sets the bit and stops */ case OP_EXACT: tcode += IMM2_SIZE; /* Fall through */ case OP_CHAR: case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: (void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf); try_next = FALSE; break; case OP_EXACTI: tcode += IMM2_SIZE; /* Fall through */ case OP_CHARI: case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf); try_next = FALSE; break; /* Special spacing and line-terminating items. These recognize specific lists of characters. The difference between VSPACE and ANYNL is that the latter can match the two-character CRLF sequence, but that is not relevant for finding the first character, so their code here is identical. */ case OP_HSPACE: SET_BIT(CHAR_HT); SET_BIT(CHAR_SPACE); #ifdef SUPPORT_UTF if (utf) { #ifdef COMPILE_PCRE8 SET_BIT(0xC2); /* For U+00A0 */ SET_BIT(0xE1); /* For U+1680, U+180E */ SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */ SET_BIT(0xE3); /* For U+3000 */ #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(0xA0); SET_BIT(0xFF); /* For characters > 255 */ #endif /* COMPILE_PCRE[8|16|32] */ } else #endif /* SUPPORT_UTF */ { #ifndef EBCDIC SET_BIT(0xA0); #endif /* Not EBCDIC */ #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(0xFF); /* For characters > 255 */ #endif /* COMPILE_PCRE[16|32] */ } try_next = FALSE; break; case OP_ANYNL: case OP_VSPACE: SET_BIT(CHAR_LF); SET_BIT(CHAR_VT); SET_BIT(CHAR_FF); SET_BIT(CHAR_CR); #ifdef SUPPORT_UTF if (utf) { #ifdef COMPILE_PCRE8 SET_BIT(0xC2); /* For U+0085 */ SET_BIT(0xE2); /* For U+2028, U+2029 */ #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(CHAR_NEL); SET_BIT(0xFF); /* For characters > 255 */ #endif /* COMPILE_PCRE[8|16|32] */ } else #endif /* SUPPORT_UTF */ { SET_BIT(CHAR_NEL); #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(0xFF); /* For characters > 255 */ #endif } try_next = FALSE; break; /* Single character types set the bits and stop. Note that if PCRE_UCP is set, we do not see these op codes because \d etc are converted to properties. Therefore, these apply in the case when only characters less than 256 are recognized to match the types. */ case OP_NOT_DIGIT: set_nottype_bits(start_bits, cbit_digit, table_limit, cd); try_next = FALSE; break; case OP_DIGIT: set_type_bits(start_bits, cbit_digit, table_limit, cd); try_next = FALSE; break; /* The cbit_space table has vertical tab as whitespace; we no longer have to play fancy tricks because Perl added VT to its whitespace at release 5.18. PCRE added it at release 8.34. */ case OP_NOT_WHITESPACE: set_nottype_bits(start_bits, cbit_space, table_limit, cd); try_next = FALSE; break; case OP_WHITESPACE: set_type_bits(start_bits, cbit_space, table_limit, cd); try_next = FALSE; break; case OP_NOT_WORDCHAR: set_nottype_bits(start_bits, cbit_word, table_limit, cd); try_next = FALSE; break; case OP_WORDCHAR: set_type_bits(start_bits, cbit_word, table_limit, cd); try_next = FALSE; break; /* One or more character type fudges the pointer and restarts, knowing it will hit a single character type and stop there. */ case OP_TYPEPLUS: case OP_TYPEMINPLUS: case OP_TYPEPOSPLUS: tcode++; break; case OP_TYPEEXACT: tcode += 1 + IMM2_SIZE; break; /* Zero or more repeats of character types set the bits and then try again. */ case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO: tcode += IMM2_SIZE; /* Fall through */ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPOSSTAR: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSQUERY: switch(tcode[1]) { default: case OP_ANY: case OP_ALLANY: return SSB_FAIL; case OP_HSPACE: SET_BIT(CHAR_HT); SET_BIT(CHAR_SPACE); #ifdef SUPPORT_UTF if (utf) { #ifdef COMPILE_PCRE8 SET_BIT(0xC2); /* For U+00A0 */ SET_BIT(0xE1); /* For U+1680, U+180E */ SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */ SET_BIT(0xE3); /* For U+3000 */ #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(0xA0); SET_BIT(0xFF); /* For characters > 255 */ #endif /* COMPILE_PCRE[8|16|32] */ } else #endif /* SUPPORT_UTF */ #ifndef EBCDIC SET_BIT(0xA0); #endif /* Not EBCDIC */ break; case OP_ANYNL: case OP_VSPACE: SET_BIT(CHAR_LF); SET_BIT(CHAR_VT); SET_BIT(CHAR_FF); SET_BIT(CHAR_CR); #ifdef SUPPORT_UTF if (utf) { #ifdef COMPILE_PCRE8 SET_BIT(0xC2); /* For U+0085 */ SET_BIT(0xE2); /* For U+2028, U+2029 */ #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(CHAR_NEL); SET_BIT(0xFF); /* For characters > 255 */ #endif /* COMPILE_PCRE16 */ } else #endif /* SUPPORT_UTF */ SET_BIT(CHAR_NEL); break; case OP_NOT_DIGIT: set_nottype_bits(start_bits, cbit_digit, table_limit, cd); break; case OP_DIGIT: set_type_bits(start_bits, cbit_digit, table_limit, cd); break; /* The cbit_space table has vertical tab as whitespace; we no longer have to play fancy tricks because Perl added VT to its whitespace at release 5.18. PCRE added it at release 8.34. */ case OP_NOT_WHITESPACE: set_nottype_bits(start_bits, cbit_space, table_limit, cd); break; case OP_WHITESPACE: set_type_bits(start_bits, cbit_space, table_limit, cd); break; case OP_NOT_WORDCHAR: set_nottype_bits(start_bits, cbit_word, table_limit, cd); break; case OP_WORDCHAR: set_type_bits(start_bits, cbit_word, table_limit, cd); break; } tcode += 2; break; /* Character class where all the information is in a bit map: set the bits and either carry on or not, according to the repeat count. If it was a negative class, and we are operating with UTF-8 characters, any byte with a value >= 0xc4 is a potentially valid starter because it starts a character with a value > 255. */ #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 case OP_XCLASS: if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0) return SSB_FAIL; /* All bits are set. */ if ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0 && (tcode[1 + LINK_SIZE] & XCL_NOT) != 0) return SSB_FAIL; #endif /* Fall through */ case OP_NCLASS: #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (utf) { start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ } #endif #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 SET_BIT(0xFF); /* For characters > 255 */ #endif /* Fall through */ case OP_CLASS: { pcre_uint8 *map; #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 map = NULL; if (*tcode == OP_XCLASS) { if ((tcode[1 + LINK_SIZE] & XCL_MAP) != 0) map = (pcre_uint8 *)(tcode + 1 + LINK_SIZE + 1); tcode += GET(tcode, 1); } else #endif { tcode++; map = (pcre_uint8 *)tcode; tcode += 32 / sizeof(pcre_uchar); } /* In UTF-8 mode, the bits in a bit map correspond to character values, not to byte values. However, the bit map we are constructing is for byte values. So we have to do a conversion for characters whose value is > 127. In fact, there are only two possible starting bytes for characters in the range 128 - 255. */ #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 if (map != NULL) #endif { #if defined SUPPORT_UTF && defined COMPILE_PCRE8 if (utf) { for (c = 0; c < 16; c++) start_bits[c] |= map[c]; for (c = 128; c < 256; c++) { if ((map[c/8] & (1 << (c&7))) != 0) { int d = (c >> 6) | 0xc0; /* Set bit for this starter */ start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */ } } } else #endif { /* In non-UTF-8 mode, the two bit maps are completely compatible. */ for (c = 0; c < 32; c++) start_bits[c] |= map[c]; } } /* Advance past the bit map, and act on what follows. For a zero minimum repeat, continue; otherwise stop processing. */ switch (*tcode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: case OP_CRPOSSTAR: case OP_CRPOSQUERY: tcode++; break; case OP_CRRANGE: case OP_CRMINRANGE: case OP_CRPOSRANGE: if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE; else try_next = FALSE; break; default: try_next = FALSE; break; } } break; /* End of bitmap class handling */ } /* End of switch */ } /* End of try_next loop */ code += GET(code, 1); /* Advance to next branch */ } while (*code == OP_ALT); return yield; } /************************************************* * Study a compiled expression * *************************************************/ /* This function is handed a compiled expression that it must study to produce information that will speed up the matching. It returns a pcre[16]_extra block which then gets handed back to pcre_exec(). Arguments: re points to the compiled expression options contains option bits errorptr points to where to place error messages; set NULL unless error Returns: pointer to a pcre[16]_extra block, with study_data filled in and the appropriate flags set; NULL on error or if no optimization possible */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION pcre_study(const pcre *external_re, int options, const char **errorptr) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION pcre16_study(const pcre16 *external_re, int options, const char **errorptr) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN pcre32_extra * PCRE_CALL_CONVENTION pcre32_study(const pcre32 *external_re, int options, const char **errorptr) #endif { int min; int count = 0; BOOL bits_set = FALSE; pcre_uint8 start_bits[32]; PUBL(extra) *extra = NULL; pcre_study_data *study; const pcre_uint8 *tables; pcre_uchar *code; compile_data compile_block; const REAL_PCRE *re = (const REAL_PCRE *)external_re; *errorptr = NULL; if (re == NULL || re->magic_number != MAGIC_NUMBER) { *errorptr = "argument is not a compiled regular expression"; return NULL; } if ((re->flags & PCRE_MODE) == 0) { #if defined COMPILE_PCRE8 *errorptr = "argument not compiled in 8 bit mode"; #elif defined COMPILE_PCRE16 *errorptr = "argument not compiled in 16 bit mode"; #elif defined COMPILE_PCRE32 *errorptr = "argument not compiled in 32 bit mode"; #endif return NULL; } if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) { *errorptr = "unknown or incorrect option bit(s) set"; return NULL; } code = (pcre_uchar *)re + re->name_table_offset + (re->name_count * re->name_entry_size); /* For an anchored pattern, or an unanchored pattern that has a first char, or a multiline pattern that matches only at "line starts", there is no point in seeking a list of starting bytes. */ if ((re->options & PCRE_ANCHORED) == 0 && (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) == 0) { int rc; /* Set the character tables in the block that is passed around */ tables = re->tables; #if defined COMPILE_PCRE8 if (tables == NULL) (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, (void *)(&tables)); #elif defined COMPILE_PCRE16 if (tables == NULL) (void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, (void *)(&tables)); #elif defined COMPILE_PCRE32 if (tables == NULL) (void)pcre32_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, (void *)(&tables)); #endif compile_block.lcc = tables + lcc_offset; compile_block.fcc = tables + fcc_offset; compile_block.cbits = tables + cbits_offset; compile_block.ctypes = tables + ctypes_offset; /* See if we can find a fixed set of initial characters for the pattern. */ memset(start_bits, 0, 32 * sizeof(pcre_uint8)); rc = set_start_bits(code, start_bits, (re->options & PCRE_UTF8) != 0, &compile_block); bits_set = rc == SSB_DONE; if (rc == SSB_UNKNOWN) { *errorptr = "internal error: opcode not recognized"; return NULL; } } /* Find the minimum length of subject string. */ switch(min = find_minlength(re, code, code, re->options, NULL, &count)) { case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; case -3: *errorptr = "internal error: opcode not recognized"; return NULL; default: break; } /* If a set of starting bytes has been identified, or if the minimum length is greater than zero, or if JIT optimization has been requested, or if PCRE_STUDY_EXTRA_NEEDED is set, get a pcre[16]_extra block and a pcre_study_data block. The study data is put in the latter, which is pointed to by the former, which may also get additional data set later by the calling program. At the moment, the size of pcre_study_data is fixed. We nevertheless save it in a field for returning via the pcre_fullinfo() function so that if it becomes variable in the future, we don't have to change that code. */ if (bits_set || min > 0 || (options & ( #ifdef SUPPORT_JIT PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE | #endif PCRE_STUDY_EXTRA_NEEDED)) != 0) { extra = (PUBL(extra) *)(PUBL(malloc)) (sizeof(PUBL(extra)) + sizeof(pcre_study_data)); if (extra == NULL) { *errorptr = "failed to get memory"; return NULL; } study = (pcre_study_data *)((char *)extra + sizeof(PUBL(extra))); extra->flags = PCRE_EXTRA_STUDY_DATA; extra->study_data = study; study->size = sizeof(pcre_study_data); study->flags = 0; /* Set the start bits always, to avoid unset memory errors if the study data is written to a file, but set the flag only if any of the bits are set, to save time looking when none are. */ if (bits_set) { study->flags |= PCRE_STUDY_MAPPED; memcpy(study->start_bits, start_bits, sizeof(start_bits)); } else memset(study->start_bits, 0, 32 * sizeof(pcre_uint8)); #ifdef PCRE_DEBUG if (bits_set) { pcre_uint8 *ptr = start_bits; int i; printf("Start bits:\n"); for (i = 0; i < 32; i++) printf("%3d: %02x%s", i * 8, *ptr++, ((i + 1) & 0x7) != 0? " " : "\n"); } #endif /* Always set the minlength value in the block, because the JIT compiler makes use of it. However, don't set the bit unless the length is greater than zero - the interpretive pcre_exec() and pcre_dfa_exec() needn't waste time checking the zero case. */ if (min > 0) { study->flags |= PCRE_STUDY_MINLEN; study->minlength = min; } else study->minlength = 0; /* If JIT support was compiled and requested, attempt the JIT compilation. If no starting bytes were found, and the minimum length is zero, and JIT compilation fails, abandon the extra block and return NULL, unless PCRE_STUDY_EXTRA_NEEDED is set. */ #ifdef SUPPORT_JIT extra->executable_jit = NULL; if ((options & PCRE_STUDY_JIT_COMPILE) != 0) PRIV(jit_compile)(re, extra, JIT_COMPILE); if ((options & PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE) != 0) PRIV(jit_compile)(re, extra, JIT_PARTIAL_SOFT_COMPILE); if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0) PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE); if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0 && (options & PCRE_STUDY_EXTRA_NEEDED) == 0) { #if defined COMPILE_PCRE8 pcre_free_study(extra); #elif defined COMPILE_PCRE16 pcre16_free_study(extra); #elif defined COMPILE_PCRE32 pcre32_free_study(extra); #endif extra = NULL; } #endif } return extra; } /************************************************* * Free the study data * *************************************************/ /* This function frees the memory that was obtained by pcre_study(). Argument: a pointer to the pcre[16]_extra block Returns: nothing */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN void pcre_free_study(pcre_extra *extra) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN void pcre16_free_study(pcre16_extra *extra) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN void pcre32_free_study(pcre32_extra *extra) #endif { if (extra == NULL) return; #ifdef SUPPORT_JIT if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL) PRIV(jit_free)(extra->executable_jit); #endif PUBL(free)(extra); } /* End of pcre_study.c */ ================================================ FILE: src/pcre/pcre_tables.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2017 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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 PCRE_INCLUDED /* This module contains some fixed tables that are used by more than one of the PCRE code modules. The tables are also #included by the pcretest program, which uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name clashes with the library. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" #endif /* PCRE_INCLUDED */ /* Table of sizes for the fixed-length opcodes. It's defined in a macro so that the definition is next to the definition of the opcodes in pcre_internal.h. */ const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS }; /* Tables of horizontal and vertical whitespace characters, suitable for adding to classes. */ const pcre_uint32 PRIV(hspace_list)[] = { HSPACE_LIST }; const pcre_uint32 PRIV(vspace_list)[] = { VSPACE_LIST }; /************************************************* * Tables for UTF-8 support * *************************************************/ /* These are the breakpoints for different numbers of bytes in a UTF-8 character. */ #if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \ || (defined PCRE_INCLUDED && (defined SUPPORT_PCRE16 || defined SUPPORT_PCRE32)) /* These tables are also required by pcretest in 16- or 32-bit mode. */ const int PRIV(utf8_table1)[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int); /* These are the indicator bits and the mask for the data bits to set in the first byte of a character, indexed by the number of additional bytes. */ const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; /* Table of the number of extra bytes, indexed by the first byte masked with 0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */ const pcre_uint8 PRIV(utf8_table4)[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; #endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE[16|32])*/ #ifdef SUPPORT_UTF /* Table to translate from particular type value to the general value. */ const pcre_uint32 PRIV(ucp_gentype)[] = { ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */ ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */ ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */ ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */ ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */ ucp_P, ucp_P, /* Ps, Po */ ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */ ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */ }; /* This table encodes the rules for finding the end of an extended grapheme cluster. Every code point has a grapheme break property which is one of the ucp_gbXX values defined in ucp.h. The 2-dimensional table is indexed by the properties of two adjacent code points. The left property selects a word from the table, and the right property selects a bit from that word like this: ucp_gbtable[left-property] & (1 << right-property) The value is non-zero if a grapheme break is NOT permitted between the relevant two code points. The breaking rules are as follows: 1. Break at the start and end of text (pretty obviously). 2. Do not break between a CR and LF; otherwise, break before and after controls. 3. Do not break Hangul syllable sequences, the rules for which are: L may be followed by L, V, LV or LVT LV or V may be followed by V or T LVT or T may be followed by T 4. Do not break before extending characters. The next two rules are only for extended grapheme clusters (but that's what we are implementing). 5. Do not break before SpacingMarks. 6. Do not break after Prepend characters. 7. Otherwise, break everywhere. */ const pcre_uint32 PRIV(ucp_gbtable[]) = { (1< 0x10ffff is not permitted PCRE_UTF8_ERR14 3-byte character with value 0xd000-0xdfff is not permitted PCRE_UTF8_ERR15 Overlong 2-byte sequence PCRE_UTF8_ERR16 Overlong 3-byte sequence PCRE_UTF8_ERR17 Overlong 4-byte sequence PCRE_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur) PCRE_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur) PCRE_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character) PCRE_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff PCRE_UTF8_ERR22 Unused (was non-character) Arguments: string points to the string length length of string, or -1 if the string is zero-terminated errp pointer to an error position offset variable Returns: = 0 if the string is a valid UTF-8 string > 0 otherwise, setting the offset of the bad character */ int PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset) { #ifdef SUPPORT_UTF register PCRE_PUCHAR p; if (length < 0) { for (p = string; *p != 0; p++); length = (int)(p - string); } for (p = string; length-- > 0; p++) { register pcre_uchar ab, c, d; c = *p; if (c < 128) continue; /* ASCII character */ if (c < 0xc0) /* Isolated 10xx xxxx byte */ { *erroroffset = (int)(p - string); return PCRE_UTF8_ERR20; } if (c >= 0xfe) /* Invalid 0xfe or 0xff bytes */ { *erroroffset = (int)(p - string); return PCRE_UTF8_ERR21; } ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */ if (length < ab) { *erroroffset = (int)(p - string); /* Missing bytes */ return ab - length; /* Codes ERR1 to ERR5 */ } length -= ab; /* Length remaining */ /* Check top bits in the second byte */ if (((d = *(++p)) & 0xc0) != 0x80) { *erroroffset = (int)(p - string) - 1; return PCRE_UTF8_ERR6; } /* For each length, check that the remaining bytes start with the 0x80 bit set and not the 0x40 bit. Then check for an overlong sequence, and for the excluded range 0xd800 to 0xdfff. */ switch (ab) { /* 2-byte character. No further bytes to check for 0x80. Check first byte for for xx00 000x (overlong sequence). */ case 1: if ((c & 0x3e) == 0) { *erroroffset = (int)(p - string) - 1; return PCRE_UTF8_ERR15; } break; /* 3-byte character. Check third byte for 0x80. Then check first 2 bytes for 1110 0000, xx0x xxxx (overlong sequence) or 1110 1101, 1010 xxxx (0xd800 - 0xdfff) */ case 2: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ { *erroroffset = (int)(p - string) - 2; return PCRE_UTF8_ERR7; } if (c == 0xe0 && (d & 0x20) == 0) { *erroroffset = (int)(p - string) - 2; return PCRE_UTF8_ERR16; } if (c == 0xed && d >= 0xa0) { *erroroffset = (int)(p - string) - 2; return PCRE_UTF8_ERR14; } break; /* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2 bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a character greater than 0x0010ffff (f4 8f bf bf) */ case 3: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ { *erroroffset = (int)(p - string) - 2; return PCRE_UTF8_ERR7; } if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ { *erroroffset = (int)(p - string) - 3; return PCRE_UTF8_ERR8; } if (c == 0xf0 && (d & 0x30) == 0) { *erroroffset = (int)(p - string) - 3; return PCRE_UTF8_ERR17; } if (c > 0xf4 || (c == 0xf4 && d > 0x8f)) { *erroroffset = (int)(p - string) - 3; return PCRE_UTF8_ERR13; } break; /* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be rejected by the length test below. However, we do the appropriate tests here so that overlong sequences get diagnosed, and also in case there is ever an option for handling these larger code points. */ /* 5-byte character. Check 3rd, 4th, and 5th bytes for 0x80. Then check for 1111 1000, xx00 0xxx */ case 4: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ { *erroroffset = (int)(p - string) - 2; return PCRE_UTF8_ERR7; } if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ { *erroroffset = (int)(p - string) - 3; return PCRE_UTF8_ERR8; } if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ { *erroroffset = (int)(p - string) - 4; return PCRE_UTF8_ERR9; } if (c == 0xf8 && (d & 0x38) == 0) { *erroroffset = (int)(p - string) - 4; return PCRE_UTF8_ERR18; } break; /* 6-byte character. Check 3rd-6th bytes for 0x80. Then check for 1111 1100, xx00 00xx. */ case 5: if ((*(++p) & 0xc0) != 0x80) /* Third byte */ { *erroroffset = (int)(p - string) - 2; return PCRE_UTF8_ERR7; } if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ { *erroroffset = (int)(p - string) - 3; return PCRE_UTF8_ERR8; } if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ { *erroroffset = (int)(p - string) - 4; return PCRE_UTF8_ERR9; } if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */ { *erroroffset = (int)(p - string) - 5; return PCRE_UTF8_ERR10; } if (c == 0xfc && (d & 0x3c) == 0) { *erroroffset = (int)(p - string) - 5; return PCRE_UTF8_ERR19; } break; } /* Character is valid under RFC 2279, but 4-byte and 5-byte characters are excluded by RFC 3629. The pointer p is currently at the last byte of the character. */ if (ab > 3) { *erroroffset = (int)(p - string) - ab; return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12; } } #else /* Not SUPPORT_UTF */ (void)(string); /* Keep picky compilers happy */ (void)(length); (void)(erroroffset); #endif return PCRE_UTF8_ERR0; /* This indicates success */ } /* End of pcre_valid_utf8.c */ ================================================ FILE: src/pcre/pcre_version.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains the external function pcre_version(), which returns a string that identifies the PCRE version that is in use. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Return version string * *************************************************/ /* These macros are the standard way of turning unquoted text into C strings. They allow macros like PCRE_MAJOR to be defined without quotes, which is convenient for user programs that want to test its value. */ #define STRING(a) # a #define XSTRING(s) STRING(s) /* A problem turned up with PCRE_PRERELEASE, which is defined empty for production releases. Originally, it was used naively in this code: return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) XSTRING(PCRE_PRERELEASE) " " XSTRING(PCRE_DATE); However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of STRING(). The C standard states: "If (before argument substitution) any argument consists of no preprocessing tokens, the behavior is undefined." It turns out the gcc treats this case as a single empty string - which is what we really want - but Visual C grumbles about the lack of an argument for the macro. Unfortunately, both are within their rights. To cope with both ways of handling this, I had resort to some messy hackery that does a test at run time. I could find no way of detecting that a macro is defined as an empty string at pre-processor time. This hack uses a standard trick for avoiding calling the STRING macro with an empty argument when doing the test. */ #if defined COMPILE_PCRE8 PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION pcre_version(void) #elif defined COMPILE_PCRE16 PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION pcre16_version(void) #elif defined COMPILE_PCRE32 PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION pcre32_version(void) #endif { return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)? XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) : XSTRING(PCRE_MAJOR.PCRE_MINOR) XSTRING(PCRE_PRERELEASE PCRE_DATE); } /* End of pcre_version.c */ ================================================ FILE: src/pcre/pcre_xclass.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2013 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module contains an internal function that is used to match an extended class. It is used by both pcre_exec() and pcre_def_exec(). */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "pcre_internal.h" /************************************************* * Match character against an XCLASS * *************************************************/ /* This function is called to match a character against an extended class that might contain values > 255 and/or Unicode properties. Arguments: c the character data points to the flag byte of the XCLASS data Returns: TRUE if character matches, else FALSE */ BOOL PRIV(xclass)(pcre_uint32 c, const pcre_uchar *data, BOOL utf) { pcre_uchar t; BOOL negated = (*data & XCL_NOT) != 0; (void)utf; #ifdef COMPILE_PCRE8 /* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ utf = TRUE; #endif /* Character values < 256 are matched against a bitmap, if one is present. If not, we still carry on, because there may be ranges that start below 256 in the additional data. */ if (c < 256) { if ((*data & XCL_HASPROP) == 0) { if ((*data & XCL_MAP) == 0) return negated; return (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0; } if ((*data & XCL_MAP) != 0 && (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0) return !negated; /* char found */ } /* First skip the bit map if present. Then match against the list of Unicode properties or large chars or ranges that end with a large char. We won't ever encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */ if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar); while ((t = *data++) != XCL_END) { pcre_uint32 x, y; if (t == XCL_SINGLE) { #ifdef SUPPORT_UTF if (utf) { GETCHARINC(x, data); /* macro generates multiple statements */ } else #endif x = *data++; if (c == x) return !negated; } else if (t == XCL_RANGE) { #ifdef SUPPORT_UTF if (utf) { GETCHARINC(x, data); /* macro generates multiple statements */ GETCHARINC(y, data); /* macro generates multiple statements */ } else #endif { x = *data++; y = *data++; } if (c >= x && c <= y) return !negated; } #ifdef SUPPORT_UCP else /* XCL_PROP & XCL_NOTPROP */ { const ucd_record *prop = GET_UCD(c); BOOL isprop = t == XCL_PROP; switch(*data) { case PT_ANY: if (isprop) return !negated; break; case PT_LAMP: if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || prop->chartype == ucp_Lt) == isprop) return !negated; break; case PT_GC: if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop) return !negated; break; case PT_PC: if ((data[1] == prop->chartype) == isprop) return !negated; break; case PT_SC: if ((data[1] == prop->script) == isprop) return !negated; break; case PT_ALNUM: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop) return !negated; break; /* Perl space used to exclude VT, but from Perl 5.18 it is included, which means that Perl space and POSIX space are now identical. PCRE was changed at release 8.34. */ case PT_SPACE: /* Perl space */ case PT_PXSPACE: /* POSIX space */ switch(c) { HSPACE_CASES: VSPACE_CASES: if (isprop) return !negated; break; default: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop) return !negated; break; } break; case PT_WORD: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE) == isprop) return !negated; break; case PT_UCNC: if (c < 0xa0) { if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || c == CHAR_GRAVE_ACCENT) == isprop) return !negated; } else { if ((c < 0xd800 || c > 0xdfff) == isprop) return !negated; } break; /* The following three properties can occur only in an XCLASS, as there is no \p or \P coding for them. */ /* Graphic character. Implement this as not Z (space or separator) and not C (other), except for Cf (format) with a few exceptions. This seems to be what Perl does. The exceptional characters are: U+061C Arabic Letter Mark U+180E Mongolian Vowel Separator U+2066 - U+2069 Various "isolate"s */ case PT_PXGRAPH: if ((PRIV(ucp_gentype)[prop->chartype] != ucp_Z && (PRIV(ucp_gentype)[prop->chartype] != ucp_C || (prop->chartype == ucp_Cf && c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069)) )) == isprop) return !negated; break; /* Printable character: same as graphic, with the addition of Zs, i.e. not Zl and not Zp, and U+180E. */ case PT_PXPRINT: if ((prop->chartype != ucp_Zl && prop->chartype != ucp_Zp && (PRIV(ucp_gentype)[prop->chartype] != ucp_C || (prop->chartype == ucp_Cf && c != 0x061c && (c < 0x2066 || c > 0x2069)) )) == isprop) return !negated; break; /* Punctuation: all Unicode punctuation, plus ASCII characters that Unicode treats as symbols rather than punctuation, for Perl compatibility (these are $+<=>^`|~). */ case PT_PXPUNCT: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P || (c < 128 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop) return !negated; break; /* This should never occur, but compilers may mutter if there is no default. */ default: return FALSE; } data += 2; } #endif /* SUPPORT_UCP */ } return negated; /* char did not match */ } /* End of pcre_xclass.c */ ================================================ FILE: src/pcre/pcrecpp.cc ================================================ // Copyright (c) 2010, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include /* for SHRT_MIN, USHRT_MAX, etc */ #include /* for memcpy */ #include #include #include #include #include "pcrecpp_internal.h" #include "pcre.h" #include "pcrecpp.h" #include "pcre_stringpiece.h" namespace pcrecpp { // Maximum number of args we can set static const int kMaxArgs = 16; static const int kVecSize = (1 + kMaxArgs) * 3; // results + PCRE workspace // Special object that stands-in for no argument Arg RE::no_arg((void*)NULL); // This is for ABI compatibility with old versions of pcre (pre-7.6), // which defined a global no_arg variable instead of putting it in the // RE class. This works on GCC >= 3, at least. It definitely works // for ELF, but may not for other object formats (Mach-O, for // instance, does not support aliases.) We could probably have a more // inclusive test if we ever needed it. (Note that not only the // __attribute__ syntax, but also __USER_LABEL_PREFIX__, are // gnu-specific.) #if defined(__GNUC__) && __GNUC__ >= 3 && defined(__ELF__) && !defined(__INTEL_COMPILER) # define ULP_AS_STRING(x) ULP_AS_STRING_INTERNAL(x) # define ULP_AS_STRING_INTERNAL(x) #x # define USER_LABEL_PREFIX_STR ULP_AS_STRING(__USER_LABEL_PREFIX__) extern Arg no_arg __attribute__((alias(USER_LABEL_PREFIX_STR "_ZN7pcrecpp2RE6no_argE"))); #endif // If a regular expression has no error, its error_ field points here static const string empty_string; // If the user doesn't ask for any options, we just use this one static RE_Options default_options; // Specials for the start of patterns. See comments where start_options is used // below. (PH June 2018) static const char *start_options[] = { "(*UTF8)", "(*UTF)", "(*UCP)", "(*NO_START_OPT)", "(*NO_AUTO_POSSESS)", "(*LIMIT_RECURSION=", "(*LIMIT_MATCH=", "(*CRLF)", "(*CR)", "(*BSR_UNICODE)", "(*BSR_ANYCRLF)", "(*ANYCRLF)", "(*ANY)", "" }; void RE::Init(const string& pat, const RE_Options* options) { pattern_ = pat; if (options == NULL) { options_ = default_options; } else { options_ = *options; } error_ = &empty_string; re_full_ = NULL; re_partial_ = NULL; re_partial_ = Compile(UNANCHORED); if (re_partial_ != NULL) { re_full_ = Compile(ANCHOR_BOTH); } } void RE::Cleanup() { if (re_full_ != NULL) (*pcre_free)(re_full_); if (re_partial_ != NULL) (*pcre_free)(re_partial_); if (error_ != &empty_string) delete error_; } RE::~RE() { Cleanup(); } pcre* RE::Compile(Anchor anchor) { // First, convert RE_Options into pcre options int pcre_options = 0; pcre_options = options_.all_options(); // Special treatment for anchoring. This is needed because at // runtime pcre only provides an option for anchoring at the // beginning of a string (unless you use offset). // // There are three types of anchoring we want: // UNANCHORED Compile the original pattern, and use // a pcre unanchored match. // ANCHOR_START Compile the original pattern, and use // a pcre anchored match. // ANCHOR_BOTH Tack a "\z" to the end of the original pattern // and use a pcre anchored match. const char* compile_error; int eoffset; pcre* re; if (anchor != ANCHOR_BOTH) { re = pcre_compile(pattern_.c_str(), pcre_options, &compile_error, &eoffset, NULL); } else { // Tack a '\z' at the end of RE. Parenthesize it first so that // the '\z' applies to all top-level alternatives in the regexp. /* When this code was written (for PCRE 6.0) it was enough just to parenthesize the entire pattern. Unfortunately, when the feature of starting patterns with (*UTF8) or (*CR) etc. was added to PCRE patterns, this code was never updated. This bug was not noticed till 2018, long after PCRE became obsolescent and its maintainer no longer around. Since PCRE is frozen, I have added a hack to check for all the existing "start of pattern" specials - knowing that no new ones will ever be added. I am not a C++ programmer, so the code style is no doubt crude. It is also inefficient, but is only run when the pattern starts with "(*". PH June 2018. */ string wrapped = ""; if (pattern_.c_str()[0] == '(' && pattern_.c_str()[1] == '*') { int kk, klen, kmat; for (;;) { // Loop for any number of leading items for (kk = 0; start_options[kk][0] != 0; kk++) { klen = strlen(start_options[kk]); kmat = strncmp(pattern_.c_str(), start_options[kk], klen); if (kmat >= 0) break; } if (kmat != 0) break; // Not found // If the item ended in "=" we must copy digits up to ")". if (start_options[kk][klen-1] == '=') { while (isdigit(pattern_.c_str()[klen])) klen++; if (pattern_.c_str()[klen] != ')') break; // Syntax error klen++; } // Move the item from the pattern to the start of the wrapped string. wrapped += pattern_.substr(0, klen); pattern_.erase(0, klen); } } // Wrap the rest of the pattern. wrapped += "(?:"; // A non-counting grouping operator wrapped += pattern_; wrapped += ")\\z"; re = pcre_compile(wrapped.c_str(), pcre_options, &compile_error, &eoffset, NULL); } if (re == NULL) { if (error_ == &empty_string) error_ = new string(compile_error); } return re; } /***** Matching interfaces *****/ bool RE::FullMatch(const StringPiece& text, const Arg& ptr1, const Arg& ptr2, const Arg& ptr3, const Arg& ptr4, const Arg& ptr5, const Arg& ptr6, const Arg& ptr7, const Arg& ptr8, const Arg& ptr9, const Arg& ptr10, const Arg& ptr11, const Arg& ptr12, const Arg& ptr13, const Arg& ptr14, const Arg& ptr15, const Arg& ptr16) const { const Arg* args[kMaxArgs]; int n = 0; if (&ptr1 == &no_arg) { goto done; } args[n++] = &ptr1; if (&ptr2 == &no_arg) { goto done; } args[n++] = &ptr2; if (&ptr3 == &no_arg) { goto done; } args[n++] = &ptr3; if (&ptr4 == &no_arg) { goto done; } args[n++] = &ptr4; if (&ptr5 == &no_arg) { goto done; } args[n++] = &ptr5; if (&ptr6 == &no_arg) { goto done; } args[n++] = &ptr6; if (&ptr7 == &no_arg) { goto done; } args[n++] = &ptr7; if (&ptr8 == &no_arg) { goto done; } args[n++] = &ptr8; if (&ptr9 == &no_arg) { goto done; } args[n++] = &ptr9; if (&ptr10 == &no_arg) { goto done; } args[n++] = &ptr10; if (&ptr11 == &no_arg) { goto done; } args[n++] = &ptr11; if (&ptr12 == &no_arg) { goto done; } args[n++] = &ptr12; if (&ptr13 == &no_arg) { goto done; } args[n++] = &ptr13; if (&ptr14 == &no_arg) { goto done; } args[n++] = &ptr14; if (&ptr15 == &no_arg) { goto done; } args[n++] = &ptr15; if (&ptr16 == &no_arg) { goto done; } args[n++] = &ptr16; done: int consumed; int vec[kVecSize]; return DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize); } bool RE::PartialMatch(const StringPiece& text, const Arg& ptr1, const Arg& ptr2, const Arg& ptr3, const Arg& ptr4, const Arg& ptr5, const Arg& ptr6, const Arg& ptr7, const Arg& ptr8, const Arg& ptr9, const Arg& ptr10, const Arg& ptr11, const Arg& ptr12, const Arg& ptr13, const Arg& ptr14, const Arg& ptr15, const Arg& ptr16) const { const Arg* args[kMaxArgs]; int n = 0; if (&ptr1 == &no_arg) { goto done; } args[n++] = &ptr1; if (&ptr2 == &no_arg) { goto done; } args[n++] = &ptr2; if (&ptr3 == &no_arg) { goto done; } args[n++] = &ptr3; if (&ptr4 == &no_arg) { goto done; } args[n++] = &ptr4; if (&ptr5 == &no_arg) { goto done; } args[n++] = &ptr5; if (&ptr6 == &no_arg) { goto done; } args[n++] = &ptr6; if (&ptr7 == &no_arg) { goto done; } args[n++] = &ptr7; if (&ptr8 == &no_arg) { goto done; } args[n++] = &ptr8; if (&ptr9 == &no_arg) { goto done; } args[n++] = &ptr9; if (&ptr10 == &no_arg) { goto done; } args[n++] = &ptr10; if (&ptr11 == &no_arg) { goto done; } args[n++] = &ptr11; if (&ptr12 == &no_arg) { goto done; } args[n++] = &ptr12; if (&ptr13 == &no_arg) { goto done; } args[n++] = &ptr13; if (&ptr14 == &no_arg) { goto done; } args[n++] = &ptr14; if (&ptr15 == &no_arg) { goto done; } args[n++] = &ptr15; if (&ptr16 == &no_arg) { goto done; } args[n++] = &ptr16; done: int consumed; int vec[kVecSize]; return DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize); } bool RE::Consume(StringPiece* input, const Arg& ptr1, const Arg& ptr2, const Arg& ptr3, const Arg& ptr4, const Arg& ptr5, const Arg& ptr6, const Arg& ptr7, const Arg& ptr8, const Arg& ptr9, const Arg& ptr10, const Arg& ptr11, const Arg& ptr12, const Arg& ptr13, const Arg& ptr14, const Arg& ptr15, const Arg& ptr16) const { const Arg* args[kMaxArgs]; int n = 0; if (&ptr1 == &no_arg) { goto done; } args[n++] = &ptr1; if (&ptr2 == &no_arg) { goto done; } args[n++] = &ptr2; if (&ptr3 == &no_arg) { goto done; } args[n++] = &ptr3; if (&ptr4 == &no_arg) { goto done; } args[n++] = &ptr4; if (&ptr5 == &no_arg) { goto done; } args[n++] = &ptr5; if (&ptr6 == &no_arg) { goto done; } args[n++] = &ptr6; if (&ptr7 == &no_arg) { goto done; } args[n++] = &ptr7; if (&ptr8 == &no_arg) { goto done; } args[n++] = &ptr8; if (&ptr9 == &no_arg) { goto done; } args[n++] = &ptr9; if (&ptr10 == &no_arg) { goto done; } args[n++] = &ptr10; if (&ptr11 == &no_arg) { goto done; } args[n++] = &ptr11; if (&ptr12 == &no_arg) { goto done; } args[n++] = &ptr12; if (&ptr13 == &no_arg) { goto done; } args[n++] = &ptr13; if (&ptr14 == &no_arg) { goto done; } args[n++] = &ptr14; if (&ptr15 == &no_arg) { goto done; } args[n++] = &ptr15; if (&ptr16 == &no_arg) { goto done; } args[n++] = &ptr16; done: int consumed; int vec[kVecSize]; if (DoMatchImpl(*input, ANCHOR_START, &consumed, args, n, vec, kVecSize)) { input->remove_prefix(consumed); return true; } else { return false; } } bool RE::FindAndConsume(StringPiece* input, const Arg& ptr1, const Arg& ptr2, const Arg& ptr3, const Arg& ptr4, const Arg& ptr5, const Arg& ptr6, const Arg& ptr7, const Arg& ptr8, const Arg& ptr9, const Arg& ptr10, const Arg& ptr11, const Arg& ptr12, const Arg& ptr13, const Arg& ptr14, const Arg& ptr15, const Arg& ptr16) const { const Arg* args[kMaxArgs]; int n = 0; if (&ptr1 == &no_arg) { goto done; } args[n++] = &ptr1; if (&ptr2 == &no_arg) { goto done; } args[n++] = &ptr2; if (&ptr3 == &no_arg) { goto done; } args[n++] = &ptr3; if (&ptr4 == &no_arg) { goto done; } args[n++] = &ptr4; if (&ptr5 == &no_arg) { goto done; } args[n++] = &ptr5; if (&ptr6 == &no_arg) { goto done; } args[n++] = &ptr6; if (&ptr7 == &no_arg) { goto done; } args[n++] = &ptr7; if (&ptr8 == &no_arg) { goto done; } args[n++] = &ptr8; if (&ptr9 == &no_arg) { goto done; } args[n++] = &ptr9; if (&ptr10 == &no_arg) { goto done; } args[n++] = &ptr10; if (&ptr11 == &no_arg) { goto done; } args[n++] = &ptr11; if (&ptr12 == &no_arg) { goto done; } args[n++] = &ptr12; if (&ptr13 == &no_arg) { goto done; } args[n++] = &ptr13; if (&ptr14 == &no_arg) { goto done; } args[n++] = &ptr14; if (&ptr15 == &no_arg) { goto done; } args[n++] = &ptr15; if (&ptr16 == &no_arg) { goto done; } args[n++] = &ptr16; done: int consumed; int vec[kVecSize]; if (DoMatchImpl(*input, UNANCHORED, &consumed, args, n, vec, kVecSize)) { input->remove_prefix(consumed); return true; } else { return false; } } bool RE::Replace(const StringPiece& rewrite, string *str) const { int vec[kVecSize]; int matches = TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize); if (matches == 0) return false; string s; if (!Rewrite(&s, rewrite, *str, vec, matches)) return false; assert(vec[0] >= 0); assert(vec[1] >= 0); str->replace(vec[0], vec[1] - vec[0], s); return true; } // Returns PCRE_NEWLINE_CRLF, PCRE_NEWLINE_CR, or PCRE_NEWLINE_LF. // Note that PCRE_NEWLINE_CRLF is defined to be P_N_CR | P_N_LF. // Modified by PH to add PCRE_NEWLINE_ANY and PCRE_NEWLINE_ANYCRLF. static int NewlineMode(int pcre_options) { // TODO: if we can make it threadsafe, cache this var int newline_mode = 0; /* if (newline_mode) return newline_mode; */ // do this once it's cached if (pcre_options & (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF| PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF)) { newline_mode = (pcre_options & (PCRE_NEWLINE_CRLF|PCRE_NEWLINE_CR|PCRE_NEWLINE_LF| PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF)); } else { int newline; pcre_config(PCRE_CONFIG_NEWLINE, &newline); if (newline == 10) newline_mode = PCRE_NEWLINE_LF; else if (newline == 13) newline_mode = PCRE_NEWLINE_CR; else if (newline == 3338) newline_mode = PCRE_NEWLINE_CRLF; else if (newline == -1) newline_mode = PCRE_NEWLINE_ANY; else if (newline == -2) newline_mode = PCRE_NEWLINE_ANYCRLF; else assert(NULL == "Unexpected return value from pcre_config(NEWLINE)"); } return newline_mode; } int RE::GlobalReplace(const StringPiece& rewrite, string *str) const { int count = 0; int vec[kVecSize]; string out; int start = 0; bool last_match_was_empty_string = false; while (start <= static_cast(str->length())) { // If the previous match was for the empty string, we shouldn't // just match again: we'll match in the same way and get an // infinite loop. Instead, we do the match in a special way: // anchored -- to force another try at the same position -- // and with a flag saying that this time, ignore empty matches. // If this special match returns, that means there's a non-empty // match at this position as well, and we can continue. If not, // we do what perl does, and just advance by one. // Notice that perl prints '@@@' for this; // perl -le '$_ = "aa"; s/b*|aa/@/g; print' int matches; if (last_match_was_empty_string) { matches = TryMatch(*str, start, ANCHOR_START, false, vec, kVecSize); if (matches <= 0) { int matchend = start + 1; // advance one character. // If the current char is CR and we're in CRLF mode, skip LF too. // Note it's better to call pcre_fullinfo() than to examine // all_options(), since options_ could have changed bewteen // compile-time and now, but this is simpler and safe enough. // Modified by PH to add ANY and ANYCRLF. if (matchend < static_cast(str->length()) && (*str)[start] == '\r' && (*str)[matchend] == '\n' && (NewlineMode(options_.all_options()) == PCRE_NEWLINE_CRLF || NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANY || NewlineMode(options_.all_options()) == PCRE_NEWLINE_ANYCRLF)) { matchend++; } // We also need to advance more than one char if we're in utf8 mode. #ifdef SUPPORT_UTF if (options_.utf8()) { while (matchend < static_cast(str->length()) && ((*str)[matchend] & 0xc0) == 0x80) matchend++; } #endif if (start < static_cast(str->length())) out.append(*str, start, matchend - start); start = matchend; last_match_was_empty_string = false; continue; } } else { matches = TryMatch(*str, start, UNANCHORED, true, vec, kVecSize); if (matches <= 0) break; } int matchstart = vec[0], matchend = vec[1]; assert(matchstart >= start); assert(matchend >= matchstart); out.append(*str, start, matchstart - start); Rewrite(&out, rewrite, *str, vec, matches); start = matchend; count++; last_match_was_empty_string = (matchstart == matchend); } if (count == 0) return 0; if (start < static_cast(str->length())) out.append(*str, start, str->length() - start); swap(out, *str); return count; } bool RE::Extract(const StringPiece& rewrite, const StringPiece& text, string *out) const { int vec[kVecSize]; int matches = TryMatch(text, 0, UNANCHORED, true, vec, kVecSize); if (matches == 0) return false; out->erase(); return Rewrite(out, rewrite, text, vec, matches); } /*static*/ string RE::QuoteMeta(const StringPiece& unquoted) { string result; // Escape any ascii character not in [A-Za-z_0-9]. // // Note that it's legal to escape a character even if it has no // special meaning in a regular expression -- so this function does // that. (This also makes it identical to the perl function of the // same name; see `perldoc -f quotemeta`.) The one exception is // escaping NUL: rather than doing backslash + NUL, like perl does, // we do '\0', because pcre itself doesn't take embedded NUL chars. for (int ii = 0; ii < unquoted.size(); ++ii) { // Note that using 'isalnum' here raises the benchmark time from // 32ns to 58ns: if (unquoted[ii] == '\0') { result += "\\0"; } else if ((unquoted[ii] < 'a' || unquoted[ii] > 'z') && (unquoted[ii] < 'A' || unquoted[ii] > 'Z') && (unquoted[ii] < '0' || unquoted[ii] > '9') && unquoted[ii] != '_' && // If this is the part of a UTF8 or Latin1 character, we need // to copy this byte without escaping. Experimentally this is // what works correctly with the regexp library. !(unquoted[ii] & 128)) { result += '\\'; result += unquoted[ii]; } else { result += unquoted[ii]; } } return result; } /***** Actual matching and rewriting code *****/ int RE::TryMatch(const StringPiece& text, int startpos, Anchor anchor, bool empty_ok, int *vec, int vecsize) const { pcre* re = (anchor == ANCHOR_BOTH) ? re_full_ : re_partial_; if (re == NULL) { //fprintf(stderr, "Matching against invalid re: %s\n", error_->c_str()); return 0; } pcre_extra extra = { 0, 0, 0, 0, 0, 0, 0, 0 }; if (options_.match_limit() > 0) { extra.flags |= PCRE_EXTRA_MATCH_LIMIT; extra.match_limit = options_.match_limit(); } if (options_.match_limit_recursion() > 0) { extra.flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; extra.match_limit_recursion = options_.match_limit_recursion(); } // int options = 0; // Changed by PH as a result of bugzilla #1288 int options = (options_.all_options() & PCRE_NO_UTF8_CHECK); if (anchor != UNANCHORED) options |= PCRE_ANCHORED; if (!empty_ok) options |= PCRE_NOTEMPTY; int rc = pcre_exec(re, // The regular expression object &extra, (text.data() == NULL) ? "" : text.data(), text.size(), startpos, options, vec, vecsize); // Handle errors if (rc == PCRE_ERROR_NOMATCH) { return 0; } else if (rc < 0) { //fprintf(stderr, "Unexpected return code: %d when matching '%s'\n", // re, pattern_.c_str()); return 0; } else if (rc == 0) { // pcre_exec() returns 0 as a special case when the number of // capturing subpatterns exceeds the size of the vector. // When this happens, there is a match and the output vector // is filled, but we miss out on the positions of the extra subpatterns. rc = vecsize / 2; } return rc; } bool RE::DoMatchImpl(const StringPiece& text, Anchor anchor, int* consumed, const Arg* const* args, int n, int* vec, int vecsize) const { assert((1 + n) * 3 <= vecsize); // results + PCRE workspace int matches = TryMatch(text, 0, anchor, true, vec, vecsize); assert(matches >= 0); // TryMatch never returns negatives if (matches == 0) return false; *consumed = vec[1]; if (n == 0 || args == NULL) { // We are not interested in results return true; } if (NumberOfCapturingGroups() < n) { // RE has fewer capturing groups than number of arg pointers passed in return false; } // If we got here, we must have matched the whole pattern. // We do not need (can not do) any more checks on the value of 'matches' here // -- see the comment for TryMatch. for (int i = 0; i < n; i++) { const int start = vec[2*(i+1)]; const int limit = vec[2*(i+1)+1]; if (!args[i]->Parse(text.data() + start, limit-start)) { // TODO: Should we indicate what the error was? return false; } } return true; } bool RE::DoMatch(const StringPiece& text, Anchor anchor, int* consumed, const Arg* const args[], int n) const { assert(n >= 0); size_t const vecsize = (1 + n) * 3; // results + PCRE workspace // (as for kVecSize) int space[21]; // use stack allocation for small vecsize (common case) int* vec = vecsize <= 21 ? space : new int[vecsize]; bool retval = DoMatchImpl(text, anchor, consumed, args, n, vec, (int)vecsize); if (vec != space) delete [] vec; return retval; } bool RE::Rewrite(string *out, const StringPiece &rewrite, const StringPiece &text, int *vec, int veclen) const { for (const char *s = rewrite.data(), *end = s + rewrite.size(); s < end; s++) { int c = *s; if (c == '\\') { c = *++s; if (isdigit(c)) { int n = (c - '0'); if (n >= veclen) { //fprintf(stderr, requested group %d in regexp %.*s\n", // n, rewrite.size(), rewrite.data()); return false; } int start = vec[2 * n]; if (start >= 0) out->append(text.data() + start, vec[2 * n + 1] - start); } else if (c == '\\') { *out += '\\'; } else { //fprintf(stderr, "invalid rewrite pattern: %.*s\n", // rewrite.size(), rewrite.data()); return false; } } else { *out += c; } } return true; } // Return the number of capturing subpatterns, or -1 if the // regexp wasn't valid on construction. int RE::NumberOfCapturingGroups() const { if (re_partial_ == NULL) return -1; int result; int pcre_retval = pcre_fullinfo(re_partial_, // The regular expression object NULL, // We did not study the pattern PCRE_INFO_CAPTURECOUNT, &result); assert(pcre_retval == 0); return result; } /***** Parsers for various types *****/ bool Arg::parse_null(const char* str, int n, void* dest) { (void)str; (void)n; // We fail if somebody asked us to store into a non-NULL void* pointer return (dest == NULL); } bool Arg::parse_string(const char* str, int n, void* dest) { if (dest == NULL) return true; reinterpret_cast(dest)->assign(str, n); return true; } bool Arg::parse_stringpiece(const char* str, int n, void* dest) { if (dest == NULL) return true; reinterpret_cast(dest)->set(str, n); return true; } bool Arg::parse_char(const char* str, int n, void* dest) { if (n != 1) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = str[0]; return true; } bool Arg::parse_uchar(const char* str, int n, void* dest) { if (n != 1) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = str[0]; return true; } // Largest number spec that we are willing to parse static const int kMaxNumberLength = 32; // REQUIRES "buf" must have length at least kMaxNumberLength+1 // REQUIRES "n > 0" // Copies "str" into "buf" and null-terminates if necessary. // Returns one of: // a. "str" if no termination is needed // b. "buf" if the string was copied and null-terminated // c. "" if the input was invalid and has no hope of being parsed static const char* TerminateNumber(char* buf, const char* str, int n) { if ((n > 0) && isspace(*str)) { // We are less forgiving than the strtoxxx() routines and do not // allow leading spaces. return ""; } // See if the character right after the input text may potentially // look like a digit. if (isdigit(str[n]) || ((str[n] >= 'a') && (str[n] <= 'f')) || ((str[n] >= 'A') && (str[n] <= 'F'))) { if (n > kMaxNumberLength) return ""; // Input too big to be a valid number memcpy(buf, str, n); buf[n] = '\0'; return buf; } else { // We can parse right out of the supplied string, so return it. return str; } } bool Arg::parse_long_radix(const char* str, int n, void* dest, int radix) { if (n == 0) return false; char buf[kMaxNumberLength+1]; str = TerminateNumber(buf, str, n); char* end; errno = 0; long r = strtol(str, &end, radix); if (end != str + n) return false; // Leftover junk if (errno) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; } bool Arg::parse_ulong_radix(const char* str, int n, void* dest, int radix) { if (n == 0) return false; char buf[kMaxNumberLength+1]; str = TerminateNumber(buf, str, n); if (str[0] == '-') return false; // strtoul() on a negative number?! char* end; errno = 0; unsigned long r = strtoul(str, &end, radix); if (end != str + n) return false; // Leftover junk if (errno) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; } bool Arg::parse_short_radix(const char* str, int n, void* dest, int radix) { long r; if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse if (r < SHRT_MIN || r > SHRT_MAX) return false; // Out of range if (dest == NULL) return true; *(reinterpret_cast(dest)) = static_cast(r); return true; } bool Arg::parse_ushort_radix(const char* str, int n, void* dest, int radix) { unsigned long r; if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse if (r > USHRT_MAX) return false; // Out of range if (dest == NULL) return true; *(reinterpret_cast(dest)) = static_cast(r); return true; } bool Arg::parse_int_radix(const char* str, int n, void* dest, int radix) { long r; if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse if (r < INT_MIN || r > INT_MAX) return false; // Out of range if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; } bool Arg::parse_uint_radix(const char* str, int n, void* dest, int radix) { unsigned long r; if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse if (r > UINT_MAX) return false; // Out of range if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; } bool Arg::parse_longlong_radix(const char* str, int n, void* dest, int radix) { #ifndef HAVE_LONG_LONG return false; #else if (n == 0) return false; char buf[kMaxNumberLength+1]; str = TerminateNumber(buf, str, n); char* end; errno = 0; #if defined HAVE_STRTOQ long long r = strtoq(str, &end, radix); #elif defined HAVE_STRTOLL long long r = strtoll(str, &end, radix); #elif defined HAVE__STRTOI64 long long r = _strtoi64(str, &end, radix); #elif defined HAVE_STRTOIMAX long long r = strtoimax(str, &end, radix); #else #error parse_longlong_radix: cannot convert input to a long-long #endif if (end != str + n) return false; // Leftover junk if (errno) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; #endif /* HAVE_LONG_LONG */ } bool Arg::parse_ulonglong_radix(const char* str, int n, void* dest, int radix) { #ifndef HAVE_UNSIGNED_LONG_LONG return false; #else if (n == 0) return false; char buf[kMaxNumberLength+1]; str = TerminateNumber(buf, str, n); if (str[0] == '-') return false; // strtoull() on a negative number?! char* end; errno = 0; #if defined HAVE_STRTOQ unsigned long long r = strtouq(str, &end, radix); #elif defined HAVE_STRTOLL unsigned long long r = strtoull(str, &end, radix); #elif defined HAVE__STRTOI64 unsigned long long r = _strtoui64(str, &end, radix); #elif defined HAVE_STRTOIMAX unsigned long long r = strtoumax(str, &end, radix); #else #error parse_ulonglong_radix: cannot convert input to a long-long #endif if (end != str + n) return false; // Leftover junk if (errno) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; #endif /* HAVE_UNSIGNED_LONG_LONG */ } bool Arg::parse_double(const char* str, int n, void* dest) { if (n == 0) return false; static const int kMaxLength = 200; char buf[kMaxLength]; if (n >= kMaxLength) return false; memcpy(buf, str, n); buf[n] = '\0'; errno = 0; char* end; double r = strtod(buf, &end); if (end != buf + n) return false; // Leftover junk if (errno) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = r; return true; } bool Arg::parse_float(const char* str, int n, void* dest) { double r; if (!parse_double(str, n, &r)) return false; if (dest == NULL) return true; *(reinterpret_cast(dest)) = static_cast(r); return true; } #define DEFINE_INTEGER_PARSERS(name) \ bool Arg::parse_##name(const char* str, int n, void* dest) { \ return parse_##name##_radix(str, n, dest, 10); \ } \ bool Arg::parse_##name##_hex(const char* str, int n, void* dest) { \ return parse_##name##_radix(str, n, dest, 16); \ } \ bool Arg::parse_##name##_octal(const char* str, int n, void* dest) { \ return parse_##name##_radix(str, n, dest, 8); \ } \ bool Arg::parse_##name##_cradix(const char* str, int n, void* dest) { \ return parse_##name##_radix(str, n, dest, 0); \ } DEFINE_INTEGER_PARSERS(short) /* */ DEFINE_INTEGER_PARSERS(ushort) /* */ DEFINE_INTEGER_PARSERS(int) /* Don't use semicolons after these */ DEFINE_INTEGER_PARSERS(uint) /* statements because they can cause */ DEFINE_INTEGER_PARSERS(long) /* compiler warnings if the checking */ DEFINE_INTEGER_PARSERS(ulong) /* level is turned up high enough. */ DEFINE_INTEGER_PARSERS(longlong) /* */ DEFINE_INTEGER_PARSERS(ulonglong) /* */ #undef DEFINE_INTEGER_PARSERS } // namespace pcrecpp ================================================ FILE: src/pcre/pcrecpp.h ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat // Support for PCRE_XXX modifiers added by Giuseppe Maxia, July 2005 #ifndef _PCRECPP_H #define _PCRECPP_H // C++ interface to the pcre regular-expression library. RE supports // Perl-style regular expressions (with extensions like \d, \w, \s, // ...). // // ----------------------------------------------------------------------- // REGEXP SYNTAX: // // This module is part of the pcre library and hence supports its syntax // for regular expressions. // // The syntax is pretty similar to Perl's. For those not familiar // with Perl's regular expressions, here are some examples of the most // commonly used extensions: // // "hello (\\w+) world" -- \w matches a "word" character // "version (\\d+)" -- \d matches a digit // "hello\\s+world" -- \s matches any whitespace character // "\\b(\\w+)\\b" -- \b matches empty string at a word boundary // "(?i)hello" -- (?i) turns on case-insensitive matching // "/\\*(.*?)\\*/" -- .*? matches . minimum no. of times possible // // ----------------------------------------------------------------------- // MATCHING INTERFACE: // // The "FullMatch" operation checks that supplied text matches a // supplied pattern exactly. // // Example: successful match // pcrecpp::RE re("h.*o"); // re.FullMatch("hello"); // // Example: unsuccessful match (requires full match): // pcrecpp::RE re("e"); // !re.FullMatch("hello"); // // Example: creating a temporary RE object: // pcrecpp::RE("h.*o").FullMatch("hello"); // // You can pass in a "const char*" or a "string" for "text". The // examples below tend to use a const char*. // // You can, as in the different examples above, store the RE object // explicitly in a variable or use a temporary RE object. The // examples below use one mode or the other arbitrarily. Either // could correctly be used for any of these examples. // // ----------------------------------------------------------------------- // MATCHING WITH SUB-STRING EXTRACTION: // // You can supply extra pointer arguments to extract matched subpieces. // // Example: extracts "ruby" into "s" and 1234 into "i" // int i; // string s; // pcrecpp::RE re("(\\w+):(\\d+)"); // re.FullMatch("ruby:1234", &s, &i); // // Example: does not try to extract any extra sub-patterns // re.FullMatch("ruby:1234", &s); // // Example: does not try to extract into NULL // re.FullMatch("ruby:1234", NULL, &i); // // Example: integer overflow causes failure // !re.FullMatch("ruby:1234567891234", NULL, &i); // // Example: fails because there aren't enough sub-patterns: // !pcrecpp::RE("\\w+:\\d+").FullMatch("ruby:1234", &s); // // Example: fails because string cannot be stored in integer // !pcrecpp::RE("(.*)").FullMatch("ruby", &i); // // The provided pointer arguments can be pointers to any scalar numeric // type, or one of // string (matched piece is copied to string) // StringPiece (StringPiece is mutated to point to matched piece) // T (where "bool T::ParseFrom(const char*, int)" exists) // NULL (the corresponding matched sub-pattern is not copied) // // CAVEAT: An optional sub-pattern that does not exist in the matched // string is assigned the empty string. Therefore, the following will // return false (because the empty string is not a valid number): // int number; // pcrecpp::RE::FullMatch("abc", "[a-z]+(\\d+)?", &number); // // ----------------------------------------------------------------------- // DO_MATCH // // The matching interface supports at most 16 arguments per call. // If you need more, consider using the more general interface // pcrecpp::RE::DoMatch(). See pcrecpp.h for the signature for DoMatch. // // ----------------------------------------------------------------------- // PARTIAL MATCHES // // You can use the "PartialMatch" operation when you want the pattern // to match any substring of the text. // // Example: simple search for a string: // pcrecpp::RE("ell").PartialMatch("hello"); // // Example: find first number in a string: // int number; // pcrecpp::RE re("(\\d+)"); // re.PartialMatch("x*100 + 20", &number); // assert(number == 100); // // ----------------------------------------------------------------------- // UTF-8 AND THE MATCHING INTERFACE: // // By default, pattern and text are plain text, one byte per character. // The UTF8 flag, passed to the constructor, causes both pattern // and string to be treated as UTF-8 text, still a byte stream but // potentially multiple bytes per character. In practice, the text // is likelier to be UTF-8 than the pattern, but the match returned // may depend on the UTF8 flag, so always use it when matching // UTF8 text. E.g., "." will match one byte normally but with UTF8 // set may match up to three bytes of a multi-byte character. // // Example: // pcrecpp::RE_Options options; // options.set_utf8(); // pcrecpp::RE re(utf8_pattern, options); // re.FullMatch(utf8_string); // // Example: using the convenience function UTF8(): // pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8()); // re.FullMatch(utf8_string); // // NOTE: The UTF8 option is ignored if pcre was not configured with the // --enable-utf8 flag. // // ----------------------------------------------------------------------- // PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE // // PCRE defines some modifiers to change the behavior of the regular // expression engine. // The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle // to pass such modifiers to a RE class. // // Currently, the following modifiers are supported // // modifier description Perl corresponding // // PCRE_CASELESS case insensitive match /i // PCRE_MULTILINE multiple lines match /m // PCRE_DOTALL dot matches newlines /s // PCRE_DOLLAR_ENDONLY $ matches only at end N/A // PCRE_EXTRA strict escape parsing N/A // PCRE_EXTENDED ignore whitespaces /x // PCRE_UTF8 handles UTF8 chars built-in // PCRE_UNGREEDY reverses * and *? N/A // PCRE_NO_AUTO_CAPTURE disables matching parens N/A (*) // // (For a full account on how each modifier works, please check the // PCRE API reference manual). // // (*) Both Perl and PCRE allow non matching parentheses by means of the // "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not // capture, while (ab|cd) does. // // For each modifier, there are two member functions whose name is made // out of the modifier in lowercase, without the "PCRE_" prefix. For // instance, PCRE_CASELESS is handled by // bool caseless(), // which returns true if the modifier is set, and // RE_Options & set_caseless(bool), // which sets or unsets the modifier. // // Moreover, PCRE_EXTRA_MATCH_LIMIT can be accessed through the // set_match_limit() and match_limit() member functions. // Setting match_limit to a non-zero value will limit the executation of // pcre to keep it from doing bad things like blowing the stack or taking // an eternity to return a result. A value of 5000 is good enough to stop // stack blowup in a 2MB thread stack. Setting match_limit to zero will // disable match limiting. Alternately, you can set match_limit_recursion() // which uses PCRE_EXTRA_MATCH_LIMIT_RECURSION to limit how much pcre // recurses. match_limit() caps the number of matches pcre does; // match_limit_recrusion() caps the depth of recursion. // // Normally, to pass one or more modifiers to a RE class, you declare // a RE_Options object, set the appropriate options, and pass this // object to a RE constructor. Example: // // RE_options opt; // opt.set_caseless(true); // // if (RE("HELLO", opt).PartialMatch("hello world")) ... // // RE_options has two constructors. The default constructor takes no // arguments and creates a set of flags that are off by default. // // The optional parameter 'option_flags' is to facilitate transfer // of legacy code from C programs. This lets you do // RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); // // But new code is better off doing // RE(pattern, // RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str); // (See below) // // If you are going to pass one of the most used modifiers, there are some // convenience functions that return a RE_Options class with the // appropriate modifier already set: // CASELESS(), UTF8(), MULTILINE(), DOTALL(), EXTENDED() // // If you need to set several options at once, and you don't want to go // through the pains of declaring a RE_Options object and setting several // options, there is a parallel method that give you such ability on the // fly. You can concatenate several set_xxxxx member functions, since each // of them returns a reference to its class object. e.g.: to pass // PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one // statement, you may write // // RE(" ^ xyz \\s+ .* blah$", RE_Options() // .set_caseless(true) // .set_extended(true) // .set_multiline(true)).PartialMatch(sometext); // // ----------------------------------------------------------------------- // SCANNING TEXT INCREMENTALLY // // The "Consume" operation may be useful if you want to repeatedly // match regular expressions at the front of a string and skip over // them as they match. This requires use of the "StringPiece" type, // which represents a sub-range of a real string. Like RE, StringPiece // is defined in the pcrecpp namespace. // // Example: read lines of the form "var = value" from a string. // string contents = ...; // Fill string somehow // pcrecpp::StringPiece input(contents); // Wrap in a StringPiece // // string var; // int value; // pcrecpp::RE re("(\\w+) = (\\d+)\n"); // while (re.Consume(&input, &var, &value)) { // ...; // } // // Each successful call to "Consume" will set "var/value", and also // advance "input" so it points past the matched text. // // The "FindAndConsume" operation is similar to "Consume" but does not // anchor your match at the beginning of the string. For example, you // could extract all words from a string by repeatedly calling // pcrecpp::RE("(\\w+)").FindAndConsume(&input, &word) // // ----------------------------------------------------------------------- // PARSING HEX/OCTAL/C-RADIX NUMBERS // // By default, if you pass a pointer to a numeric value, the // corresponding text is interpreted as a base-10 number. You can // instead wrap the pointer with a call to one of the operators Hex(), // Octal(), or CRadix() to interpret the text in another base. The // CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) // prefixes, but defaults to base-10. // // Example: // int a, b, c, d; // pcrecpp::RE re("(.*) (.*) (.*) (.*)"); // re.FullMatch("100 40 0100 0x40", // pcrecpp::Octal(&a), pcrecpp::Hex(&b), // pcrecpp::CRadix(&c), pcrecpp::CRadix(&d)); // will leave 64 in a, b, c, and d. // // ----------------------------------------------------------------------- // REPLACING PARTS OF STRINGS // // You can replace the first match of "pattern" in "str" with // "rewrite". Within "rewrite", backslash-escaped digits (\1 to \9) // can be used to insert text matching corresponding parenthesized // group from the pattern. \0 in "rewrite" refers to the entire // matching text. E.g., // // string s = "yabba dabba doo"; // pcrecpp::RE("b+").Replace("d", &s); // // will leave "s" containing "yada dabba doo". The result is true if // the pattern matches and a replacement occurs, or false otherwise. // // GlobalReplace() is like Replace(), except that it replaces all // occurrences of the pattern in the string with the rewrite. // Replacements are not subject to re-matching. E.g., // // string s = "yabba dabba doo"; // pcrecpp::RE("b+").GlobalReplace("d", &s); // // will leave "s" containing "yada dada doo". It returns the number // of replacements made. // // Extract() is like Replace(), except that if the pattern matches, // "rewrite" is copied into "out" (an additional argument) with // substitutions. The non-matching portions of "text" are ignored. // Returns true iff a match occurred and the extraction happened // successfully. If no match occurs, the string is left unaffected. #include #include #include // defines the Arg class // This isn't technically needed here, but we include it // anyway so folks who include pcrecpp.h don't have to. #include namespace pcrecpp { #define PCRE_SET_OR_CLEAR(b, o) \ if (b) all_options_ |= (o); else all_options_ &= ~(o); \ return *this #define PCRE_IS_SET(o) \ (all_options_ & o) == o /***** Compiling regular expressions: the RE class *****/ // RE_Options allow you to set options to be passed along to pcre, // along with other options we put on top of pcre. // Only 9 modifiers, plus match_limit and match_limit_recursion, // are supported now. class PCRECPP_EXP_DEFN RE_Options { public: // constructor RE_Options() : match_limit_(0), match_limit_recursion_(0), all_options_(0) {} // alternative constructor. // To facilitate transfer of legacy code from C programs // // This lets you do // RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str); // But new code is better off doing // RE(pattern, // RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str); RE_Options(int option_flags) : match_limit_(0), match_limit_recursion_(0), all_options_(option_flags) {} // we're fine with the default destructor, copy constructor, etc. // accessors and mutators int match_limit() const { return match_limit_; }; RE_Options &set_match_limit(int limit) { match_limit_ = limit; return *this; } int match_limit_recursion() const { return match_limit_recursion_; }; RE_Options &set_match_limit_recursion(int limit) { match_limit_recursion_ = limit; return *this; } bool caseless() const { return PCRE_IS_SET(PCRE_CASELESS); } RE_Options &set_caseless(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_CASELESS); } bool multiline() const { return PCRE_IS_SET(PCRE_MULTILINE); } RE_Options &set_multiline(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_MULTILINE); } bool dotall() const { return PCRE_IS_SET(PCRE_DOTALL); } RE_Options &set_dotall(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_DOTALL); } bool extended() const { return PCRE_IS_SET(PCRE_EXTENDED); } RE_Options &set_extended(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_EXTENDED); } bool dollar_endonly() const { return PCRE_IS_SET(PCRE_DOLLAR_ENDONLY); } RE_Options &set_dollar_endonly(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_DOLLAR_ENDONLY); } bool extra() const { return PCRE_IS_SET(PCRE_EXTRA); } RE_Options &set_extra(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_EXTRA); } bool ungreedy() const { return PCRE_IS_SET(PCRE_UNGREEDY); } RE_Options &set_ungreedy(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_UNGREEDY); } bool utf8() const { return PCRE_IS_SET(PCRE_UTF8); } RE_Options &set_utf8(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_UTF8); } bool no_auto_capture() const { return PCRE_IS_SET(PCRE_NO_AUTO_CAPTURE); } RE_Options &set_no_auto_capture(bool x) { PCRE_SET_OR_CLEAR(x, PCRE_NO_AUTO_CAPTURE); } RE_Options &set_all_options(int opt) { all_options_ = opt; return *this; } int all_options() const { return all_options_ ; } // TODO: add other pcre flags private: int match_limit_; int match_limit_recursion_; int all_options_; }; // These functions return some common RE_Options static inline RE_Options UTF8() { return RE_Options().set_utf8(true); } static inline RE_Options CASELESS() { return RE_Options().set_caseless(true); } static inline RE_Options MULTILINE() { return RE_Options().set_multiline(true); } static inline RE_Options DOTALL() { return RE_Options().set_dotall(true); } static inline RE_Options EXTENDED() { return RE_Options().set_extended(true); } // Interface for regular expression matching. Also corresponds to a // pre-compiled regular expression. An "RE" object is safe for // concurrent use by multiple threads. class PCRECPP_EXP_DEFN RE { public: // We provide implicit conversions from strings so that users can // pass in a string or a "const char*" wherever an "RE" is expected. RE(const string& pat) { Init(pat, NULL); } RE(const string& pat, const RE_Options& option) { Init(pat, &option); } RE(const char* pat) { Init(pat, NULL); } RE(const char* pat, const RE_Options& option) { Init(pat, &option); } RE(const unsigned char* pat) { Init(reinterpret_cast(pat), NULL); } RE(const unsigned char* pat, const RE_Options& option) { Init(reinterpret_cast(pat), &option); } // Copy constructor & assignment - note that these are expensive // because they recompile the expression. RE(const RE& re) { Init(re.pattern_, &re.options_); } const RE& operator=(const RE& re) { if (this != &re) { Cleanup(); // This is the code that originally came from Google // Init(re.pattern_.c_str(), &re.options_); // This is the replacement from Ari Pollak Init(re.pattern_, &re.options_); } return *this; } ~RE(); // The string specification for this RE. E.g. // RE re("ab*c?d+"); // re.pattern(); // "ab*c?d+" const string& pattern() const { return pattern_; } // If RE could not be created properly, returns an error string. // Else returns the empty string. const string& error() const { return *error_; } /***** The useful part: the matching interface *****/ // This is provided so one can do pattern.ReplaceAll() just as // easily as ReplaceAll(pattern-text, ....) bool FullMatch(const StringPiece& text, const Arg& ptr1 = no_arg, const Arg& ptr2 = no_arg, const Arg& ptr3 = no_arg, const Arg& ptr4 = no_arg, const Arg& ptr5 = no_arg, const Arg& ptr6 = no_arg, const Arg& ptr7 = no_arg, const Arg& ptr8 = no_arg, const Arg& ptr9 = no_arg, const Arg& ptr10 = no_arg, const Arg& ptr11 = no_arg, const Arg& ptr12 = no_arg, const Arg& ptr13 = no_arg, const Arg& ptr14 = no_arg, const Arg& ptr15 = no_arg, const Arg& ptr16 = no_arg) const; bool PartialMatch(const StringPiece& text, const Arg& ptr1 = no_arg, const Arg& ptr2 = no_arg, const Arg& ptr3 = no_arg, const Arg& ptr4 = no_arg, const Arg& ptr5 = no_arg, const Arg& ptr6 = no_arg, const Arg& ptr7 = no_arg, const Arg& ptr8 = no_arg, const Arg& ptr9 = no_arg, const Arg& ptr10 = no_arg, const Arg& ptr11 = no_arg, const Arg& ptr12 = no_arg, const Arg& ptr13 = no_arg, const Arg& ptr14 = no_arg, const Arg& ptr15 = no_arg, const Arg& ptr16 = no_arg) const; bool Consume(StringPiece* input, const Arg& ptr1 = no_arg, const Arg& ptr2 = no_arg, const Arg& ptr3 = no_arg, const Arg& ptr4 = no_arg, const Arg& ptr5 = no_arg, const Arg& ptr6 = no_arg, const Arg& ptr7 = no_arg, const Arg& ptr8 = no_arg, const Arg& ptr9 = no_arg, const Arg& ptr10 = no_arg, const Arg& ptr11 = no_arg, const Arg& ptr12 = no_arg, const Arg& ptr13 = no_arg, const Arg& ptr14 = no_arg, const Arg& ptr15 = no_arg, const Arg& ptr16 = no_arg) const; bool FindAndConsume(StringPiece* input, const Arg& ptr1 = no_arg, const Arg& ptr2 = no_arg, const Arg& ptr3 = no_arg, const Arg& ptr4 = no_arg, const Arg& ptr5 = no_arg, const Arg& ptr6 = no_arg, const Arg& ptr7 = no_arg, const Arg& ptr8 = no_arg, const Arg& ptr9 = no_arg, const Arg& ptr10 = no_arg, const Arg& ptr11 = no_arg, const Arg& ptr12 = no_arg, const Arg& ptr13 = no_arg, const Arg& ptr14 = no_arg, const Arg& ptr15 = no_arg, const Arg& ptr16 = no_arg) const; bool Replace(const StringPiece& rewrite, string *str) const; int GlobalReplace(const StringPiece& rewrite, string *str) const; bool Extract(const StringPiece &rewrite, const StringPiece &text, string *out) const; // Escapes all potentially meaningful regexp characters in // 'unquoted'. The returned string, used as a regular expression, // will exactly match the original string. For example, // 1.5-2.0? // may become: // 1\.5\-2\.0\? // Note QuoteMeta behaves the same as perl's QuoteMeta function, // *except* that it escapes the NUL character (\0) as backslash + 0, // rather than backslash + NUL. static string QuoteMeta(const StringPiece& unquoted); /***** Generic matching interface *****/ // Type of match (TODO: Should be restructured as part of RE_Options) enum Anchor { UNANCHORED, // No anchoring ANCHOR_START, // Anchor at start only ANCHOR_BOTH // Anchor at start and end }; // General matching routine. Stores the length of the match in // "*consumed" if successful. bool DoMatch(const StringPiece& text, Anchor anchor, int* consumed, const Arg* const* args, int n) const; // Return the number of capturing subpatterns, or -1 if the // regexp wasn't valid on construction. int NumberOfCapturingGroups() const; // The default value for an argument, to indicate the end of the argument // list. This must be used only in optional argument defaults. It should NOT // be passed explicitly. Some people have tried to use it like this: // // FullMatch(x, y, &z, no_arg, &w); // // This is a mistake, and will not work. static Arg no_arg; private: void Init(const string& pattern, const RE_Options* options); void Cleanup(); // Match against "text", filling in "vec" (up to "vecsize" * 2/3) with // pairs of integers for the beginning and end positions of matched // text. The first pair corresponds to the entire matched text; // subsequent pairs correspond, in order, to parentheses-captured // matches. Returns the number of pairs (one more than the number of // the last subpattern with a match) if matching was successful // and zero if the match failed. // I.e. for RE("(foo)|(bar)|(baz)") it will return 2, 3, and 4 when matching // against "foo", "bar", and "baz" respectively. // When matching RE("(foo)|hello") against "hello", it will return 1. // But the values for all subpattern are filled in into "vec". int TryMatch(const StringPiece& text, int startpos, Anchor anchor, bool empty_ok, int *vec, int vecsize) const; // Append the "rewrite" string, with backslash subsitutions from "text" // and "vec", to string "out". bool Rewrite(string *out, const StringPiece& rewrite, const StringPiece& text, int *vec, int veclen) const; // internal implementation for DoMatch bool DoMatchImpl(const StringPiece& text, Anchor anchor, int* consumed, const Arg* const args[], int n, int* vec, int vecsize) const; // Compile the regexp for the specified anchoring mode pcre* Compile(Anchor anchor); string pattern_; RE_Options options_; pcre* re_full_; // For full matches pcre* re_partial_; // For partial matches const string* error_; // Error indicator (or points to empty string) }; } // namespace pcrecpp #endif /* _PCRECPP_H */ ================================================ FILE: src/pcre/pcrecpp_internal.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* Copyright (c) 2005, Google Inc. 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 the University of Cambridge 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 PCRECPP_INTERNAL_H #define PCRECPP_INTERNAL_H /* When compiling a DLL for Windows, the exported symbols have to be declared using some MS magic. I found some useful information on this web page: http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the information there, using __declspec(dllexport) without "extern" we have a definition; with "extern" we have a declaration. The settings here override the setting in pcre.h. We use: PCRECPP_EXP_DECL for declarations PCRECPP_EXP_DEFN for definitions of exported functions */ #ifndef PCRECPP_EXP_DECL # ifdef _WIN32 # ifndef PCRE_STATIC # define PCRECPP_EXP_DECL extern __declspec(dllexport) # define PCRECPP_EXP_DEFN __declspec(dllexport) # else # define PCRECPP_EXP_DECL extern # define PCRECPP_EXP_DEFN # endif # else # define PCRECPP_EXP_DECL extern # define PCRECPP_EXP_DEFN # endif #endif #endif /* PCRECPP_INTERNAL_H */ /* End of pcrecpp_internal.h */ ================================================ FILE: src/pcre/pcrecpp_unittest.cc ================================================ // -*- coding: utf-8 -*- // // Copyright (c) 2005 - 2010, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat // // TODO: Test extractions for PartialMatch/Consume #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include /* for memset and strcmp */ #include #include #include "pcrecpp.h" using std::string; using pcrecpp::StringPiece; using pcrecpp::RE; using pcrecpp::RE_Options; using pcrecpp::Hex; using pcrecpp::Octal; using pcrecpp::CRadix; static bool VERBOSE_TEST = false; // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of // compilation mode. Therefore, it is safe to do things like: // CHECK_EQ(fp->Write(x), 4) #define CHECK(condition) do { \ if (!(condition)) { \ fprintf(stderr, "%s:%d: Check failed: %s\n", \ __FILE__, __LINE__, #condition); \ exit(1); \ } \ } while (0) #define CHECK_EQ(a, b) CHECK(a == b) static void Timing1(int num_iters) { // Same pattern lots of times RE pattern("ruby:\\d+"); StringPiece p("ruby:1234"); for (int j = num_iters; j > 0; j--) { CHECK(pattern.FullMatch(p)); } } static void Timing2(int num_iters) { // Same pattern lots of times RE pattern("ruby:(\\d+)"); int i; for (int j = num_iters; j > 0; j--) { CHECK(pattern.FullMatch("ruby:1234", &i)); CHECK_EQ(i, 1234); } } static void Timing3(int num_iters) { string text_string; for (int j = num_iters; j > 0; j--) { text_string += "this is another line\n"; } RE line_matcher(".*\n"); string line; StringPiece text(text_string); int counter = 0; while (line_matcher.Consume(&text)) { counter++; } printf("Matched %d lines\n", counter); } #if 0 // uncomment this if you have a way of defining VirtualProcessSize() static void LeakTest() { // Check for memory leaks unsigned long long initial_size = 0; for (int i = 0; i < 100000; i++) { if (i == 50000) { initial_size = VirtualProcessSize(); printf("Size after 50000: %llu\n", initial_size); } char buf[100]; // definitely big enough sprintf(buf, "pat%09d", i); RE newre(buf); } uint64 final_size = VirtualProcessSize(); printf("Size after 100000: %llu\n", final_size); const double growth = double(final_size - initial_size) / final_size; printf("Growth: %0.2f%%", growth * 100); CHECK(growth < 0.02); // Allow < 2% growth } #endif static void RadixTests() { printf("Testing hex\n"); #define CHECK_HEX(type, value) \ do { \ type v; \ CHECK(RE("([0-9a-fA-F]+)[uUlL]*").FullMatch(#value, Hex(&v))); \ CHECK_EQ(v, 0x ## value); \ CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0x" #value, CRadix(&v))); \ CHECK_EQ(v, 0x ## value); \ } while(0) CHECK_HEX(short, 2bad); CHECK_HEX(unsigned short, 2badU); CHECK_HEX(int, dead); CHECK_HEX(unsigned int, deadU); CHECK_HEX(long, 7eadbeefL); CHECK_HEX(unsigned long, deadbeefUL); #ifdef HAVE_LONG_LONG CHECK_HEX(long long, 12345678deadbeefLL); #endif #ifdef HAVE_UNSIGNED_LONG_LONG CHECK_HEX(unsigned long long, cafebabedeadbeefULL); #endif #undef CHECK_HEX printf("Testing octal\n"); #define CHECK_OCTAL(type, value) \ do { \ type v; \ CHECK(RE("([0-7]+)[uUlL]*").FullMatch(#value, Octal(&v))); \ CHECK_EQ(v, 0 ## value); \ CHECK(RE("([0-9a-fA-FxX]+)[uUlL]*").FullMatch("0" #value, CRadix(&v))); \ CHECK_EQ(v, 0 ## value); \ } while(0) CHECK_OCTAL(short, 77777); CHECK_OCTAL(unsigned short, 177777U); CHECK_OCTAL(int, 17777777777); CHECK_OCTAL(unsigned int, 37777777777U); CHECK_OCTAL(long, 17777777777L); CHECK_OCTAL(unsigned long, 37777777777UL); #ifdef HAVE_LONG_LONG CHECK_OCTAL(long long, 777777777777777777777LL); #endif #ifdef HAVE_UNSIGNED_LONG_LONG CHECK_OCTAL(unsigned long long, 1777777777777777777777ULL); #endif #undef CHECK_OCTAL printf("Testing decimal\n"); #define CHECK_DECIMAL(type, value) \ do { \ type v; \ CHECK(RE("(-?[0-9]+)[uUlL]*").FullMatch(#value, &v)); \ CHECK_EQ(v, value); \ CHECK(RE("(-?[0-9a-fA-FxX]+)[uUlL]*").FullMatch(#value, CRadix(&v))); \ CHECK_EQ(v, value); \ } while(0) CHECK_DECIMAL(short, -1); CHECK_DECIMAL(unsigned short, 9999); CHECK_DECIMAL(int, -1000); CHECK_DECIMAL(unsigned int, 12345U); CHECK_DECIMAL(long, -10000000L); CHECK_DECIMAL(unsigned long, 3083324652U); #ifdef HAVE_LONG_LONG CHECK_DECIMAL(long long, -100000000000000LL); #endif #ifdef HAVE_UNSIGNED_LONG_LONG CHECK_DECIMAL(unsigned long long, 1234567890987654321ULL); #endif #undef CHECK_DECIMAL } static void TestReplace() { printf("Testing Replace\n"); struct ReplaceTest { const char *regexp; const char *rewrite; const char *original; const char *single; const char *global; int global_count; // the expected return value from ReplaceAll }; static const ReplaceTest tests[] = { { "(qu|[b-df-hj-np-tv-z]*)([a-z]+)", "\\2\\1ay", "the quick brown fox jumps over the lazy dogs.", "ethay quick brown fox jumps over the lazy dogs.", "ethay ickquay ownbray oxfay umpsjay overay ethay azylay ogsday.", 9 }, { "\\w+", "\\0-NOSPAM", "paul.haahr@google.com", "paul-NOSPAM.haahr@google.com", "paul-NOSPAM.haahr-NOSPAM@google-NOSPAM.com-NOSPAM", 4 }, { "^", "(START)", "foo", "(START)foo", "(START)foo", 1 }, { "^", "(START)", "", "(START)", "(START)", 1 }, { "$", "(END)", "", "(END)", "(END)", 1 }, { "b", "bb", "ababababab", "abbabababab", "abbabbabbabbabb", 5 }, { "b", "bb", "bbbbbb", "bbbbbbb", "bbbbbbbbbbbb", 6 }, { "b+", "bb", "bbbbbb", "bb", "bb", 1 }, { "b*", "bb", "bbbbbb", "bb", "bbbb", 2 }, { "b*", "bb", "aaaaa", "bbaaaaa", "bbabbabbabbabbabb", 6 }, { "b*", "bb", "aa\naa\n", "bbaa\naa\n", "bbabbabb\nbbabbabb\nbb", 7 }, { "b*", "bb", "aa\raa\r", "bbaa\raa\r", "bbabbabb\rbbabbabb\rbb", 7 }, { "b*", "bb", "aa\r\naa\r\n", "bbaa\r\naa\r\n", "bbabbabb\r\nbbabbabb\r\nbb", 7 }, // Check empty-string matching (it's tricky!) { "aa|b*", "@", "aa", "@", "@@", 2 }, { "b*|aa", "@", "aa", "@aa", "@@@", 3 }, #ifdef SUPPORT_UTF { "b*", "bb", "\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\xB8", // utf8 "bb\xE3\x83\x9B\xE3\x83\xBC\xE3\x83\xA0\xE3\x81\xB8", "bb\xE3\x83\x9B""bb""\xE3\x83\xBC""bb""\xE3\x83\xA0""bb""\xE3\x81\xB8""bb", 5 }, { "b*", "bb", "\xE3\x83\x9B\r\n\xE3\x83\xBC\r\xE3\x83\xA0\n\xE3\x81\xB8\r\n", // utf8 "bb\xE3\x83\x9B\r\n\xE3\x83\xBC\r\xE3\x83\xA0\n\xE3\x81\xB8\r\n", ("bb\xE3\x83\x9B""bb\r\nbb""\xE3\x83\xBC""bb\rbb""\xE3\x83\xA0" "bb\nbb""\xE3\x81\xB8""bb\r\nbb"), 9 }, #endif { "", NULL, NULL, NULL, NULL, 0 } }; #ifdef SUPPORT_UTF const bool support_utf8 = true; #else const bool support_utf8 = false; #endif for (const ReplaceTest *t = tests; t->original != NULL; ++t) { RE re(t->regexp, RE_Options(PCRE_NEWLINE_CRLF).set_utf8(support_utf8)); assert(re.error().empty()); string one(t->original); CHECK(re.Replace(t->rewrite, &one)); CHECK_EQ(one, t->single); string all(t->original); const int replace_count = re.GlobalReplace(t->rewrite, &all); CHECK_EQ(all, t->global); CHECK_EQ(replace_count, t->global_count); } // One final test: test \r\n replacement when we're not in CRLF mode { RE re("b*", RE_Options(PCRE_NEWLINE_CR).set_utf8(support_utf8)); assert(re.error().empty()); string all("aa\r\naa\r\n"); CHECK_EQ(re.GlobalReplace("bb", &all), 9); CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb")); } { RE re("b*", RE_Options(PCRE_NEWLINE_LF).set_utf8(support_utf8)); assert(re.error().empty()); string all("aa\r\naa\r\n"); CHECK_EQ(re.GlobalReplace("bb", &all), 9); CHECK_EQ(all, string("bbabbabb\rbb\nbbabbabb\rbb\nbb")); } // TODO: test what happens when no PCRE_NEWLINE_* flag is set. // Alas, the answer depends on how pcre was compiled. } static void TestExtract() { printf("Testing Extract\n"); string s; CHECK(RE("(.*)@([^.]*)").Extract("\\2!\\1", "boris@kremvax.ru", &s)); CHECK_EQ(s, "kremvax!boris"); // check the RE interface as well CHECK(RE(".*").Extract("'\\0'", "foo", &s)); CHECK_EQ(s, "'foo'"); CHECK(!RE("bar").Extract("'\\0'", "baz", &s)); CHECK_EQ(s, "'foo'"); } static void TestConsume() { printf("Testing Consume\n"); string word; string s(" aaa b!@#$@#$cccc"); StringPiece input(s); RE r("\\s*(\\w+)"); // matches a word, possibly proceeded by whitespace CHECK(r.Consume(&input, &word)); CHECK_EQ(word, "aaa"); CHECK(r.Consume(&input, &word)); CHECK_EQ(word, "b"); CHECK(! r.Consume(&input, &word)); } static void TestFindAndConsume() { printf("Testing FindAndConsume\n"); string word; string s(" aaa b!@#$@#$cccc"); StringPiece input(s); RE r("(\\w+)"); // matches a word CHECK(r.FindAndConsume(&input, &word)); CHECK_EQ(word, "aaa"); CHECK(r.FindAndConsume(&input, &word)); CHECK_EQ(word, "b"); CHECK(r.FindAndConsume(&input, &word)); CHECK_EQ(word, "cccc"); CHECK(! r.FindAndConsume(&input, &word)); } static void TestMatchNumberPeculiarity() { printf("Testing match-number peculiarity\n"); string word1; string word2; string word3; RE r("(foo)|(bar)|(baz)"); CHECK(r.PartialMatch("foo", &word1, &word2, &word3)); CHECK_EQ(word1, "foo"); CHECK_EQ(word2, ""); CHECK_EQ(word3, ""); CHECK(r.PartialMatch("bar", &word1, &word2, &word3)); CHECK_EQ(word1, ""); CHECK_EQ(word2, "bar"); CHECK_EQ(word3, ""); CHECK(r.PartialMatch("baz", &word1, &word2, &word3)); CHECK_EQ(word1, ""); CHECK_EQ(word2, ""); CHECK_EQ(word3, "baz"); CHECK(!r.PartialMatch("f", &word1, &word2, &word3)); string a; CHECK(RE("(foo)|hello").FullMatch("hello", &a)); CHECK_EQ(a, ""); } static void TestRecursion() { printf("Testing recursion\n"); // Get one string that passes (sometimes), one that never does. string text_good("abcdefghijk"); string text_bad("acdefghijkl"); // According to pcretest, matching text_good against (\w+)*b // requires match_limit of at least 8192, and match_recursion_limit // of at least 37. RE_Options options_ml; options_ml.set_match_limit(8192); RE re("(\\w+)*b", options_ml); CHECK(re.PartialMatch(text_good) == true); CHECK(re.PartialMatch(text_bad) == false); CHECK(re.FullMatch(text_good) == false); CHECK(re.FullMatch(text_bad) == false); options_ml.set_match_limit(1024); RE re2("(\\w+)*b", options_ml); CHECK(re2.PartialMatch(text_good) == false); // because of match_limit CHECK(re2.PartialMatch(text_bad) == false); CHECK(re2.FullMatch(text_good) == false); CHECK(re2.FullMatch(text_bad) == false); RE_Options options_mlr; options_mlr.set_match_limit_recursion(50); RE re3("(\\w+)*b", options_mlr); CHECK(re3.PartialMatch(text_good) == true); CHECK(re3.PartialMatch(text_bad) == false); CHECK(re3.FullMatch(text_good) == false); CHECK(re3.FullMatch(text_bad) == false); options_mlr.set_match_limit_recursion(10); RE re4("(\\w+)*b", options_mlr); CHECK(re4.PartialMatch(text_good) == false); CHECK(re4.PartialMatch(text_bad) == false); CHECK(re4.FullMatch(text_good) == false); CHECK(re4.FullMatch(text_bad) == false); } // A meta-quoted string, interpreted as a pattern, should always match // the original unquoted string. static void TestQuoteMeta(string unquoted, RE_Options options = RE_Options()) { string quoted = RE::QuoteMeta(unquoted); RE re(quoted, options); CHECK(re.FullMatch(unquoted)); } // A string containing meaningful regexp characters, which is then meta- // quoted, should not generally match a string the unquoted string does. static void NegativeTestQuoteMeta(string unquoted, string should_not_match, RE_Options options = RE_Options()) { string quoted = RE::QuoteMeta(unquoted); RE re(quoted, options); CHECK(!re.FullMatch(should_not_match)); } // Tests that quoted meta characters match their original strings, // and that a few things that shouldn't match indeed do not. static void TestQuotaMetaSimple() { TestQuoteMeta("foo"); TestQuoteMeta("foo.bar"); TestQuoteMeta("foo\\.bar"); TestQuoteMeta("[1-9]"); TestQuoteMeta("1.5-2.0?"); TestQuoteMeta("\\d"); TestQuoteMeta("Who doesn't like ice cream?"); TestQuoteMeta("((a|b)c?d*e+[f-h]i)"); TestQuoteMeta("((?!)xxx).*yyy"); TestQuoteMeta("(["); TestQuoteMeta(string("foo\0bar", 7)); } static void TestQuoteMetaSimpleNegative() { NegativeTestQuoteMeta("foo", "bar"); NegativeTestQuoteMeta("...", "bar"); NegativeTestQuoteMeta("\\.", "."); NegativeTestQuoteMeta("\\.", ".."); NegativeTestQuoteMeta("(a)", "a"); NegativeTestQuoteMeta("(a|b)", "a"); NegativeTestQuoteMeta("(a|b)", "(a)"); NegativeTestQuoteMeta("(a|b)", "a|b"); NegativeTestQuoteMeta("[0-9]", "0"); NegativeTestQuoteMeta("[0-9]", "0-9"); NegativeTestQuoteMeta("[0-9]", "[9]"); NegativeTestQuoteMeta("((?!)xxx)", "xxx"); } static void TestQuoteMetaLatin1() { TestQuoteMeta("3\xb2 = 9"); } static void TestQuoteMetaUtf8() { #ifdef SUPPORT_UTF TestQuoteMeta("Pl\xc3\xa1\x63ido Domingo", pcrecpp::UTF8()); TestQuoteMeta("xyz", pcrecpp::UTF8()); // No fancy utf8 TestQuoteMeta("\xc2\xb0", pcrecpp::UTF8()); // 2-byte utf8 (degree symbol) TestQuoteMeta("27\xc2\xb0 degrees", pcrecpp::UTF8()); // As a middle character TestQuoteMeta("\xe2\x80\xb3", pcrecpp::UTF8()); // 3-byte utf8 (double prime) TestQuoteMeta("\xf0\x9d\x85\x9f", pcrecpp::UTF8()); // 4-byte utf8 (music note) TestQuoteMeta("27\xc2\xb0"); // Interpreted as Latin-1, but should still work NegativeTestQuoteMeta("27\xc2\xb0", // 2-byte utf (degree symbol) "27\\\xc2\\\xb0", pcrecpp::UTF8()); #endif } static void TestQuoteMetaAll() { printf("Testing QuoteMeta\n"); TestQuotaMetaSimple(); TestQuoteMetaSimpleNegative(); TestQuoteMetaLatin1(); TestQuoteMetaUtf8(); } // // Options tests contributed by // Giuseppe Maxia, CTO, Stardata s.r.l. // July 2005 // static void GetOneOptionResult( const char *option_name, const char *regex, const char *str, RE_Options options, bool full, string expected) { printf("Testing Option <%s>\n", option_name); if(VERBOSE_TEST) printf("/%s/ finds \"%s\" within \"%s\" \n", regex, expected.c_str(), str); string captured(""); if (full) RE(regex,options).FullMatch(str, &captured); else RE(regex,options).PartialMatch(str, &captured); CHECK_EQ(captured, expected); } static void TestOneOption( const char *option_name, const char *regex, const char *str, RE_Options options, bool full, bool assertive = true) { printf("Testing Option <%s>\n", option_name); if (VERBOSE_TEST) printf("'%s' %s /%s/ \n", str, (assertive? "matches" : "doesn't match"), regex); if (assertive) { if (full) CHECK(RE(regex,options).FullMatch(str)); else CHECK(RE(regex,options).PartialMatch(str)); } else { if (full) CHECK(!RE(regex,options).FullMatch(str)); else CHECK(!RE(regex,options).PartialMatch(str)); } } static void Test_CASELESS() { RE_Options options; RE_Options options2; options.set_caseless(true); TestOneOption("CASELESS (class)", "HELLO", "hello", options, false); TestOneOption("CASELESS (class2)", "HELLO", "hello", options2.set_caseless(true), false); TestOneOption("CASELESS (class)", "^[A-Z]+$", "Hello", options, false); TestOneOption("CASELESS (function)", "HELLO", "hello", pcrecpp::CASELESS(), false); TestOneOption("CASELESS (function)", "^[A-Z]+$", "Hello", pcrecpp::CASELESS(), false); options.set_caseless(false); TestOneOption("no CASELESS", "HELLO", "hello", options, false, false); } static void Test_MULTILINE() { RE_Options options; RE_Options options2; const char *str = "HELLO\n" "cruel\n" "world\n"; options.set_multiline(true); TestOneOption("MULTILINE (class)", "^cruel$", str, options, false); TestOneOption("MULTILINE (class2)", "^cruel$", str, options2.set_multiline(true), false); TestOneOption("MULTILINE (function)", "^cruel$", str, pcrecpp::MULTILINE(), false); options.set_multiline(false); TestOneOption("no MULTILINE", "^cruel$", str, options, false, false); } static void Test_DOTALL() { RE_Options options; RE_Options options2; const char *str = "HELLO\n" "cruel\n" "world"; options.set_dotall(true); TestOneOption("DOTALL (class)", "HELLO.*world", str, options, true); TestOneOption("DOTALL (class2)", "HELLO.*world", str, options2.set_dotall(true), true); TestOneOption("DOTALL (function)", "HELLO.*world", str, pcrecpp::DOTALL(), true); options.set_dotall(false); TestOneOption("no DOTALL", "HELLO.*world", str, options, true, false); } static void Test_DOLLAR_ENDONLY() { RE_Options options; RE_Options options2; const char *str = "HELLO world\n"; TestOneOption("no DOLLAR_ENDONLY", "world$", str, options, false); options.set_dollar_endonly(true); TestOneOption("DOLLAR_ENDONLY 1", "world$", str, options, false, false); TestOneOption("DOLLAR_ENDONLY 2", "world$", str, options2.set_dollar_endonly(true), false, false); } static void Test_EXTRA() { RE_Options options; const char *str = "HELLO"; options.set_extra(true); TestOneOption("EXTRA 1", "\\HELL\\O", str, options, true, false ); TestOneOption("EXTRA 2", "\\HELL\\O", str, RE_Options().set_extra(true), true, false ); options.set_extra(false); TestOneOption("no EXTRA", "\\HELL\\O", str, options, true ); } static void Test_EXTENDED() { RE_Options options; RE_Options options2; const char *str = "HELLO world"; options.set_extended(true); TestOneOption("EXTENDED (class)", "HELLO world", str, options, false, false); TestOneOption("EXTENDED (class2)", "HELLO world", str, options2.set_extended(true), false, false); TestOneOption("EXTENDED (class)", "^ HE L{2} O " "\\s+ " "\\w+ $ ", str, options, false); TestOneOption("EXTENDED (function)", "HELLO world", str, pcrecpp::EXTENDED(), false, false); TestOneOption("EXTENDED (function)", "^ HE L{2} O " "\\s+ " "\\w+ $ ", str, pcrecpp::EXTENDED(), false); options.set_extended(false); TestOneOption("no EXTENDED", "HELLO world", str, options, false); } static void Test_NO_AUTO_CAPTURE() { RE_Options options; const char *str = "HELLO world"; string captured; printf("Testing Option \n"); if (VERBOSE_TEST) printf("parentheses capture text\n"); RE re("(world|universe)$", options); CHECK(re.Extract("\\1", str , &captured)); CHECK_EQ(captured, "world"); options.set_no_auto_capture(true); printf("testing Option \n"); if (VERBOSE_TEST) printf("parentheses do not capture text\n"); re.Extract("\\1",str, &captured ); CHECK_EQ(captured, "world"); } static void Test_UNGREEDY() { RE_Options options; const char *str = "HELLO, 'this' is the 'world'"; options.set_ungreedy(true); GetOneOptionResult("UNGREEDY 1", "('.*')", str, options, false, "'this'" ); GetOneOptionResult("UNGREEDY 2", "('.*')", str, RE_Options().set_ungreedy(true), false, "'this'" ); GetOneOptionResult("UNGREEDY", "('.*?')", str, options, false, "'this' is the 'world'" ); options.set_ungreedy(false); GetOneOptionResult("no UNGREEDY", "('.*')", str, options, false, "'this' is the 'world'" ); GetOneOptionResult("no UNGREEDY", "('.*?')", str, options, false, "'this'" ); } static void Test_all_options() { const char *str = "HELLO\n" "cruel\n" "world"; RE_Options options; options.set_all_options(PCRE_CASELESS | PCRE_DOTALL); TestOneOption("all_options (CASELESS|DOTALL)", "^hello.*WORLD", str , options, false); options.set_all_options(0); TestOneOption("all_options (0)", "^hello.*WORLD", str , options, false, false); options.set_all_options(PCRE_MULTILINE | PCRE_EXTENDED); TestOneOption("all_options (MULTILINE|EXTENDED)", " ^ c r u e l $ ", str, options, false); TestOneOption("all_options (MULTILINE|EXTENDED) with constructor", " ^ c r u e l $ ", str, RE_Options(PCRE_MULTILINE | PCRE_EXTENDED), false); TestOneOption("all_options (MULTILINE|EXTENDED) with concatenation", " ^ c r u e l $ ", str, RE_Options() .set_multiline(true) .set_extended(true), false); options.set_all_options(0); TestOneOption("all_options (0)", "^ c r u e l $", str, options, false, false); } static void TestOptions() { printf("Testing Options\n"); Test_CASELESS(); Test_MULTILINE(); Test_DOTALL(); Test_DOLLAR_ENDONLY(); Test_EXTENDED(); Test_NO_AUTO_CAPTURE(); Test_UNGREEDY(); Test_EXTRA(); Test_all_options(); } static void TestConstructors() { printf("Testing constructors\n"); RE_Options options; options.set_dotall(true); const char *str = "HELLO\n" "cruel\n" "world"; RE orig("HELLO.*world", options); CHECK(orig.FullMatch(str)); RE copy1(orig); CHECK(copy1.FullMatch(str)); RE copy2("not a match"); CHECK(!copy2.FullMatch(str)); copy2 = copy1; CHECK(copy2.FullMatch(str)); copy2 = orig; CHECK(copy2.FullMatch(str)); // Make sure when we assign to ourselves, nothing bad happens orig = orig; copy1 = copy1; copy2 = copy2; CHECK(orig.FullMatch(str)); CHECK(copy1.FullMatch(str)); CHECK(copy2.FullMatch(str)); } int main(int argc, char** argv) { // Treat any flag as --help if (argc > 1 && argv[1][0] == '-') { printf("Usage: %s [timing1|timing2|timing3 num-iters]\n" " If 'timingX ###' is specified, run the given timing test\n" " with the given number of iterations, rather than running\n" " the default corectness test.\n", argv[0]); return 0; } if (argc > 1) { if ( argc == 2 || atoi(argv[2]) == 0) { printf("timing mode needs a num-iters argument\n"); return 1; } if (!strcmp(argv[1], "timing1")) Timing1(atoi(argv[2])); else if (!strcmp(argv[1], "timing2")) Timing2(atoi(argv[2])); else if (!strcmp(argv[1], "timing3")) Timing3(atoi(argv[2])); else printf("Unknown argument '%s'\n", argv[1]); return 0; } printf("PCRE C++ wrapper tests\n"); printf("Testing FullMatch\n"); int i; string s; /***** FullMatch with no args *****/ CHECK(RE("h.*o").FullMatch("hello")); CHECK(!RE("h.*o").FullMatch("othello")); // Must be anchored at front CHECK(!RE("h.*o").FullMatch("hello!")); // Must be anchored at end CHECK(RE("a*").FullMatch("aaaa")); // Fullmatch with normal op CHECK(RE("a*?").FullMatch("aaaa")); // Fullmatch with nongreedy op CHECK(RE("a*?\\z").FullMatch("aaaa")); // Two unusual ops /***** FullMatch with args *****/ // Zero-arg CHECK(RE("\\d+").FullMatch("1001")); // Single-arg CHECK(RE("(\\d+)").FullMatch("1001", &i)); CHECK_EQ(i, 1001); CHECK(RE("(-?\\d+)").FullMatch("-123", &i)); CHECK_EQ(i, -123); CHECK(!RE("()\\d+").FullMatch("10", &i)); CHECK(!RE("(\\d+)").FullMatch("1234567890123456789012345678901234567890", &i)); // Digits surrounding integer-arg CHECK(RE("1(\\d*)4").FullMatch("1234", &i)); CHECK_EQ(i, 23); CHECK(RE("(\\d)\\d+").FullMatch("1234", &i)); CHECK_EQ(i, 1); CHECK(RE("(-\\d)\\d+").FullMatch("-1234", &i)); CHECK_EQ(i, -1); CHECK(RE("(\\d)").PartialMatch("1234", &i)); CHECK_EQ(i, 1); CHECK(RE("(-\\d)").PartialMatch("-1234", &i)); CHECK_EQ(i, -1); // String-arg CHECK(RE("h(.*)o").FullMatch("hello", &s)); CHECK_EQ(s, string("ell")); // StringPiece-arg StringPiece sp; CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &sp, &i)); CHECK_EQ(sp.size(), 4); CHECK(memcmp(sp.data(), "ruby", 4) == 0); CHECK_EQ(i, 1234); // Multi-arg CHECK(RE("(\\w+):(\\d+)").FullMatch("ruby:1234", &s, &i)); CHECK_EQ(s, string("ruby")); CHECK_EQ(i, 1234); // Ignore non-void* NULL arg CHECK(RE("he(.*)lo").FullMatch("hello", (char*)NULL)); CHECK(RE("h(.*)o").FullMatch("hello", (string*)NULL)); CHECK(RE("h(.*)o").FullMatch("hello", (StringPiece*)NULL)); CHECK(RE("(.*)").FullMatch("1234", (int*)NULL)); #ifdef HAVE_LONG_LONG CHECK(RE("(.*)").FullMatch("1234567890123456", (long long*)NULL)); #endif CHECK(RE("(.*)").FullMatch("123.4567890123456", (double*)NULL)); CHECK(RE("(.*)").FullMatch("123.4567890123456", (float*)NULL)); // Fail on non-void* NULL arg if the match doesn't parse for the given type. CHECK(!RE("h(.*)lo").FullMatch("hello", &s, (char*)NULL)); CHECK(!RE("(.*)").FullMatch("hello", (int*)NULL)); CHECK(!RE("(.*)").FullMatch("1234567890123456", (int*)NULL)); CHECK(!RE("(.*)").FullMatch("hello", (double*)NULL)); CHECK(!RE("(.*)").FullMatch("hello", (float*)NULL)); // Ignored arg CHECK(RE("(\\w+)(:)(\\d+)").FullMatch("ruby:1234", &s, (void*)NULL, &i)); CHECK_EQ(s, string("ruby")); CHECK_EQ(i, 1234); // Type tests { char c; CHECK(RE("(H)ello").FullMatch("Hello", &c)); CHECK_EQ(c, 'H'); } { unsigned char c; CHECK(RE("(H)ello").FullMatch("Hello", &c)); CHECK_EQ(c, static_cast('H')); } { short v; CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); CHECK(RE("(-?\\d+)").FullMatch("-100", &v)); CHECK_EQ(v, -100); CHECK(RE("(-?\\d+)").FullMatch("32767", &v)); CHECK_EQ(v, 32767); CHECK(RE("(-?\\d+)").FullMatch("-32768", &v)); CHECK_EQ(v, -32768); CHECK(!RE("(-?\\d+)").FullMatch("-32769", &v)); CHECK(!RE("(-?\\d+)").FullMatch("32768", &v)); } { unsigned short v; CHECK(RE("(\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); CHECK(RE("(\\d+)").FullMatch("32767", &v)); CHECK_EQ(v, 32767); CHECK(RE("(\\d+)").FullMatch("65535", &v)); CHECK_EQ(v, 65535); CHECK(!RE("(\\d+)").FullMatch("65536", &v)); } { int v; static const int max_value = 0x7fffffff; static const int min_value = -max_value - 1; CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); CHECK(RE("(-?\\d+)").FullMatch("-100", &v)); CHECK_EQ(v, -100); CHECK(RE("(-?\\d+)").FullMatch("2147483647", &v)); CHECK_EQ(v, max_value); CHECK(RE("(-?\\d+)").FullMatch("-2147483648", &v)); CHECK_EQ(v, min_value); CHECK(!RE("(-?\\d+)").FullMatch("-2147483649", &v)); CHECK(!RE("(-?\\d+)").FullMatch("2147483648", &v)); } { unsigned int v; static const unsigned int max_value = 0xfffffffful; CHECK(RE("(\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); CHECK(RE("(\\d+)").FullMatch("4294967295", &v)); CHECK_EQ(v, max_value); CHECK(!RE("(\\d+)").FullMatch("4294967296", &v)); } #ifdef HAVE_LONG_LONG # if defined(__MINGW__) || defined(__MINGW32__) # define LLD "%I64d" # define LLU "%I64u" # else # define LLD "%lld" # define LLU "%llu" # endif { long long v; static const long long max_value = 0x7fffffffffffffffLL; static const long long min_value = -max_value - 1; char buf[32]; // definitely big enough for a long long CHECK(RE("(-?\\d+)").FullMatch("100", &v)); CHECK_EQ(v, 100); CHECK(RE("(-?\\d+)").FullMatch("-100",&v)); CHECK_EQ(v, -100); sprintf(buf, LLD, max_value); CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value); sprintf(buf, LLD, min_value); CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, min_value); sprintf(buf, LLD, max_value); assert(buf[strlen(buf)-1] != '9'); buf[strlen(buf)-1]++; CHECK(!RE("(-?\\d+)").FullMatch(buf, &v)); sprintf(buf, LLD, min_value); assert(buf[strlen(buf)-1] != '9'); buf[strlen(buf)-1]++; CHECK(!RE("(-?\\d+)").FullMatch(buf, &v)); } #endif #if defined HAVE_UNSIGNED_LONG_LONG && defined HAVE_LONG_LONG { unsigned long long v; long long v2; static const unsigned long long max_value = 0xffffffffffffffffULL; char buf[32]; // definitely big enough for a unsigned long long CHECK(RE("(-?\\d+)").FullMatch("100",&v)); CHECK_EQ(v, 100); CHECK(RE("(-?\\d+)").FullMatch("-100",&v2)); CHECK_EQ(v2, -100); sprintf(buf, LLU, max_value); CHECK(RE("(-?\\d+)").FullMatch(buf,&v)); CHECK_EQ(v, max_value); assert(buf[strlen(buf)-1] != '9'); buf[strlen(buf)-1]++; CHECK(!RE("(-?\\d+)").FullMatch(buf, &v)); } #endif { float v; CHECK(RE("(.*)").FullMatch("100", &v)); CHECK(RE("(.*)").FullMatch("-100.", &v)); CHECK(RE("(.*)").FullMatch("1e23", &v)); } { double v; CHECK(RE("(.*)").FullMatch("100", &v)); CHECK(RE("(.*)").FullMatch("-100.", &v)); CHECK(RE("(.*)").FullMatch("1e23", &v)); } // Check that matching is fully anchored CHECK(!RE("(\\d+)").FullMatch("x1001", &i)); CHECK(!RE("(\\d+)").FullMatch("1001x", &i)); CHECK(RE("x(\\d+)").FullMatch("x1001", &i)); CHECK_EQ(i, 1001); CHECK(RE("(\\d+)x").FullMatch("1001x", &i)); CHECK_EQ(i, 1001); // Braces CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcd")); CHECK(RE("[0-9a-f+.-]{5,}").FullMatch("0abcde")); CHECK(!RE("[0-9a-f+.-]{5,}").FullMatch("0abc")); // Complicated RE CHECK(RE("foo|bar|[A-Z]").FullMatch("foo")); CHECK(RE("foo|bar|[A-Z]").FullMatch("bar")); CHECK(RE("foo|bar|[A-Z]").FullMatch("X")); CHECK(!RE("foo|bar|[A-Z]").FullMatch("XY")); // Check full-match handling (needs '$' tacked on internally) CHECK(RE("fo|foo").FullMatch("fo")); CHECK(RE("fo|foo").FullMatch("foo")); CHECK(RE("fo|foo$").FullMatch("fo")); CHECK(RE("fo|foo$").FullMatch("foo")); CHECK(RE("foo$").FullMatch("foo")); CHECK(!RE("foo\\$").FullMatch("foo$bar")); CHECK(!RE("fo|bar").FullMatch("fox")); // Uncomment the following if we change the handling of '$' to // prevent it from matching a trailing newline if (false) { // Check that we don't get bitten by pcre's special handling of a // '\n' at the end of the string matching '$' CHECK(!RE("foo$").PartialMatch("foo\n")); } // Number of args int a[16]; CHECK(RE("").FullMatch("")); memset(a, 0, sizeof(0)); CHECK(RE("(\\d){1}").FullMatch("1", &a[0])); CHECK_EQ(a[0], 1); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)").FullMatch("12", &a[0], &a[1])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)(\\d)").FullMatch("123", &a[0], &a[1], &a[2])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); CHECK_EQ(a[2], 3); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)(\\d)(\\d)").FullMatch("1234", &a[0], &a[1], &a[2], &a[3])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); CHECK_EQ(a[2], 3); CHECK_EQ(a[3], 4); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("12345", &a[0], &a[1], &a[2], &a[3], &a[4])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); CHECK_EQ(a[2], 3); CHECK_EQ(a[3], 4); CHECK_EQ(a[4], 5); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("123456", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); CHECK_EQ(a[2], 3); CHECK_EQ(a[3], 4); CHECK_EQ(a[4], 5); CHECK_EQ(a[5], 6); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch("1234567", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); CHECK_EQ(a[2], 3); CHECK_EQ(a[3], 4); CHECK_EQ(a[4], 5); CHECK_EQ(a[5], 6); CHECK_EQ(a[6], 7); memset(a, 0, sizeof(0)); CHECK(RE("(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)" "(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)").FullMatch( "1234567890123456", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9], &a[10], &a[11], &a[12], &a[13], &a[14], &a[15])); CHECK_EQ(a[0], 1); CHECK_EQ(a[1], 2); CHECK_EQ(a[2], 3); CHECK_EQ(a[3], 4); CHECK_EQ(a[4], 5); CHECK_EQ(a[5], 6); CHECK_EQ(a[6], 7); CHECK_EQ(a[7], 8); CHECK_EQ(a[8], 9); CHECK_EQ(a[9], 0); CHECK_EQ(a[10], 1); CHECK_EQ(a[11], 2); CHECK_EQ(a[12], 3); CHECK_EQ(a[13], 4); CHECK_EQ(a[14], 5); CHECK_EQ(a[15], 6); /***** PartialMatch *****/ printf("Testing PartialMatch\n"); CHECK(RE("h.*o").PartialMatch("hello")); CHECK(RE("h.*o").PartialMatch("othello")); CHECK(RE("h.*o").PartialMatch("hello!")); CHECK(RE("((((((((((((((((((((x))))))))))))))))))))").PartialMatch("x")); /***** other tests *****/ RadixTests(); TestReplace(); TestExtract(); TestConsume(); TestFindAndConsume(); TestQuoteMetaAll(); TestMatchNumberPeculiarity(); // Check the pattern() accessor { const string kPattern = "http://([^/]+)/.*"; const RE re(kPattern); CHECK_EQ(kPattern, re.pattern()); } // Check RE error field. { RE re("foo"); CHECK(re.error().empty()); // Must have no error } #ifdef SUPPORT_UTF // Check UTF-8 handling { printf("Testing UTF-8 handling\n"); // Three Japanese characters (nihongo) const unsigned char utf8_string[] = { 0xe6, 0x97, 0xa5, // 65e5 0xe6, 0x9c, 0xac, // 627c 0xe8, 0xaa, 0x9e, // 8a9e 0 }; const unsigned char utf8_pattern[] = { '.', 0xe6, 0x9c, 0xac, // 627c '.', 0 }; // Both should match in either mode, bytes or UTF-8 RE re_test1("........."); CHECK(re_test1.FullMatch(utf8_string)); RE re_test2("...", pcrecpp::UTF8()); CHECK(re_test2.FullMatch(utf8_string)); // PH added these tests for leading option settings RE re_testZ0("(*CR)(*NO_START_OPT)........."); CHECK(re_testZ0.FullMatch(utf8_string)); #ifdef SUPPORT_UTF RE re_testZ1("(*UTF8)..."); CHECK(re_testZ1.FullMatch(utf8_string)); RE re_testZ2("(*UTF)..."); CHECK(re_testZ2.FullMatch(utf8_string)); #ifdef SUPPORT_UCP RE re_testZ3("(*UCP)(*UTF)..."); CHECK(re_testZ3.FullMatch(utf8_string)); RE re_testZ4("(*UCP)(*LIMIT_MATCH=1000)(*UTF)..."); CHECK(re_testZ4.FullMatch(utf8_string)); RE re_testZ5("(*UCP)(*LIMIT_MATCH=1000)(*ANY)(*UTF)..."); CHECK(re_testZ5.FullMatch(utf8_string)); #endif #endif // Check that '.' matches one byte or UTF-8 character // according to the mode. string ss; RE re_test3("(.)"); CHECK(re_test3.PartialMatch(utf8_string, &ss)); CHECK_EQ(ss, string("\xe6")); RE re_test4("(.)", pcrecpp::UTF8()); CHECK(re_test4.PartialMatch(utf8_string, &ss)); CHECK_EQ(ss, string("\xe6\x97\xa5")); // Check that string matches itself in either mode RE re_test5(utf8_string); CHECK(re_test5.FullMatch(utf8_string)); RE re_test6(utf8_string, pcrecpp::UTF8()); CHECK(re_test6.FullMatch(utf8_string)); // Check that pattern matches string only in UTF8 mode RE re_test7(utf8_pattern); CHECK(!re_test7.FullMatch(utf8_string)); RE re_test8(utf8_pattern, pcrecpp::UTF8()); CHECK(re_test8.FullMatch(utf8_string)); } // Check that ungreedy, UTF8 regular expressions don't match when they // oughtn't -- see bug 82246. { // This code always worked. const char* pattern = "\\w+X"; const string target = "a aX"; RE match_sentence(pattern); RE match_sentence_re(pattern, pcrecpp::UTF8()); CHECK(!match_sentence.FullMatch(target)); CHECK(!match_sentence_re.FullMatch(target)); } { const char* pattern = "(?U)\\w+X"; const string target = "a aX"; RE match_sentence(pattern); RE match_sentence_re(pattern, pcrecpp::UTF8()); CHECK(!match_sentence.FullMatch(target)); CHECK(!match_sentence_re.FullMatch(target)); } #endif /* def SUPPORT_UTF */ printf("Testing error reporting\n"); { RE re("a\\1"); CHECK(!re.error().empty()); } { RE re("a[x"); CHECK(!re.error().empty()); } { RE re("a[z-a]"); CHECK(!re.error().empty()); } { RE re("a[[:foobar:]]"); CHECK(!re.error().empty()); } { RE re("a(b"); CHECK(!re.error().empty()); } { RE re("a\\"); CHECK(!re.error().empty()); } // Test that recursion is stopped TestRecursion(); // Test Options if (getenv("VERBOSE_TEST") != NULL) VERBOSE_TEST = true; TestOptions(); // Test the constructors TestConstructors(); // Done printf("OK\n"); return 0; } ================================================ FILE: src/pcre/pcrecpparg.h.in ================================================ // Copyright (c) 2005, Google Inc. // 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 Google Inc. 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. // // Author: Sanjay Ghemawat #ifndef _PCRECPPARG_H #define _PCRECPPARG_H #include // for NULL #include #include namespace pcrecpp { class StringPiece; // Hex/Octal/Binary? // Special class for parsing into objects that define a ParseFrom() method template class _RE_MatchObject { public: static inline bool Parse(const char* str, int n, void* dest) { if (dest == NULL) return true; T* object = reinterpret_cast(dest); return object->ParseFrom(str, n); } }; class PCRECPP_EXP_DEFN Arg { public: // Empty constructor so we can declare arrays of Arg Arg(); // Constructor specially designed for NULL arguments Arg(void*); typedef bool (*Parser)(const char* str, int n, void* dest); // Type-specific parsers #define PCRE_MAKE_PARSER(type,name) \ Arg(type* p) : arg_(p), parser_(name) { } \ Arg(type* p, Parser parser) : arg_(p), parser_(parser) { } PCRE_MAKE_PARSER(char, parse_char); PCRE_MAKE_PARSER(unsigned char, parse_uchar); PCRE_MAKE_PARSER(short, parse_short); PCRE_MAKE_PARSER(unsigned short, parse_ushort); PCRE_MAKE_PARSER(int, parse_int); PCRE_MAKE_PARSER(unsigned int, parse_uint); PCRE_MAKE_PARSER(long, parse_long); PCRE_MAKE_PARSER(unsigned long, parse_ulong); #if @pcre_have_long_long@ PCRE_MAKE_PARSER(long long, parse_longlong); #endif #if @pcre_have_ulong_long@ PCRE_MAKE_PARSER(unsigned long long, parse_ulonglong); #endif PCRE_MAKE_PARSER(float, parse_float); PCRE_MAKE_PARSER(double, parse_double); PCRE_MAKE_PARSER(std::string, parse_string); PCRE_MAKE_PARSER(StringPiece, parse_stringpiece); #undef PCRE_MAKE_PARSER // Generic constructor template Arg(T*, Parser parser); // Generic constructor template template Arg(T* p) : arg_(p), parser_(_RE_MatchObject::Parse) { } // Parse the data bool Parse(const char* str, int n) const; private: void* arg_; Parser parser_; static bool parse_null (const char* str, int n, void* dest); static bool parse_char (const char* str, int n, void* dest); static bool parse_uchar (const char* str, int n, void* dest); static bool parse_float (const char* str, int n, void* dest); static bool parse_double (const char* str, int n, void* dest); static bool parse_string (const char* str, int n, void* dest); static bool parse_stringpiece (const char* str, int n, void* dest); #define PCRE_DECLARE_INTEGER_PARSER(name) \ private: \ static bool parse_ ## name(const char* str, int n, void* dest); \ static bool parse_ ## name ## _radix( \ const char* str, int n, void* dest, int radix); \ public: \ static bool parse_ ## name ## _hex(const char* str, int n, void* dest); \ static bool parse_ ## name ## _octal(const char* str, int n, void* dest); \ static bool parse_ ## name ## _cradix(const char* str, int n, void* dest) PCRE_DECLARE_INTEGER_PARSER(short); PCRE_DECLARE_INTEGER_PARSER(ushort); PCRE_DECLARE_INTEGER_PARSER(int); PCRE_DECLARE_INTEGER_PARSER(uint); PCRE_DECLARE_INTEGER_PARSER(long); PCRE_DECLARE_INTEGER_PARSER(ulong); PCRE_DECLARE_INTEGER_PARSER(longlong); PCRE_DECLARE_INTEGER_PARSER(ulonglong); #undef PCRE_DECLARE_INTEGER_PARSER }; inline Arg::Arg() : arg_(NULL), parser_(parse_null) { } inline Arg::Arg(void* p) : arg_(p), parser_(parse_null) { } inline bool Arg::Parse(const char* str, int n) const { return (*parser_)(str, n, arg_); } // This part of the parser, appropriate only for ints, deals with bases #define MAKE_INTEGER_PARSER(type, name) \ inline Arg Hex(type* ptr) { \ return Arg(ptr, Arg::parse_ ## name ## _hex); } \ inline Arg Octal(type* ptr) { \ return Arg(ptr, Arg::parse_ ## name ## _octal); } \ inline Arg CRadix(type* ptr) { \ return Arg(ptr, Arg::parse_ ## name ## _cradix); } MAKE_INTEGER_PARSER(short, short) /* */ MAKE_INTEGER_PARSER(unsigned short, ushort) /* */ MAKE_INTEGER_PARSER(int, int) /* Don't use semicolons */ MAKE_INTEGER_PARSER(unsigned int, uint) /* after these statement */ MAKE_INTEGER_PARSER(long, long) /* because they can cause */ MAKE_INTEGER_PARSER(unsigned long, ulong) /* compiler warnings if */ #if @pcre_have_long_long@ /* the checking level is */ MAKE_INTEGER_PARSER(long long, longlong) /* turned up high enough. */ #endif /* */ #if @pcre_have_ulong_long@ /* */ MAKE_INTEGER_PARSER(unsigned long long, ulonglong) /* */ #endif #undef PCRE_IS_SET #undef PCRE_SET_OR_CLEAR #undef MAKE_INTEGER_PARSER } // namespace pcrecpp #endif /* _PCRECPPARG_H */ ================================================ FILE: src/pcre/pcredemo.c ================================================ /************************************************* * PCRE DEMONSTRATION PROGRAM * *************************************************/ /* This is a demonstration program to illustrate the most straightforward ways of calling the PCRE regular expression library from a C program. See the pcresample documentation for a short discussion ("man pcresample" if you have the PCRE man pages installed). In Unix-like environments, if PCRE is installed in your standard system libraries, you should be able to compile this program using this command: gcc -Wall pcredemo.c -lpcre -o pcredemo If PCRE is not installed in a standard place, it is likely to be installed with support for the pkg-config mechanism. If you have pkg-config, you can compile this program using this command: gcc -Wall pcredemo.c `pkg-config --cflags --libs libpcre` -o pcredemo If you do not have pkg-config, you may have to use this: gcc -Wall pcredemo.c -I/usr/local/include -L/usr/local/lib \ -R/usr/local/lib -lpcre -o pcredemo Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and library files for PCRE are installed on your system. Only some operating systems (e.g. Solaris) use the -R option. Building under Windows: If you want to statically link this program against a non-dll .a file, you must define PCRE_STATIC before including pcre.h, otherwise the pcre_malloc() and pcre_free() exported functions will be declared __declspec(dllimport), with unwanted results. So in this environment, uncomment the following line. */ /* #define PCRE_STATIC */ #include #include #include #define OVECCOUNT 30 /* should be a multiple of 3 */ int main(int argc, char **argv) { pcre *re; const char *error; char *pattern; char *subject; unsigned char *name_table; unsigned int option_bits; int erroffset; int find_all; int crlf_is_newline; int namecount; int name_entry_size; int ovector[OVECCOUNT]; int subject_length; int rc, i; int utf8; /************************************************************************** * First, sort out the command line. There is only one possible option at * * the moment, "-g" to request repeated matching to find all occurrences, * * like Perl's /g option. We set the variable find_all to a non-zero value * * if the -g option is present. Apart from that, there must be exactly two * * arguments. * **************************************************************************/ find_all = 0; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-g") == 0) find_all = 1; else break; } /* After the options, we require exactly two arguments, which are the pattern, and the subject string. */ if (argc - i != 2) { printf("Two arguments required: a regex and a subject string\n"); return 1; } pattern = argv[i]; subject = argv[i+1]; subject_length = (int)strlen(subject); /************************************************************************* * Now we are going to compile the regular expression pattern, and handle * * and errors that are detected. * *************************************************************************/ re = pcre_compile( pattern, /* the pattern */ 0, /* default options */ &error, /* for error message */ &erroffset, /* for error offset */ NULL); /* use default character tables */ /* Compilation failed: print the error message and exit */ if (re == NULL) { printf("PCRE compilation failed at offset %d: %s\n", erroffset, error); return 1; } /************************************************************************* * If the compilation succeeded, we call PCRE again, in order to do a * * pattern match against the subject string. This does just ONE match. If * * further matching is needed, it will be done below. * *************************************************************************/ rc = pcre_exec( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ subject, /* the subject string */ subject_length, /* the length of the subject */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* output vector for substring information */ OVECCOUNT); /* number of elements in the output vector */ /* Matching failed: handle error cases */ if (rc < 0) { switch(rc) { case PCRE_ERROR_NOMATCH: printf("No match\n"); break; /* Handle other special cases if you like */ default: printf("Matching error %d\n", rc); break; } pcre_free(re); /* Release memory used for the compiled pattern */ return 1; } /* Match succeded */ printf("\nMatch succeeded at offset %d\n", ovector[0]); /************************************************************************* * We have found the first match within the subject string. If the output * * vector wasn't big enough, say so. Then output any substrings that were * * captured. * *************************************************************************/ /* The output vector wasn't big enough */ if (rc == 0) { rc = OVECCOUNT/3; printf("ovector only has room for %d captured substrings\n", rc - 1); } /* Show substrings stored in the output vector by number. Obviously, in a real application you might want to do things other than print them. */ for (i = 0; i < rc; i++) { char *substring_start = subject + ovector[2*i]; int substring_length = ovector[2*i+1] - ovector[2*i]; printf("%2d: %.*s\n", i, substring_length, substring_start); } /************************************************************************** * That concludes the basic part of this demonstration program. We have * * compiled a pattern, and performed a single match. The code that follows * * shows first how to access named substrings, and then how to code for * * repeated matches on the same subject. * **************************************************************************/ /* See if there are any named substrings, and if so, show them by name. First we have to extract the count of named parentheses from the pattern. */ (void)pcre_fullinfo( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_NAMECOUNT, /* number of named substrings */ &namecount); /* where to put the answer */ if (namecount <= 0) printf("No named substrings\n"); else { unsigned char *tabptr; printf("Named substrings\n"); /* Before we can access the substrings, we must extract the table for translating names to numbers, and the size of each entry in the table. */ (void)pcre_fullinfo( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_NAMETABLE, /* address of the table */ &name_table); /* where to put the answer */ (void)pcre_fullinfo( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ PCRE_INFO_NAMEENTRYSIZE, /* size of each entry in the table */ &name_entry_size); /* where to put the answer */ /* Now we can scan the table and, for each entry, print the number, the name, and the substring itself. */ tabptr = name_table; for (i = 0; i < namecount; i++) { int n = (tabptr[0] << 8) | tabptr[1]; printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2, ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]); tabptr += name_entry_size; } } /************************************************************************* * If the "-g" option was given on the command line, we want to continue * * to search for additional matches in the subject string, in a similar * * way to the /g option in Perl. This turns out to be trickier than you * * might think because of the possibility of matching an empty string. * * What happens is as follows: * * * * If the previous match was NOT for an empty string, we can just start * * the next match at the end of the previous one. * * * * If the previous match WAS for an empty string, we can't do that, as it * * would lead to an infinite loop. Instead, a special call of pcre_exec() * * is made with the PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED flags set. * * The first of these tells PCRE that an empty string at the start of the * * subject is not a valid match; other possibilities must be tried. The * * second flag restricts PCRE to one match attempt at the initial string * * position. If this match succeeds, an alternative to the empty string * * match has been found, and we can print it and proceed round the loop, * * advancing by the length of whatever was found. If this match does not * * succeed, we still stay in the loop, advancing by just one character. * * In UTF-8 mode, which can be set by (*UTF8) in the pattern, this may be * * more than one byte. * * * * However, there is a complication concerned with newlines. When the * * newline convention is such that CRLF is a valid newline, we must * * advance by two characters rather than one. The newline convention can * * be set in the regex by (*CR), etc.; if not, we must find the default. * *************************************************************************/ if (!find_all) /* Check for -g */ { pcre_free(re); /* Release the memory used for the compiled pattern */ return 0; /* Finish unless -g was given */ } /* Before running the loop, check for UTF-8 and whether CRLF is a valid newline sequence. First, find the options with which the regex was compiled; extract the UTF-8 state, and mask off all but the newline options. */ (void)pcre_fullinfo(re, NULL, PCRE_INFO_OPTIONS, &option_bits); utf8 = option_bits & PCRE_UTF8; option_bits &= PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_CRLF| PCRE_NEWLINE_ANY|PCRE_NEWLINE_ANYCRLF; /* If no newline options were set, find the default newline convention from the build configuration. */ if (option_bits == 0) { int d; (void)pcre_config(PCRE_CONFIG_NEWLINE, &d); /* Note that these values are always the ASCII ones, even in EBCDIC environments. CR = 13, NL = 10. */ option_bits = (d == 13)? PCRE_NEWLINE_CR : (d == 10)? PCRE_NEWLINE_LF : (d == (13<<8 | 10))? PCRE_NEWLINE_CRLF : (d == -2)? PCRE_NEWLINE_ANYCRLF : (d == -1)? PCRE_NEWLINE_ANY : 0; } /* See if CRLF is a valid newline sequence. */ crlf_is_newline = option_bits == PCRE_NEWLINE_ANY || option_bits == PCRE_NEWLINE_CRLF || option_bits == PCRE_NEWLINE_ANYCRLF; /* Loop for second and subsequent matches */ for (;;) { int options = 0; /* Normally no options */ int start_offset = ovector[1]; /* Start at end of previous match */ /* If the previous match was for an empty string, we are finished if we are at the end of the subject. Otherwise, arrange to run another match at the same point to see if a non-empty match can be found. */ if (ovector[0] == ovector[1]) { if (ovector[0] == subject_length) break; options = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED; } /* Run the next matching operation */ rc = pcre_exec( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ subject, /* the subject string */ subject_length, /* the length of the subject */ start_offset, /* starting offset in the subject */ options, /* options */ ovector, /* output vector for substring information */ OVECCOUNT); /* number of elements in the output vector */ /* This time, a result of NOMATCH isn't an error. If the value in "options" is zero, it just means we have found all possible matches, so the loop ends. Otherwise, it means we have failed to find a non-empty-string match at a point where there was a previous empty-string match. In this case, we do what Perl does: advance the matching position by one character, and continue. We do this by setting the "end of previous match" offset, because that is picked up at the top of the loop as the point at which to start again. There are two complications: (a) When CRLF is a valid newline sequence, and the current position is just before it, advance by an extra byte. (b) Otherwise we must ensure that we skip an entire UTF-8 character if we are in UTF-8 mode. */ if (rc == PCRE_ERROR_NOMATCH) { if (options == 0) break; /* All matches found */ ovector[1] = start_offset + 1; /* Advance one byte */ if (crlf_is_newline && /* If CRLF is newline & */ start_offset < subject_length - 1 && /* we are at CRLF, */ subject[start_offset] == '\r' && subject[start_offset + 1] == '\n') ovector[1] += 1; /* Advance by one more. */ else if (utf8) /* Otherwise, ensure we */ { /* advance a whole UTF-8 */ while (ovector[1] < subject_length) /* character. */ { if ((subject[ovector[1]] & 0xc0) != 0x80) break; ovector[1] += 1; } } continue; /* Go round the loop again */ } /* Other matching errors are not recoverable. */ if (rc < 0) { printf("Matching error %d\n", rc); pcre_free(re); /* Release memory used for the compiled pattern */ return 1; } /* Match succeded */ printf("\nMatch succeeded again at offset %d\n", ovector[0]); /* The match succeeded, but the output vector wasn't big enough. */ if (rc == 0) { rc = OVECCOUNT/3; printf("ovector only has room for %d captured substrings\n", rc - 1); } /* As before, show substrings stored in the output vector by number, and then also any named substrings. */ for (i = 0; i < rc; i++) { char *substring_start = subject + ovector[2*i]; int substring_length = ovector[2*i+1] - ovector[2*i]; printf("%2d: %.*s\n", i, substring_length, substring_start); } if (namecount <= 0) printf("No named substrings\n"); else { unsigned char *tabptr = name_table; printf("Named substrings\n"); for (i = 0; i < namecount; i++) { int n = (tabptr[0] << 8) | tabptr[1]; printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2, ovector[2*n+1] - ovector[2*n], subject + ovector[2*n]); tabptr += name_entry_size; } } } /* End of loop to find second and subsequent matches */ printf("\n"); pcre_free(re); /* Release memory used for the compiled pattern */ return 0; } /* End of pcredemo.c */ ================================================ FILE: src/pcre/pcregexp.pas ================================================ { pcRegExp - Perl compatible regular expressions for Virtual Pascal (c) 2001 Peter S. Voronov aka Chem O'Dun Based on PCRE library interface unit for Virtual Pascal. (c) 2001 Alexander Tokarev The current PCRE version is: 3.7 This software may be distributed under the terms of the modified BSD license Copyright (c) 2001, Alexander Tokarev 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 the 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 HOLDER 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. The PCRE library is written by: Philip Hazel Copyright (c) 1997-2004 University of Cambridge AngelsHolocaust 4-11-04 updated to use version v5.0 (INFO: this is regex-directed, NFA) AH: 9-11-04 - pcre_free: removed var, pcre already gives the ptr, now everything works as it should (no more crashes) -> removed CheckRegExp because pcre handles errors perfectly 10-11-04 - added pcError (errorhandling), pcInit 13-11-04 - removed the ErrorPos = 0 check -> always print erroroffset 17-10-05 - support for \1-\9 backreferences in TpcRegExp.GetReplStr 17-02-06 - added RunTimeOptions: caller can set options while searching 19-02-06 - added SearchOfs(): let PCRE use the complete string and offset into the string itself 20-12-06 - support for version 7.0 27.08.08 - support for v7.7 } {$H+} {$DEFINE PCRE_3_7} {$DEFINE PCRE_5_0} {$DEFINE PCRE_7_0} {$DEFINE PCRE_7_7} Unit pcregexp; Interface uses objects; Type PpcRegExp = ^TpcRegExp; // TpcRegExp = object TpcRegExp = object(TObject) MatchesCount: integer; RegExpC, RegExpExt : Pointer; Matches:Pointer; RegExp: shortstring; SourceLen: integer; PartialMatch : boolean; Error : boolean; ErrorMsg : Pchar; ErrorPos : integer; RunTimeOptions: Integer; // options which can be set by the caller constructor Init(const ARegExp : shortstring; AOptions : integer; ALocale : Pointer); function Search(AStr: Pchar; ALen : longint) : boolean; virtual; function SearchNext( AStr: Pchar; ALen : longint) : boolean; virtual; function SearchOfs ( AStr: Pchar; ALen, AOfs : longint) : boolean; virtual; function MatchSub(ANom: integer; var Pos, Len : longint) : boolean; virtual; function MatchFull(var Pos, Len : longint) : boolean; virtual; function GetSubStr(ANom: integer; AStr: Pchar) : string; virtual; function GetFullStr(AStr: Pchar) : string; virtual; function GetReplStr(AStr: Pchar; const ARepl: string) : string; virtual; function GetPreSubStr(AStr: Pchar) : string; virtual; function GetPostSubStr(AStr: Pchar) : string; virtual; function ErrorStr : string; virtual; destructor Done; virtual; end; function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean; function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string; function pcFastGrepMatch(WildCard, aStr: string): Boolean; function pcFastGrepSub(WildCard, aStr, aRepl: string): string; {$IFDEF PCRE_5_0} function pcGetVersion : pchar; {$ENDIF} function pcError (var pRegExp : Pointer) : Boolean; function pcInit (const Pattern: Shortstring; CaseSens: Boolean) : Pointer; Const { Options } PCRE_CASELESS = $0001; PCRE_MULTILINE = $0002; PCRE_DOTALL = $0004; PCRE_EXTENDED = $0008; PCRE_ANCHORED = $0010; PCRE_DOLLAR_ENDONLY = $0020; PCRE_EXTRA = $0040; PCRE_NOTBOL = $0080; PCRE_NOTEOL = $0100; PCRE_UNGREEDY = $0200; PCRE_NOTEMPTY = $0400; {$IFDEF PCRE_5_0} PCRE_UTF8 = $0800; PCRE_NO_AUTO_CAPTURE = $1000; PCRE_NO_UTF8_CHECK = $2000; PCRE_AUTO_CALLOUT = $4000; PCRE_PARTIAL = $8000; {$ENDIF} {$IFDEF PCRE_7_0} PCRE_DFA_SHORTEST = $00010000; PCRE_DFA_RESTART = $00020000; PCRE_FIRSTLINE = $00040000; PCRE_DUPNAMES = $00080000; PCRE_NEWLINE_CR = $00100000; PCRE_NEWLINE_LF = $00200000; PCRE_NEWLINE_CRLF = $00300000; PCRE_NEWLINE_ANY = $00400000; PCRE_NEWLINE_ANYCRLF = $00500000; PCRE_NEWLINE_BITS = PCRE_NEWLINE_CR or PCRE_NEWLINE_LF or PCRE_NEWLINE_ANY; {$ENDIF} {$IFDEF PCRE_7_7} PCRE_BSR_ANYCRLF = $00800000; PCRE_BSR_UNICODE = $01000000; PCRE_JAVASCRIPT_COMPAT= $02000000; {$ENDIF} PCRE_COMPILE_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_AUTO_CALLOUT + PCRE_CASELESS + PCRE_DOLLAR_ENDONLY + PCRE_DOTALL + PCRE_EXTENDED + PCRE_EXTRA + PCRE_MULTILINE + PCRE_NO_AUTO_CAPTURE + PCRE_UNGREEDY + PCRE_UTF8 + PCRE_NO_UTF8_CHECK {$IFDEF PCRE_7_0} + PCRE_DUPNAMES + PCRE_FIRSTLINE + PCRE_NEWLINE_BITS {$ENDIF} {$IFDEF PCRE_7_7} + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE + PCRE_JAVASCRIPT_COMPAT {$ENDIF} ; PCRE_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL + PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL {$IFDEF PCRE_7_0} + PCRE_NEWLINE_BITS {$ENDIF} {$IFDEF PCRE_7_7} + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE {$ENDIF} ; {$IFDEF PCRE_7_0} PCRE_DFA_EXEC_ALLOWED_OPTIONS = PCRE_ANCHORED + PCRE_NOTBOL + PCRE_NOTEOL + PCRE_NOTEMPTY + PCRE_NO_UTF8_CHECK + PCRE_PARTIAL + PCRE_DFA_SHORTEST + PCRE_DFA_RESTART + PCRE_NEWLINE_BITS {$IFDEF PCRE_7_7} + PCRE_BSR_ANYCRLF + PCRE_BSR_UNICODE {$ENDIF} ; {$ENDIF} { Exec-time and get/set-time error codes } PCRE_ERROR_NOMATCH = -1; PCRE_ERROR_NULL = -2; PCRE_ERROR_BADOPTION = -3; PCRE_ERROR_BADMAGIC = -4; PCRE_ERROR_UNKNOWN_MODE = -5; PCRE_ERROR_NOMEMORY = -6; PCRE_ERROR_NOSUBSTRING = -7; {$IFDEF PCRE_5_0} PCRE_ERROR_MATCHLIMIT = -8; PCRE_ERROR_CALLOUT = -9; { Never used by PCRE itself } PCRE_ERROR_BADUTF8 = -10; PCRE_ERROR_BADUTF8_OFFSET = -11; PCRE_ERROR_PARTIAL = -12; PCRE_ERROR_BADPARTIAL = -13; PCRE_ERROR_INTERNAL = -14; PCRE_ERROR_BADCOUNT = -15; {$ENDIF} {$IFDEF PCRE_7_0} PCRE_ERROR_DFA_UITEM = -16; PCRE_ERROR_DFA_UCOND = -17; PCRE_ERROR_DFA_UMLIMIT = -18; PCRE_ERROR_DFA_WSSIZE = -19; PCRE_ERROR_DFA_RECURSE = -20; PCRE_ERROR_RECURSIONLIMIT = -21; PCRE_ERROR_NULLWSLIMIT = -22; PCRE_ERROR_BADNEWLINE = -23; {$ENDIF} { Request types for pcre_fullinfo() } PCRE_INFO_OPTIONS = 0; PCRE_INFO_SIZE = 1; PCRE_INFO_CAPTURECOUNT = 2; PCRE_INFO_BACKREFMAX = 3; PCRE_INFO_FIRSTBYTE = 4; PCRE_INFO_FIRSTCHAR = 4; { For backwards compatibility } PCRE_INFO_FIRSTTABLE = 5; {$IFDEF PCRE_5_0} PCRE_INFO_LASTLITERAL = 6; PCRE_INFO_NAMEENTRYSIZE = 7; PCRE_INFO_NAMECOUNT = 8; PCRE_INFO_NAMETABLE = 9; PCRE_INFO_STUDYSIZE = 10; PCRE_INFO_DEFAULT_TABLES = 11; {$ENDIF PCRE_5_0} {$IFDEF PCRE_7_7} PCRE_INFO_OKPARTIAL = 12; PCRE_INFO_JCHANGED = 13; PCRE_INFO_HASCRORLF = 14; {$ENDIF} { Request types for pcre_config() } {$IFDEF PCRE_5_0} PCRE_CONFIG_UTF8 = 0; PCRE_CONFIG_NEWLINE = 1; PCRE_CONFIG_LINK_SIZE = 2; PCRE_CONFIG_POSIX_MALLOC_THRESHOLD = 3; PCRE_CONFIG_MATCH_LIMIT = 4; PCRE_CONFIG_STACKRECURSE = 5; PCRE_CONFIG_UNICODE_PROPERTIES = 6; {$ENDIF PCRE_5_0} {$IFDEF PCRE_7_0} PCRE_CONFIG_MATCH_LIMIT_RECURSION = 7; {$ENDIF} {$IFDEF PCRE_7_7} PCRE_CONFIG_BSR = 8; {$ENDIF} { Bit flags for the pcre_extra structure } {$IFDEF PCRE_5_0} PCRE_EXTRA_STUDY_DATA = $0001; PCRE_EXTRA_MATCH_LIMIT = $0002; PCRE_EXTRA_CALLOUT_DATA = $0004; PCRE_EXTRA_TABLES = $0008; {$ENDIF PCRE_5_0} {$IFDEF PCRE_7_0} PCRE_EXTRA_MATCH_LIMIT_RECURSION = $0010; {$ENDIF} Const // DefaultOptions : integer = 0; DefaultLocaleTable : pointer = nil; {$IFDEF PCRE_5_0} { The structure for passing additional data to pcre_exec(). This is defined in such as way as to be extensible. Always add new fields at the end, in order to remain compatible. } type ppcre_extra = ^tpcre_extra; tpcre_extra = record flags : longint; { Bits for which fields are set } study_data : pointer; { Opaque data from pcre_study() } match_limit : longint; { Maximum number of calls to match() } callout_data : pointer; { Data passed back in callouts } tables : pointer; { Pointer to character tables } match_limit_recursion: longint; { Max recursive calls to match() } end; type ppcre_callout_block = ^pcre_callout_block; pcre_callout_block = record version, (* ------------------------ Version 0 ------------------------------- *) callout_number : integer; offset_vector : pointer; subject : pchar; subject_length, start_match, current_position, capture_top, capture_last : integer; callout_data : pointer; (* ------------------- Added for Version 1 -------------------------- *) pattern_position, next_item_length : integer; end; {$ENDIF PCRE_5_0} {$OrgName+} {$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL} { local replacement of external pcre memory management functions } function pcre_malloc( size : integer ) : pointer; procedure pcre_free( {var} p : pointer ); {$IFDEF PCRE_5_0} const pcre_stack_malloc: function ( size : integer ): pointer = pcre_malloc; pcre_stack_free: procedure ( {var} p : pointer ) = pcre_free; function pcre_callout(var p : ppcre_callout_block) : integer; {$ENDIF PCRE_5_0} {$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL} Implementation Uses strings, collect, messages, dnapp, commands, advance0, stringsx {$IFDEF VIRTUALPASCAL} ,vpsyslow {$ENDIF VIRTUALPASCAL}; Const MAGIC_NUMBER = $50435245; { 'PCRE' } MAX_MATCHES = 90; { changed in 3.5 version; should be divisible by 3, was 64} Type PMatchArray = ^TMatchArray; TMatchArray = array[0..( MAX_MATCHES * 3 )] of integer; PRegExpCollection = ^TRegExpCollection; TRegExpCollection = object(TSortedCollection) MaxRegExp : integer; SearchRegExp : shortstring; CompareModeInsert : boolean; constructor Init(AMaxRegExp:integer); procedure FreeItem(P: Pointer); virtual; function Compare(P1, P2: Pointer): Integer; virtual; function Find(ARegExp:shortstring;var P: PpcRegExp):boolean; virtual; function CheckNew(ARegExp:shortstring):PpcRegExp;virtual; end; Var PRegExpCache : PRegExpCollection; {$IFDEF VIRTUALPASCAL} {&Cdecl+} {$ENDIF VIRTUALPASCAL} { imported original pcre functions } function pcre_compile( const pattern : PChar; options : integer; var errorptr : PChar; var erroroffset : integer; const tables : PChar ) : pointer {pcre}; external; {$IFDEF PCRE_7_0} function pcre_compile2( const pattern : PChar; options : integer; var errorcodeptr : Integer; var errorptr : PChar; var erroroffset : integer; const tables : PChar ) : pointer {pcre}; external; {$ENDIF} {$IFDEF PCRE_5_0} function pcre_config( what : integer; where : pointer) : integer; external; function pcre_copy_named_substring( const code : pointer {pcre}; const subject : pchar; var ovector : integer; stringcount : integer; const stringname : pchar; var buffer : pchar; size : integer) : integer; external; function pcre_copy_substring( const subject : pchar; var ovector : integer; stringcount, stringnumber : integer; var buffer : pchar; size : integer ) : integer; external; function pcre_exec( const argument_re : pointer {pcre}; const extra_data : pointer {pcre_extra}; {$ELSE} function pcre_exec( const external_re : pointer; const external_extra : pointer; {$ENDIF} const subject : PChar; length, start_offset, options : integer; offsets : pointer; offsetcount : integer ) : integer; external; {$IFDEF PCRE_7_0} function pcre_dfa_exec( const argument_re : pointer {pcre}; const extra_data : pointer {pcre_extra}; const subject : pchar; length, start_offset, options : integer; offsets : pointer; offsetcount : integer; workspace : pointer; wscount : integer ) : integer; external; {$ENDIF} {$IFDEF PCRE_5_0} procedure pcre_free_substring( const p : pchar ); external; procedure pcre_free_substring_list( var p : pchar ); external; function pcre_fullinfo( const argument_re : pointer {pcre}; const extra_data : pointer {pcre_extra}; what : integer; where : pointer ) : integer; external; function pcre_get_named_substring( const code : pointer {pcre}; const subject : pchar; var ovector : integer; stringcount : integer; const stringname : pchar; var stringptr : pchar ) : integer; external; function pcre_get_stringnumber( const code : pointer {pcre}; const stringname : pchar ) : integer; external; function pcre_get_stringtable_entries( const code : pointer {pcre}; const stringname : pchar; var firstptr, lastptr : pchar ) : integer; external; function pcre_get_substring( const subject : pchar; var ovector : integer; stringcount, stringnumber : integer; var stringptr : pchar ) : integer; external; function pcre_get_substring_list( const subject : pchar; var ovector : integer; stringcount : integer; listptr : pointer {const char ***listptr}) : integer; external; function pcre_info( const argument_re : pointer {pcre}; var optptr : integer; var first_byte : integer ) : integer; external; function pcre_maketables : pchar; external; {$ENDIF} {$IFDEF PCRE_7_0} function pcre_refcount( const argument_re : pointer {pcre}; adjust : integer ) : pchar; external; {$ENDIF} function pcre_study( const external_re : pointer {pcre}; options : integer; var errorptr : PChar ) : pointer {pcre_extra}; external; {$IFDEF PCRE_5_0} function pcre_version : pchar; external; {$ENDIF} function pcre_malloc( size : integer ) : pointer; begin GetMem( result, size ); end; procedure pcre_free( {var} p : pointer ); begin if (p <> nil) then FreeMem( p, 0 ); {@p := nil;} end; {$IFDEF PCRE_5_0} (* Called from PCRE as a result of the (?C) item. We print out where we are in the match. Yield zero unless more callouts than the fail count, or the callout data is not zero. *) function pcre_callout; begin end; {$ENDIF} {$IFDEF VIRTUALPASCAL} {&Cdecl-} {$ENDIF VIRTUALPASCAL} // Always include the newest version of the library {$IFDEF PCRE_7_7} {$L pcre77.lib} {$ELSE} {$IFDEF PCRE_7_0} {$L pcre70.lib} {$ELSE} {$IFDEF PCRE_5_0} {$L pcre50.lib} {$ELSE} {$IFDEF PCRE_3_7} {$L pcre37.lib} {$ENDIF PCRE_3_7} {$ENDIF PCRE_5_0} {$ENDIF PCRE_7_0} {$ENDIF PCRE_7_7} {TpcRegExp} constructor TpcRegExp.Init(const ARegExp:shortstring; AOptions:integer; ALocale : Pointer); var pRegExp : PChar; begin RegExp:=ARegExp; RegExpC:=nil; RegExpExt:=nil; Matches:=nil; MatchesCount:=0; Error:=true; ErrorMsg:=nil; ErrorPos:=0; RunTimeOptions := 0; if length(RegExp) < 255 then begin RegExp[length(RegExp)+1]:=#0; pRegExp:=@RegExp[1]; end else begin GetMem(pRegExp,length(RegExp)+1); pRegExp:=strpcopy(pRegExp,RegExp); end; RegExpC := pcre_compile( pRegExp, AOptions and PCRE_COMPILE_ALLOWED_OPTIONS, ErrorMsg, ErrorPos, ALocale); if length(RegExp) = 255 then StrDispose(pRegExp); if RegExpC = nil then exit; ErrorMsg:=nil; RegExpExt := pcre_study( RegExpC, 0, ErrorMsg ); if (RegExpExt = nil) and (ErrorMsg <> nil) then begin pcre_free(RegExpC); exit; end; GetMem(Matches,SizeOf(TMatchArray)); Error:=false; end; destructor TpcRegExp.Done; begin if RegExpC <> nil then pcre_free(RegExpC); if RegExpExt <> nil then pcre_free(RegExpExt); if Matches <> nil then FreeMem(Matches,SizeOf(TMatchArray)); end; function TpcRegExp.SearchNext( AStr: Pchar; ALen : longint ) : boolean; var Options: Integer; begin // must handle PCRE_ERROR_PARTIAL here Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and PCRE_EXEC_ALLOWED_OPTIONS; if MatchesCount > 0 then MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, PMatchArray(Matches)^[1], Options, Matches, MAX_MATCHES ) else MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, 0, Options, Matches, MAX_MATCHES ); { if MatchesCount = 0 then MatchesCount := MatchesCount div 3;} PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL; SearchNext := MatchesCount > 0; end; function TpcRegExp.Search( AStr: Pchar; ALen : longint):boolean; begin MatchesCount:=0; Search:=SearchNext(AStr,ALen); SourceLen:=ALen; end; function TpcRegExp.SearchOfs( AStr: Pchar; ALen, AOfs: longint ) : boolean; var Options: Integer; begin MatchesCount:=0; Options := (RunTimeOptions or startup.MiscMultiData.cfgRegEx.DefaultOptions) and PCRE_EXEC_ALLOWED_OPTIONS; MatchesCount:=pcre_exec( RegExpC, RegExpExt, AStr, ALen, AOfs, Options, Matches, MAX_MATCHES ); PartialMatch := MatchesCount = PCRE_ERROR_PARTIAL; SearchOfs := MatchesCount > 0; SourceLen := ALen-AOfs; end; function TpcRegExp.MatchSub(ANom:integer; var Pos,Len:longint):boolean; begin if (MatchesCount > 0) and (ANom <= (MatchesCount-1)) then begin ANom:=ANom*2; Pos:=PMatchArray(Matches)^[ANom]; Len:=PMatchArray(Matches)^[ANom+1]-Pos; MatchSub:=true; end else MatchSub:=false; end; function TpcRegExp.MatchFull(var Pos,Len:longint):boolean; begin MatchFull:=MatchSub(0,Pos,Len); end; function TpcRegExp.GetSubStr(ANom: integer; AStr: Pchar):string; var s: ansistring; pos,len: longint; begin s:=''; if MatchSub(ANom, pos, len) then begin setlength(s, len); Move(AStr[pos], s[1], len); end; GetSubStr:=s; end; function TpcRegExp.GetPreSubStr(AStr: Pchar):string; var s: ansistring; l: longint; begin s:=''; if (MatchesCount > 0) then begin l:=PMatchArray(Matches)^[0]-1; if l > 0 then begin setlength(s,l); Move(AStr[1],s[1],l); end; end; GetPreSubStr:=s; end; function TpcRegExp.GetPostSubStr(AStr: Pchar):string; var s: ansistring; l: longint; ANom: integer; begin s:=''; if (MatchesCount > 0) then begin ANom:=(MatchesCount-1){*2} shl 1; l:=SourceLen-PMatchArray(Matches)^[ANom+1]+1; if l > 0 then begin setlength(s,l); Move(AStr[PMatchArray(Matches)^[ANom+1]],s[1],l); end; end; GetPostSubStr:=s; end; function TpcRegExp.GetFullStr(AStr: Pchar):string; var s: ansistring; l: longint; begin GetFullStr:=GetSubStr(0,AStr); end; function TpcRegExp.GetReplStr(AStr: Pchar; const ARepl: string):string; var s: ansistring; l,i,lasti: longint; begin l:=length(ARepl); i:=1; lasti:=1; s:=''; while i <= l do begin case ARepl[i] of '\' : begin if i < l then begin s:=s+copy(ARepl,lasti,i-lasti){+ARepl[i+1]}; {AH 17-10-05 support for POSIX \1-\9 backreferences} case ARepl[i+1] of '0' : s:=s+GetFullStr(AStr); '1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr); else s:=s+ARepl[i+1]; // copy the escaped character end; end; inc(i); lasti:=i+1; end; '$' : begin if i < l then begin s:=s+copy(ARepl,lasti,i-lasti); case ARepl[i+1] of '&' : s:=s+GetFullStr(AStr); '1'..'9' : s:=s+GetSubStr(ord(ARepl[i+1])-ord('0'),AStr); '`' : s:=s+GetPreSubStr(AStr); #39 : s:=s+GetPostSubStr(AStr); end; end; inc(i); lasti:=i+1; end; end; inc(i); end; if lasti <= {AH 25-10-2004 added =, else l==1 won't work} l then s:=s+copy(ARepl,lasti,l-lasti+1); GetReplStr:=s; end; function TpcRegExp.ErrorStr:string; begin ErrorStr:=StrPas(ErrorMsg); end; {TRegExpCollection} constructor TRegExpCollection.Init(AMaxRegExp: integer); begin Inherited Init(1,1); MaxRegExp:=AMaxRegExp; CompareModeInsert:=true; end; procedure TRegExpCollection.FreeItem(P: Pointer); begin if P <> nil then begin Dispose(PpcRegExp(P),Done); end; end; function TRegExpCollection.Compare(P1, P2: Pointer): Integer; //var // l,l1,l2,i : byte; //// wPos: pchar; begin if CompareModeInsert then begin // l1:=length(PpcRegExp(P1)^.RegExp); // l2:=length(PpcRegExp(P2)^.RegExp); // if l1 > l2 then l:=l2 else // l:=l1; // for i:=1 to l do // if PpcRegExp(P1).RegExp[i] <> PpcRegExp(P2).RegExp[i] then break; // if i <=l then // Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(PpcRegExp(P2).RegExp[i]) else // Compare:=l1-l2; Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, PpcRegExp(P2).RegExp, False); end else begin // l1:=length(PpcRegExp(P1)^.RegExp); // l2:=length(SearchRegExp); // if l1 > l2 then l:=l2 else // l:=l1; // for i:=1 to l do // if PpcRegExp(P1).RegExp[i] <> SearchRegExp[i] then // begin // Compare:=ord(PpcRegExp(P1).RegExp[i])-ord(SearchRegExp[i]); // break; // end; // if i > l then Compare:=l1-l2; Compare := stringsx.PasStrCmp(PpcRegExp(P1).RegExp, SearchRegExp, False); end; end; function TRegExpCollection.Find(ARegExp:shortstring;var P: PpcRegExp):boolean; var I : integer; begin CompareModeInsert:=false; SearchRegExp:=ARegExp; if Search(nil,I) then begin P:=PpcRegExp(At(I)); Find:=true; end else begin P:=nil; Find:=false; end; CompareModeInsert:=true; end; function TRegExpCollection.CheckNew(ARegExp:shortstring):PpcRegExp; var P : PpcRegExp; begin if not Find(ARegExp,P) then begin if Count = MaxRegExp then AtFree(0); P:=New(ppcRegExp,Init(ARegExp,PCRE_CASELESS,nil)); Insert(P); end; CheckNew:=P; end; function pcGrepMatch(WildCard, aStr: string; AOptions:integer; ALocale : Pointer): Boolean; var PpcRE:PpcRegExp; begin PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale)); pcGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr)); Dispose(PpcRE,Done); end; function pcGrepSub(WildCard, aStr, aRepl: string; AOptions:integer; ALocale : Pointer): string; var PpcRE:PpcRegExp; begin PpcRE:=New(ppcRegExp,Init(WildCard,AOptions,Alocale)); if PpcRE^.Search(pchar(AStr),Length(AStr)) then pcGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl) else pcGrepSub:=''; Dispose(PpcRE,Done); end; function pcFastGrepMatch(WildCard, aStr: string): Boolean; var PpcRE:PpcRegExp; begin PpcRE:=PRegExpCache^.CheckNew(WildCard); pcFastGrepMatch:=PpcRE^.Search(pchar(AStr),Length(AStr)); end; function pcFastGrepSub(WildCard, aStr, aRepl: string): string; var PpcRE:PpcRegExp; begin PpcRE:=PRegExpCache^.CheckNew(WildCard); if PpcRE^.Search(pchar(AStr),Length(AStr)) then pcFastGrepSub:=PpcRE^.GetReplStr(pchar(AStr),ARepl) else pcFastGrepSub:=''; end; {$IFDEF PCRE_5_0} function pcGetVersion : pchar; assembler; {$FRAME-}{$USES none} asm call pcre_version end; {$ENDIF PCRE_5_0} function pcError; var P: ppcRegExp absolute pRegExp; begin Result := (P = nil) or P^.Error; If Result and (P <> nil) then begin { if P^.ErrorPos = 0 then MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"', nil,mfConfirmation+mfOkButton) else} MessageBox(GetString(erRegExpCompile)+'"'+P^.ErrorStr+'"'+GetString(erRegExpCompPos), @P^.ErrorPos,mfConfirmation+mfOkButton); Dispose(P, Done); P:=nil; end; end; function pcInit; var Options : Integer; begin If CaseSens then Options := 0 else Options := PCRE_CASELESS; Result := New( PpcRegExp, Init( Pattern, {DefaultOptions} startup.MiscMultiData.cfgRegEx.DefaultOptions or Options, DefaultLocaleTable) ); end; Initialization PRegExpCache:=New(PRegExpCollection,Init(64)); Finalization Dispose(PRegExpCache,Done); End. ================================================ FILE: src/pcre/pcregrep.c ================================================ /************************************************* * pcregrep program * *************************************************/ /* This is a grep program that uses the PCRE regular expression library to do its pattern matching. On Unix-like, Windows, and native z/OS systems it can recurse into directories, and in z/OS it can handle PDS files. Note that for native z/OS, in addition to defining the NATIVE_ZOS macro, an additional header is required. That header is not included in the main PCRE distribution because other apparatus is needed to compile pcregrep for z/OS. The header can be found in the special z/OS distribution, which is available from www.zaconsultants.net or from www.cbttape.org. Copyright (c) 1997-2014 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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 HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef SUPPORT_LIBZ #include #endif #ifdef SUPPORT_LIBBZ2 #include #endif #include "pcre.h" #define FALSE 0 #define TRUE 1 typedef int BOOL; #define OFFSET_SIZE 99 #if BUFSIZ > 8192 #define MAXPATLEN BUFSIZ #else #define MAXPATLEN 8192 #endif #define PATBUFSIZE (MAXPATLEN + 10) /* Allows for prefix+suffix */ /* Values for the "filenames" variable, which specifies options for file name output. The order is important; it is assumed that a file name is wanted for all values greater than FN_DEFAULT. */ enum { FN_NONE, FN_DEFAULT, FN_MATCH_ONLY, FN_NOMATCH_ONLY, FN_FORCE }; /* File reading styles */ enum { FR_PLAIN, FR_LIBZ, FR_LIBBZ2 }; /* Actions for the -d and -D options */ enum { dee_READ, dee_SKIP, dee_RECURSE }; enum { DEE_READ, DEE_SKIP }; /* Actions for special processing options (flag bits) */ #define PO_WORD_MATCH 0x0001 #define PO_LINE_MATCH 0x0002 #define PO_FIXED_STRINGS 0x0004 /* Line ending types */ enum { EL_LF, EL_CR, EL_CRLF, EL_ANY, EL_ANYCRLF }; /* Binary file options */ enum { BIN_BINARY, BIN_NOMATCH, BIN_TEXT }; /* In newer versions of gcc, with FORTIFY_SOURCE set (the default in some environments), a warning is issued if the value of fwrite() is ignored. Unfortunately, casting to (void) does not suppress the warning. To get round this, we use a macro that compiles a fudge. Oddly, this does not also seem to apply to fprintf(). */ #define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {} /************************************************* * Global variables * *************************************************/ /* Jeffrey Friedl has some debugging requirements that are not part of the regular code. */ #ifdef JFRIEDL_DEBUG static int S_arg = -1; static unsigned int jfriedl_XR = 0; /* repeat regex attempt this many times */ static unsigned int jfriedl_XT = 0; /* replicate text this many times */ static const char *jfriedl_prefix = ""; static const char *jfriedl_postfix = ""; #endif static int endlinetype; static char *colour_string = (char *)"1;31"; static char *colour_option = NULL; static char *dee_option = NULL; static char *DEE_option = NULL; static char *locale = NULL; static char *main_buffer = NULL; static char *newline = NULL; static char *om_separator = (char *)""; static char *stdin_name = (char *)"(standard input)"; static const unsigned char *pcretables = NULL; static int after_context = 0; static int before_context = 0; static int binary_files = BIN_BINARY; static int both_context = 0; static int bufthird = PCREGREP_BUFSIZE; static int bufsize = 3*PCREGREP_BUFSIZE; #if defined HAVE_WINDOWS_H && HAVE_WINDOWS_H static int dee_action = dee_SKIP; #else static int dee_action = dee_READ; #endif static int DEE_action = DEE_READ; static int error_count = 0; static int filenames = FN_DEFAULT; static int pcre_options = 0; static int process_options = 0; #ifdef SUPPORT_PCREGREP_JIT static int study_options = PCRE_STUDY_JIT_COMPILE; #else static int study_options = 0; #endif static unsigned long int match_limit = 0; static unsigned long int match_limit_recursion = 0; static BOOL count_only = FALSE; static BOOL do_colour = FALSE; static BOOL file_offsets = FALSE; static BOOL hyphenpending = FALSE; static BOOL invert = FALSE; static BOOL line_buffered = FALSE; static BOOL line_offsets = FALSE; static BOOL multiline = FALSE; static BOOL number = FALSE; static BOOL omit_zero_count = FALSE; static BOOL resource_error = FALSE; static BOOL quiet = FALSE; static BOOL show_only_matching = FALSE; static BOOL silent = FALSE; static BOOL utf8 = FALSE; /* Structure for list of --only-matching capturing numbers. */ typedef struct omstr { struct omstr *next; int groupnum; } omstr; static omstr *only_matching = NULL; static omstr *only_matching_last = NULL; /* Structure for holding the two variables that describe a number chain. */ typedef struct omdatastr { omstr **anchor; omstr **lastptr; } omdatastr; static omdatastr only_matching_data = { &only_matching, &only_matching_last }; /* Structure for list of file names (for -f and --{in,ex}clude-from) */ typedef struct fnstr { struct fnstr *next; char *name; } fnstr; static fnstr *exclude_from = NULL; static fnstr *exclude_from_last = NULL; static fnstr *include_from = NULL; static fnstr *include_from_last = NULL; static fnstr *file_lists = NULL; static fnstr *file_lists_last = NULL; static fnstr *pattern_files = NULL; static fnstr *pattern_files_last = NULL; /* Structure for holding the two variables that describe a file name chain. */ typedef struct fndatastr { fnstr **anchor; fnstr **lastptr; } fndatastr; static fndatastr exclude_from_data = { &exclude_from, &exclude_from_last }; static fndatastr include_from_data = { &include_from, &include_from_last }; static fndatastr file_lists_data = { &file_lists, &file_lists_last }; static fndatastr pattern_files_data = { &pattern_files, &pattern_files_last }; /* Structure for pattern and its compiled form; used for matching patterns and also for include/exclude patterns. */ typedef struct patstr { struct patstr *next; char *string; pcre *compiled; pcre_extra *hint; } patstr; static patstr *patterns = NULL; static patstr *patterns_last = NULL; static patstr *include_patterns = NULL; static patstr *include_patterns_last = NULL; static patstr *exclude_patterns = NULL; static patstr *exclude_patterns_last = NULL; static patstr *include_dir_patterns = NULL; static patstr *include_dir_patterns_last = NULL; static patstr *exclude_dir_patterns = NULL; static patstr *exclude_dir_patterns_last = NULL; /* Structure holding the two variables that describe a pattern chain. A pointer to such structures is used for each appropriate option. */ typedef struct patdatastr { patstr **anchor; patstr **lastptr; } patdatastr; static patdatastr match_patdata = { &patterns, &patterns_last }; static patdatastr include_patdata = { &include_patterns, &include_patterns_last }; static patdatastr exclude_patdata = { &exclude_patterns, &exclude_patterns_last }; static patdatastr include_dir_patdata = { &include_dir_patterns, &include_dir_patterns_last }; static patdatastr exclude_dir_patdata = { &exclude_dir_patterns, &exclude_dir_patterns_last }; static patstr **incexlist[4] = { &include_patterns, &exclude_patterns, &include_dir_patterns, &exclude_dir_patterns }; static const char *incexname[4] = { "--include", "--exclude", "--include-dir", "--exclude-dir" }; /* Structure for options and list of them */ enum { OP_NODATA, OP_STRING, OP_OP_STRING, OP_NUMBER, OP_LONGNUMBER, OP_OP_NUMBER, OP_OP_NUMBERS, OP_PATLIST, OP_FILELIST, OP_BINFILES }; typedef struct option_item { int type; int one_char; void *dataptr; const char *long_name; const char *help_text; } option_item; /* Options without a single-letter equivalent get a negative value. This can be used to identify them. */ #define N_COLOUR (-1) #define N_EXCLUDE (-2) #define N_EXCLUDE_DIR (-3) #define N_HELP (-4) #define N_INCLUDE (-5) #define N_INCLUDE_DIR (-6) #define N_LABEL (-7) #define N_LOCALE (-8) #define N_NULL (-9) #define N_LOFFSETS (-10) #define N_FOFFSETS (-11) #define N_LBUFFER (-12) #define N_M_LIMIT (-13) #define N_M_LIMIT_REC (-14) #define N_BUFSIZE (-15) #define N_NOJIT (-16) #define N_FILE_LIST (-17) #define N_BINARY_FILES (-18) #define N_EXCLUDE_FROM (-19) #define N_INCLUDE_FROM (-20) #define N_OM_SEPARATOR (-21) static option_item optionlist[] = { { OP_NODATA, N_NULL, NULL, "", "terminate options" }, { OP_NODATA, N_HELP, NULL, "help", "display this help and exit" }, { OP_NUMBER, 'A', &after_context, "after-context=number", "set number of following context lines" }, { OP_NODATA, 'a', NULL, "text", "treat binary files as text" }, { OP_NUMBER, 'B', &before_context, "before-context=number", "set number of prior context lines" }, { OP_BINFILES, N_BINARY_FILES, NULL, "binary-files=word", "set treatment of binary files" }, { OP_NUMBER, N_BUFSIZE,&bufthird, "buffer-size=number", "set processing buffer size parameter" }, { OP_OP_STRING, N_COLOUR, &colour_option, "color=option", "matched text color option" }, { OP_OP_STRING, N_COLOUR, &colour_option, "colour=option", "matched text colour option" }, { OP_NUMBER, 'C', &both_context, "context=number", "set number of context lines, before & after" }, { OP_NODATA, 'c', NULL, "count", "print only a count of matching lines per FILE" }, { OP_STRING, 'D', &DEE_option, "devices=action","how to handle devices, FIFOs, and sockets" }, { OP_STRING, 'd', &dee_option, "directories=action", "how to handle directories" }, { OP_PATLIST, 'e', &match_patdata, "regex(p)=pattern", "specify pattern (may be used more than once)" }, { OP_NODATA, 'F', NULL, "fixed-strings", "patterns are sets of newline-separated strings" }, { OP_FILELIST, 'f', &pattern_files_data, "file=path", "read patterns from file" }, { OP_FILELIST, N_FILE_LIST, &file_lists_data, "file-list=path","read files to search from file" }, { OP_NODATA, N_FOFFSETS, NULL, "file-offsets", "output file offsets, not text" }, { OP_NODATA, 'H', NULL, "with-filename", "force the prefixing filename on output" }, { OP_NODATA, 'h', NULL, "no-filename", "suppress the prefixing filename on output" }, { OP_NODATA, 'I', NULL, "", "treat binary files as not matching (ignore)" }, { OP_NODATA, 'i', NULL, "ignore-case", "ignore case distinctions" }, #ifdef SUPPORT_PCREGREP_JIT { OP_NODATA, N_NOJIT, NULL, "no-jit", "do not use just-in-time compiler optimization" }, #else { OP_NODATA, N_NOJIT, NULL, "no-jit", "ignored: this pcregrep does not support JIT" }, #endif { OP_NODATA, 'l', NULL, "files-with-matches", "print only FILE names containing matches" }, { OP_NODATA, 'L', NULL, "files-without-match","print only FILE names not containing matches" }, { OP_STRING, N_LABEL, &stdin_name, "label=name", "set name for standard input" }, { OP_NODATA, N_LBUFFER, NULL, "line-buffered", "use line buffering" }, { OP_NODATA, N_LOFFSETS, NULL, "line-offsets", "output line numbers and offsets, not text" }, { OP_STRING, N_LOCALE, &locale, "locale=locale", "use the named locale" }, { OP_LONGNUMBER, N_M_LIMIT, &match_limit, "match-limit=number", "set PCRE match limit option" }, { OP_LONGNUMBER, N_M_LIMIT_REC, &match_limit_recursion, "recursion-limit=number", "set PCRE match recursion limit option" }, { OP_NODATA, 'M', NULL, "multiline", "run in multiline mode" }, { OP_STRING, 'N', &newline, "newline=type", "set newline type (CR, LF, CRLF, ANYCRLF or ANY)" }, { OP_NODATA, 'n', NULL, "line-number", "print line number with output lines" }, { OP_OP_NUMBERS, 'o', &only_matching_data, "only-matching=n", "show only the part of the line that matched" }, { OP_STRING, N_OM_SEPARATOR, &om_separator, "om-separator=text", "set separator for multiple -o output" }, { OP_NODATA, 'q', NULL, "quiet", "suppress output, just set return code" }, { OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" }, { OP_PATLIST, N_EXCLUDE,&exclude_patdata, "exclude=pattern","exclude matching files when recursing" }, { OP_PATLIST, N_INCLUDE,&include_patdata, "include=pattern","include matching files when recursing" }, { OP_PATLIST, N_EXCLUDE_DIR,&exclude_dir_patdata, "exclude-dir=pattern","exclude matching directories when recursing" }, { OP_PATLIST, N_INCLUDE_DIR,&include_dir_patdata, "include-dir=pattern","include matching directories when recursing" }, { OP_FILELIST, N_EXCLUDE_FROM,&exclude_from_data, "exclude-from=path", "read exclude list from file" }, { OP_FILELIST, N_INCLUDE_FROM,&include_from_data, "include-from=path", "read include list from file" }, /* These two were accidentally implemented with underscores instead of hyphens in the option names. As this was not discovered for several releases, the incorrect versions are left in the table for compatibility. However, the --help function misses out any option that has an underscore in its name. */ { OP_PATLIST, N_EXCLUDE_DIR,&exclude_dir_patdata, "exclude_dir=pattern","exclude matching directories when recursing" }, { OP_PATLIST, N_INCLUDE_DIR,&include_dir_patdata, "include_dir=pattern","include matching directories when recursing" }, #ifdef JFRIEDL_DEBUG { OP_OP_NUMBER, 'S', &S_arg, "jeffS", "replace matched (sub)string with X" }, #endif { OP_NODATA, 's', NULL, "no-messages", "suppress error messages" }, { OP_NODATA, 'u', NULL, "utf-8", "use UTF-8 mode" }, { OP_NODATA, 'V', NULL, "version", "print version information and exit" }, { OP_NODATA, 'v', NULL, "invert-match", "select non-matching lines" }, { OP_NODATA, 'w', NULL, "word-regex(p)", "force patterns to match only as words" }, { OP_NODATA, 'x', NULL, "line-regex(p)", "force patterns to match only whole lines" }, { OP_NODATA, 0, NULL, NULL, NULL } }; /* Tables for prefixing and suffixing patterns, according to the -w, -x, and -F options. These set the 1, 2, and 4 bits in process_options, respectively. Note that the combination of -w and -x has the same effect as -x on its own, so we can treat them as the same. Note that the MAXPATLEN macro assumes the longest prefix+suffix is 10 characters; if anything longer is added, it must be adjusted. */ static const char *prefix[] = { "", "\\b", "^(?:", "^(?:", "\\Q", "\\b\\Q", "^(?:\\Q", "^(?:\\Q" }; static const char *suffix[] = { "", "\\b", ")$", ")$", "\\E", "\\E\\b", "\\E)$", "\\E)$" }; /* UTF-8 tables - used only when the newline setting is "any". */ const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; const char utf8_table4[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; /************************************************* * Exit from the program * *************************************************/ /* If there has been a resource error, give a suitable message. Argument: the return code Returns: does not return */ static void pcregrep_exit(int rc) { if (resource_error) { fprintf(stderr, "pcregrep: Error %d, %d or %d means that a resource limit " "was exceeded.\n", PCRE_ERROR_MATCHLIMIT, PCRE_ERROR_RECURSIONLIMIT, PCRE_ERROR_JIT_STACKLIMIT); fprintf(stderr, "pcregrep: Check your regex for nested unlimited loops.\n"); } exit(rc); } /************************************************* * Add item to chain of patterns * *************************************************/ /* Used to add an item onto a chain, or just return an unconnected item if the "after" argument is NULL. Arguments: s pattern string to add after if not NULL points to item to insert after Returns: new pattern block or NULL on error */ static patstr * add_pattern(char *s, patstr *after) { patstr *p = (patstr *)malloc(sizeof(patstr)); if (p == NULL) { fprintf(stderr, "pcregrep: malloc failed\n"); pcregrep_exit(2); } if (strlen(s) > MAXPATLEN) { fprintf(stderr, "pcregrep: pattern is too long (limit is %d bytes)\n", MAXPATLEN); free(p); return NULL; } p->next = NULL; p->string = s; p->compiled = NULL; p->hint = NULL; if (after != NULL) { p->next = after->next; after->next = p; } return p; } /************************************************* * Free chain of patterns * *************************************************/ /* Used for several chains of patterns. Argument: pointer to start of chain Returns: nothing */ static void free_pattern_chain(patstr *pc) { while (pc != NULL) { patstr *p = pc; pc = p->next; if (p->hint != NULL) pcre_free_study(p->hint); if (p->compiled != NULL) pcre_free(p->compiled); free(p); } } /************************************************* * Free chain of file names * *************************************************/ /* Argument: pointer to start of chain Returns: nothing */ static void free_file_chain(fnstr *fn) { while (fn != NULL) { fnstr *f = fn; fn = f->next; free(f); } } /************************************************* * OS-specific functions * *************************************************/ /* These functions are defined so that they can be made system specific. At present there are versions for Unix-style environments, Windows, native z/OS, and "no support". */ /************* Directory scanning Unix-style and z/OS ***********/ #if (defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H) || defined NATIVE_ZOS #include #include #include #if defined NATIVE_ZOS /************* Directory and PDS/E scanning for z/OS ***********/ /************* z/OS looks mostly like Unix with USS ************/ /* However, z/OS needs the #include statements in this header */ #include "pcrzosfs.h" /* That header is not included in the main PCRE distribution because other apparatus is needed to compile pcregrep for z/OS. The header can be found in the special z/OS distribution, which is available from www.zaconsultants.net or from www.cbttape.org. */ #endif typedef DIR directory_type; #define FILESEP '/' static int isdirectory(char *filename) { struct stat statbuf; if (stat(filename, &statbuf) < 0) return 0; /* In the expectation that opening as a file will fail */ return (statbuf.st_mode & S_IFMT) == S_IFDIR; } static directory_type * opendirectory(char *filename) { return opendir(filename); } static char * readdirectory(directory_type *dir) { for (;;) { struct dirent *dent = readdir(dir); if (dent == NULL) return NULL; if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) return dent->d_name; } /* Control never reaches here */ } static void closedirectory(directory_type *dir) { closedir(dir); } /************* Test for regular file, Unix-style **********/ static int isregfile(char *filename) { struct stat statbuf; if (stat(filename, &statbuf) < 0) return 1; /* In the expectation that opening as a file will fail */ return (statbuf.st_mode & S_IFMT) == S_IFREG; } #if defined NATIVE_ZOS /************* Test for a terminal in z/OS **********/ /* isatty() does not work in a TSO environment, so always give FALSE.*/ static BOOL is_stdout_tty(void) { return FALSE; } static BOOL is_file_tty(FILE *f) { return FALSE; } /************* Test for a terminal, Unix-style **********/ #else static BOOL is_stdout_tty(void) { return isatty(fileno(stdout)); } static BOOL is_file_tty(FILE *f) { return isatty(fileno(f)); } #endif /* End of Unix-style or native z/OS environment functions. */ /************* Directory scanning in Windows ***********/ /* I (Philip Hazel) have no means of testing this code. It was contributed by Lionel Fourquaux. David Burgess added a patch to define INVALID_FILE_ATTRIBUTES when it did not exist. David Byron added a patch that moved the #include of to before the INVALID_FILE_ATTRIBUTES definition rather than after. The double test below stops gcc 4.4.4 grumbling that HAVE_WINDOWS_H is undefined when it is indeed undefined. */ #elif defined HAVE_WINDOWS_H && HAVE_WINDOWS_H #ifndef STRICT # define STRICT #endif #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #include #ifndef INVALID_FILE_ATTRIBUTES #define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF #endif typedef struct directory_type { HANDLE handle; BOOL first; WIN32_FIND_DATA data; } directory_type; #define FILESEP '/' int isdirectory(char *filename) { DWORD attr = GetFileAttributes(filename); if (attr == INVALID_FILE_ATTRIBUTES) return 0; return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0; } directory_type * opendirectory(char *filename) { size_t len; char *pattern; directory_type *dir; DWORD err; len = strlen(filename); pattern = (char *)malloc(len + 3); dir = (directory_type *)malloc(sizeof(*dir)); if ((pattern == NULL) || (dir == NULL)) { fprintf(stderr, "pcregrep: malloc failed\n"); pcregrep_exit(2); } memcpy(pattern, filename, len); memcpy(&(pattern[len]), "\\*", 3); dir->handle = FindFirstFile(pattern, &(dir->data)); if (dir->handle != INVALID_HANDLE_VALUE) { free(pattern); dir->first = TRUE; return dir; } err = GetLastError(); free(pattern); free(dir); errno = (err == ERROR_ACCESS_DENIED) ? EACCES : ENOENT; return NULL; } char * readdirectory(directory_type *dir) { for (;;) { if (!dir->first) { if (!FindNextFile(dir->handle, &(dir->data))) return NULL; } else { dir->first = FALSE; } if (strcmp(dir->data.cFileName, ".") != 0 && strcmp(dir->data.cFileName, "..") != 0) return dir->data.cFileName; } #ifndef _MSC_VER return NULL; /* Keep compiler happy; never executed */ #endif } void closedirectory(directory_type *dir) { FindClose(dir->handle); free(dir); } /************* Test for regular file in Windows **********/ /* I don't know how to do this, or if it can be done; assume all paths are regular if they are not directories. */ int isregfile(char *filename) { return !isdirectory(filename); } /************* Test for a terminal in Windows **********/ /* I don't know how to do this; assume never */ static BOOL is_stdout_tty(void) { return FALSE; } static BOOL is_file_tty(FILE *f) { return FALSE; } /* End of Windows functions */ /************* Directory scanning when we can't do it ***********/ /* The type is void, and apart from isdirectory(), the functions do nothing. */ #else #define FILESEP 0 typedef void directory_type; int isdirectory(char *filename) { return 0; } directory_type * opendirectory(char *filename) { return (directory_type*)0;} char *readdirectory(directory_type *dir) { return (char*)0;} void closedirectory(directory_type *dir) {} /************* Test for regular file when we can't do it **********/ /* Assume all files are regular. */ int isregfile(char *filename) { return 1; } /************* Test for a terminal when we can't do it **********/ static BOOL is_stdout_tty(void) { return FALSE; } static BOOL is_file_tty(FILE *f) { return FALSE; } #endif /* End of system-specific functions */ #ifndef HAVE_STRERROR /************************************************* * Provide strerror() for non-ANSI libraries * *************************************************/ /* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror() in their libraries, but can provide the same facility by this simple alternative function. */ extern int sys_nerr; extern char *sys_errlist[]; char * strerror(int n) { if (n < 0 || n >= sys_nerr) return "unknown error number"; return sys_errlist[n]; } #endif /* HAVE_STRERROR */ /************************************************* * Usage function * *************************************************/ static int usage(int rc) { option_item *op; fprintf(stderr, "Usage: pcregrep [-"); for (op = optionlist; op->one_char != 0; op++) { if (op->one_char > 0) fprintf(stderr, "%c", op->one_char); } fprintf(stderr, "] [long options] [pattern] [files]\n"); fprintf(stderr, "Type `pcregrep --help' for more information and the long " "options.\n"); return rc; } /************************************************* * Help function * *************************************************/ static void help(void) { option_item *op; printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n"); printf("Search for PATTERN in each FILE or standard input.\n"); printf("PATTERN must be present if neither -e nor -f is used.\n"); printf("\"-\" can be used as a file name to mean STDIN.\n"); #ifdef SUPPORT_LIBZ printf("Files whose names end in .gz are read using zlib.\n"); #endif #ifdef SUPPORT_LIBBZ2 printf("Files whose names end in .bz2 are read using bzlib2.\n"); #endif #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2 printf("Other files and the standard input are read as plain files.\n\n"); #else printf("All files are read as plain files, without any interpretation.\n\n"); #endif printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n"); printf("Options:\n"); for (op = optionlist; op->one_char != 0; op++) { int n; char s[4]; /* Two options were accidentally implemented and documented with underscores instead of hyphens in their names, something that was not noticed for quite a few releases. When fixing this, I left the underscored versions in the list in case people were using them. However, we don't want to display them in the help data. There are no other options that contain underscores, and we do not expect ever to implement such options. Therefore, just omit any option that contains an underscore. */ if (strchr(op->long_name, '_') != NULL) continue; if (op->one_char > 0 && (op->long_name)[0] == 0) n = 31 - printf(" -%c", op->one_char); else { if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, " "); n = 31 - printf(" %s --%s", s, op->long_name); } if (n < 1) n = 1; printf("%.*s%s\n", n, " ", op->help_text); } printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n"); printf("The default value for --buffer-size is %d.\n", PCREGREP_BUFSIZE); printf("When reading patterns or file names from a file, trailing white\n"); printf("space is removed and blank lines are ignored.\n"); printf("The maximum size of any pattern is %d bytes.\n", MAXPATLEN); printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n"); printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n"); } /************************************************* * Test exclude/includes * *************************************************/ /* If any exclude pattern matches, the path is excluded. Otherwise, unless there are no includes, the path must match an include pattern. Arguments: path the path to be matched ip the chain of include patterns ep the chain of exclude patterns Returns: TRUE if the path is not excluded */ static BOOL test_incexc(char *path, patstr *ip, patstr *ep) { int plen = strlen(path); for (; ep != NULL; ep = ep->next) { if (pcre_exec(ep->compiled, NULL, path, plen, 0, 0, NULL, 0) >= 0) return FALSE; } if (ip == NULL) return TRUE; for (; ip != NULL; ip = ip->next) { if (pcre_exec(ip->compiled, NULL, path, plen, 0, 0, NULL, 0) >= 0) return TRUE; } return FALSE; } /************************************************* * Decode integer argument value * *************************************************/ /* Integer arguments can be followed by K or M. Avoid the use of strtoul() because SunOS4 doesn't have it. This is used only for unpicking arguments, so just keep it simple. Arguments: option_data the option data string op the option item (for error messages) longop TRUE if option given in long form Returns: a long integer */ static long int decode_number(char *option_data, option_item *op, BOOL longop) { unsigned long int n = 0; char *endptr = option_data; while (*endptr != 0 && isspace((unsigned char)(*endptr))) endptr++; while (isdigit((unsigned char)(*endptr))) n = n * 10 + (int)(*endptr++ - '0'); if (toupper(*endptr) == 'K') { n *= 1024; endptr++; } else if (toupper(*endptr) == 'M') { n *= 1024*1024; endptr++; } if (*endptr != 0) /* Error */ { if (longop) { char *equals = strchr(op->long_name, '='); int nlen = (equals == NULL)? (int)strlen(op->long_name) : (int)(equals - op->long_name); fprintf(stderr, "pcregrep: Malformed number \"%s\" after --%.*s\n", option_data, nlen, op->long_name); } else fprintf(stderr, "pcregrep: Malformed number \"%s\" after -%c\n", option_data, op->one_char); pcregrep_exit(usage(2)); } return n; } /************************************************* * Add item to a chain of numbers * *************************************************/ /* Used to add an item onto a chain, or just return an unconnected item if the "after" argument is NULL. Arguments: n the number to add after if not NULL points to item to insert after Returns: new number block */ static omstr * add_number(int n, omstr *after) { omstr *om = (omstr *)malloc(sizeof(omstr)); if (om == NULL) { fprintf(stderr, "pcregrep: malloc failed\n"); pcregrep_exit(2); } om->next = NULL; om->groupnum = n; if (after != NULL) { om->next = after->next; after->next = om; } return om; } /************************************************* * Read one line of input * *************************************************/ /* Normally, input is read using fread() into a large buffer, so many lines may be read at once. However, doing this for tty input means that no output appears until a lot of input has been typed. Instead, tty input is handled line by line. We cannot use fgets() for this, because it does not stop at a binary zero, and therefore there is no way of telling how many characters it has read, because there may be binary zeros embedded in the data. Arguments: buffer the buffer to read into length the maximum number of characters to read f the file Returns: the number of characters read, zero at end of file */ static unsigned int read_one_line(char *buffer, int length, FILE *f) { int c; int yield = 0; while ((c = fgetc(f)) != EOF) { buffer[yield++] = c; if (c == '\n' || yield >= length) break; } return yield; } /************************************************* * Find end of line * *************************************************/ /* The length of the endline sequence that is found is set via lenptr. This may be zero at the very end of the file if there is no line-ending sequence there. Arguments: p current position in line endptr end of available data lenptr where to put the length of the eol sequence Returns: pointer after the last byte of the line, including the newline byte(s) */ static char * end_of_line(char *p, char *endptr, int *lenptr) { switch(endlinetype) { default: /* Just in case */ case EL_LF: while (p < endptr && *p != '\n') p++; if (p < endptr) { *lenptr = 1; return p + 1; } *lenptr = 0; return endptr; case EL_CR: while (p < endptr && *p != '\r') p++; if (p < endptr) { *lenptr = 1; return p + 1; } *lenptr = 0; return endptr; case EL_CRLF: for (;;) { while (p < endptr && *p != '\r') p++; if (++p >= endptr) { *lenptr = 0; return endptr; } if (*p == '\n') { *lenptr = 2; return p + 1; } } break; case EL_ANYCRLF: while (p < endptr) { int extra = 0; register int c = *((unsigned char *)p); if (utf8 && c >= 0xc0) { int gcii, gcss; extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */ gcss = 6*extra; c = (c & utf8_table3[extra]) << gcss; for (gcii = 1; gcii <= extra; gcii++) { gcss -= 6; c |= (p[gcii] & 0x3f) << gcss; } } p += 1 + extra; switch (c) { case '\n': *lenptr = 1; return p; case '\r': if (p < endptr && *p == '\n') { *lenptr = 2; p++; } else *lenptr = 1; return p; default: break; } } /* End of loop for ANYCRLF case */ *lenptr = 0; /* Must have hit the end */ return endptr; case EL_ANY: while (p < endptr) { int extra = 0; register int c = *((unsigned char *)p); if (utf8 && c >= 0xc0) { int gcii, gcss; extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */ gcss = 6*extra; c = (c & utf8_table3[extra]) << gcss; for (gcii = 1; gcii <= extra; gcii++) { gcss -= 6; c |= (p[gcii] & 0x3f) << gcss; } } p += 1 + extra; switch (c) { case '\n': /* LF */ case '\v': /* VT */ case '\f': /* FF */ *lenptr = 1; return p; case '\r': /* CR */ if (p < endptr && *p == '\n') { *lenptr = 2; p++; } else *lenptr = 1; return p; #ifndef EBCDIC case 0x85: /* Unicode NEL */ *lenptr = utf8? 2 : 1; return p; case 0x2028: /* Unicode LS */ case 0x2029: /* Unicode PS */ *lenptr = 3; return p; #endif /* Not EBCDIC */ default: break; } } /* End of loop for ANY case */ *lenptr = 0; /* Must have hit the end */ return endptr; } /* End of overall switch */ } /************************************************* * Find start of previous line * *************************************************/ /* This is called when looking back for before lines to print. Arguments: p start of the subsequent line startptr start of available data Returns: pointer to the start of the previous line */ static char * previous_line(char *p, char *startptr) { switch(endlinetype) { default: /* Just in case */ case EL_LF: p--; while (p > startptr && p[-1] != '\n') p--; return p; case EL_CR: p--; while (p > startptr && p[-1] != '\n') p--; return p; case EL_CRLF: for (;;) { p -= 2; while (p > startptr && p[-1] != '\n') p--; if (p <= startptr + 1 || p[-2] == '\r') return p; } /* Control can never get here */ case EL_ANY: case EL_ANYCRLF: if (*(--p) == '\n' && p > startptr && p[-1] == '\r') p--; if (utf8) while ((*p & 0xc0) == 0x80) p--; while (p > startptr) { register unsigned int c; char *pp = p - 1; if (utf8) { int extra = 0; while ((*pp & 0xc0) == 0x80) pp--; c = *((unsigned char *)pp); if (c >= 0xc0) { int gcii, gcss; extra = utf8_table4[c & 0x3f]; /* Number of additional bytes */ gcss = 6*extra; c = (c & utf8_table3[extra]) << gcss; for (gcii = 1; gcii <= extra; gcii++) { gcss -= 6; c |= (pp[gcii] & 0x3f) << gcss; } } } else c = *((unsigned char *)pp); if (endlinetype == EL_ANYCRLF) switch (c) { case '\n': /* LF */ case '\r': /* CR */ return p; default: break; } else switch (c) { case '\n': /* LF */ case '\v': /* VT */ case '\f': /* FF */ case '\r': /* CR */ #ifndef EBCDIE case 0x85: /* Unicode NEL */ case 0x2028: /* Unicode LS */ case 0x2029: /* Unicode PS */ #endif /* Not EBCDIC */ return p; default: break; } p = pp; /* Back one character */ } /* End of loop for ANY case */ return startptr; /* Hit start of data */ } /* End of overall switch */ } /************************************************* * Print the previous "after" lines * *************************************************/ /* This is called if we are about to lose said lines because of buffer filling, and at the end of the file. The data in the line is written using fwrite() so that a binary zero does not terminate it. Arguments: lastmatchnumber the number of the last matching line, plus one lastmatchrestart where we restarted after the last match endptr end of available data printname filename for printing Returns: nothing */ static void do_after_lines(unsigned long int lastmatchnumber, char *lastmatchrestart, char *endptr, char *printname) { if (after_context > 0 && lastmatchnumber > 0) { int count = 0; while (lastmatchrestart < endptr && count++ < after_context) { int ellength; char *pp = lastmatchrestart; if (printname != NULL) fprintf(stdout, "%s-", printname); if (number) fprintf(stdout, "%lu-", lastmatchnumber++); pp = end_of_line(pp, endptr, &ellength); FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout); lastmatchrestart = pp; } hyphenpending = TRUE; } } /************************************************* * Apply patterns to subject till one matches * *************************************************/ /* This function is called to run through all patterns, looking for a match. It is used multiple times for the same subject when colouring is enabled, in order to find all possible matches. Arguments: matchptr the start of the subject length the length of the subject to match options options for pcre_exec startoffset where to start matching offsets the offets vector to fill in mrc address of where to put the result of pcre_exec() Returns: TRUE if there was a match FALSE if there was no match invert if there was a non-fatal error */ static BOOL match_patterns(char *matchptr, size_t length, unsigned int options, int startoffset, int *offsets, int *mrc) { int i; size_t slen = length; patstr *p = patterns; const char *msg = "this text:\n\n"; if (slen > 200) { slen = 200; msg = "text that starts:\n\n"; } for (i = 1; p != NULL; p = p->next, i++) { *mrc = pcre_exec(p->compiled, p->hint, matchptr, (int)length, startoffset, options, offsets, OFFSET_SIZE); if (*mrc >= 0) return TRUE; if (*mrc == PCRE_ERROR_NOMATCH) continue; fprintf(stderr, "pcregrep: pcre_exec() gave error %d while matching ", *mrc); if (patterns->next != NULL) fprintf(stderr, "pattern number %d to ", i); fprintf(stderr, "%s", msg); FWRITE(matchptr, 1, slen, stderr); /* In case binary zero included */ fprintf(stderr, "\n\n"); if (*mrc == PCRE_ERROR_MATCHLIMIT || *mrc == PCRE_ERROR_RECURSIONLIMIT || *mrc == PCRE_ERROR_JIT_STACKLIMIT) resource_error = TRUE; if (error_count++ > 20) { fprintf(stderr, "pcregrep: Too many errors - abandoned.\n"); pcregrep_exit(2); } return invert; /* No more matching; don't show the line again */ } return FALSE; /* No match, no errors */ } /************************************************* * Grep an individual file * *************************************************/ /* This is called from grep_or_recurse() below. It uses a buffer that is three times the value of bufthird. The matching point is never allowed to stray into the top third of the buffer, thus keeping more of the file available for context printing or for multiline scanning. For large files, the pointer will be in the middle third most of the time, so the bottom third is available for "before" context printing. Arguments: handle the fopened FILE stream for a normal file the gzFile pointer when reading is via libz the BZFILE pointer when reading is via libbz2 frtype FR_PLAIN, FR_LIBZ, or FR_LIBBZ2 filename the file name or NULL (for errors) printname the file name if it is to be printed for each match or NULL if the file name is not to be printed it cannot be NULL if filenames[_nomatch]_only is set Returns: 0 if there was at least one match 1 otherwise (no matches) 2 if an overlong line is encountered 3 if there is a read error on a .bz2 file */ static int pcregrep(void *handle, int frtype, char *filename, char *printname) { int rc = 1; int filepos = 0; int offsets[OFFSET_SIZE]; unsigned long int linenumber = 1; unsigned long int lastmatchnumber = 0; unsigned long int count = 0; char *lastmatchrestart = NULL; char *ptr = main_buffer; char *endptr; size_t bufflength; BOOL binary = FALSE; BOOL endhyphenpending = FALSE; BOOL input_line_buffered = line_buffered; FILE *in = NULL; /* Ensure initialized */ #ifdef SUPPORT_LIBZ gzFile ingz = NULL; #endif #ifdef SUPPORT_LIBBZ2 BZFILE *inbz2 = NULL; #endif /* Do the first read into the start of the buffer and set up the pointer to end of what we have. In the case of libz, a non-zipped .gz file will be read as a plain file. However, if a .bz2 file isn't actually bzipped, the first read will fail. */ (void)frtype; #ifdef SUPPORT_LIBZ if (frtype == FR_LIBZ) { ingz = (gzFile)handle; bufflength = gzread (ingz, main_buffer, bufsize); } else #endif #ifdef SUPPORT_LIBBZ2 if (frtype == FR_LIBBZ2) { inbz2 = (BZFILE *)handle; bufflength = BZ2_bzread(inbz2, main_buffer, bufsize); if ((int)bufflength < 0) return 2; /* Gotcha: bufflength is size_t; */ } /* without the cast it is unsigned. */ else #endif { in = (FILE *)handle; if (is_file_tty(in)) input_line_buffered = TRUE; bufflength = input_line_buffered? read_one_line(main_buffer, bufsize, in) : fread(main_buffer, 1, bufsize, in); } endptr = main_buffer + bufflength; /* Unless binary-files=text, see if we have a binary file. This uses the same rule as GNU grep, namely, a search for a binary zero byte near the start of the file. */ if (binary_files != BIN_TEXT) { binary = memchr(main_buffer, 0, (bufflength > 1024)? 1024 : bufflength) != NULL; if (binary && binary_files == BIN_NOMATCH) return 1; } /* Loop while the current pointer is not at the end of the file. For large files, endptr will be at the end of the buffer when we are in the middle of the file, but ptr will never get there, because as soon as it gets over 2/3 of the way, the buffer is shifted left and re-filled. */ while (ptr < endptr) { int endlinelength; int mrc = 0; int startoffset = 0; int prevoffsets[2]; unsigned int options = 0; BOOL match; char *matchptr = ptr; char *t = ptr; size_t length, linelength; prevoffsets[0] = prevoffsets[1] = -1; /* At this point, ptr is at the start of a line. We need to find the length of the subject string to pass to pcre_exec(). In multiline mode, it is the length remainder of the data in the buffer. Otherwise, it is the length of the next line, excluding the terminating newline. After matching, we always advance by the length of the next line. In multiline mode the PCRE_FIRSTLINE option is used for compiling, so that any match is constrained to be in the first line. */ t = end_of_line(t, endptr, &endlinelength); linelength = t - ptr - endlinelength; length = multiline? (size_t)(endptr - ptr) : linelength; /* Check to see if the line we are looking at extends right to the very end of the buffer without a line terminator. This means the line is too long to handle. */ if (endlinelength == 0 && t == main_buffer + bufsize) { fprintf(stderr, "pcregrep: line %lu%s%s is too long for the internal buffer\n" "pcregrep: check the --buffer-size option\n", linenumber, (filename == NULL)? "" : " of file ", (filename == NULL)? "" : filename); return 2; } /* Extra processing for Jeffrey Friedl's debugging. */ #ifdef JFRIEDL_DEBUG if (jfriedl_XT || jfriedl_XR) { # include # include struct timeval start_time, end_time; struct timezone dummy; int i; if (jfriedl_XT) { unsigned long newlen = length * jfriedl_XT + strlen(jfriedl_prefix) + strlen(jfriedl_postfix); const char *orig = ptr; ptr = malloc(newlen + 1); if (!ptr) { printf("out of memory"); pcregrep_exit(2); } endptr = ptr; strcpy(endptr, jfriedl_prefix); endptr += strlen(jfriedl_prefix); for (i = 0; i < jfriedl_XT; i++) { strncpy(endptr, orig, length); endptr += length; } strcpy(endptr, jfriedl_postfix); endptr += strlen(jfriedl_postfix); length = newlen; } if (gettimeofday(&start_time, &dummy) != 0) perror("bad gettimeofday"); for (i = 0; i < jfriedl_XR; i++) match = (pcre_exec(patterns->compiled, patterns->hint, ptr, length, 0, PCRE_NOTEMPTY, offsets, OFFSET_SIZE) >= 0); if (gettimeofday(&end_time, &dummy) != 0) perror("bad gettimeofday"); double delta = ((end_time.tv_sec + (end_time.tv_usec / 1000000.0)) - (start_time.tv_sec + (start_time.tv_usec / 1000000.0))); printf("%s TIMER[%.4f]\n", match ? "MATCH" : "FAIL", delta); return 0; } #endif /* We come back here after a match when show_only_matching is set, in order to find any further matches in the same line. This applies to --only-matching, --file-offsets, and --line-offsets. */ ONLY_MATCHING_RESTART: /* Run through all the patterns until one matches or there is an error other than NOMATCH. This code is in a subroutine so that it can be re-used for finding subsequent matches when colouring matched lines. After finding one match, set PCRE_NOTEMPTY to disable any further matches of null strings in this line. */ match = match_patterns(matchptr, length, options, startoffset, offsets, &mrc); options = PCRE_NOTEMPTY; /* If it's a match or a not-match (as required), do what's wanted. */ if (match != invert) { BOOL hyphenprinted = FALSE; /* We've failed if we want a file that doesn't have any matches. */ if (filenames == FN_NOMATCH_ONLY) return 1; /* If all we want is a yes/no answer, stop now. */ if (quiet) return 0; /* Just count if just counting is wanted. */ else if (count_only) count++; /* When handling a binary file and binary-files==binary, the "binary" variable will be set true (it's false in all other cases). In this situation we just want to output the file name. No need to scan further. */ else if (binary) { fprintf(stdout, "Binary file %s matches\n", filename); return 0; } /* If all we want is a file name, there is no need to scan any more lines in the file. */ else if (filenames == FN_MATCH_ONLY) { fprintf(stdout, "%s\n", printname); return 0; } /* The --only-matching option prints just the substring that matched, and/or one or more captured portions of it, as long as these strings are not empty. The --file-offsets and --line-offsets options output offsets for the matching substring (all three set show_only_matching). None of these mutually exclusive options prints any context. Afterwards, adjust the start and then jump back to look for further matches in the same line. If we are in invert mode, however, nothing is printed and we do not restart - this could still be useful because the return code is set. */ else if (show_only_matching) { if (!invert) { int oldstartoffset = startoffset; /* It is possible, when a lookbehind assertion contains \K, for the same string to be found again. The code below advances startoffset, but until it is past the "bumpalong" offset that gave the match, the same substring will be returned. The PCRE1 library does not return the bumpalong offset, so all we can do is ignore repeated strings. (PCRE2 does this better.) */ if (prevoffsets[0] != offsets[0] || prevoffsets[1] != offsets[1]) { prevoffsets[0] = offsets[0]; prevoffsets[1] = offsets[1]; if (printname != NULL) fprintf(stdout, "%s:", printname); if (number) fprintf(stdout, "%lu:", linenumber); /* Handle --line-offsets */ if (line_offsets) fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr), offsets[1] - offsets[0]); /* Handle --file-offsets */ else if (file_offsets) fprintf(stdout, "%d,%d\n", (int)(filepos + matchptr + offsets[0] - ptr), offsets[1] - offsets[0]); /* Handle --only-matching, which may occur many times */ else { BOOL printed = FALSE; omstr *om; for (om = only_matching; om != NULL; om = om->next) { int n = om->groupnum; if (n < mrc) { int plen = offsets[2*n + 1] - offsets[2*n]; if (plen > 0) { if (printed) fprintf(stdout, "%s", om_separator); if (do_colour) fprintf(stdout, "%c[%sm", 0x1b, colour_string); FWRITE(matchptr + offsets[n*2], 1, plen, stdout); if (do_colour) fprintf(stdout, "%c[00m", 0x1b); printed = TRUE; } } } if (printed || printname != NULL || number) fprintf(stdout, "\n"); } } /* Prepare to repeat to find the next match. If the patterned contained a lookbehind tht included \K, it is possible that the end of the match might be at or before the actual strting offset we have just used. We need to start one character further on. Unfortunately, for unanchored patterns, the actual start offset can be greater that the one that was set as a result of "bumpalong". PCRE1 does not return the actual start offset, so we have to check against the original start offset. This may lead to duplicates - we we need the fudge above to avoid printing them. (PCRE2 does this better.) */ match = FALSE; if (line_buffered) fflush(stdout); rc = 0; /* Had some success */ startoffset = offsets[1]; /* Restart after the match */ if (startoffset <= oldstartoffset) { if ((size_t)startoffset >= length) goto END_ONE_MATCH; /* We were at the end */ startoffset = oldstartoffset + 1; if (utf8) while ((matchptr[startoffset] & 0xc0) == 0x80) startoffset++; } /* If the current match ended past the end of the line (only possible in multiline mode), we must move on to the line in which it did end before searching for more matches. */ while (startoffset > (int)linelength) { matchptr = ptr += linelength + endlinelength; filepos += (int)(linelength + endlinelength); linenumber++; startoffset -= (int)(linelength + endlinelength); t = end_of_line(ptr, endptr, &endlinelength); linelength = t - ptr - endlinelength; length = (size_t)(endptr - ptr); } goto ONLY_MATCHING_RESTART; } } /* This is the default case when none of the above options is set. We print the matching lines(s), possibly preceded and/or followed by other lines of context. */ else { /* See if there is a requirement to print some "after" lines from a previous match. We never print any overlaps. */ if (after_context > 0 && lastmatchnumber > 0) { int ellength; int linecount = 0; char *p = lastmatchrestart; while (p < ptr && linecount < after_context) { p = end_of_line(p, ptr, &ellength); linecount++; } /* It is important to advance lastmatchrestart during this printing so that it interacts correctly with any "before" printing below. Print each line's data using fwrite() in case there are binary zeroes. */ while (lastmatchrestart < p) { char *pp = lastmatchrestart; if (printname != NULL) fprintf(stdout, "%s-", printname); if (number) fprintf(stdout, "%lu-", lastmatchnumber++); pp = end_of_line(pp, endptr, &ellength); FWRITE(lastmatchrestart, 1, pp - lastmatchrestart, stdout); lastmatchrestart = pp; } if (lastmatchrestart != ptr) hyphenpending = TRUE; } /* If there were non-contiguous lines printed above, insert hyphens. */ if (hyphenpending) { fprintf(stdout, "--\n"); hyphenpending = FALSE; hyphenprinted = TRUE; } /* See if there is a requirement to print some "before" lines for this match. Again, don't print overlaps. */ if (before_context > 0) { int linecount = 0; char *p = ptr; while (p > main_buffer && (lastmatchnumber == 0 || p > lastmatchrestart) && linecount < before_context) { linecount++; p = previous_line(p, main_buffer); } if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted) fprintf(stdout, "--\n"); while (p < ptr) { int ellength; char *pp = p; if (printname != NULL) fprintf(stdout, "%s-", printname); if (number) fprintf(stdout, "%lu-", linenumber - linecount--); pp = end_of_line(pp, endptr, &ellength); FWRITE(p, 1, pp - p, stdout); p = pp; } } /* Now print the matching line(s); ensure we set hyphenpending at the end of the file if any context lines are being output. */ if (after_context > 0 || before_context > 0) endhyphenpending = TRUE; if (printname != NULL) fprintf(stdout, "%s:", printname); if (number) fprintf(stdout, "%lu:", linenumber); /* In multiline mode, we want to print to the end of the line in which the end of the matched string is found, so we adjust linelength and the line number appropriately, but only when there actually was a match (invert not set). Because the PCRE_FIRSTLINE option is set, the start of the match will always be before the first newline sequence. */ if (multiline & !invert) { char *endmatch = ptr + offsets[1]; t = ptr; while (t <= endmatch) { t = end_of_line(t, endptr, &endlinelength); if (t < endmatch) linenumber++; else break; } linelength = t - ptr - endlinelength; } /*** NOTE: Use only fwrite() to output the data line, so that binary zeroes are treated as just another data character. */ /* This extra option, for Jeffrey Friedl's debugging requirements, replaces the matched string, or a specific captured string if it exists, with X. When this happens, colouring is ignored. */ #ifdef JFRIEDL_DEBUG if (S_arg >= 0 && S_arg < mrc) { int first = S_arg * 2; int last = first + 1; FWRITE(ptr, 1, offsets[first], stdout); fprintf(stdout, "X"); FWRITE(ptr + offsets[last], 1, linelength - offsets[last], stdout); } else #endif /* We have to split the line(s) up if colouring, and search for further matches, but not of course if the line is a non-match. */ if (do_colour && !invert) { int plength; FWRITE(ptr, 1, offsets[0], stdout); fprintf(stdout, "%c[%sm", 0x1b, colour_string); FWRITE(ptr + offsets[0], 1, offsets[1] - offsets[0], stdout); fprintf(stdout, "%c[00m", 0x1b); for (;;) { startoffset = offsets[1]; if (startoffset >= (int)linelength + endlinelength || !match_patterns(matchptr, length, options, startoffset, offsets, &mrc)) break; FWRITE(matchptr + startoffset, 1, offsets[0] - startoffset, stdout); fprintf(stdout, "%c[%sm", 0x1b, colour_string); FWRITE(matchptr + offsets[0], 1, offsets[1] - offsets[0], stdout); fprintf(stdout, "%c[00m", 0x1b); } /* In multiline mode, we may have already printed the complete line and its line-ending characters (if they matched the pattern), so there may be no more to print. */ plength = (int)((linelength + endlinelength) - startoffset); if (plength > 0) FWRITE(ptr + startoffset, 1, plength, stdout); } /* Not colouring; no need to search for further matches */ else FWRITE(ptr, 1, linelength + endlinelength, stdout); } /* End of doing what has to be done for a match. If --line-buffered was given, flush the output. */ if (line_buffered) fflush(stdout); rc = 0; /* Had some success */ /* Remember where the last match happened for after_context. We remember where we are about to restart, and that line's number. */ lastmatchrestart = ptr + linelength + endlinelength; lastmatchnumber = linenumber + 1; } /* For a match in multiline inverted mode (which of course did not cause anything to be printed), we have to move on to the end of the match before proceeding. */ if (multiline && invert && match) { int ellength; char *endmatch = ptr + offsets[1]; t = ptr; while (t < endmatch) { t = end_of_line(t, endptr, &ellength); if (t <= endmatch) linenumber++; else break; } endmatch = end_of_line(endmatch, endptr, &ellength); linelength = endmatch - ptr - ellength; } /* Advance to after the newline and increment the line number. The file offset to the current line is maintained in filepos. */ END_ONE_MATCH: ptr += linelength + endlinelength; filepos += (int)(linelength + endlinelength); linenumber++; /* If input is line buffered, and the buffer is not yet full, read another line and add it into the buffer. */ if (input_line_buffered && bufflength < (size_t)bufsize) { int add = read_one_line(ptr, bufsize - (int)(ptr - main_buffer), in); bufflength += add; endptr += add; } /* If we haven't yet reached the end of the file (the buffer is full), and the current point is in the top 1/3 of the buffer, slide the buffer down by 1/3 and refill it. Before we do this, if some unprinted "after" lines are about to be lost, print them. */ if (bufflength >= (size_t)bufsize && ptr > main_buffer + 2*bufthird) { if (after_context > 0 && lastmatchnumber > 0 && lastmatchrestart < main_buffer + bufthird) { do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname); lastmatchnumber = 0; } /* Now do the shuffle */ memmove(main_buffer, main_buffer + bufthird, 2*bufthird); ptr -= bufthird; #ifdef SUPPORT_LIBZ if (frtype == FR_LIBZ) bufflength = 2*bufthird + gzread (ingz, main_buffer + 2*bufthird, bufthird); else #endif #ifdef SUPPORT_LIBBZ2 if (frtype == FR_LIBBZ2) bufflength = 2*bufthird + BZ2_bzread(inbz2, main_buffer + 2*bufthird, bufthird); else #endif bufflength = 2*bufthird + (input_line_buffered? read_one_line(main_buffer + 2*bufthird, bufthird, in) : fread(main_buffer + 2*bufthird, 1, bufthird, in)); endptr = main_buffer + bufflength; /* Adjust any last match point */ if (lastmatchnumber > 0) lastmatchrestart -= bufthird; } } /* Loop through the whole file */ /* End of file; print final "after" lines if wanted; do_after_lines sets hyphenpending if it prints something. */ if (!show_only_matching && !count_only) { do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname); hyphenpending |= endhyphenpending; } /* Print the file name if we are looking for those without matches and there were none. If we found a match, we won't have got this far. */ if (filenames == FN_NOMATCH_ONLY) { fprintf(stdout, "%s\n", printname); return 0; } /* Print the match count if wanted */ if (count_only && !quiet) { if (count > 0 || !omit_zero_count) { if (printname != NULL && filenames != FN_NONE) fprintf(stdout, "%s:", printname); fprintf(stdout, "%lu\n", count); } } return rc; } /************************************************* * Grep a file or recurse into a directory * *************************************************/ /* Given a path name, if it's a directory, scan all the files if we are recursing; if it's a file, grep it. Arguments: pathname the path to investigate dir_recurse TRUE if recursing is wanted (-r or -drecurse) only_one_at_top TRUE if the path is the only one at toplevel Returns: -1 the file/directory was skipped 0 if there was at least one match 1 if there were no matches 2 there was some kind of error However, file opening failures are suppressed if "silent" is set. */ static int grep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top) { int rc = 1; int frtype; void *handle; char *lastcomp; FILE *in = NULL; /* Ensure initialized */ #ifdef SUPPORT_LIBZ gzFile ingz = NULL; #endif #ifdef SUPPORT_LIBBZ2 BZFILE *inbz2 = NULL; #endif #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2 int pathlen; #endif #if defined NATIVE_ZOS int zos_type; FILE *zos_test_file; #endif /* If the file name is "-" we scan stdin */ if (strcmp(pathname, "-") == 0) { return pcregrep(stdin, FR_PLAIN, stdin_name, (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))? stdin_name : NULL); } /* Inclusion and exclusion: --include-dir and --exclude-dir apply only to directories, whereas --include and --exclude apply to everything else. The test is against the final component of the path. */ lastcomp = strrchr(pathname, FILESEP); lastcomp = (lastcomp == NULL)? pathname : lastcomp + 1; /* If the file is a directory, skip if not recursing or if explicitly excluded. Otherwise, scan the directory and recurse for each path within it. The scanning code is localized so it can be made system-specific. */ /* For z/OS, determine the file type. */ #if defined NATIVE_ZOS zos_test_file = fopen(pathname,"rb"); if (zos_test_file == NULL) { if (!silent) fprintf(stderr, "pcregrep: failed to test next file %s\n", pathname, strerror(errno)); return -1; } zos_type = identifyzosfiletype (zos_test_file); fclose (zos_test_file); /* Handle a PDS in separate code */ if (zos_type == __ZOS_PDS || zos_type == __ZOS_PDSE) { return travelonpdsdir (pathname, only_one_at_top); } /* Deal with regular files in the normal way below. These types are: zos_type == __ZOS_PDS_MEMBER zos_type == __ZOS_PS zos_type == __ZOS_VSAM_KSDS zos_type == __ZOS_VSAM_ESDS zos_type == __ZOS_VSAM_RRDS */ /* Handle a z/OS directory using common code. */ else if (zos_type == __ZOS_HFS) { #endif /* NATIVE_ZOS */ /* Handle directories: common code for all OS */ if (isdirectory(pathname)) { if (dee_action == dee_SKIP || !test_incexc(lastcomp, include_dir_patterns, exclude_dir_patterns)) return -1; if (dee_action == dee_RECURSE) { char buffer[2048]; char *nextfile; directory_type *dir = opendirectory(pathname); if (dir == NULL) { if (!silent) fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", pathname, strerror(errno)); return 2; } while ((nextfile = readdirectory(dir)) != NULL) { int frc; int fnlength = strlen(pathname) + strlen(nextfile) + 2; if (fnlength > 2048) { fprintf(stderr, "pcregrep: recursive filename is too long\n"); rc = 2; break; } sprintf(buffer, "%s%c%s", pathname, FILESEP, nextfile); frc = grep_or_recurse(buffer, dir_recurse, FALSE); if (frc > 1) rc = frc; else if (frc == 0 && rc == 1) rc = 0; } closedirectory(dir); return rc; } } #if defined NATIVE_ZOS } #endif /* If the file is not a directory, check for a regular file, and if it is not, skip it if that's been requested. Otherwise, check for an explicit inclusion or exclusion. */ else if ( #if defined NATIVE_ZOS (zos_type == __ZOS_NOFILE && DEE_action == DEE_SKIP) || #else /* all other OS */ (!isregfile(pathname) && DEE_action == DEE_SKIP) || #endif !test_incexc(lastcomp, include_patterns, exclude_patterns)) return -1; /* File skipped */ /* Control reaches here if we have a regular file, or if we have a directory and recursion or skipping was not requested, or if we have anything else and skipping was not requested. The scan proceeds. If this is the first and only argument at top level, we don't show the file name, unless we are only showing the file name, or the filename was forced (-H). */ #if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2 pathlen = (int)(strlen(pathname)); #endif /* Open using zlib if it is supported and the file name ends with .gz. */ #ifdef SUPPORT_LIBZ if (pathlen > 3 && strcmp(pathname + pathlen - 3, ".gz") == 0) { ingz = gzopen(pathname, "rb"); if (ingz == NULL) { if (!silent) fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname, strerror(errno)); return 2; } handle = (void *)ingz; frtype = FR_LIBZ; } else #endif /* Otherwise open with bz2lib if it is supported and the name ends with .bz2. */ #ifdef SUPPORT_LIBBZ2 if (pathlen > 4 && strcmp(pathname + pathlen - 4, ".bz2") == 0) { inbz2 = BZ2_bzopen(pathname, "rb"); handle = (void *)inbz2; frtype = FR_LIBBZ2; } else #endif /* Otherwise use plain fopen(). The label is so that we can come back here if an attempt to read a .bz2 file indicates that it really is a plain file. */ #ifdef SUPPORT_LIBBZ2 PLAIN_FILE: #endif { in = fopen(pathname, "rb"); handle = (void *)in; frtype = FR_PLAIN; } /* All the opening methods return errno when they fail. */ if (handle == NULL) { if (!silent) fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname, strerror(errno)); return 2; } /* Now grep the file */ rc = pcregrep(handle, frtype, pathname, (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL); /* Close in an appropriate manner. */ #ifdef SUPPORT_LIBZ if (frtype == FR_LIBZ) gzclose(ingz); else #endif /* If it is a .bz2 file and the result is 3, it means that the first attempt to read failed. If the error indicates that the file isn't in fact bzipped, try again as a normal file. */ #ifdef SUPPORT_LIBBZ2 if (frtype == FR_LIBBZ2) { if (rc == 3) { int errnum; const char *err = BZ2_bzerror(inbz2, &errnum); if (errnum == BZ_DATA_ERROR_MAGIC) { BZ2_bzclose(inbz2); goto PLAIN_FILE; } else if (!silent) fprintf(stderr, "pcregrep: Failed to read %s using bzlib: %s\n", pathname, err); rc = 2; /* The normal "something went wrong" code */ } BZ2_bzclose(inbz2); } else #endif /* Normal file close */ fclose(in); /* Pass back the yield from pcregrep(). */ return rc; } /************************************************* * Handle a single-letter, no data option * *************************************************/ static int handle_option(int letter, int options) { switch(letter) { case N_FOFFSETS: file_offsets = TRUE; break; case N_HELP: help(); pcregrep_exit(0); case N_LBUFFER: line_buffered = TRUE; break; case N_LOFFSETS: line_offsets = number = TRUE; break; case N_NOJIT: study_options &= ~PCRE_STUDY_JIT_COMPILE; break; case 'a': binary_files = BIN_TEXT; break; case 'c': count_only = TRUE; break; case 'F': process_options |= PO_FIXED_STRINGS; break; case 'H': filenames = FN_FORCE; break; case 'I': binary_files = BIN_NOMATCH; break; case 'h': filenames = FN_NONE; break; case 'i': options |= PCRE_CASELESS; break; case 'l': omit_zero_count = TRUE; filenames = FN_MATCH_ONLY; break; case 'L': filenames = FN_NOMATCH_ONLY; break; case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break; case 'n': number = TRUE; break; case 'o': only_matching_last = add_number(0, only_matching_last); if (only_matching == NULL) only_matching = only_matching_last; break; case 'q': quiet = TRUE; break; case 'r': dee_action = dee_RECURSE; break; case 's': silent = TRUE; break; case 'u': options |= PCRE_UTF8; utf8 = TRUE; break; case 'v': invert = TRUE; break; case 'w': process_options |= PO_WORD_MATCH; break; case 'x': process_options |= PO_LINE_MATCH; break; case 'V': fprintf(stdout, "pcregrep version %s\n", pcre_version()); pcregrep_exit(0); break; default: fprintf(stderr, "pcregrep: Unknown option -%c\n", letter); pcregrep_exit(usage(2)); } return options; } /************************************************* * Construct printed ordinal * *************************************************/ /* This turns a number into "1st", "3rd", etc. */ static char * ordin(int n) { static char buffer[14]; char *p = buffer; sprintf(p, "%d", n); while (*p != 0) p++; switch (n%10) { case 1: strcpy(p, "st"); break; case 2: strcpy(p, "nd"); break; case 3: strcpy(p, "rd"); break; default: strcpy(p, "th"); break; } return buffer; } /************************************************* * Compile a single pattern * *************************************************/ /* Do nothing if the pattern has already been compiled. This is the case for include/exclude patterns read from a file. When the -F option has been used, each "pattern" may be a list of strings, separated by line breaks. They will be matched literally. We split such a string and compile the first substring, inserting an additional block into the pattern chain. Arguments: p points to the pattern block options the PCRE options popts the processing options fromfile TRUE if the pattern was read from a file fromtext file name or identifying text (e.g. "include") count 0 if this is the only command line pattern, or number of the command line pattern, or linenumber for a pattern from a file Returns: TRUE on success, FALSE after an error */ static BOOL compile_pattern(patstr *p, int options, int popts, int fromfile, const char *fromtext, int count) { char buffer[PATBUFSIZE]; const char *error; char *ps = p->string; int patlen = strlen(ps); int errptr; if (p->compiled != NULL) return TRUE; if ((popts & PO_FIXED_STRINGS) != 0) { int ellength; char *eop = ps + patlen; char *pe = end_of_line(ps, eop, &ellength); if (ellength != 0) { if (add_pattern(pe, p) == NULL) return FALSE; patlen = (int)(pe - ps - ellength); } } if (snprintf(buffer, PATBUFSIZE, "%s%.*s%s", prefix[popts], patlen, ps, suffix[popts]) > PATBUFSIZE) { fprintf(stderr, "pcregrep: Buffer overflow while compiling \"%s\"\n", ps); return FALSE; } p->compiled = pcre_compile(buffer, options, &error, &errptr, pcretables); if (p->compiled != NULL) return TRUE; /* Handle compile errors */ errptr -= (int)strlen(prefix[popts]); if (errptr > patlen) errptr = patlen; if (fromfile) { fprintf(stderr, "pcregrep: Error in regex in line %d of %s " "at offset %d: %s\n", count, fromtext, errptr, error); } else { if (count == 0) fprintf(stderr, "pcregrep: Error in %s regex at offset %d: %s\n", fromtext, errptr, error); else fprintf(stderr, "pcregrep: Error in %s %s regex at offset %d: %s\n", ordin(count), fromtext, errptr, error); } return FALSE; } /************************************************* * Read and compile a file of patterns * *************************************************/ /* This is used for --filelist, --include-from, and --exclude-from. Arguments: name the name of the file; "-" is stdin patptr pointer to the pattern chain anchor patlastptr pointer to the last pattern pointer popts the process options to pass to pattern_compile() Returns: TRUE if all went well */ static BOOL read_pattern_file(char *name, patstr **patptr, patstr **patlastptr, int popts) { int linenumber = 0; FILE *f; char *filename; char buffer[PATBUFSIZE]; if (strcmp(name, "-") == 0) { f = stdin; filename = stdin_name; } else { f = fopen(name, "r"); if (f == NULL) { fprintf(stderr, "pcregrep: Failed to open %s: %s\n", name, strerror(errno)); return FALSE; } filename = name; } while (fgets(buffer, PATBUFSIZE, f) != NULL) { char *s = buffer + (int)strlen(buffer); while (s > buffer && isspace((unsigned char)(s[-1]))) s--; *s = 0; linenumber++; if (buffer[0] == 0) continue; /* Skip blank lines */ /* Note: this call to add_pattern() puts a pointer to the local variable "buffer" into the pattern chain. However, that pointer is used only when compiling the pattern, which happens immediately below, so we flatten it afterwards, as a precaution against any later code trying to use it. */ *patlastptr = add_pattern(buffer, *patlastptr); if (*patlastptr == NULL) { if (f != stdin) fclose(f); return FALSE; } if (*patptr == NULL) *patptr = *patlastptr; /* This loop is needed because compiling a "pattern" when -F is set may add on additional literal patterns if the original contains a newline. In the common case, it never will, because fgets() stops at a newline. However, the -N option can be used to give pcregrep a different newline setting. */ for(;;) { if (!compile_pattern(*patlastptr, pcre_options, popts, TRUE, filename, linenumber)) { if (f != stdin) fclose(f); return FALSE; } (*patlastptr)->string = NULL; /* Insurance */ if ((*patlastptr)->next == NULL) break; *patlastptr = (*patlastptr)->next; } } if (f != stdin) fclose(f); return TRUE; } /************************************************* * Main program * *************************************************/ /* Returns 0 if something matched, 1 if nothing matched, 2 after an error. */ int main(int argc, char **argv) { int i, j; int rc = 1; BOOL only_one_at_top; patstr *cp; fnstr *fn; const char *locale_from = "--locale"; const char *error; #ifdef SUPPORT_PCREGREP_JIT pcre_jit_stack *jit_stack = NULL; #endif /* Set the default line ending value from the default in the PCRE library; "lf", "cr", "crlf", and "any" are supported. Anything else is treated as "lf". Note that the return values from pcre_config(), though derived from the ASCII codes, are the same in EBCDIC environments, so we must use the actual values rather than escapes such as as '\r'. */ (void)pcre_config(PCRE_CONFIG_NEWLINE, &i); switch(i) { default: newline = (char *)"lf"; break; case 13: newline = (char *)"cr"; break; case (13 << 8) | 10: newline = (char *)"crlf"; break; case -1: newline = (char *)"any"; break; case -2: newline = (char *)"anycrlf"; break; } /* Process the options */ for (i = 1; i < argc; i++) { option_item *op = NULL; char *option_data = (char *)""; /* default to keep compiler happy */ BOOL longop; BOOL longopwasequals = FALSE; if (argv[i][0] != '-') break; /* If we hit an argument that is just "-", it may be a reference to STDIN, but only if we have previously had -e or -f to define the patterns. */ if (argv[i][1] == 0) { if (pattern_files != NULL || patterns != NULL) break; else pcregrep_exit(usage(2)); } /* Handle a long name option, or -- to terminate the options */ if (argv[i][1] == '-') { char *arg = argv[i] + 2; char *argequals = strchr(arg, '='); if (*arg == 0) /* -- terminates options */ { i++; break; /* out of the options-handling loop */ } longop = TRUE; /* Some long options have data that follows after =, for example file=name. Some options have variations in the long name spelling: specifically, we allow "regexp" because GNU grep allows it, though I personally go along with Jeffrey Friedl and Larry Wall in preferring "regex" without the "p". These options are entered in the table as "regex(p)". Options can be in both these categories. */ for (op = optionlist; op->one_char != 0; op++) { char *opbra = strchr(op->long_name, '('); char *equals = strchr(op->long_name, '='); /* Handle options with only one spelling of the name */ if (opbra == NULL) /* Does not contain '(' */ { if (equals == NULL) /* Not thing=data case */ { if (strcmp(arg, op->long_name) == 0) break; } else /* Special case xxx=data */ { int oplen = (int)(equals - op->long_name); int arglen = (argequals == NULL)? (int)strlen(arg) : (int)(argequals - arg); if (oplen == arglen && strncmp(arg, op->long_name, oplen) == 0) { option_data = arg + arglen; if (*option_data == '=') { option_data++; longopwasequals = TRUE; } break; } } } /* Handle options with an alternate spelling of the name */ else { char buff1[24]; char buff2[24]; int baselen = (int)(opbra - op->long_name); int fulllen = (int)(strchr(op->long_name, ')') - op->long_name + 1); int arglen = (argequals == NULL || equals == NULL)? (int)strlen(arg) : (int)(argequals - arg); if (snprintf(buff1, sizeof(buff1), "%.*s", baselen, op->long_name) > (int)sizeof(buff1) || snprintf(buff2, sizeof(buff2), "%s%.*s", buff1, fulllen - baselen - 2, opbra + 1) > (int)sizeof(buff2)) { fprintf(stderr, "pcregrep: Buffer overflow when parsing %s option\n", op->long_name); pcregrep_exit(2); } if (strncmp(arg, buff1, arglen) == 0 || strncmp(arg, buff2, arglen) == 0) { if (equals != NULL && argequals != NULL) { option_data = argequals; if (*option_data == '=') { option_data++; longopwasequals = TRUE; } } break; } } } if (op->one_char == 0) { fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]); pcregrep_exit(usage(2)); } } /* Jeffrey Friedl's debugging harness uses these additional options which are not in the right form for putting in the option table because they use only one hyphen, yet are more than one character long. By putting them separately here, they will not get displayed as part of the help() output, but I don't think Jeffrey will care about that. */ #ifdef JFRIEDL_DEBUG else if (strcmp(argv[i], "-pre") == 0) { jfriedl_prefix = argv[++i]; continue; } else if (strcmp(argv[i], "-post") == 0) { jfriedl_postfix = argv[++i]; continue; } else if (strcmp(argv[i], "-XT") == 0) { sscanf(argv[++i], "%d", &jfriedl_XT); continue; } else if (strcmp(argv[i], "-XR") == 0) { sscanf(argv[++i], "%d", &jfriedl_XR); continue; } #endif /* One-char options; many that have no data may be in a single argument; we continue till we hit the last one or one that needs data. */ else { char *s = argv[i] + 1; longop = FALSE; while (*s != 0) { for (op = optionlist; op->one_char != 0; op++) { if (*s == op->one_char) break; } if (op->one_char == 0) { fprintf(stderr, "pcregrep: Unknown option letter '%c' in \"%s\"\n", *s, argv[i]); pcregrep_exit(usage(2)); } option_data = s+1; /* Break out if this is the last character in the string; it's handled below like a single multi-char option. */ if (*option_data == 0) break; /* Check for a single-character option that has data: OP_OP_NUMBER(S) are used for ones that either have a numerical number or defaults, i.e. the data is optional. If a digit follows, there is data; if not, carry on with other single-character options in the same string. */ if (op->type == OP_OP_NUMBER || op->type == OP_OP_NUMBERS) { if (isdigit((unsigned char)s[1])) break; } else /* Check for an option with data */ { if (op->type != OP_NODATA) break; } /* Handle a single-character option with no data, then loop for the next character in the string. */ pcre_options = handle_option(*s++, pcre_options); } } /* At this point we should have op pointing to a matched option. If the type is NO_DATA, it means that there is no data, and the option might set something in the PCRE options. */ if (op->type == OP_NODATA) { pcre_options = handle_option(op->one_char, pcre_options); continue; } /* If the option type is OP_OP_STRING or OP_OP_NUMBER(S), it's an option that either has a value or defaults to something. It cannot have data in a separate item. At the moment, the only such options are "colo(u)r", "only-matching", and Jeffrey Friedl's special -S debugging option. */ if (*option_data == 0 && (op->type == OP_OP_STRING || op->type == OP_OP_NUMBER || op->type == OP_OP_NUMBERS)) { switch (op->one_char) { case N_COLOUR: colour_option = (char *)"auto"; break; case 'o': only_matching_last = add_number(0, only_matching_last); if (only_matching == NULL) only_matching = only_matching_last; break; #ifdef JFRIEDL_DEBUG case 'S': S_arg = 0; break; #endif } continue; } /* Otherwise, find the data string for the option. */ if (*option_data == 0) { if (i >= argc - 1 || longopwasequals) { fprintf(stderr, "pcregrep: Data missing after %s\n", argv[i]); pcregrep_exit(usage(2)); } option_data = argv[++i]; } /* If the option type is OP_OP_NUMBERS, the value is a number that is to be added to a chain of numbers. */ if (op->type == OP_OP_NUMBERS) { unsigned long int n = decode_number(option_data, op, longop); omdatastr *omd = (omdatastr *)op->dataptr; *(omd->lastptr) = add_number((int)n, *(omd->lastptr)); if (*(omd->anchor) == NULL) *(omd->anchor) = *(omd->lastptr); } /* If the option type is OP_PATLIST, it's the -e option, or one of the include/exclude options, which can be called multiple times to create lists of patterns. */ else if (op->type == OP_PATLIST) { patdatastr *pd = (patdatastr *)op->dataptr; *(pd->lastptr) = add_pattern(option_data, *(pd->lastptr)); if (*(pd->lastptr) == NULL) goto EXIT2; if (*(pd->anchor) == NULL) *(pd->anchor) = *(pd->lastptr); } /* If the option type is OP_FILELIST, it's one of the options that names a file. */ else if (op->type == OP_FILELIST) { fndatastr *fd = (fndatastr *)op->dataptr; fn = (fnstr *)malloc(sizeof(fnstr)); if (fn == NULL) { fprintf(stderr, "pcregrep: malloc failed\n"); goto EXIT2; } fn->next = NULL; fn->name = option_data; if (*(fd->anchor) == NULL) *(fd->anchor) = fn; else (*(fd->lastptr))->next = fn; *(fd->lastptr) = fn; } /* Handle OP_BINARY_FILES */ else if (op->type == OP_BINFILES) { if (strcmp(option_data, "binary") == 0) binary_files = BIN_BINARY; else if (strcmp(option_data, "without-match") == 0) binary_files = BIN_NOMATCH; else if (strcmp(option_data, "text") == 0) binary_files = BIN_TEXT; else { fprintf(stderr, "pcregrep: unknown value \"%s\" for binary-files\n", option_data); pcregrep_exit(usage(2)); } } /* Otherwise, deal with a single string or numeric data value. */ else if (op->type != OP_NUMBER && op->type != OP_LONGNUMBER && op->type != OP_OP_NUMBER) { *((char **)op->dataptr) = option_data; } else { unsigned long int n = decode_number(option_data, op, longop); if (op->type == OP_LONGNUMBER) *((unsigned long int *)op->dataptr) = n; else *((int *)op->dataptr) = n; } } /* Options have been decoded. If -C was used, its value is used as a default for -A and -B. */ if (both_context > 0) { if (after_context == 0) after_context = both_context; if (before_context == 0) before_context = both_context; } /* Only one of --only-matching, --file-offsets, or --line-offsets is permitted. However, all three set show_only_matching because they display, each in their own way, only the data that has matched. */ if ((only_matching != NULL && (file_offsets || line_offsets)) || (file_offsets && line_offsets)) { fprintf(stderr, "pcregrep: Cannot mix --only-matching, --file-offsets " "and/or --line-offsets\n"); pcregrep_exit(usage(2)); } if (only_matching != NULL || file_offsets || line_offsets) show_only_matching = TRUE; /* If a locale has not been provided as an option, see if the LC_CTYPE or LC_ALL environment variable is set, and if so, use it. */ if (locale == NULL) { locale = getenv("LC_ALL"); locale_from = "LC_ALL"; } if (locale == NULL) { locale = getenv("LC_CTYPE"); locale_from = "LC_CTYPE"; } /* If a locale is set, use it to generate the tables the PCRE needs. Otherwise, pcretables==NULL, which causes the use of default tables. */ if (locale != NULL) { if (setlocale(LC_CTYPE, locale) == NULL) { fprintf(stderr, "pcregrep: Failed to set locale %s (obtained from %s)\n", locale, locale_from); goto EXIT2; } pcretables = pcre_maketables(); } /* Sort out colouring */ if (colour_option != NULL && strcmp(colour_option, "never") != 0) { if (strcmp(colour_option, "always") == 0) do_colour = TRUE; else if (strcmp(colour_option, "auto") == 0) do_colour = is_stdout_tty(); else { fprintf(stderr, "pcregrep: Unknown colour setting \"%s\"\n", colour_option); goto EXIT2; } if (do_colour) { char *cs = getenv("PCREGREP_COLOUR"); if (cs == NULL) cs = getenv("PCREGREP_COLOR"); if (cs != NULL) colour_string = cs; } } /* Interpret the newline type; the default settings are Unix-like. */ if (strcmp(newline, "cr") == 0 || strcmp(newline, "CR") == 0) { pcre_options |= PCRE_NEWLINE_CR; endlinetype = EL_CR; } else if (strcmp(newline, "lf") == 0 || strcmp(newline, "LF") == 0) { pcre_options |= PCRE_NEWLINE_LF; endlinetype = EL_LF; } else if (strcmp(newline, "crlf") == 0 || strcmp(newline, "CRLF") == 0) { pcre_options |= PCRE_NEWLINE_CRLF; endlinetype = EL_CRLF; } else if (strcmp(newline, "any") == 0 || strcmp(newline, "ANY") == 0) { pcre_options |= PCRE_NEWLINE_ANY; endlinetype = EL_ANY; } else if (strcmp(newline, "anycrlf") == 0 || strcmp(newline, "ANYCRLF") == 0) { pcre_options |= PCRE_NEWLINE_ANYCRLF; endlinetype = EL_ANYCRLF; } else { fprintf(stderr, "pcregrep: Invalid newline specifier \"%s\"\n", newline); goto EXIT2; } /* Interpret the text values for -d and -D */ if (dee_option != NULL) { if (strcmp(dee_option, "read") == 0) dee_action = dee_READ; else if (strcmp(dee_option, "recurse") == 0) dee_action = dee_RECURSE; else if (strcmp(dee_option, "skip") == 0) dee_action = dee_SKIP; else { fprintf(stderr, "pcregrep: Invalid value \"%s\" for -d\n", dee_option); goto EXIT2; } } if (DEE_option != NULL) { if (strcmp(DEE_option, "read") == 0) DEE_action = DEE_READ; else if (strcmp(DEE_option, "skip") == 0) DEE_action = DEE_SKIP; else { fprintf(stderr, "pcregrep: Invalid value \"%s\" for -D\n", DEE_option); goto EXIT2; } } /* Check the values for Jeffrey Friedl's debugging options. */ #ifdef JFRIEDL_DEBUG if (S_arg > 9) { fprintf(stderr, "pcregrep: bad value for -S option\n"); return 2; } if (jfriedl_XT != 0 || jfriedl_XR != 0) { if (jfriedl_XT == 0) jfriedl_XT = 1; if (jfriedl_XR == 0) jfriedl_XR = 1; } #endif /* Get memory for the main buffer. */ bufsize = 3*bufthird; main_buffer = (char *)malloc(bufsize); if (main_buffer == NULL) { fprintf(stderr, "pcregrep: malloc failed\n"); goto EXIT2; } /* If no patterns were provided by -e, and there are no files provided by -f, the first argument is the one and only pattern, and it must exist. */ if (patterns == NULL && pattern_files == NULL) { if (i >= argc) return usage(2); patterns = patterns_last = add_pattern(argv[i++], NULL); if (patterns == NULL) goto EXIT2; } /* Compile the patterns that were provided on the command line, either by multiple uses of -e or as a single unkeyed pattern. We cannot do this until after all the command-line options are read so that we know which PCRE options to use. When -F is used, compile_pattern() may add another block into the chain, so we must not access the next pointer till after the compile. */ for (j = 1, cp = patterns; cp != NULL; j++, cp = cp->next) { if (!compile_pattern(cp, pcre_options, process_options, FALSE, "command-line", (j == 1 && patterns->next == NULL)? 0 : j)) goto EXIT2; } /* Read and compile the regular expressions that are provided in files. */ for (fn = pattern_files; fn != NULL; fn = fn->next) { if (!read_pattern_file(fn->name, &patterns, &patterns_last, process_options)) goto EXIT2; } /* Study the regular expressions, as we will be running them many times. If an extra block is needed for a limit, set PCRE_STUDY_EXTRA_NEEDED so that one is returned, even if studying produces no data. */ if (match_limit > 0 || match_limit_recursion > 0) study_options |= PCRE_STUDY_EXTRA_NEEDED; /* Unless JIT has been explicitly disabled, arrange a stack for it to use. */ #ifdef SUPPORT_PCREGREP_JIT if ((study_options & PCRE_STUDY_JIT_COMPILE) != 0) jit_stack = pcre_jit_stack_alloc(32*1024, 1024*1024); #endif for (j = 1, cp = patterns; cp != NULL; j++, cp = cp->next) { cp->hint = pcre_study(cp->compiled, study_options, &error); if (error != NULL) { if (patterns->next == NULL) fprintf(stderr, "pcregrep: Error while studying regex: %s\n", error); else fprintf(stderr, "pcregrep: Error while studying regex number %d: %s\n", j, error); goto EXIT2; } #ifdef SUPPORT_PCREGREP_JIT if (jit_stack != NULL && cp->hint != NULL) pcre_assign_jit_stack(cp->hint, NULL, jit_stack); #endif } /* If --match-limit or --recursion-limit was set, put the value(s) into the pcre_extra block for each pattern. There will always be an extra block because of the use of PCRE_STUDY_EXTRA_NEEDED above. */ for (cp = patterns; cp != NULL; cp = cp->next) { if (match_limit > 0) { cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT; cp->hint->match_limit = match_limit; } if (match_limit_recursion > 0) { cp->hint->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; cp->hint->match_limit_recursion = match_limit_recursion; } } /* If there are include or exclude patterns read from the command line, compile them. -F, -w, and -x do not apply, so the third argument of compile_pattern is 0. */ for (j = 0; j < 4; j++) { int k; for (k = 1, cp = *(incexlist[j]); cp != NULL; k++, cp = cp->next) { if (!compile_pattern(cp, pcre_options, 0, FALSE, incexname[j], (k == 1 && cp->next == NULL)? 0 : k)) goto EXIT2; } } /* Read and compile include/exclude patterns from files. */ for (fn = include_from; fn != NULL; fn = fn->next) { if (!read_pattern_file(fn->name, &include_patterns, &include_patterns_last, 0)) goto EXIT2; } for (fn = exclude_from; fn != NULL; fn = fn->next) { if (!read_pattern_file(fn->name, &exclude_patterns, &exclude_patterns_last, 0)) goto EXIT2; } /* If there are no files that contain lists of files to search, and there are no file arguments, search stdin, and then exit. */ if (file_lists == NULL && i >= argc) { rc = pcregrep(stdin, FR_PLAIN, stdin_name, (filenames > FN_DEFAULT)? stdin_name : NULL); goto EXIT; } /* If any files that contains a list of files to search have been specified, read them line by line and search the given files. */ for (fn = file_lists; fn != NULL; fn = fn->next) { char buffer[PATBUFSIZE]; FILE *fl; if (strcmp(fn->name, "-") == 0) fl = stdin; else { fl = fopen(fn->name, "rb"); if (fl == NULL) { fprintf(stderr, "pcregrep: Failed to open %s: %s\n", fn->name, strerror(errno)); goto EXIT2; } } while (fgets(buffer, PATBUFSIZE, fl) != NULL) { int frc; char *end = buffer + (int)strlen(buffer); while (end > buffer && isspace(end[-1])) end--; *end = 0; if (*buffer != 0) { frc = grep_or_recurse(buffer, dee_action == dee_RECURSE, FALSE); if (frc > 1) rc = frc; else if (frc == 0 && rc == 1) rc = 0; } } if (fl != stdin) fclose(fl); } /* After handling file-list, work through remaining arguments. Pass in the fact that there is only one argument at top level - this suppresses the file name if the argument is not a directory and filenames are not otherwise forced. */ only_one_at_top = i == argc - 1 && file_lists == NULL; for (; i < argc; i++) { int frc = grep_or_recurse(argv[i], dee_action == dee_RECURSE, only_one_at_top); if (frc > 1) rc = frc; else if (frc == 0 && rc == 1) rc = 0; } EXIT: #ifdef SUPPORT_PCREGREP_JIT if (jit_stack != NULL) pcre_jit_stack_free(jit_stack); #endif free(main_buffer); free((void *)pcretables); free_pattern_chain(patterns); free_pattern_chain(include_patterns); free_pattern_chain(include_dir_patterns); free_pattern_chain(exclude_patterns); free_pattern_chain(exclude_dir_patterns); free_file_chain(exclude_from); free_file_chain(include_from); free_file_chain(pattern_files); free_file_chain(file_lists); while (only_matching != NULL) { omstr *this = only_matching; only_matching = this->next; free(this); } pcregrep_exit(rc); EXIT2: rc = 2; goto EXIT; } /* End of pcregrep */ ================================================ FILE: src/pcre/pcreposix.c ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ /* PCRE is a library of functions to support regular expressions whose syntax and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Copyright (c) 1997-2018 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This module is a wrapper that provides a POSIX API to the underlying PCRE functions. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* Ensure that the PCREPOSIX_EXP_xxx macros are set appropriately for compiling these functions. This must come before including pcreposix.h, where they are set for an application (using these functions) if they have not previously been set. */ #if defined(_WIN32) && !defined(PCRE_STATIC) # define PCREPOSIX_EXP_DECL extern __declspec(dllexport) # define PCREPOSIX_EXP_DEFN __declspec(dllexport) #endif /* We include pcre.h before pcre_internal.h so that the PCRE library functions are declared as "import" for Windows by defining PCRE_EXP_DECL as "import". This is needed even though pcre_internal.h itself includes pcre.h, because it does so after it has set PCRE_EXP_DECL to "export" if it is not already set. */ #include "pcre.h" #include "pcre_internal.h" #include "pcreposix.h" /* Table to translate PCRE compile time error codes into POSIX error codes. */ static const int eint[] = { 0, /* no error */ REG_EESCAPE, /* \ at end of pattern */ REG_EESCAPE, /* \c at end of pattern */ REG_EESCAPE, /* unrecognized character follows \ */ REG_BADBR, /* numbers out of order in {} quantifier */ /* 5 */ REG_BADBR, /* number too big in {} quantifier */ REG_EBRACK, /* missing terminating ] for character class */ REG_ECTYPE, /* invalid escape sequence in character class */ REG_ERANGE, /* range out of order in character class */ REG_BADRPT, /* nothing to repeat */ /* 10 */ REG_BADRPT, /* operand of unlimited repeat could match the empty string */ REG_ASSERT, /* internal error: unexpected repeat */ REG_BADPAT, /* unrecognized character after (? */ REG_BADPAT, /* POSIX named classes are supported only within a class */ REG_EPAREN, /* missing ) */ /* 15 */ REG_ESUBREG, /* reference to non-existent subpattern */ REG_INVARG, /* erroffset passed as NULL */ REG_INVARG, /* unknown option bit(s) set */ REG_EPAREN, /* missing ) after comment */ REG_ESIZE, /* parentheses nested too deeply */ /* 20 */ REG_ESIZE, /* regular expression too large */ REG_ESPACE, /* failed to get memory */ REG_EPAREN, /* unmatched parentheses */ REG_ASSERT, /* internal error: code overflow */ REG_BADPAT, /* unrecognized character after (?< */ /* 25 */ REG_BADPAT, /* lookbehind assertion is not fixed length */ REG_BADPAT, /* malformed number or name after (?( */ REG_BADPAT, /* conditional group contains more than two branches */ REG_BADPAT, /* assertion expected after (?( */ REG_BADPAT, /* (?R or (?[+-]digits must be followed by ) */ /* 30 */ REG_ECTYPE, /* unknown POSIX class name */ REG_BADPAT, /* POSIX collating elements are not supported */ REG_INVARG, /* this version of PCRE is not compiled with PCRE_UTF8 support */ REG_BADPAT, /* spare error */ REG_BADPAT, /* character value in \x{} or \o{} is too large */ /* 35 */ REG_BADPAT, /* invalid condition (?(0) */ REG_BADPAT, /* \C not allowed in lookbehind assertion */ REG_EESCAPE, /* PCRE does not support \L, \l, \N, \U, or \u */ REG_BADPAT, /* number after (?C is > 255 */ REG_BADPAT, /* closing ) for (?C expected */ /* 40 */ REG_BADPAT, /* recursive call could loop indefinitely */ REG_BADPAT, /* unrecognized character after (?P */ REG_BADPAT, /* syntax error in subpattern name (missing terminator) */ REG_BADPAT, /* two named subpatterns have the same name */ REG_BADPAT, /* invalid UTF-8 string */ /* 45 */ REG_BADPAT, /* support for \P, \p, and \X has not been compiled */ REG_BADPAT, /* malformed \P or \p sequence */ REG_BADPAT, /* unknown property name after \P or \p */ REG_BADPAT, /* subpattern name is too long (maximum 32 characters) */ REG_BADPAT, /* too many named subpatterns (maximum 10,000) */ /* 50 */ REG_BADPAT, /* repeated subpattern is too long */ REG_BADPAT, /* octal value is greater than \377 (not in UTF-8 mode) */ REG_BADPAT, /* internal error: overran compiling workspace */ REG_BADPAT, /* internal error: previously-checked referenced subpattern not found */ REG_BADPAT, /* DEFINE group contains more than one branch */ /* 55 */ REG_BADPAT, /* repeating a DEFINE group is not allowed */ REG_INVARG, /* inconsistent NEWLINE options */ REG_BADPAT, /* \g is not followed followed by an (optionally braced) non-zero number */ REG_BADPAT, /* a numbered reference must not be zero */ REG_BADPAT, /* an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) */ /* 60 */ REG_BADPAT, /* (*VERB) not recognized */ REG_BADPAT, /* number is too big */ REG_BADPAT, /* subpattern name expected */ REG_BADPAT, /* digit expected after (?+ */ REG_BADPAT, /* ] is an invalid data character in JavaScript compatibility mode */ /* 65 */ REG_BADPAT, /* different names for subpatterns of the same number are not allowed */ REG_BADPAT, /* (*MARK) must have an argument */ REG_INVARG, /* this version of PCRE is not compiled with PCRE_UCP support */ REG_BADPAT, /* \c must be followed by an ASCII character */ REG_BADPAT, /* \k is not followed by a braced, angle-bracketed, or quoted name */ /* 70 */ REG_BADPAT, /* internal error: unknown opcode in find_fixedlength() */ REG_BADPAT, /* \N is not supported in a class */ REG_BADPAT, /* too many forward references */ REG_BADPAT, /* disallowed UTF-8/16/32 code point (>= 0xd800 && <= 0xdfff) */ REG_BADPAT, /* invalid UTF-16 string (should not occur) */ /* 75 */ REG_BADPAT, /* overlong MARK name */ REG_BADPAT, /* character value in \u.... sequence is too large */ REG_BADPAT, /* invalid UTF-32 string (should not occur) */ REG_BADPAT, /* setting UTF is disabled by the application */ REG_BADPAT, /* non-hex character in \\x{} (closing brace missing?) */ /* 80 */ REG_BADPAT, /* non-octal character in \o{} (closing brace missing?) */ REG_BADPAT, /* missing opening brace after \o */ REG_BADPAT, /* parentheses too deeply nested */ REG_BADPAT, /* invalid range in character class */ REG_BADPAT, /* group name must start with a non-digit */ /* 85 */ REG_BADPAT, /* parentheses too deeply nested (stack check) */ REG_BADPAT, /* missing digits in \x{} or \o{} */ REG_BADPAT /* pattern too complicated */ }; /* Table of texts corresponding to POSIX error codes */ static const char *const pstring[] = { "", /* Dummy for value 0 */ "internal error", /* REG_ASSERT */ "invalid repeat counts in {}", /* BADBR */ "pattern error", /* BADPAT */ "? * + invalid", /* BADRPT */ "unbalanced {}", /* EBRACE */ "unbalanced []", /* EBRACK */ "collation error - not relevant", /* ECOLLATE */ "bad class", /* ECTYPE */ "bad escape sequence", /* EESCAPE */ "empty expression", /* EMPTY */ "unbalanced ()", /* EPAREN */ "bad range inside []", /* ERANGE */ "expression too big", /* ESIZE */ "failed to get memory", /* ESPACE */ "bad back reference", /* ESUBREG */ "bad argument", /* INVARG */ "match failed" /* NOMATCH */ }; /************************************************* * Translate error code to string * *************************************************/ PCREPOSIX_EXP_DEFN size_t PCRE_CALL_CONVENTION regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { const char *message, *addmessage; size_t length, addlength; message = (errcode >= (int)(sizeof(pstring)/sizeof(char *)))? "unknown error code" : pstring[errcode]; length = strlen(message) + 1; addmessage = " at offset "; addlength = (preg != NULL && (int)preg->re_erroffset != -1)? strlen(addmessage) + 6 : 0; if (errbuf_size > 0) { if (addlength > 0 && errbuf_size >= length + addlength) sprintf(errbuf, "%s%s%-6d", message, addmessage, (int)preg->re_erroffset); else { strncpy(errbuf, message, errbuf_size - 1); errbuf[errbuf_size-1] = 0; } } return length + addlength; } /************************************************* * Free store held by a regex * *************************************************/ PCREPOSIX_EXP_DEFN void PCRE_CALL_CONVENTION regfree(regex_t *preg) { (PUBL(free))(preg->re_pcre); } /************************************************* * Compile a regular expression * *************************************************/ /* Arguments: preg points to a structure for recording the compiled expression pattern the pattern to compile cflags compilation flags Returns: 0 on success various non-zero codes on failure */ PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION regcomp(regex_t *preg, const char *pattern, int cflags) { const char *errorptr; int erroffset; int errorcode; int options = 0; int re_nsub = 0; if ((cflags & REG_ICASE) != 0) options |= PCRE_CASELESS; if ((cflags & REG_NEWLINE) != 0) options |= PCRE_MULTILINE; if ((cflags & REG_DOTALL) != 0) options |= PCRE_DOTALL; if ((cflags & REG_NOSUB) != 0) options |= PCRE_NO_AUTO_CAPTURE; if ((cflags & REG_UTF8) != 0) options |= PCRE_UTF8; if ((cflags & REG_UCP) != 0) options |= PCRE_UCP; if ((cflags & REG_UNGREEDY) != 0) options |= PCRE_UNGREEDY; preg->re_pcre = pcre_compile2(pattern, options, &errorcode, &errorptr, &erroffset, NULL); preg->re_erroffset = erroffset; /* Safety: if the error code is too big for the translation vector (which should not happen, but we all make mistakes), return REG_BADPAT. */ if (preg->re_pcre == NULL) { return (errorcode < (int)(sizeof(eint)/sizeof(const int)))? eint[errorcode] : REG_BADPAT; } (void)pcre_fullinfo((const pcre *)preg->re_pcre, NULL, PCRE_INFO_CAPTURECOUNT, &re_nsub); preg->re_nsub = (size_t)re_nsub; return 0; } /************************************************* * Match a regular expression * *************************************************/ /* Unfortunately, PCRE requires 3 ints of working space for each captured substring, so we have to get and release working store instead of just using the POSIX structures as was done in earlier releases when PCRE needed only 2 ints. However, if the number of possible capturing brackets is small, use a block of store on the stack, to reduce the use of malloc/free. The threshold is in a macro that can be changed at configure time. If REG_NOSUB was specified at compile time, the PCRE_NO_AUTO_CAPTURE flag will be set. When this is the case, the nmatch and pmatch arguments are ignored, and the only result is yes/no/error. */ PCREPOSIX_EXP_DEFN int PCRE_CALL_CONVENTION regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { int rc, so, eo; int options = 0; int *ovector = NULL; int small_ovector[POSIX_MALLOC_THRESHOLD * 3]; BOOL allocated_ovector = FALSE; BOOL nosub = (REAL_PCRE_OPTIONS((const pcre *)preg->re_pcre) & PCRE_NO_AUTO_CAPTURE) != 0; if ((eflags & REG_NOTBOL) != 0) options |= PCRE_NOTBOL; if ((eflags & REG_NOTEOL) != 0) options |= PCRE_NOTEOL; if ((eflags & REG_NOTEMPTY) != 0) options |= PCRE_NOTEMPTY; ((regex_t *)preg)->re_erroffset = (size_t)(-1); /* Only has meaning after compile */ /* When no string data is being returned, or no vector has been passed in which to put it, ensure that nmatch is zero. Otherwise, ensure the vector for holding the return data is large enough. */ if (nosub || pmatch == NULL) nmatch = 0; else if (nmatch > 0) { if (nmatch <= POSIX_MALLOC_THRESHOLD) { ovector = &(small_ovector[0]); } else { if (nmatch > INT_MAX/(sizeof(int) * 3)) return REG_ESPACE; ovector = (int *)malloc(sizeof(int) * nmatch * 3); if (ovector == NULL) return REG_ESPACE; allocated_ovector = TRUE; } } /* REG_STARTEND is a BSD extension, to allow for non-NUL-terminated strings. The man page from OS X says "REG_STARTEND affects only the location of the string, not how it is matched". That is why the "so" value is used to bump the start location rather than being passed as a PCRE "starting offset". */ if ((eflags & REG_STARTEND) != 0) { if (pmatch == NULL) return REG_INVARG; so = pmatch[0].rm_so; eo = pmatch[0].rm_eo; } else { so = 0; eo = (int)strlen(string); } rc = pcre_exec((const pcre *)preg->re_pcre, NULL, string + so, (eo - so), 0, options, ovector, (int)(nmatch * 3)); if (rc == 0) rc = (int)nmatch; /* All captured slots were filled in */ /* Successful match */ if (rc >= 0) { size_t i; if (!nosub) { for (i = 0; i < (size_t)rc; i++) { pmatch[i].rm_so = (ovector[i*2] < 0)? -1 : ovector[i*2] + so; pmatch[i].rm_eo = (ovector[i*2+1] < 0)? -1: ovector[i*2+1] + so; } if (allocated_ovector) free(ovector); for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1; } return 0; } /* Unsuccessful match */ if (allocated_ovector) free(ovector); switch(rc) { /* ========================================================================== */ /* These cases are never obeyed. This is a fudge that causes a compile-time error if the vector eint, which is indexed by compile-time error number, is not the correct length. It seems to be the only way to do such a check at compile time, as the sizeof() operator does not work in the C preprocessor. As all the PCRE_ERROR_xxx values are negative, we can use 0 and 1. */ case 0: case (sizeof(eint)/sizeof(int) == ERRCOUNT): return REG_ASSERT; /* ========================================================================== */ case PCRE_ERROR_NOMATCH: return REG_NOMATCH; case PCRE_ERROR_NULL: return REG_INVARG; case PCRE_ERROR_BADOPTION: return REG_INVARG; case PCRE_ERROR_BADMAGIC: return REG_INVARG; case PCRE_ERROR_UNKNOWN_NODE: return REG_ASSERT; case PCRE_ERROR_NOMEMORY: return REG_ESPACE; case PCRE_ERROR_MATCHLIMIT: return REG_ESPACE; case PCRE_ERROR_BADUTF8: return REG_INVARG; case PCRE_ERROR_BADUTF8_OFFSET: return REG_INVARG; case PCRE_ERROR_BADMODE: return REG_INVARG; default: return REG_ASSERT; } } /* End of pcreposix.c */ ================================================ FILE: src/pcre/pcreposix.h ================================================ /************************************************* * Perl-Compatible Regular Expressions * *************************************************/ #ifndef _PCREPOSIX_H #define _PCREPOSIX_H /* This is the header for the POSIX wrapper interface to the PCRE Perl- Compatible Regular Expression library. It defines the things POSIX says should be there. I hope. Copyright (c) 1997-2012 University of Cambridge ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* Have to include stdlib.h in order to ensure that size_t is defined. */ #include /* Allow for C++ users */ #ifdef __cplusplus extern "C" { #endif /* Options, mostly defined by POSIX, but with some extras. */ #define REG_ICASE 0x0001 /* Maps to PCRE_CASELESS */ #define REG_NEWLINE 0x0002 /* Maps to PCRE_MULTILINE */ #define REG_NOTBOL 0x0004 /* Maps to PCRE_NOTBOL */ #define REG_NOTEOL 0x0008 /* Maps to PCRE_NOTEOL */ #define REG_DOTALL 0x0010 /* NOT defined by POSIX; maps to PCRE_DOTALL */ #define REG_NOSUB 0x0020 /* Maps to PCRE_NO_AUTO_CAPTURE */ #define REG_UTF8 0x0040 /* NOT defined by POSIX; maps to PCRE_UTF8 */ #define REG_STARTEND 0x0080 /* BSD feature: pass subject string by so,eo */ #define REG_NOTEMPTY 0x0100 /* NOT defined by POSIX; maps to PCRE_NOTEMPTY */ #define REG_UNGREEDY 0x0200 /* NOT defined by POSIX; maps to PCRE_UNGREEDY */ #define REG_UCP 0x0400 /* NOT defined by POSIX; maps to PCRE_UCP */ /* This is not used by PCRE, but by defining it we make it easier to slot PCRE into existing programs that make POSIX calls. */ #define REG_EXTENDED 0 /* Error values. Not all these are relevant or used by the wrapper. */ enum { REG_ASSERT = 1, /* internal error ? */ REG_BADBR, /* invalid repeat counts in {} */ REG_BADPAT, /* pattern error */ REG_BADRPT, /* ? * + invalid */ REG_EBRACE, /* unbalanced {} */ REG_EBRACK, /* unbalanced [] */ REG_ECOLLATE, /* collation error - not relevant */ REG_ECTYPE, /* bad class */ REG_EESCAPE, /* bad escape sequence */ REG_EMPTY, /* empty expression */ REG_EPAREN, /* unbalanced () */ REG_ERANGE, /* bad range inside [] */ REG_ESIZE, /* expression too big */ REG_ESPACE, /* failed to get memory */ REG_ESUBREG, /* bad back reference */ REG_INVARG, /* bad argument */ REG_NOMATCH /* match failed */ }; /* The structure representing a compiled regular expression. */ typedef struct { void *re_pcre; size_t re_nsub; size_t re_erroffset; } regex_t; /* The structure in which a captured offset is returned. */ typedef int regoff_t; typedef struct { regoff_t rm_so; regoff_t rm_eo; } regmatch_t; /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate export settings are needed, and are set in pcreposix.c before including this file. */ #if defined(_WIN32) && !defined(PCRE_STATIC) && !defined(PCREPOSIX_EXP_DECL) # define PCREPOSIX_EXP_DECL extern __declspec(dllimport) # define PCREPOSIX_EXP_DEFN __declspec(dllimport) #endif /* By default, we use the standard "extern" declarations. */ #ifndef PCREPOSIX_EXP_DECL # ifdef __cplusplus # define PCREPOSIX_EXP_DECL extern "C" # define PCREPOSIX_EXP_DEFN extern "C" # else # define PCREPOSIX_EXP_DECL extern # define PCREPOSIX_EXP_DEFN extern # endif #endif /* The functions */ PCREPOSIX_EXP_DECL int regcomp(regex_t *, const char *, int); PCREPOSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t, regmatch_t *, int); PCREPOSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t); PCREPOSIX_EXP_DECL void regfree(regex_t *); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* End of pcreposix.h */ ================================================ FILE: src/pcre/pcretest.c ================================================ /************************************************* * PCRE testing program * *************************************************/ /* This program was hacked up as a tester for PCRE. I really should have written it more tidily in the first place. Will I ever learn? It has grown and been extended and consequently is now rather, er, *very* untidy in places. The addition of 16-bit support has made it even worse. :-( ----------------------------------------------------------------------------- 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 the University of Cambridge 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. ----------------------------------------------------------------------------- */ /* This program now supports the testing of all of the 8-bit, 16-bit, and 32-bit PCRE libraries in a single program. This is different from the modules such as pcre_compile.c in the library itself, which are compiled separately for each mode. If two modes are enabled, for example, pcre_compile.c is compiled twice. By contrast, pcretest.c is compiled only once. Therefore, it must not make use of any of the macros from pcre_internal.h that depend on COMPILE_PCRE8, COMPILE_PCRE16, or COMPILE_PCRE32. It does, however, make use of SUPPORT_PCRE8, SUPPORT_PCRE16, and SUPPORT_PCRE32 to ensure that it calls only supported library functions. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include /* Both libreadline and libedit are optionally supported. The user-supplied original patch uses readline/readline.h for libedit, but in at least one system it is installed as editline/readline.h, so the configuration code now looks for that first, falling back to readline/readline.h. */ #if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT) #ifdef HAVE_UNISTD_H #include #endif #if defined(SUPPORT_LIBREADLINE) #include #include #else #if defined(HAVE_EDITLINE_READLINE_H) #include #else #include #endif #endif #endif /* A number of things vary for Windows builds. Originally, pcretest opened its input and output without "b"; then I was told that "b" was needed in some environments, so it was added for release 5.0 to both the input and output. (It makes no difference on Unix-like systems.) Later I was told that it is wrong for the input on Windows. I've now abstracted the modes into two macros that are set here, to make it easier to fiddle with them, and removed "b" from the input mode under Windows. */ #if defined(_WIN32) || defined(WIN32) #include /* For _setmode() */ #include /* For _O_BINARY */ #define INPUT_MODE "r" #define OUTPUT_MODE "wb" #ifndef isatty #define isatty _isatty /* This is what Windows calls them, I'm told, */ #endif /* though in some environments they seem to */ /* be already defined, hence the #ifndefs. */ #ifndef fileno #define fileno _fileno #endif /* A user sent this fix for Borland Builder 5 under Windows. */ #ifdef __BORLANDC__ #define _setmode(handle, mode) setmode(handle, mode) #endif /* Not Windows */ #else #include /* These two includes are needed */ #include /* for setrlimit(). */ #if defined NATIVE_ZOS /* z/OS uses non-binary I/O */ #define INPUT_MODE "r" #define OUTPUT_MODE "w" #else #define INPUT_MODE "rb" #define OUTPUT_MODE "wb" #endif #endif #ifdef __VMS #include void vms_setsymbol( char *, char *, int ); #endif #define PRIV(name) name /* We have to include pcre_internal.h because we need the internal info for displaying the results of pcre_study() and we also need to know about the internal macros, structures, and other internal data values; pcretest has "inside information" compared to a program that strictly follows the PCRE API. Although pcre_internal.h does itself include pcre.h, we explicitly include it here before pcre_internal.h so that the PCRE_EXP_xxx macros get set appropriately for an application, not for building PCRE. */ #include "pcre.h" #include "pcre_internal.h" /* The pcre_printint() function, which prints the internal form of a compiled regex, is held in a separate file so that (a) it can be compiled in either 8-, 16- or 32-bit mode, and (b) it can be #included directly in pcre_compile.c when that is compiled in debug mode. */ #ifdef SUPPORT_PCRE8 void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths); #endif #ifdef SUPPORT_PCRE16 void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths); #endif #ifdef SUPPORT_PCRE32 void pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths); #endif /* We need access to some of the data tables that PCRE uses. So as not to have to keep two copies, we include the source files here, changing the names of the external symbols to prevent clashes. */ #define PCRE_INCLUDED #include "pcre_tables.c" #include "pcre_ucd.c" /* The definition of the macro PRINTABLE, which determines whether to print an output character as-is or as a hex value when showing compiled patterns, is the same as in the printint.src file. We uses it here in cases when the locale has not been explicitly changed, so as to get consistent output from systems that differ in their output from isprint() even in the "C" locale. */ #ifdef EBCDIC #define PRINTABLE(c) ((c) >= 64 && (c) < 255) #else #define PRINTABLE(c) ((c) >= 32 && (c) < 127) #endif #define PRINTOK(c) (locale_set? (((c) < 256) && isprint(c)) : PRINTABLE(c)) /* Posix support is disabled in 16 or 32 bit only mode. */ #if !defined SUPPORT_PCRE8 && !defined NOPOSIX #define NOPOSIX #endif /* It is possible to compile this test program without including support for testing the POSIX interface, though this is not available via the standard Makefile. */ #if !defined NOPOSIX #include "pcreposix.h" #endif /* It is also possible, originally for the benefit of a version that was imported into Exim, to build pcretest without support for UTF8 or UTF16 (define NOUTF), without the interface to the DFA matcher (NODFA). In fact, we automatically cut out the UTF support if PCRE is built without it. */ #ifndef SUPPORT_UTF #ifndef NOUTF #define NOUTF #endif #endif /* To make the code a bit tidier for 8/16/32-bit support, we define macros for all the pcre[16]_xxx functions (except pcre16_fullinfo, which is called only from one place and is handled differently). I couldn't dream up any way of using a single macro to do this in a generic way, because of the many different argument requirements. We know that at least one of SUPPORT_PCRE8 and SUPPORT_PCRE16 must be set. First define macros for each individual mode; then use these in the definitions of generic macros. **** Special note about the PCHARSxxx macros: the address of the string to be printed is always given as two arguments: a base address followed by an offset. The base address is cast to the correct data size for 8 or 16 bit data; the offset is in units of this size. If the string were given as base+offset in one argument, the casting might be incorrectly applied. */ #ifdef SUPPORT_PCRE8 #define PCHARS8(lv, p, offset, len, f) \ lv = pchars((pcre_uint8 *)(p) + offset, len, f) #define PCHARSV8(p, offset, len, f) \ (void)pchars((pcre_uint8 *)(p) + offset, len, f) #define READ_CAPTURE_NAME8(p, cn8, cn16, cn32, re) \ p = read_capture_name8(p, cn8, re) #define STRLEN8(p) ((int)strlen((char *)p)) #define SET_PCRE_CALLOUT8(callout) \ pcre_callout = callout #define SET_PCRE_STACK_GUARD8(stack_guard) \ pcre_stack_guard = stack_guard #define PCRE_ASSIGN_JIT_STACK8(extra, callback, userdata) \ pcre_assign_jit_stack(extra, callback, userdata) #define PCRE_COMPILE8(re, pat, options, error, erroffset, tables) \ re = pcre_compile((char *)pat, options, error, erroffset, tables) #define PCRE_COPY_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) \ rc = pcre_copy_named_substring(re, (char *)bptr, offsets, count, \ (char *)namesptr, cbuffer, size) #define PCRE_COPY_SUBSTRING8(rc, bptr, offsets, count, i, cbuffer, size) \ rc = pcre_copy_substring((char *)bptr, offsets, count, i, cbuffer, size) #define PCRE_DFA_EXEC8(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) \ count = pcre_dfa_exec(re, extra, (char *)bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) #define PCRE_EXEC8(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) \ count = pcre_exec(re, extra, (char *)bptr, len, start_offset, options, \ offsets, size_offsets) #define PCRE_FREE_STUDY8(extra) \ pcre_free_study(extra) #define PCRE_FREE_SUBSTRING8(substring) \ pcre_free_substring(substring) #define PCRE_FREE_SUBSTRING_LIST8(listptr) \ pcre_free_substring_list(listptr) #define PCRE_GET_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) \ rc = pcre_get_named_substring(re, (char *)bptr, offsets, count, \ (char *)getnamesptr, subsptr) #define PCRE_GET_STRINGNUMBER8(n, rc, ptr) \ n = pcre_get_stringnumber(re, (char *)ptr) #define PCRE_GET_SUBSTRING8(rc, bptr, offsets, count, i, subsptr) \ rc = pcre_get_substring((char *)bptr, offsets, count, i, subsptr) #define PCRE_GET_SUBSTRING_LIST8(rc, bptr, offsets, count, listptr) \ rc = pcre_get_substring_list((const char *)bptr, offsets, count, listptr) #define PCRE_PATTERN_TO_HOST_BYTE_ORDER8(rc, re, extra, tables) \ rc = pcre_pattern_to_host_byte_order(re, extra, tables) #define PCRE_PRINTINT8(re, outfile, debug_lengths) \ pcre_printint(re, outfile, debug_lengths) #define PCRE_STUDY8(extra, re, options, error) \ extra = pcre_study(re, options, error) #define PCRE_JIT_STACK_ALLOC8(startsize, maxsize) \ pcre_jit_stack_alloc(startsize, maxsize) #define PCRE_JIT_STACK_FREE8(stack) \ pcre_jit_stack_free(stack) #define pcre8_maketables pcre_maketables #endif /* SUPPORT_PCRE8 */ /* -----------------------------------------------------------*/ #ifdef SUPPORT_PCRE16 #define PCHARS16(lv, p, offset, len, f) \ lv = pchars16((PCRE_SPTR16)(p) + offset, len, f) #define PCHARSV16(p, offset, len, f) \ (void)pchars16((PCRE_SPTR16)(p) + offset, len, f) #define READ_CAPTURE_NAME16(p, cn8, cn16, cn32, re) \ p = read_capture_name16(p, cn16, re) #define STRLEN16(p) ((int)strlen16((PCRE_SPTR16)p)) #define SET_PCRE_CALLOUT16(callout) \ pcre16_callout = (int (*)(pcre16_callout_block *))callout #define SET_PCRE_STACK_GUARD16(stack_guard) \ pcre16_stack_guard = (int (*)(void))stack_guard #define PCRE_ASSIGN_JIT_STACK16(extra, callback, userdata) \ pcre16_assign_jit_stack((pcre16_extra *)extra, \ (pcre16_jit_callback)callback, userdata) #define PCRE_COMPILE16(re, pat, options, error, erroffset, tables) \ re = (pcre *)pcre16_compile((PCRE_SPTR16)pat, options, error, erroffset, \ tables) #define PCRE_COPY_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) \ rc = pcre16_copy_named_substring((pcre16 *)re, (PCRE_SPTR16)bptr, offsets, \ count, (PCRE_SPTR16)namesptr, (PCRE_UCHAR16 *)cbuffer, size/2) #define PCRE_COPY_SUBSTRING16(rc, bptr, offsets, count, i, cbuffer, size) \ rc = pcre16_copy_substring((PCRE_SPTR16)bptr, offsets, count, i, \ (PCRE_UCHAR16 *)cbuffer, size/2) #define PCRE_DFA_EXEC16(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) \ count = pcre16_dfa_exec((pcre16 *)re, (pcre16_extra *)extra, \ (PCRE_SPTR16)bptr, len, start_offset, options, offsets, size_offsets, \ workspace, size_workspace) #define PCRE_EXEC16(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) \ count = pcre16_exec((pcre16 *)re, (pcre16_extra *)extra, (PCRE_SPTR16)bptr, \ len, start_offset, options, offsets, size_offsets) #define PCRE_FREE_STUDY16(extra) \ pcre16_free_study((pcre16_extra *)extra) #define PCRE_FREE_SUBSTRING16(substring) \ pcre16_free_substring((PCRE_SPTR16)substring) #define PCRE_FREE_SUBSTRING_LIST16(listptr) \ pcre16_free_substring_list((PCRE_SPTR16 *)listptr) #define PCRE_GET_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) \ rc = pcre16_get_named_substring((pcre16 *)re, (PCRE_SPTR16)bptr, offsets, \ count, (PCRE_SPTR16)getnamesptr, (PCRE_SPTR16 *)(void*)subsptr) #define PCRE_GET_STRINGNUMBER16(n, rc, ptr) \ n = pcre16_get_stringnumber(re, (PCRE_SPTR16)ptr) #define PCRE_GET_SUBSTRING16(rc, bptr, offsets, count, i, subsptr) \ rc = pcre16_get_substring((PCRE_SPTR16)bptr, offsets, count, i, \ (PCRE_SPTR16 *)(void*)subsptr) #define PCRE_GET_SUBSTRING_LIST16(rc, bptr, offsets, count, listptr) \ rc = pcre16_get_substring_list((PCRE_SPTR16)bptr, offsets, count, \ (PCRE_SPTR16 **)(void*)listptr) #define PCRE_PATTERN_TO_HOST_BYTE_ORDER16(rc, re, extra, tables) \ rc = pcre16_pattern_to_host_byte_order((pcre16 *)re, (pcre16_extra *)extra, \ tables) #define PCRE_PRINTINT16(re, outfile, debug_lengths) \ pcre16_printint(re, outfile, debug_lengths) #define PCRE_STUDY16(extra, re, options, error) \ extra = (pcre_extra *)pcre16_study((pcre16 *)re, options, error) #define PCRE_JIT_STACK_ALLOC16(startsize, maxsize) \ (pcre_jit_stack *)pcre16_jit_stack_alloc(startsize, maxsize) #define PCRE_JIT_STACK_FREE16(stack) \ pcre16_jit_stack_free((pcre16_jit_stack *)stack) #endif /* SUPPORT_PCRE16 */ /* -----------------------------------------------------------*/ #ifdef SUPPORT_PCRE32 #define PCHARS32(lv, p, offset, len, f) \ lv = pchars32((PCRE_SPTR32)(p) + offset, len, use_utf, f) #define PCHARSV32(p, offset, len, f) \ (void)pchars32((PCRE_SPTR32)(p) + offset, len, use_utf, f) #define READ_CAPTURE_NAME32(p, cn8, cn16, cn32, re) \ p = read_capture_name32(p, cn32, re) #define STRLEN32(p) ((int)strlen32((PCRE_SPTR32)p)) #define SET_PCRE_CALLOUT32(callout) \ pcre32_callout = (int (*)(pcre32_callout_block *))callout #define SET_PCRE_STACK_GUARD32(stack_guard) \ pcre32_stack_guard = (int (*)(void))stack_guard #define PCRE_ASSIGN_JIT_STACK32(extra, callback, userdata) \ pcre32_assign_jit_stack((pcre32_extra *)extra, \ (pcre32_jit_callback)callback, userdata) #define PCRE_COMPILE32(re, pat, options, error, erroffset, tables) \ re = (pcre *)pcre32_compile((PCRE_SPTR32)pat, options, error, erroffset, \ tables) #define PCRE_COPY_NAMED_SUBSTRING32(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) \ rc = pcre32_copy_named_substring((pcre32 *)re, (PCRE_SPTR32)bptr, offsets, \ count, (PCRE_SPTR32)namesptr, (PCRE_UCHAR32 *)cbuffer, size/4) #define PCRE_COPY_SUBSTRING32(rc, bptr, offsets, count, i, cbuffer, size) \ rc = pcre32_copy_substring((PCRE_SPTR32)bptr, offsets, count, i, \ (PCRE_UCHAR32 *)cbuffer, size/4) #define PCRE_DFA_EXEC32(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) \ count = pcre32_dfa_exec((pcre32 *)re, (pcre32_extra *)extra, \ (PCRE_SPTR32)bptr, len, start_offset, options, offsets, size_offsets, \ workspace, size_workspace) #define PCRE_EXEC32(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) \ count = pcre32_exec((pcre32 *)re, (pcre32_extra *)extra, (PCRE_SPTR32)bptr, \ len, start_offset, options, offsets, size_offsets) #define PCRE_FREE_STUDY32(extra) \ pcre32_free_study((pcre32_extra *)extra) #define PCRE_FREE_SUBSTRING32(substring) \ pcre32_free_substring((PCRE_SPTR32)substring) #define PCRE_FREE_SUBSTRING_LIST32(listptr) \ pcre32_free_substring_list((PCRE_SPTR32 *)listptr) #define PCRE_GET_NAMED_SUBSTRING32(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) \ rc = pcre32_get_named_substring((pcre32 *)re, (PCRE_SPTR32)bptr, offsets, \ count, (PCRE_SPTR32)getnamesptr, (PCRE_SPTR32 *)(void*)subsptr) #define PCRE_GET_STRINGNUMBER32(n, rc, ptr) \ n = pcre32_get_stringnumber(re, (PCRE_SPTR32)ptr) #define PCRE_GET_SUBSTRING32(rc, bptr, offsets, count, i, subsptr) \ rc = pcre32_get_substring((PCRE_SPTR32)bptr, offsets, count, i, \ (PCRE_SPTR32 *)(void*)subsptr) #define PCRE_GET_SUBSTRING_LIST32(rc, bptr, offsets, count, listptr) \ rc = pcre32_get_substring_list((PCRE_SPTR32)bptr, offsets, count, \ (PCRE_SPTR32 **)(void*)listptr) #define PCRE_PATTERN_TO_HOST_BYTE_ORDER32(rc, re, extra, tables) \ rc = pcre32_pattern_to_host_byte_order((pcre32 *)re, (pcre32_extra *)extra, \ tables) #define PCRE_PRINTINT32(re, outfile, debug_lengths) \ pcre32_printint(re, outfile, debug_lengths) #define PCRE_STUDY32(extra, re, options, error) \ extra = (pcre_extra *)pcre32_study((pcre32 *)re, options, error) #define PCRE_JIT_STACK_ALLOC32(startsize, maxsize) \ (pcre_jit_stack *)pcre32_jit_stack_alloc(startsize, maxsize) #define PCRE_JIT_STACK_FREE32(stack) \ pcre32_jit_stack_free((pcre32_jit_stack *)stack) #endif /* SUPPORT_PCRE32 */ /* ----- More than one mode is supported; a runtime test is needed, except for pcre_config(), and the JIT stack functions, when it doesn't matter which available version is called. ----- */ enum { PCRE8_MODE, PCRE16_MODE, PCRE32_MODE }; #if (defined (SUPPORT_PCRE8) + defined (SUPPORT_PCRE16) + \ defined (SUPPORT_PCRE32)) >= 2 #define CHAR_SIZE (1 << pcre_mode) /* There doesn't seem to be an easy way of writing these macros that can cope with the 3 pairs of bit sizes plus all three bit sizes. So just handle all the cases separately. */ /* ----- All three modes supported ----- */ #if defined(SUPPORT_PCRE8) && defined(SUPPORT_PCRE16) && defined(SUPPORT_PCRE32) #define PCHARS(lv, p, offset, len, f) \ if (pcre_mode == PCRE32_MODE) \ PCHARS32(lv, p, offset, len, f); \ else if (pcre_mode == PCRE16_MODE) \ PCHARS16(lv, p, offset, len, f); \ else \ PCHARS8(lv, p, offset, len, f) #define PCHARSV(p, offset, len, f) \ if (pcre_mode == PCRE32_MODE) \ PCHARSV32(p, offset, len, f); \ else if (pcre_mode == PCRE16_MODE) \ PCHARSV16(p, offset, len, f); \ else \ PCHARSV8(p, offset, len, f) #define READ_CAPTURE_NAME(p, cn8, cn16, cn32, re) \ if (pcre_mode == PCRE32_MODE) \ READ_CAPTURE_NAME32(p, cn8, cn16, cn32, re); \ else if (pcre_mode == PCRE16_MODE) \ READ_CAPTURE_NAME16(p, cn8, cn16, cn32, re); \ else \ READ_CAPTURE_NAME8(p, cn8, cn16, cn32, re) #define SET_PCRE_CALLOUT(callout) \ if (pcre_mode == PCRE32_MODE) \ SET_PCRE_CALLOUT32(callout); \ else if (pcre_mode == PCRE16_MODE) \ SET_PCRE_CALLOUT16(callout); \ else \ SET_PCRE_CALLOUT8(callout) #define SET_PCRE_STACK_GUARD(stack_guard) \ if (pcre_mode == PCRE32_MODE) \ SET_PCRE_STACK_GUARD32(stack_guard); \ else if (pcre_mode == PCRE16_MODE) \ SET_PCRE_STACK_GUARD16(stack_guard); \ else \ SET_PCRE_STACK_GUARD8(stack_guard) #define STRLEN(p) (pcre_mode == PCRE32_MODE ? STRLEN32(p) : pcre_mode == PCRE16_MODE ? STRLEN16(p) : STRLEN8(p)) #define PCRE_ASSIGN_JIT_STACK(extra, callback, userdata) \ if (pcre_mode == PCRE32_MODE) \ PCRE_ASSIGN_JIT_STACK32(extra, callback, userdata); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_ASSIGN_JIT_STACK16(extra, callback, userdata); \ else \ PCRE_ASSIGN_JIT_STACK8(extra, callback, userdata) #define PCRE_COMPILE(re, pat, options, error, erroffset, tables) \ if (pcre_mode == PCRE32_MODE) \ PCRE_COMPILE32(re, pat, options, error, erroffset, tables); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_COMPILE16(re, pat, options, error, erroffset, tables); \ else \ PCRE_COMPILE8(re, pat, options, error, erroffset, tables) #define PCRE_CONFIG pcre_config #define PCRE_COPY_NAMED_SUBSTRING(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) \ if (pcre_mode == PCRE32_MODE) \ PCRE_COPY_NAMED_SUBSTRING32(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_COPY_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size); \ else \ PCRE_COPY_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) #define PCRE_COPY_SUBSTRING(rc, bptr, offsets, count, i, cbuffer, size) \ if (pcre_mode == PCRE32_MODE) \ PCRE_COPY_SUBSTRING32(rc, bptr, offsets, count, i, cbuffer, size); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_COPY_SUBSTRING16(rc, bptr, offsets, count, i, cbuffer, size); \ else \ PCRE_COPY_SUBSTRING8(rc, bptr, offsets, count, i, cbuffer, size) #define PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) \ if (pcre_mode == PCRE32_MODE) \ PCRE_DFA_EXEC32(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_DFA_EXEC16(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace); \ else \ PCRE_DFA_EXEC8(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) #define PCRE_EXEC(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) \ if (pcre_mode == PCRE32_MODE) \ PCRE_EXEC32(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_EXEC16(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets); \ else \ PCRE_EXEC8(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) #define PCRE_FREE_STUDY(extra) \ if (pcre_mode == PCRE32_MODE) \ PCRE_FREE_STUDY32(extra); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_FREE_STUDY16(extra); \ else \ PCRE_FREE_STUDY8(extra) #define PCRE_FREE_SUBSTRING(substring) \ if (pcre_mode == PCRE32_MODE) \ PCRE_FREE_SUBSTRING32(substring); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_FREE_SUBSTRING16(substring); \ else \ PCRE_FREE_SUBSTRING8(substring) #define PCRE_FREE_SUBSTRING_LIST(listptr) \ if (pcre_mode == PCRE32_MODE) \ PCRE_FREE_SUBSTRING_LIST32(listptr); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_FREE_SUBSTRING_LIST16(listptr); \ else \ PCRE_FREE_SUBSTRING_LIST8(listptr) #define PCRE_GET_NAMED_SUBSTRING(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) \ if (pcre_mode == PCRE32_MODE) \ PCRE_GET_NAMED_SUBSTRING32(rc, re, bptr, offsets, count, \ getnamesptr, subsptr); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_GET_NAMED_SUBSTRING16(rc, re, bptr, offsets, count, \ getnamesptr, subsptr); \ else \ PCRE_GET_NAMED_SUBSTRING8(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) #define PCRE_GET_STRINGNUMBER(n, rc, ptr) \ if (pcre_mode == PCRE32_MODE) \ PCRE_GET_STRINGNUMBER32(n, rc, ptr); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_GET_STRINGNUMBER16(n, rc, ptr); \ else \ PCRE_GET_STRINGNUMBER8(n, rc, ptr) #define PCRE_GET_SUBSTRING(rc, bptr, use_offsets, count, i, subsptr) \ if (pcre_mode == PCRE32_MODE) \ PCRE_GET_SUBSTRING32(rc, bptr, use_offsets, count, i, subsptr); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_GET_SUBSTRING16(rc, bptr, use_offsets, count, i, subsptr); \ else \ PCRE_GET_SUBSTRING8(rc, bptr, use_offsets, count, i, subsptr) #define PCRE_GET_SUBSTRING_LIST(rc, bptr, offsets, count, listptr) \ if (pcre_mode == PCRE32_MODE) \ PCRE_GET_SUBSTRING_LIST32(rc, bptr, offsets, count, listptr); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_GET_SUBSTRING_LIST16(rc, bptr, offsets, count, listptr); \ else \ PCRE_GET_SUBSTRING_LIST8(rc, bptr, offsets, count, listptr) #define PCRE_JIT_STACK_ALLOC(startsize, maxsize) \ (pcre_mode == PCRE32_MODE ? \ PCRE_JIT_STACK_ALLOC32(startsize, maxsize) \ : pcre_mode == PCRE16_MODE ? \ PCRE_JIT_STACK_ALLOC16(startsize, maxsize) \ : PCRE_JIT_STACK_ALLOC8(startsize, maxsize)) #define PCRE_JIT_STACK_FREE(stack) \ if (pcre_mode == PCRE32_MODE) \ PCRE_JIT_STACK_FREE32(stack); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_JIT_STACK_FREE16(stack); \ else \ PCRE_JIT_STACK_FREE8(stack) #define PCRE_MAKETABLES \ (pcre_mode == PCRE32_MODE ? pcre32_maketables() : pcre_mode == PCRE16_MODE ? pcre16_maketables() : pcre_maketables()) #define PCRE_PATTERN_TO_HOST_BYTE_ORDER(rc, re, extra, tables) \ if (pcre_mode == PCRE32_MODE) \ PCRE_PATTERN_TO_HOST_BYTE_ORDER32(rc, re, extra, tables); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_PATTERN_TO_HOST_BYTE_ORDER16(rc, re, extra, tables); \ else \ PCRE_PATTERN_TO_HOST_BYTE_ORDER8(rc, re, extra, tables) #define PCRE_PRINTINT(re, outfile, debug_lengths) \ if (pcre_mode == PCRE32_MODE) \ PCRE_PRINTINT32(re, outfile, debug_lengths); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_PRINTINT16(re, outfile, debug_lengths); \ else \ PCRE_PRINTINT8(re, outfile, debug_lengths) #define PCRE_STUDY(extra, re, options, error) \ if (pcre_mode == PCRE32_MODE) \ PCRE_STUDY32(extra, re, options, error); \ else if (pcre_mode == PCRE16_MODE) \ PCRE_STUDY16(extra, re, options, error); \ else \ PCRE_STUDY8(extra, re, options, error) /* ----- Two out of three modes are supported ----- */ #else /* We can use some macro trickery to make a single set of definitions work in the three different cases. */ /* ----- 32-bit and 16-bit but not 8-bit supported ----- */ #if defined(SUPPORT_PCRE32) && defined(SUPPORT_PCRE16) #define BITONE 32 #define BITTWO 16 /* ----- 32-bit and 8-bit but not 16-bit supported ----- */ #elif defined(SUPPORT_PCRE32) && defined(SUPPORT_PCRE8) #define BITONE 32 #define BITTWO 8 /* ----- 16-bit and 8-bit but not 32-bit supported ----- */ #else #define BITONE 16 #define BITTWO 8 #endif #define glue(a,b) a##b #define G(a,b) glue(a,b) /* ----- Common macros for two-mode cases ----- */ #define PCHARS(lv, p, offset, len, f) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCHARS,BITONE)(lv, p, offset, len, f); \ else \ G(PCHARS,BITTWO)(lv, p, offset, len, f) #define PCHARSV(p, offset, len, f) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCHARSV,BITONE)(p, offset, len, f); \ else \ G(PCHARSV,BITTWO)(p, offset, len, f) #define READ_CAPTURE_NAME(p, cn8, cn16, cn32, re) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(READ_CAPTURE_NAME,BITONE)(p, cn8, cn16, cn32, re); \ else \ G(READ_CAPTURE_NAME,BITTWO)(p, cn8, cn16, cn32, re) #define SET_PCRE_CALLOUT(callout) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(SET_PCRE_CALLOUT,BITONE)(callout); \ else \ G(SET_PCRE_CALLOUT,BITTWO)(callout) #define SET_PCRE_STACK_GUARD(stack_guard) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(SET_PCRE_STACK_GUARD,BITONE)(stack_guard); \ else \ G(SET_PCRE_STACK_GUARD,BITTWO)(stack_guard) #define STRLEN(p) ((pcre_mode == G(G(PCRE,BITONE),_MODE)) ? \ G(STRLEN,BITONE)(p) : G(STRLEN,BITTWO)(p)) #define PCRE_ASSIGN_JIT_STACK(extra, callback, userdata) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_ASSIGN_JIT_STACK,BITONE)(extra, callback, userdata); \ else \ G(PCRE_ASSIGN_JIT_STACK,BITTWO)(extra, callback, userdata) #define PCRE_COMPILE(re, pat, options, error, erroffset, tables) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_COMPILE,BITONE)(re, pat, options, error, erroffset, tables); \ else \ G(PCRE_COMPILE,BITTWO)(re, pat, options, error, erroffset, tables) #define PCRE_CONFIG G(G(pcre,BITONE),_config) #define PCRE_COPY_NAMED_SUBSTRING(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_COPY_NAMED_SUBSTRING,BITONE)(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size); \ else \ G(PCRE_COPY_NAMED_SUBSTRING,BITTWO)(rc, re, bptr, offsets, count, \ namesptr, cbuffer, size) #define PCRE_COPY_SUBSTRING(rc, bptr, offsets, count, i, cbuffer, size) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_COPY_SUBSTRING,BITONE)(rc, bptr, offsets, count, i, cbuffer, size); \ else \ G(PCRE_COPY_SUBSTRING,BITTWO)(rc, bptr, offsets, count, i, cbuffer, size) #define PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_DFA_EXEC,BITONE)(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace); \ else \ G(PCRE_DFA_EXEC,BITTWO)(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets, workspace, size_workspace) #define PCRE_EXEC(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_EXEC,BITONE)(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets); \ else \ G(PCRE_EXEC,BITTWO)(count, re, extra, bptr, len, start_offset, options, \ offsets, size_offsets) #define PCRE_FREE_STUDY(extra) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_FREE_STUDY,BITONE)(extra); \ else \ G(PCRE_FREE_STUDY,BITTWO)(extra) #define PCRE_FREE_SUBSTRING(substring) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_FREE_SUBSTRING,BITONE)(substring); \ else \ G(PCRE_FREE_SUBSTRING,BITTWO)(substring) #define PCRE_FREE_SUBSTRING_LIST(listptr) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_FREE_SUBSTRING_LIST,BITONE)(listptr); \ else \ G(PCRE_FREE_SUBSTRING_LIST,BITTWO)(listptr) #define PCRE_GET_NAMED_SUBSTRING(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_GET_NAMED_SUBSTRING,BITONE)(rc, re, bptr, offsets, count, \ getnamesptr, subsptr); \ else \ G(PCRE_GET_NAMED_SUBSTRING,BITTWO)(rc, re, bptr, offsets, count, \ getnamesptr, subsptr) #define PCRE_GET_STRINGNUMBER(n, rc, ptr) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_GET_STRINGNUMBER,BITONE)(n, rc, ptr); \ else \ G(PCRE_GET_STRINGNUMBER,BITTWO)(n, rc, ptr) #define PCRE_GET_SUBSTRING(rc, bptr, use_offsets, count, i, subsptr) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_GET_SUBSTRING,BITONE)(rc, bptr, use_offsets, count, i, subsptr); \ else \ G(PCRE_GET_SUBSTRING,BITTWO)(rc, bptr, use_offsets, count, i, subsptr) #define PCRE_GET_SUBSTRING_LIST(rc, bptr, offsets, count, listptr) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_GET_SUBSTRING_LIST,BITONE)(rc, bptr, offsets, count, listptr); \ else \ G(PCRE_GET_SUBSTRING_LIST,BITTWO)(rc, bptr, offsets, count, listptr) #define PCRE_JIT_STACK_ALLOC(startsize, maxsize) \ (pcre_mode == G(G(PCRE,BITONE),_MODE)) ? \ G(PCRE_JIT_STACK_ALLOC,BITONE)(startsize, maxsize) \ : G(PCRE_JIT_STACK_ALLOC,BITTWO)(startsize, maxsize) #define PCRE_JIT_STACK_FREE(stack) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_JIT_STACK_FREE,BITONE)(stack); \ else \ G(PCRE_JIT_STACK_FREE,BITTWO)(stack) #define PCRE_MAKETABLES \ (pcre_mode == G(G(PCRE,BITONE),_MODE)) ? \ G(G(pcre,BITONE),_maketables)() : G(G(pcre,BITTWO),_maketables)() #define PCRE_PATTERN_TO_HOST_BYTE_ORDER(rc, re, extra, tables) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_PATTERN_TO_HOST_BYTE_ORDER,BITONE)(rc, re, extra, tables); \ else \ G(PCRE_PATTERN_TO_HOST_BYTE_ORDER,BITTWO)(rc, re, extra, tables) #define PCRE_PRINTINT(re, outfile, debug_lengths) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_PRINTINT,BITONE)(re, outfile, debug_lengths); \ else \ G(PCRE_PRINTINT,BITTWO)(re, outfile, debug_lengths) #define PCRE_STUDY(extra, re, options, error) \ if (pcre_mode == G(G(PCRE,BITONE),_MODE)) \ G(PCRE_STUDY,BITONE)(extra, re, options, error); \ else \ G(PCRE_STUDY,BITTWO)(extra, re, options, error) #endif /* Two out of three modes */ /* ----- End of cases where more than one mode is supported ----- */ /* ----- Only 8-bit mode is supported ----- */ #elif defined SUPPORT_PCRE8 #define CHAR_SIZE 1 #define PCHARS PCHARS8 #define PCHARSV PCHARSV8 #define READ_CAPTURE_NAME READ_CAPTURE_NAME8 #define SET_PCRE_CALLOUT SET_PCRE_CALLOUT8 #define SET_PCRE_STACK_GUARD SET_PCRE_STACK_GUARD8 #define STRLEN STRLEN8 #define PCRE_ASSIGN_JIT_STACK PCRE_ASSIGN_JIT_STACK8 #define PCRE_COMPILE PCRE_COMPILE8 #define PCRE_CONFIG pcre_config #define PCRE_COPY_NAMED_SUBSTRING PCRE_COPY_NAMED_SUBSTRING8 #define PCRE_COPY_SUBSTRING PCRE_COPY_SUBSTRING8 #define PCRE_DFA_EXEC PCRE_DFA_EXEC8 #define PCRE_EXEC PCRE_EXEC8 #define PCRE_FREE_STUDY PCRE_FREE_STUDY8 #define PCRE_FREE_SUBSTRING PCRE_FREE_SUBSTRING8 #define PCRE_FREE_SUBSTRING_LIST PCRE_FREE_SUBSTRING_LIST8 #define PCRE_GET_NAMED_SUBSTRING PCRE_GET_NAMED_SUBSTRING8 #define PCRE_GET_STRINGNUMBER PCRE_GET_STRINGNUMBER8 #define PCRE_GET_SUBSTRING PCRE_GET_SUBSTRING8 #define PCRE_GET_SUBSTRING_LIST PCRE_GET_SUBSTRING_LIST8 #define PCRE_JIT_STACK_ALLOC PCRE_JIT_STACK_ALLOC8 #define PCRE_JIT_STACK_FREE PCRE_JIT_STACK_FREE8 #define PCRE_MAKETABLES pcre_maketables() #define PCRE_PATTERN_TO_HOST_BYTE_ORDER PCRE_PATTERN_TO_HOST_BYTE_ORDER8 #define PCRE_PRINTINT PCRE_PRINTINT8 #define PCRE_STUDY PCRE_STUDY8 /* ----- Only 16-bit mode is supported ----- */ #elif defined SUPPORT_PCRE16 #define CHAR_SIZE 2 #define PCHARS PCHARS16 #define PCHARSV PCHARSV16 #define READ_CAPTURE_NAME READ_CAPTURE_NAME16 #define SET_PCRE_CALLOUT SET_PCRE_CALLOUT16 #define SET_PCRE_STACK_GUARD SET_PCRE_STACK_GUARD16 #define STRLEN STRLEN16 #define PCRE_ASSIGN_JIT_STACK PCRE_ASSIGN_JIT_STACK16 #define PCRE_COMPILE PCRE_COMPILE16 #define PCRE_CONFIG pcre16_config #define PCRE_COPY_NAMED_SUBSTRING PCRE_COPY_NAMED_SUBSTRING16 #define PCRE_COPY_SUBSTRING PCRE_COPY_SUBSTRING16 #define PCRE_DFA_EXEC PCRE_DFA_EXEC16 #define PCRE_EXEC PCRE_EXEC16 #define PCRE_FREE_STUDY PCRE_FREE_STUDY16 #define PCRE_FREE_SUBSTRING PCRE_FREE_SUBSTRING16 #define PCRE_FREE_SUBSTRING_LIST PCRE_FREE_SUBSTRING_LIST16 #define PCRE_GET_NAMED_SUBSTRING PCRE_GET_NAMED_SUBSTRING16 #define PCRE_GET_STRINGNUMBER PCRE_GET_STRINGNUMBER16 #define PCRE_GET_SUBSTRING PCRE_GET_SUBSTRING16 #define PCRE_GET_SUBSTRING_LIST PCRE_GET_SUBSTRING_LIST16 #define PCRE_JIT_STACK_ALLOC PCRE_JIT_STACK_ALLOC16 #define PCRE_JIT_STACK_FREE PCRE_JIT_STACK_FREE16 #define PCRE_MAKETABLES pcre16_maketables() #define PCRE_PATTERN_TO_HOST_BYTE_ORDER PCRE_PATTERN_TO_HOST_BYTE_ORDER16 #define PCRE_PRINTINT PCRE_PRINTINT16 #define PCRE_STUDY PCRE_STUDY16 /* ----- Only 32-bit mode is supported ----- */ #elif defined SUPPORT_PCRE32 #define CHAR_SIZE 4 #define PCHARS PCHARS32 #define PCHARSV PCHARSV32 #define READ_CAPTURE_NAME READ_CAPTURE_NAME32 #define SET_PCRE_CALLOUT SET_PCRE_CALLOUT32 #define SET_PCRE_STACK_GUARD SET_PCRE_STACK_GUARD32 #define STRLEN STRLEN32 #define PCRE_ASSIGN_JIT_STACK PCRE_ASSIGN_JIT_STACK32 #define PCRE_COMPILE PCRE_COMPILE32 #define PCRE_CONFIG pcre32_config #define PCRE_COPY_NAMED_SUBSTRING PCRE_COPY_NAMED_SUBSTRING32 #define PCRE_COPY_SUBSTRING PCRE_COPY_SUBSTRING32 #define PCRE_DFA_EXEC PCRE_DFA_EXEC32 #define PCRE_EXEC PCRE_EXEC32 #define PCRE_FREE_STUDY PCRE_FREE_STUDY32 #define PCRE_FREE_SUBSTRING PCRE_FREE_SUBSTRING32 #define PCRE_FREE_SUBSTRING_LIST PCRE_FREE_SUBSTRING_LIST32 #define PCRE_GET_NAMED_SUBSTRING PCRE_GET_NAMED_SUBSTRING32 #define PCRE_GET_STRINGNUMBER PCRE_GET_STRINGNUMBER32 #define PCRE_GET_SUBSTRING PCRE_GET_SUBSTRING32 #define PCRE_GET_SUBSTRING_LIST PCRE_GET_SUBSTRING_LIST32 #define PCRE_JIT_STACK_ALLOC PCRE_JIT_STACK_ALLOC32 #define PCRE_JIT_STACK_FREE PCRE_JIT_STACK_FREE32 #define PCRE_MAKETABLES pcre32_maketables() #define PCRE_PATTERN_TO_HOST_BYTE_ORDER PCRE_PATTERN_TO_HOST_BYTE_ORDER32 #define PCRE_PRINTINT PCRE_PRINTINT32 #define PCRE_STUDY PCRE_STUDY32 #endif /* ----- End of mode-specific function call macros ----- */ /* Other parameters */ #ifndef CLOCKS_PER_SEC #ifdef CLK_TCK #define CLOCKS_PER_SEC CLK_TCK #else #define CLOCKS_PER_SEC 100 #endif #endif #if !defined NODFA #define DFA_WS_DIMENSION 1000 #endif /* This is the default loop count for timing. */ #define LOOPREPEAT 500000 /* Static variables */ static FILE *outfile; static int log_store = 0; static int callout_count; static int callout_extra; static int callout_fail_count; static int callout_fail_id; static int debug_lengths; static int first_callout; static int jit_was_used; static int locale_set = 0; static int show_malloc; static int stack_guard_return; static int use_utf; static const unsigned char *last_callout_mark = NULL; /* The buffers grow automatically if very long input lines are encountered. */ static int buffer_size = 50000; static pcre_uint8 *buffer = NULL; static pcre_uint8 *pbuffer = NULL; /* Just as a safety check, make sure that COMPILE_PCRE[16|32] are *not* set. */ #ifdef COMPILE_PCRE16 #error COMPILE_PCRE16 must not be set when compiling pcretest.c #endif #ifdef COMPILE_PCRE32 #error COMPILE_PCRE32 must not be set when compiling pcretest.c #endif /* We need buffers for building 16/32-bit strings, and the tables of operator lengths that are used for 16/32-bit compiling, in order to swap bytes in a pattern for saving/reloading testing. Luckily, the data for these tables is defined as a macro. However, we must ensure that LINK_SIZE and IMM2_SIZE (which are used in the tables) are adjusted appropriately for the 16/32-bit world. LINK_SIZE is also used later in this program. */ #ifdef SUPPORT_PCRE16 #undef IMM2_SIZE #define IMM2_SIZE 1 #if LINK_SIZE == 2 #undef LINK_SIZE #define LINK_SIZE 1 #elif LINK_SIZE == 3 || LINK_SIZE == 4 #undef LINK_SIZE #define LINK_SIZE 2 #else #error LINK_SIZE must be either 2, 3, or 4 #endif static int buffer16_size = 0; static pcre_uint16 *buffer16 = NULL; static const pcre_uint16 OP_lengths16[] = { OP_LENGTHS }; #endif /* SUPPORT_PCRE16 */ #ifdef SUPPORT_PCRE32 #undef IMM2_SIZE #define IMM2_SIZE 1 #undef LINK_SIZE #define LINK_SIZE 1 static int buffer32_size = 0; static pcre_uint32 *buffer32 = NULL; static const pcre_uint32 OP_lengths32[] = { OP_LENGTHS }; #endif /* SUPPORT_PCRE32 */ /* If we have 8-bit support, default to it; if there is also 16-or 32-bit support, it can be changed by an option. If there is no 8-bit support, there must be 16-or 32-bit support, so default it to 1. */ #if defined SUPPORT_PCRE8 static int pcre_mode = PCRE8_MODE; #elif defined SUPPORT_PCRE16 static int pcre_mode = PCRE16_MODE; #elif defined SUPPORT_PCRE32 static int pcre_mode = PCRE32_MODE; #endif /* JIT study options for -s+n and /S+n where '1' <= n <= '7'. */ static int jit_study_bits[] = { PCRE_STUDY_JIT_COMPILE, PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE, PCRE_STUDY_JIT_COMPILE + PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE, PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE, PCRE_STUDY_JIT_COMPILE + PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE, PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE + PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE, PCRE_STUDY_JIT_COMPILE + PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE + PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE }; #define PCRE_STUDY_ALLJIT (PCRE_STUDY_JIT_COMPILE | \ PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) /* Textual explanations for runtime error codes */ static const char *errtexts[] = { NULL, /* 0 is no error */ NULL, /* NOMATCH is handled specially */ "NULL argument passed", "bad option value", "magic number missing", "unknown opcode - pattern overwritten?", "no more memory", NULL, /* never returned by pcre_exec() or pcre_dfa_exec() */ "match limit exceeded", "callout error code", NULL, /* BADUTF8/16 is handled specially */ NULL, /* BADUTF8/16 offset is handled specially */ NULL, /* PARTIAL is handled specially */ "not used - internal error", "internal error - pattern overwritten?", "bad count value", "item unsupported for DFA matching", "backreference condition or recursion test not supported for DFA matching", "match limit not supported for DFA matching", "workspace size exceeded in DFA matching", "too much recursion for DFA matching", "recursion limit exceeded", "not used - internal error", "invalid combination of newline options", "bad offset value", NULL, /* SHORTUTF8/16 is handled specially */ "nested recursion at the same subject position", "JIT stack limit reached", "pattern compiled in wrong mode: 8-bit/16-bit error", "pattern compiled with other endianness", "invalid data in workspace for DFA restart", "bad JIT option", "bad length" }; /************************************************* * Alternate character tables * *************************************************/ /* By default, the "tables" pointer when calling PCRE is set to NULL, thereby using the default tables of the library. However, the T option can be used to select alternate sets of tables, for different kinds of testing. Note also that the L (locale) option also adjusts the tables. */ /* This is the set of tables distributed as default with PCRE. It recognizes only ASCII characters. */ static const pcre_uint8 tables0[] = { /* This table is a lower casing table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table is a case flipping table. */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, /* This table contains bit maps for various character classes. Each map is 32 bytes long and the bits run from the least significant end of each byte. The classes that have their own maps are: space, xdigit, digit, upper, lower, word, graph, print, punct, and cntrl. Other classes are built from combinations. */ 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* This table identifies various classes of character by individual bits: 0x01 white space character 0x02 letter 0x04 decimal digit 0x08 hexadecimal digit 0x10 alphanumeric or '_' 0x80 regular expression metacharacter or binary zero */ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */ 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ /* This is a set of tables that came originally from a Windows user. It seems to be at least an approximation of ISO 8859. In particular, there are characters greater than 128 that are marked as spaces, letters, etc. */ static const pcre_uint8 tables1[] = { 0,1,2,3,4,5,6,7, 8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, 24,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39, 40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63, 64,97,98,99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,91,92,93,94,95, 96,97,98,99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,215, 248,249,250,251,252,253,254,223, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247, 248,249,250,251,252,253,254,255, 0,1,2,3,4,5,6,7, 8,9,10,11,12,13,14,15, 16,17,18,19,20,21,22,23, 24,25,26,27,28,29,30,31, 32,33,34,35,36,37,38,39, 40,41,42,43,44,45,46,47, 48,49,50,51,52,53,54,55, 56,57,58,59,60,61,62,63, 64,97,98,99,100,101,102,103, 104,105,106,107,108,109,110,111, 112,113,114,115,116,117,118,119, 120,121,122,91,92,93,94,95, 96,65,66,67,68,69,70,71, 72,73,74,75,76,77,78,79, 80,81,82,83,84,85,86,87, 88,89,90,123,124,125,126,127, 128,129,130,131,132,133,134,135, 136,137,138,139,140,141,142,143, 144,145,146,147,148,149,150,151, 152,153,154,155,156,157,158,159, 160,161,162,163,164,165,166,167, 168,169,170,171,172,173,174,175, 176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191, 224,225,226,227,228,229,230,231, 232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,215, 248,249,250,251,252,253,254,223, 192,193,194,195,196,197,198,199, 200,201,202,203,204,205,206,207, 208,209,210,211,212,213,214,247, 216,217,218,219,220,221,222,255, 0,62,0,0,1,0,0,0, 0,0,0,0,0,0,0,0, 32,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,255,3, 126,0,0,0,126,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,255,3, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,12,2, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 254,255,255,7,0,0,0,0, 0,0,0,0,0,0,0,0, 255,255,127,127,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,254,255,255,7, 0,0,0,0,0,4,32,4, 0,0,0,128,255,255,127,255, 0,0,0,0,0,0,255,3, 254,255,255,135,254,255,255,7, 0,0,0,0,0,4,44,6, 255,255,127,255,255,255,127,255, 0,0,0,0,254,255,255,255, 255,255,255,255,255,255,255,127, 0,0,0,0,254,255,255,255, 255,255,255,255,255,255,255,255, 0,2,0,0,255,255,255,255, 255,255,255,255,255,255,255,127, 0,0,0,0,255,255,255,255, 255,255,255,255,255,255,255,255, 0,0,0,0,254,255,0,252, 1,0,0,248,1,0,0,120, 0,0,0,0,254,255,255,255, 0,0,128,0,0,0,128,0, 255,255,255,255,0,0,0,0, 0,0,0,0,0,0,0,128, 255,255,255,255,0,0,0,0, 0,0,0,0,0,0,0,0, 128,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,0,0,128,0,0,0, 128,128,128,128,0,0,128,0, 28,28,28,28,28,28,28,28, 28,28,0,0,0,0,0,128, 0,26,26,26,26,26,26,18, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,18, 18,18,18,128,128,0,128,16, 0,26,26,26,26,26,26,18, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,18, 18,18,18,128,128,0,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,0,18,0,0,0,0,0, 0,0,20,20,0,18,0,0, 0,20,18,0,0,0,0,0, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,0, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,18, 18,18,18,18,18,18,18,0, 18,18,18,18,18,18,18,18 }; #ifndef HAVE_STRERROR /************************************************* * Provide strerror() for non-ANSI libraries * *************************************************/ /* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror() in their libraries, but can provide the same facility by this simple alternative function. */ extern int sys_nerr; extern char *sys_errlist[]; char * strerror(int n) { if (n < 0 || n >= sys_nerr) return "unknown error number"; return sys_errlist[n]; } #endif /* HAVE_STRERROR */ /************************************************* * Print newline configuration * *************************************************/ /* Arguments: rc the return code from PCRE_CONFIG_NEWLINE isc TRUE if called from "-C newline" Returns: nothing */ static void print_newline_config(int rc, BOOL isc) { const char *s = NULL; if (!isc) printf(" Newline sequence is "); switch(rc) { case CHAR_CR: s = "CR"; break; case CHAR_LF: s = "LF"; break; case (CHAR_CR<<8 | CHAR_LF): s = "CRLF"; break; case -1: s = "ANY"; break; case -2: s = "ANYCRLF"; break; default: printf("a non-standard value: 0x%04x\n", rc); return; } printf("%s\n", s); } /************************************************* * JIT memory callback * *************************************************/ static pcre_jit_stack* jit_callback(void *arg) { jit_was_used = TRUE; return (pcre_jit_stack *)arg; } #if !defined NOUTF || defined SUPPORT_PCRE16 || defined SUPPORT_PCRE32 /************************************************* * Convert UTF-8 string to value * *************************************************/ /* This function takes one or more bytes that represents a UTF-8 character, and returns the value of the character. Argument: utf8bytes a pointer to the byte vector vptr a pointer to an int to receive the value Returns: > 0 => the number of bytes consumed -6 to 0 => malformed UTF-8 character at offset = (-return) */ static int utf82ord(pcre_uint8 *utf8bytes, pcre_uint32 *vptr) { pcre_uint32 c = *utf8bytes++; pcre_uint32 d = c; int i, j, s; for (i = -1; i < 6; i++) /* i is number of additional bytes */ { if ((d & 0x80) == 0) break; d <<= 1; } if (i == -1) { *vptr = c; return 1; } /* ascii character */ if (i == 0 || i == 6) return 0; /* invalid UTF-8 */ /* i now has a value in the range 1-5 */ s = 6*i; d = (c & utf8_table3[i]) << s; for (j = 0; j < i; j++) { c = *utf8bytes++; if ((c & 0xc0) != 0x80) return -(j+1); s -= 6; d |= (c & 0x3f) << s; } /* Check that encoding was the correct unique one */ for (j = 0; j < utf8_table1_size; j++) if (d <= (pcre_uint32)utf8_table1[j]) break; if (j != i) return -(i+1); /* Valid value */ *vptr = d; return i+1; } #endif /* NOUTF || SUPPORT_PCRE16 */ #if defined SUPPORT_PCRE8 && !defined NOUTF /************************************************* * Convert character value to UTF-8 * *************************************************/ /* This function takes an integer value in the range 0 - 0x7fffffff and encodes it as a UTF-8 character in 0 to 6 bytes. Arguments: cvalue the character value utf8bytes pointer to buffer for result - at least 6 bytes long Returns: number of characters placed in the buffer */ static int ord2utf8(pcre_uint32 cvalue, pcre_uint8 *utf8bytes) { register int i, j; if (cvalue > 0x7fffffffu) return -1; for (i = 0; i < utf8_table1_size; i++) if (cvalue <= (pcre_uint32)utf8_table1[i]) break; utf8bytes += i; for (j = i; j > 0; j--) { *utf8bytes-- = 0x80 | (cvalue & 0x3f); cvalue >>= 6; } *utf8bytes = utf8_table2[i] | cvalue; return i + 1; } #endif #ifdef SUPPORT_PCRE16 /************************************************* * Convert a string to 16-bit * *************************************************/ /* In non-UTF mode, the space needed for a 16-bit string is exactly double the 8-bit size. For a UTF-8 string, the size needed for UTF-16 is no more than double, because up to 0xffff uses no more than 3 bytes in UTF-8 but possibly 4 in UTF-16. Higher values use 4 bytes in UTF-8 and up to 4 bytes in UTF-16. The result is always left in buffer16. Note that this function does not object to surrogate values. This is deliberate; it makes it possible to construct UTF-16 strings that are invalid, for the purpose of testing that they are correctly faulted. Patterns to be converted are either plain ASCII or UTF-8; data lines are always in UTF-8 so that values greater than 255 can be handled. Arguments: data TRUE if converting a data line; FALSE for a regex p points to a byte string utf true if UTF-8 (to be converted to UTF-16) len number of bytes in the string (excluding trailing zero) Returns: number of 16-bit data items used (excluding trailing zero) OR -1 if a UTF-8 string is malformed OR -2 if a value > 0x10ffff is encountered OR -3 if a value > 0xffff is encountered when not in UTF mode */ static int to16(int data, pcre_uint8 *p, int utf, int len) { pcre_uint16 *pp; if (buffer16_size < 2*len + 2) { if (buffer16 != NULL) free(buffer16); buffer16_size = 2*len + 2; buffer16 = (pcre_uint16 *)malloc(buffer16_size); if (buffer16 == NULL) { fprintf(stderr, "pcretest: malloc(%d) failed for buffer16\n", buffer16_size); exit(1); } } pp = buffer16; if (!utf && !data) { while (len-- > 0) *pp++ = *p++; } else { pcre_uint32 c = 0; while (len > 0) { int chlen = utf82ord(p, &c); if (chlen <= 0) return -1; if (c > 0x10ffff) return -2; p += chlen; len -= chlen; if (c < 0x10000) *pp++ = c; else { if (!utf) return -3; c -= 0x10000; *pp++ = 0xD800 | (c >> 10); *pp++ = 0xDC00 | (c & 0x3ff); } } } *pp = 0; return pp - buffer16; } #endif #ifdef SUPPORT_PCRE32 /************************************************* * Convert a string to 32-bit * *************************************************/ /* In non-UTF mode, the space needed for a 32-bit string is exactly four times the 8-bit size. For a UTF-8 string, the size needed for UTF-32 is no more than four times, because up to 0xffff uses no more than 3 bytes in UTF-8 but possibly 4 in UTF-32. Higher values use 4 bytes in UTF-8 and up to 4 bytes in UTF-32. The result is always left in buffer32. Note that this function does not object to surrogate values. This is deliberate; it makes it possible to construct UTF-32 strings that are invalid, for the purpose of testing that they are correctly faulted. Patterns to be converted are either plain ASCII or UTF-8; data lines are always in UTF-8 so that values greater than 255 can be handled. Arguments: data TRUE if converting a data line; FALSE for a regex p points to a byte string utf true if UTF-8 (to be converted to UTF-32) len number of bytes in the string (excluding trailing zero) Returns: number of 32-bit data items used (excluding trailing zero) OR -1 if a UTF-8 string is malformed OR -2 if a value > 0x10ffff is encountered OR -3 if an ill-formed value is encountered (i.e. a surrogate) */ static int to32(int data, pcre_uint8 *p, int utf, int len) { pcre_uint32 *pp; if (buffer32_size < 4*len + 4) { if (buffer32 != NULL) free(buffer32); buffer32_size = 4*len + 4; buffer32 = (pcre_uint32 *)malloc(buffer32_size); if (buffer32 == NULL) { fprintf(stderr, "pcretest: malloc(%d) failed for buffer32\n", buffer32_size); exit(1); } } pp = buffer32; if (!utf && !data) { while (len-- > 0) *pp++ = *p++; } else { pcre_uint32 c = 0; while (len > 0) { int chlen = utf82ord(p, &c); if (chlen <= 0) return -1; if (utf) { if (c > 0x10ffff) return -2; if (!data && (c & 0xfffff800u) == 0xd800u) return -3; } p += chlen; len -= chlen; *pp++ = c; } } *pp = 0; return pp - buffer32; } /* Check that a 32-bit character string is valid UTF-32. Arguments: string points to the string length length of string, or -1 if the string is zero-terminated Returns: TRUE if the string is a valid UTF-32 string FALSE otherwise */ #ifdef NEVER /* Not used */ #ifdef SUPPORT_UTF static BOOL valid_utf32(pcre_uint32 *string, int length) { register pcre_uint32 *p; register pcre_uint32 c; for (p = string; length-- > 0; p++) { c = *p; if (c > 0x10ffffu) return FALSE; /* Too big */ if ((c & 0xfffff800u) == 0xd800u) return FALSE; /* Surrogate */ } return TRUE; } #endif /* SUPPORT_UTF */ #endif /* NEVER */ #endif /* SUPPORT_PCRE32 */ /************************************************* * Read or extend an input line * *************************************************/ /* Input lines are read into buffer, but both patterns and data lines can be continued over multiple input lines. In addition, if the buffer fills up, we want to automatically expand it so as to be able to handle extremely large lines that are needed for certain stress tests. When the input buffer is expanded, the other two buffers must also be expanded likewise, and the contents of pbuffer, which are a copy of the input for callouts, must be preserved (for when expansion happens for a data line). This is not the most optimal way of handling this, but hey, this is just a test program! Arguments: f the file to read start where in buffer to start (this *must* be within buffer) prompt for stdin or readline() Returns: pointer to the start of new data could be a copy of start, or could be moved NULL if no data read and EOF reached */ static pcre_uint8 * extend_inputline(FILE *f, pcre_uint8 *start, const char *prompt) { pcre_uint8 *here = start; for (;;) { size_t rlen = (size_t)(buffer_size - (here - buffer)); if (rlen > 1000) { int dlen; /* If libreadline or libedit support is required, use readline() to read a line if the input is a terminal. Note that readline() removes the trailing newline, so we must put it back again, to be compatible with fgets(). */ #if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT) if (isatty(fileno(f))) { size_t len; char *s = readline(prompt); if (s == NULL) return (here == start)? NULL : start; len = strlen(s); if (len > 0) add_history(s); if (len > rlen - 1) len = rlen - 1; memcpy(here, s, len); here[len] = '\n'; here[len+1] = 0; free(s); } else #endif /* Read the next line by normal means, prompting if the file is stdin. */ { if (f == stdin) printf("%s", prompt); if (fgets((char *)here, rlen, f) == NULL) return (here == start)? NULL : start; } dlen = (int)strlen((char *)here); if (dlen > 0 && here[dlen - 1] == '\n') return start; here += dlen; } else { int new_buffer_size = 2*buffer_size; pcre_uint8 *new_buffer = (pcre_uint8 *)malloc(new_buffer_size); pcre_uint8 *new_pbuffer = (pcre_uint8 *)malloc(new_buffer_size); if (new_buffer == NULL || new_pbuffer == NULL) { fprintf(stderr, "pcretest: malloc(%d) failed\n", new_buffer_size); exit(1); } memcpy(new_buffer, buffer, buffer_size); memcpy(new_pbuffer, pbuffer, buffer_size); buffer_size = new_buffer_size; start = new_buffer + (start - buffer); here = new_buffer + (here - buffer); free(buffer); free(pbuffer); buffer = new_buffer; pbuffer = new_pbuffer; } } /* Control never gets here */ } /************************************************* * Read number from string * *************************************************/ /* We don't use strtoul() because SunOS4 doesn't have it. Rather than mess around with conditional compilation, just do the job by hand. It is only used for unpicking arguments, so just keep it simple. Arguments: str string to be converted endptr where to put the end pointer Returns: the unsigned long */ static int get_value(pcre_uint8 *str, pcre_uint8 **endptr) { int result = 0; while(*str != 0 && isspace(*str)) str++; while (isdigit(*str)) result = result * 10 + (int)(*str++ - '0'); *endptr = str; return(result); } /************************************************* * Print one character * *************************************************/ /* Print a single character either literally, or as a hex escape. */ static int pchar(pcre_uint32 c, FILE *f) { int n = 0; char tempbuffer[16]; if (PRINTOK(c)) { if (f != NULL) fprintf(f, "%c", c); return 1; } if (c < 0x100) { if (use_utf) { if (f != NULL) fprintf(f, "\\x{%02x}", c); return 6; } else { if (f != NULL) fprintf(f, "\\x%02x", c); return 4; } } if (f != NULL) n = fprintf(f, "\\x{%02x}", c); else n = sprintf(tempbuffer, "\\x{%02x}", c); return n >= 0 ? n : 0; } #ifdef SUPPORT_PCRE8 /************************************************* * Print 8-bit character string * *************************************************/ /* Must handle UTF-8 strings in utf8 mode. Yields number of characters printed. If handed a NULL file, just counts chars without printing. */ static int pchars(pcre_uint8 *p, int length, FILE *f) { pcre_uint32 c = 0; int yield = 0; if (length < 0) length = strlen((char *)p); while (length-- > 0) { #if !defined NOUTF if (use_utf) { int rc = utf82ord(p, &c); if (rc > 0 && rc <= length + 1) /* Mustn't run over the end */ { length -= rc - 1; p += rc; yield += pchar(c, f); continue; } } #endif c = *p++; yield += pchar(c, f); } return yield; } #endif #ifdef SUPPORT_PCRE16 /************************************************* * Find length of 0-terminated 16-bit string * *************************************************/ static int strlen16(PCRE_SPTR16 p) { PCRE_SPTR16 pp = p; while (*pp != 0) pp++; return (int)(pp - p); } #endif /* SUPPORT_PCRE16 */ #ifdef SUPPORT_PCRE32 /************************************************* * Find length of 0-terminated 32-bit string * *************************************************/ static int strlen32(PCRE_SPTR32 p) { PCRE_SPTR32 pp = p; while (*pp != 0) pp++; return (int)(pp - p); } #endif /* SUPPORT_PCRE32 */ #ifdef SUPPORT_PCRE16 /************************************************* * Print 16-bit character string * *************************************************/ /* Must handle UTF-16 strings in utf mode. Yields number of characters printed. If handed a NULL file, just counts chars without printing. */ static int pchars16(PCRE_SPTR16 p, int length, FILE *f) { int yield = 0; if (length < 0) length = strlen16(p); while (length-- > 0) { pcre_uint32 c = *p++ & 0xffff; #if !defined NOUTF if (use_utf && c >= 0xD800 && c < 0xDC00 && length > 0) { int d = *p & 0xffff; if (d >= 0xDC00 && d <= 0xDFFF) { c = ((c & 0x3ff) << 10) + (d & 0x3ff) + 0x10000; length--; p++; } } #endif yield += pchar(c, f); } return yield; } #endif /* SUPPORT_PCRE16 */ #ifdef SUPPORT_PCRE32 /************************************************* * Print 32-bit character string * *************************************************/ /* Must handle UTF-32 strings in utf mode. Yields number of characters printed. If handed a NULL file, just counts chars without printing. */ static int pchars32(PCRE_SPTR32 p, int length, BOOL utf, FILE *f) { int yield = 0; (void)(utf); /* Avoid compiler warning */ if (length < 0) length = strlen32(p); while (length-- > 0) { pcre_uint32 c = *p++; yield += pchar(c, f); } return yield; } #endif /* SUPPORT_PCRE32 */ #ifdef SUPPORT_PCRE8 /************************************************* * Read a capture name (8-bit) and check it * *************************************************/ static pcre_uint8 * read_capture_name8(pcre_uint8 *p, pcre_uint8 **pp, pcre *re) { pcre_uint8 *npp = *pp; while (isalnum(*p)) *npp++ = *p++; *npp++ = 0; *npp = 0; if (pcre_get_stringnumber(re, (char *)(*pp)) < 0) { fprintf(outfile, "no parentheses with name \""); PCHARSV(*pp, 0, -1, outfile); fprintf(outfile, "\"\n"); } *pp = npp; return p; } #endif /* SUPPORT_PCRE8 */ #ifdef SUPPORT_PCRE16 /************************************************* * Read a capture name (16-bit) and check it * *************************************************/ /* Note that the text being read is 8-bit. */ static pcre_uint8 * read_capture_name16(pcre_uint8 *p, pcre_uint16 **pp, pcre *re) { pcre_uint16 *npp = *pp; while (isalnum(*p)) *npp++ = *p++; *npp++ = 0; *npp = 0; if (pcre16_get_stringnumber((pcre16 *)re, (PCRE_SPTR16)(*pp)) < 0) { fprintf(outfile, "no parentheses with name \""); PCHARSV(*pp, 0, -1, outfile); fprintf(outfile, "\"\n"); } *pp = npp; return p; } #endif /* SUPPORT_PCRE16 */ #ifdef SUPPORT_PCRE32 /************************************************* * Read a capture name (32-bit) and check it * *************************************************/ /* Note that the text being read is 8-bit. */ static pcre_uint8 * read_capture_name32(pcre_uint8 *p, pcre_uint32 **pp, pcre *re) { pcre_uint32 *npp = *pp; while (isalnum(*p)) *npp++ = *p++; *npp++ = 0; *npp = 0; if (pcre32_get_stringnumber((pcre32 *)re, (PCRE_SPTR32)(*pp)) < 0) { fprintf(outfile, "no parentheses with name \""); PCHARSV(*pp, 0, -1, outfile); fprintf(outfile, "\"\n"); } *pp = npp; return p; } #endif /* SUPPORT_PCRE32 */ /************************************************* * Stack guard function * *************************************************/ /* Called from PCRE when set in pcre_stack_guard. We give an error (non-zero) return when a count overflows. */ static int stack_guard(void) { return stack_guard_return; } /************************************************* * Callout function * *************************************************/ /* Called from PCRE as a result of the (?C) item. We print out where we are in the match. Yield zero unless more callouts than the fail count, or the callout data is not zero. */ static int callout(pcre_callout_block *cb) { FILE *f = (first_callout | callout_extra)? outfile : NULL; int i, current_position, pre_start, post_start, subject_length; if (callout_extra) { fprintf(f, "Callout %d: last capture = %d\n", cb->callout_number, cb->capture_last); if (cb->offset_vector != NULL) { for (i = 0; i < cb->capture_top * 2; i += 2) { if (cb->offset_vector[i] < 0) fprintf(f, "%2d: \n", i/2); else { fprintf(f, "%2d: ", i/2); PCHARSV(cb->subject, cb->offset_vector[i], cb->offset_vector[i+1] - cb->offset_vector[i], f); fprintf(f, "\n"); } } } } /* Re-print the subject in canonical form, the first time or if giving full datails. On subsequent calls in the same match, we use pchars just to find the printed lengths of the substrings. */ if (f != NULL) fprintf(f, "--->"); /* If a lookbehind is involved, the current position may be earlier than the match start. If so, use the match start instead. */ current_position = (cb->current_position >= cb->start_match)? cb->current_position : cb->start_match; PCHARS(pre_start, cb->subject, 0, cb->start_match, f); PCHARS(post_start, cb->subject, cb->start_match, current_position - cb->start_match, f); PCHARS(subject_length, cb->subject, 0, cb->subject_length, NULL); PCHARSV(cb->subject, current_position, cb->subject_length - current_position, f); if (f != NULL) fprintf(f, "\n"); /* Always print appropriate indicators, with callout number if not already shown. For automatic callouts, show the pattern offset. */ if (cb->callout_number == 255) { fprintf(outfile, "%+3d ", cb->pattern_position); if (cb->pattern_position > 99) fprintf(outfile, "\n "); } else { if (callout_extra) fprintf(outfile, " "); else fprintf(outfile, "%3d ", cb->callout_number); } for (i = 0; i < pre_start; i++) fprintf(outfile, " "); fprintf(outfile, "^"); if (post_start > 0) { for (i = 0; i < post_start - 1; i++) fprintf(outfile, " "); fprintf(outfile, "^"); } for (i = 0; i < subject_length - pre_start - post_start + 4; i++) fprintf(outfile, " "); fprintf(outfile, "%.*s", (cb->next_item_length == 0)? 1 : cb->next_item_length, pbuffer + cb->pattern_position); fprintf(outfile, "\n"); first_callout = 0; if (cb->mark != last_callout_mark) { if (cb->mark == NULL) fprintf(outfile, "Latest Mark: \n"); else { fprintf(outfile, "Latest Mark: "); PCHARSV(cb->mark, 0, -1, outfile); putc('\n', outfile); } last_callout_mark = cb->mark; } if (cb->callout_data != NULL) { int callout_data = *((int *)(cb->callout_data)); if (callout_data != 0) { fprintf(outfile, "Callout data = %d\n", callout_data); return callout_data; } } return (cb->callout_number != callout_fail_id)? 0 : (++callout_count >= callout_fail_count)? 1 : 0; } /************************************************* * Local malloc functions * *************************************************/ /* Alternative malloc function, to test functionality and save the size of a compiled re, which is the first store request that pcre_compile() makes. The show_malloc variable is set only during matching. */ static void *new_malloc(size_t size) { void *block = malloc(size); if (show_malloc) fprintf(outfile, "malloc %3d %p\n", (int)size, block); return block; } static void new_free(void *block) { if (show_malloc) fprintf(outfile, "free %p\n", block); free(block); } /* For recursion malloc/free, to test stacking calls */ static void *stack_malloc(size_t size) { void *block = malloc(size); if (show_malloc) fprintf(outfile, "stack_malloc %3d %p\n", (int)size, block); return block; } static void stack_free(void *block) { if (show_malloc) fprintf(outfile, "stack_free %p\n", block); free(block); } /************************************************* * Call pcre_fullinfo() * *************************************************/ /* Get one piece of information from the pcre_fullinfo() function. When only one of 8-, 16- or 32-bit is supported, pcre_mode should always have the correct value, but the code is defensive. Arguments: re compiled regex study study data option PCRE_INFO_xxx option ptr where to put the data Returns: 0 when OK, < 0 on error */ static int new_info(pcre *re, pcre_extra *study, int option, void *ptr) { int rc; if (pcre_mode == PCRE32_MODE) #ifdef SUPPORT_PCRE32 rc = pcre32_fullinfo((pcre32 *)re, (pcre32_extra *)study, option, ptr); #else rc = PCRE_ERROR_BADMODE; #endif else if (pcre_mode == PCRE16_MODE) #ifdef SUPPORT_PCRE16 rc = pcre16_fullinfo((pcre16 *)re, (pcre16_extra *)study, option, ptr); #else rc = PCRE_ERROR_BADMODE; #endif else #ifdef SUPPORT_PCRE8 rc = pcre_fullinfo(re, study, option, ptr); #else rc = PCRE_ERROR_BADMODE; #endif if (rc < 0 && rc != PCRE_ERROR_UNSET) { fprintf(outfile, "Error %d from pcre%s_fullinfo(%d)\n", rc, pcre_mode == PCRE32_MODE ? "32" : pcre_mode == PCRE16_MODE ? "16" : "", option); if (rc == PCRE_ERROR_BADMODE) fprintf(outfile, "Running in %d-bit mode but pattern was compiled in " "%d-bit mode\n", 8 * CHAR_SIZE, 8 * (REAL_PCRE_FLAGS(re) & PCRE_MODE_MASK)); } return rc; } /************************************************* * Swap byte functions * *************************************************/ /* The following functions swap the bytes of a pcre_uint16 and pcre_uint32 value, respectively. Arguments: value any number Returns: the byte swapped value */ static pcre_uint32 swap_uint32(pcre_uint32 value) { return ((value & 0x000000ff) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | (value >> 24); } static pcre_uint16 swap_uint16(pcre_uint16 value) { return (value >> 8) | (value << 8); } /************************************************* * Flip bytes in a compiled pattern * *************************************************/ /* This function is called if the 'F' option was present on a pattern that is to be written to a file. We flip the bytes of all the integer fields in the regex data block and the study block. In 16-bit mode this also flips relevant bytes in the pattern itself. This is to make it possible to test PCRE's ability to reload byte-flipped patterns, e.g. those compiled on a different architecture. */ #if defined SUPPORT_PCRE8 || defined SUPPORT_PCRE16 static void regexflip8_or_16(pcre *ere, pcre_extra *extra) { real_pcre8_or_16 *re = (real_pcre8_or_16 *)ere; #ifdef SUPPORT_PCRE16 int op; pcre_uint16 *ptr = (pcre_uint16 *)re + re->name_table_offset; int length = re->name_count * re->name_entry_size; #ifdef SUPPORT_UTF BOOL utf = (re->options & PCRE_UTF16) != 0; BOOL utf16_char = FALSE; #endif /* SUPPORT_UTF */ #endif /* SUPPORT_PCRE16 */ /* Always flip the bytes in the main data block and study blocks. */ re->magic_number = REVERSED_MAGIC_NUMBER; re->size = swap_uint32(re->size); re->options = swap_uint32(re->options); re->flags = swap_uint32(re->flags); re->limit_match = swap_uint32(re->limit_match); re->limit_recursion = swap_uint32(re->limit_recursion); re->first_char = swap_uint16(re->first_char); re->req_char = swap_uint16(re->req_char); re->max_lookbehind = swap_uint16(re->max_lookbehind); re->top_bracket = swap_uint16(re->top_bracket); re->top_backref = swap_uint16(re->top_backref); re->name_table_offset = swap_uint16(re->name_table_offset); re->name_entry_size = swap_uint16(re->name_entry_size); re->name_count = swap_uint16(re->name_count); re->ref_count = swap_uint16(re->ref_count); if (extra != NULL && (extra->flags & PCRE_EXTRA_STUDY_DATA) != 0) { pcre_study_data *rsd = (pcre_study_data *)(extra->study_data); rsd->size = swap_uint32(rsd->size); rsd->flags = swap_uint32(rsd->flags); rsd->minlength = swap_uint32(rsd->minlength); } /* In 8-bit mode, that is all we need to do. In 16-bit mode we must swap bytes in the name table, if present, and then in the pattern itself. */ #ifdef SUPPORT_PCRE16 if (pcre_mode != PCRE16_MODE) return; while(TRUE) { /* Swap previous characters. */ while (length-- > 0) { *ptr = swap_uint16(*ptr); ptr++; } #ifdef SUPPORT_UTF if (utf16_char) { if ((ptr[-1] & 0xfc00) == 0xd800) { /* We know that there is only one extra character in UTF-16. */ *ptr = swap_uint16(*ptr); ptr++; } } utf16_char = FALSE; #endif /* SUPPORT_UTF */ /* Get next opcode. */ length = 0; op = *ptr; *ptr++ = swap_uint16(op); switch (op) { case OP_END: return; #ifdef SUPPORT_UTF case OP_CHAR: case OP_CHARI: case OP_NOT: case OP_NOTI: case OP_STAR: case OP_MINSTAR: case OP_PLUS: case OP_MINPLUS: case OP_QUERY: case OP_MINQUERY: case OP_UPTO: case OP_MINUPTO: case OP_EXACT: case OP_POSSTAR: case OP_POSPLUS: case OP_POSQUERY: case OP_POSUPTO: case OP_STARI: case OP_MINSTARI: case OP_PLUSI: case OP_MINPLUSI: case OP_QUERYI: case OP_MINQUERYI: case OP_UPTOI: case OP_MINUPTOI: case OP_EXACTI: case OP_POSSTARI: case OP_POSPLUSI: case OP_POSQUERYI: case OP_POSUPTOI: case OP_NOTSTAR: case OP_NOTMINSTAR: case OP_NOTPLUS: case OP_NOTMINPLUS: case OP_NOTQUERY: case OP_NOTMINQUERY: case OP_NOTUPTO: case OP_NOTMINUPTO: case OP_NOTEXACT: case OP_NOTPOSSTAR: case OP_NOTPOSPLUS: case OP_NOTPOSQUERY: case OP_NOTPOSUPTO: case OP_NOTSTARI: case OP_NOTMINSTARI: case OP_NOTPLUSI: case OP_NOTMINPLUSI: case OP_NOTQUERYI: case OP_NOTMINQUERYI: case OP_NOTUPTOI: case OP_NOTMINUPTOI: case OP_NOTEXACTI: case OP_NOTPOSSTARI: case OP_NOTPOSPLUSI: case OP_NOTPOSQUERYI: case OP_NOTPOSUPTOI: if (utf) utf16_char = TRUE; #endif /* Fall through. */ default: length = OP_lengths16[op] - 1; break; case OP_CLASS: case OP_NCLASS: /* Skip the character bit map. */ ptr += 32/sizeof(pcre_uint16); length = 0; break; case OP_XCLASS: /* LINK_SIZE can be 1 or 2 in 16 bit mode. */ if (LINK_SIZE > 1) length = (int)((((unsigned int)(ptr[0]) << 16) | (unsigned int)(ptr[1])) - (1 + LINK_SIZE + 1)); else length = (int)((unsigned int)(ptr[0]) - (1 + LINK_SIZE + 1)); /* Reverse the size of the XCLASS instance. */ *ptr = swap_uint16(*ptr); ptr++; if (LINK_SIZE > 1) { *ptr = swap_uint16(*ptr); ptr++; } op = *ptr; *ptr = swap_uint16(op); ptr++; if ((op & XCL_MAP) != 0) { /* Skip the character bit map. */ ptr += 32/sizeof(pcre_uint16); length -= 32/sizeof(pcre_uint16); } break; } } /* Control should never reach here in 16 bit mode. */ #endif /* SUPPORT_PCRE16 */ } #endif /* SUPPORT_PCRE[8|16] */ #if defined SUPPORT_PCRE32 static void regexflip_32(pcre *ere, pcre_extra *extra) { real_pcre32 *re = (real_pcre32 *)ere; int op; pcre_uint32 *ptr = (pcre_uint32 *)re + re->name_table_offset; int length = re->name_count * re->name_entry_size; /* Always flip the bytes in the main data block and study blocks. */ re->magic_number = REVERSED_MAGIC_NUMBER; re->size = swap_uint32(re->size); re->options = swap_uint32(re->options); re->flags = swap_uint32(re->flags); re->limit_match = swap_uint32(re->limit_match); re->limit_recursion = swap_uint32(re->limit_recursion); re->first_char = swap_uint32(re->first_char); re->req_char = swap_uint32(re->req_char); re->max_lookbehind = swap_uint16(re->max_lookbehind); re->top_bracket = swap_uint16(re->top_bracket); re->top_backref = swap_uint16(re->top_backref); re->name_table_offset = swap_uint16(re->name_table_offset); re->name_entry_size = swap_uint16(re->name_entry_size); re->name_count = swap_uint16(re->name_count); re->ref_count = swap_uint16(re->ref_count); if (extra != NULL && (extra->flags & PCRE_EXTRA_STUDY_DATA) != 0) { pcre_study_data *rsd = (pcre_study_data *)(extra->study_data); rsd->size = swap_uint32(rsd->size); rsd->flags = swap_uint32(rsd->flags); rsd->minlength = swap_uint32(rsd->minlength); } /* In 32-bit mode we must swap bytes in the name table, if present, and then in the pattern itself. */ while(TRUE) { /* Swap previous characters. */ while (length-- > 0) { *ptr = swap_uint32(*ptr); ptr++; } /* Get next opcode. */ length = 0; op = *ptr; *ptr++ = swap_uint32(op); switch (op) { case OP_END: return; default: length = OP_lengths32[op] - 1; break; case OP_CLASS: case OP_NCLASS: /* Skip the character bit map. */ ptr += 32/sizeof(pcre_uint32); length = 0; break; case OP_XCLASS: /* LINK_SIZE can only be 1 in 32-bit mode. */ length = (int)((unsigned int)(ptr[0]) - (1 + LINK_SIZE + 1)); /* Reverse the size of the XCLASS instance. */ *ptr = swap_uint32(*ptr); ptr++; op = *ptr; *ptr = swap_uint32(op); ptr++; if ((op & XCL_MAP) != 0) { /* Skip the character bit map. */ ptr += 32/sizeof(pcre_uint32); length -= 32/sizeof(pcre_uint32); } break; } } /* Control should never reach here in 32 bit mode. */ } #endif /* SUPPORT_PCRE32 */ static void regexflip(pcre *ere, pcre_extra *extra) { #if defined SUPPORT_PCRE32 if (REAL_PCRE_FLAGS(ere) & PCRE_MODE32) regexflip_32(ere, extra); #endif #if defined SUPPORT_PCRE8 || defined SUPPORT_PCRE16 if (REAL_PCRE_FLAGS(ere) & (PCRE_MODE8 | PCRE_MODE16)) regexflip8_or_16(ere, extra); #endif } /************************************************* * Check match or recursion limit * *************************************************/ static int check_match_limit(pcre *re, pcre_extra *extra, pcre_uint8 *bptr, int len, int start_offset, int options, int *use_offsets, int use_size_offsets, int flag, unsigned long int *limit, int errnumber, const char *msg) { int count; int min = 0; int mid = 64; int max = -1; extra->flags |= flag; for (;;) { *limit = mid; PCRE_EXEC(count, re, extra, bptr, len, start_offset, options, use_offsets, use_size_offsets); if (count == errnumber) { /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */ min = mid; mid = (mid == max - 1)? max : (max > 0)? (min + max)/2 : mid*2; } else if (count >= 0 || count == PCRE_ERROR_NOMATCH || count == PCRE_ERROR_PARTIAL) { if (mid == min + 1) { fprintf(outfile, "Minimum %s limit = %d\n", msg, mid); break; } /* fprintf(outfile, "Testing %s limit = %d\n", msg, mid); */ max = mid; mid = (min + mid)/2; } else break; /* Some other error */ } extra->flags &= ~flag; return count; } /************************************************* * Case-independent strncmp() function * *************************************************/ /* Arguments: s first string t second string n number of characters to compare Returns: < 0, = 0, or > 0, according to the comparison */ static int strncmpic(pcre_uint8 *s, pcre_uint8 *t, int n) { while (n--) { int c = tolower(*s++) - tolower(*t++); if (c) return c; } return 0; } /************************************************* * Check multicharacter option * *************************************************/ /* This is used both at compile and run-time to check for escapes. Print a message and return 0 if there is no match. Arguments: p points after the leading '<' f file for error message nl TRUE to check only for newline settings stype "modifier" or "escape sequence" Returns: appropriate PCRE_NEWLINE_xxx flags, or 0 */ static int check_mc_option(pcre_uint8 *p, FILE *f, BOOL nl, const char *stype) { if (strncmpic(p, (pcre_uint8 *)"cr>", 3) == 0) return PCRE_NEWLINE_CR; if (strncmpic(p, (pcre_uint8 *)"lf>", 3) == 0) return PCRE_NEWLINE_LF; if (strncmpic(p, (pcre_uint8 *)"crlf>", 5) == 0) return PCRE_NEWLINE_CRLF; if (strncmpic(p, (pcre_uint8 *)"anycrlf>", 8) == 0) return PCRE_NEWLINE_ANYCRLF; if (strncmpic(p, (pcre_uint8 *)"any>", 4) == 0) return PCRE_NEWLINE_ANY; if (strncmpic(p, (pcre_uint8 *)"bsr_anycrlf>", 12) == 0) return PCRE_BSR_ANYCRLF; if (strncmpic(p, (pcre_uint8 *)"bsr_unicode>", 12) == 0) return PCRE_BSR_UNICODE; if (!nl) { if (strncmpic(p, (pcre_uint8 *)"JS>", 3) == 0) return PCRE_JAVASCRIPT_COMPAT; } fprintf(f, "Unknown %s at: <%s\n", stype, p); return 0; } /************************************************* * Usage function * *************************************************/ static void usage(void) { printf("Usage: pcretest [options] [ []]\n\n"); printf("Input and output default to stdin and stdout.\n"); #if defined(SUPPORT_LIBREADLINE) || defined(SUPPORT_LIBEDIT) printf("If input is a terminal, readline() is used to read from it.\n"); #else printf("This version of pcretest is not linked with readline().\n"); #endif printf("\nOptions:\n"); #ifdef SUPPORT_PCRE16 printf(" -16 use the 16-bit library\n"); #endif #ifdef SUPPORT_PCRE32 printf(" -32 use the 32-bit library\n"); #endif printf(" -b show compiled code\n"); printf(" -C show PCRE compile-time options and exit\n"); printf(" -C arg show a specific compile-time option and exit\n"); printf(" with its value if numeric (else 0). The arg can be:\n"); printf(" linksize internal link size [2, 3, 4]\n"); printf(" pcre8 8 bit library support enabled [0, 1]\n"); printf(" pcre16 16 bit library support enabled [0, 1]\n"); printf(" pcre32 32 bit library support enabled [0, 1]\n"); printf(" utf Unicode Transformation Format supported [0, 1]\n"); printf(" ucp Unicode Properties supported [0, 1]\n"); printf(" jit Just-in-time compiler supported [0, 1]\n"); printf(" newline Newline type [CR, LF, CRLF, ANYCRLF, ANY]\n"); printf(" bsr \\R type [ANYCRLF, ANY]\n"); printf(" -d debug: show compiled code and information (-b and -i)\n"); #if !defined NODFA printf(" -dfa force DFA matching for all subjects\n"); #endif printf(" -help show usage information\n"); printf(" -i show information about compiled patterns\n" " -M find MATCH_LIMIT minimum for each subject\n" " -m output memory used information\n" " -O set PCRE_NO_AUTO_POSSESS on each pattern\n" " -o set size of offsets vector to \n"); #if !defined NOPOSIX printf(" -p use POSIX interface\n"); #endif printf(" -q quiet: do not output PCRE version number at start\n"); printf(" -S set stack size to megabytes\n"); printf(" -s force each pattern to be studied at basic level\n" " -s+ force each pattern to be studied, using JIT if available\n" " -s++ ditto, verifying when JIT was actually used\n" " -s+n force each pattern to be studied, using JIT if available,\n" " where 1 <= n <= 7 selects JIT options\n" " -s++n ditto, verifying when JIT was actually used\n" " -t time compilation and execution\n"); printf(" -t time compilation and execution, repeating times\n"); printf(" -tm time execution (matching) only\n"); printf(" -tm time execution (matching) only, repeating times\n"); printf(" -T same as -t, but show total times at the end\n"); printf(" -TM same as -tm, but show total time at the end\n"); } /************************************************* * Main Program * *************************************************/ /* Read lines from named file or stdin and write to named file or stdout; lines consist of a regular expression, in delimiters and optionally followed by options, followed by a set of test data, terminated by an empty line. */ int main(int argc, char **argv) { FILE *infile = stdin; const char *version; int options = 0; int study_options = 0; int default_find_match_limit = FALSE; pcre_uint32 default_options = 0; int op = 1; int timeit = 0; int timeitm = 0; int showtotaltimes = 0; int showinfo = 0; int showstore = 0; int force_study = -1; int force_study_options = 0; int quiet = 0; int size_offsets = 45; int size_offsets_max; int *offsets = NULL; int debug = 0; int done = 0; int all_use_dfa = 0; int verify_jit = 0; int yield = 0; int stack_size; pcre_uint8 *dbuffer = NULL; pcre_uint8 lockout[24] = { 0 }; size_t dbuffer_size = 1u << 14; clock_t total_compile_time = 0; clock_t total_study_time = 0; clock_t total_match_time = 0; #if !defined NOPOSIX int posix = 0; #endif #if !defined NODFA int *dfa_workspace = NULL; #endif pcre_jit_stack *jit_stack = NULL; /* These vectors store, end-to-end, a list of zero-terminated captured substring names, each list itself being terminated by an empty name. Assume that 1024 is plenty long enough for the few names we'll be testing. It is easiest to keep separate 8-, 16- and 32-bit versions, using the 32-bit version for the actual memory, to ensure alignment. */ pcre_uint32 copynames[1024]; pcre_uint32 getnames[1024]; #ifdef SUPPORT_PCRE32 pcre_uint32 *cn32ptr; pcre_uint32 *gn32ptr; #endif #ifdef SUPPORT_PCRE16 pcre_uint16 *copynames16 = (pcre_uint16 *)copynames; pcre_uint16 *getnames16 = (pcre_uint16 *)getnames; pcre_uint16 *cn16ptr; pcre_uint16 *gn16ptr; #endif #ifdef SUPPORT_PCRE8 pcre_uint8 *copynames8 = (pcre_uint8 *)copynames; pcre_uint8 *getnames8 = (pcre_uint8 *)getnames; pcre_uint8 *cn8ptr; pcre_uint8 *gn8ptr; #endif /* Get buffers from malloc() so that valgrind will check their misuse when debugging. They grow automatically when very long lines are read. The 16- and 32-bit buffers (buffer16, buffer32) are obtained only if needed. */ buffer = (pcre_uint8 *)malloc(buffer_size); pbuffer = (pcre_uint8 *)malloc(buffer_size); /* The outfile variable is static so that new_malloc can use it. */ outfile = stdout; /* The following _setmode() stuff is some Windows magic that tells its runtime library to translate CRLF into a single LF character. At least, that's what I've been told: never having used Windows I take this all on trust. Originally it set 0x8000, but then I was advised that _O_BINARY was better. */ #if defined(_WIN32) || defined(WIN32) _setmode( _fileno( stdout ), _O_BINARY ); #endif /* Get the version number: both pcre_version() and pcre16_version() give the same answer. We just need to ensure that we call one that is available. */ #if defined SUPPORT_PCRE8 version = pcre_version(); #elif defined SUPPORT_PCRE16 version = pcre16_version(); #elif defined SUPPORT_PCRE32 version = pcre32_version(); #endif /* Scan options */ while (argc > 1 && argv[op][0] == '-') { pcre_uint8 *endptr; char *arg = argv[op]; if (strcmp(arg, "-m") == 0) showstore = 1; else if (strcmp(arg, "-s") == 0) force_study = 0; else if (strncmp(arg, "-s+", 3) == 0) { arg += 3; if (*arg == '+') { arg++; verify_jit = TRUE; } force_study = 1; if (*arg == 0) force_study_options = jit_study_bits[6]; else if (*arg >= '1' && *arg <= '7') force_study_options = jit_study_bits[*arg - '1']; else goto BAD_ARG; } else if (strcmp(arg, "-8") == 0) { #ifdef SUPPORT_PCRE8 pcre_mode = PCRE8_MODE; #else printf("** This version of PCRE was built without 8-bit support\n"); exit(1); #endif } else if (strcmp(arg, "-16") == 0) { #ifdef SUPPORT_PCRE16 pcre_mode = PCRE16_MODE; #else printf("** This version of PCRE was built without 16-bit support\n"); exit(1); #endif } else if (strcmp(arg, "-32") == 0) { #ifdef SUPPORT_PCRE32 pcre_mode = PCRE32_MODE; #else printf("** This version of PCRE was built without 32-bit support\n"); exit(1); #endif } else if (strcmp(arg, "-q") == 0) quiet = 1; else if (strcmp(arg, "-b") == 0) debug = 1; else if (strcmp(arg, "-i") == 0) showinfo = 1; else if (strcmp(arg, "-d") == 0) showinfo = debug = 1; else if (strcmp(arg, "-M") == 0) default_find_match_limit = TRUE; else if (strcmp(arg, "-O") == 0) default_options |= PCRE_NO_AUTO_POSSESS; #if !defined NODFA else if (strcmp(arg, "-dfa") == 0) all_use_dfa = 1; #endif else if (strcmp(arg, "-o") == 0 && argc > 2 && ((size_offsets = get_value((pcre_uint8 *)argv[op+1], &endptr)), *endptr == 0)) { op++; argc--; } else if (strcmp(arg, "-t") == 0 || strcmp(arg, "-tm") == 0 || strcmp(arg, "-T") == 0 || strcmp(arg, "-TM") == 0) { int temp; int both = arg[2] == 0; showtotaltimes = arg[1] == 'T'; if (argc > 2 && (temp = get_value((pcre_uint8 *)argv[op+1], &endptr), *endptr == 0)) { timeitm = temp; op++; argc--; } else timeitm = LOOPREPEAT; if (both) timeit = timeitm; } else if (strcmp(arg, "-S") == 0 && argc > 2 && ((stack_size = get_value((pcre_uint8 *)argv[op+1], &endptr)), *endptr == 0)) { #if defined(_WIN32) || defined(WIN32) || defined(__minix) || defined(NATIVE_ZOS) || defined(__VMS) printf("PCRE: -S not supported on this OS\n"); exit(1); #else int rc; struct rlimit rlim; getrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = stack_size * 1024 * 1024; rc = setrlimit(RLIMIT_STACK, &rlim); if (rc != 0) { printf("PCRE: setrlimit() failed with error %d\n", rc); exit(1); } op++; argc--; #endif } #if !defined NOPOSIX else if (strcmp(arg, "-p") == 0) posix = 1; #endif else if (strcmp(arg, "-C") == 0) { int rc; unsigned long int lrc; if (argc > 2) { if (strcmp(argv[op + 1], "linksize") == 0) { (void)PCRE_CONFIG(PCRE_CONFIG_LINK_SIZE, &rc); printf("%d\n", rc); yield = rc; #ifdef __VMS vms_setsymbol("LINKSIZE",0,yield ); #endif } else if (strcmp(argv[op + 1], "pcre8") == 0) { #ifdef SUPPORT_PCRE8 printf("1\n"); yield = 1; #else printf("0\n"); yield = 0; #endif #ifdef __VMS vms_setsymbol("PCRE8",0,yield ); #endif } else if (strcmp(argv[op + 1], "pcre16") == 0) { #ifdef SUPPORT_PCRE16 printf("1\n"); yield = 1; #else printf("0\n"); yield = 0; #endif #ifdef __VMS vms_setsymbol("PCRE16",0,yield ); #endif } else if (strcmp(argv[op + 1], "pcre32") == 0) { #ifdef SUPPORT_PCRE32 printf("1\n"); yield = 1; #else printf("0\n"); yield = 0; #endif #ifdef __VMS vms_setsymbol("PCRE32",0,yield ); #endif } else if (strcmp(argv[op + 1], "utf") == 0) { #ifdef SUPPORT_PCRE8 if (pcre_mode == PCRE8_MODE) (void)pcre_config(PCRE_CONFIG_UTF8, &rc); #endif #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) (void)pcre16_config(PCRE_CONFIG_UTF16, &rc); #endif #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) (void)pcre32_config(PCRE_CONFIG_UTF32, &rc); #endif printf("%d\n", rc); yield = rc; #ifdef __VMS vms_setsymbol("UTF",0,yield ); #endif } else if (strcmp(argv[op + 1], "ucp") == 0) { (void)PCRE_CONFIG(PCRE_CONFIG_UNICODE_PROPERTIES, &rc); printf("%d\n", rc); yield = rc; } else if (strcmp(argv[op + 1], "jit") == 0) { (void)PCRE_CONFIG(PCRE_CONFIG_JIT, &rc); printf("%d\n", rc); yield = rc; } else if (strcmp(argv[op + 1], "newline") == 0) { (void)PCRE_CONFIG(PCRE_CONFIG_NEWLINE, &rc); print_newline_config(rc, TRUE); } else if (strcmp(argv[op + 1], "bsr") == 0) { (void)PCRE_CONFIG(PCRE_CONFIG_BSR, &rc); printf("%s\n", rc? "ANYCRLF" : "ANY"); } else if (strcmp(argv[op + 1], "ebcdic") == 0) { #ifdef EBCDIC printf("1\n"); yield = 1; #else printf("0\n"); #endif } else if (strcmp(argv[op + 1], "ebcdic-nl") == 0) { #ifdef EBCDIC printf("0x%02x\n", CHAR_LF); #else printf("0\n"); #endif } else { printf("Unknown -C option: %s\n", argv[op + 1]); } goto EXIT; } /* No argument for -C: output all configuration information. */ printf("PCRE version %s\n", version); printf("Compiled with\n"); #ifdef EBCDIC printf(" EBCDIC code support: LF is 0x%02x\n", CHAR_LF); #endif /* At least one of SUPPORT_PCRE8 and SUPPORT_PCRE16 will be set. If both are set, either both UTFs are supported or both are not supported. */ #ifdef SUPPORT_PCRE8 printf(" 8-bit support\n"); (void)pcre_config(PCRE_CONFIG_UTF8, &rc); printf (" %sUTF-8 support\n", rc ? "" : "No "); #endif #ifdef SUPPORT_PCRE16 printf(" 16-bit support\n"); (void)pcre16_config(PCRE_CONFIG_UTF16, &rc); printf (" %sUTF-16 support\n", rc ? "" : "No "); #endif #ifdef SUPPORT_PCRE32 printf(" 32-bit support\n"); (void)pcre32_config(PCRE_CONFIG_UTF32, &rc); printf (" %sUTF-32 support\n", rc ? "" : "No "); #endif (void)PCRE_CONFIG(PCRE_CONFIG_UNICODE_PROPERTIES, &rc); printf(" %sUnicode properties support\n", rc? "" : "No "); (void)PCRE_CONFIG(PCRE_CONFIG_JIT, &rc); if (rc) { const char *arch; (void)PCRE_CONFIG(PCRE_CONFIG_JITTARGET, (void *)(&arch)); printf(" Just-in-time compiler support: %s\n", arch); } else printf(" No just-in-time compiler support\n"); (void)PCRE_CONFIG(PCRE_CONFIG_NEWLINE, &rc); print_newline_config(rc, FALSE); (void)PCRE_CONFIG(PCRE_CONFIG_BSR, &rc); printf(" \\R matches %s\n", rc? "CR, LF, or CRLF only" : "all Unicode newlines"); (void)PCRE_CONFIG(PCRE_CONFIG_LINK_SIZE, &rc); printf(" Internal link size = %d\n", rc); (void)PCRE_CONFIG(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc); printf(" POSIX malloc threshold = %d\n", rc); (void)PCRE_CONFIG(PCRE_CONFIG_PARENS_LIMIT, &lrc); printf(" Parentheses nest limit = %ld\n", lrc); (void)PCRE_CONFIG(PCRE_CONFIG_MATCH_LIMIT, &lrc); printf(" Default match limit = %ld\n", lrc); (void)PCRE_CONFIG(PCRE_CONFIG_MATCH_LIMIT_RECURSION, &lrc); printf(" Default recursion depth limit = %ld\n", lrc); (void)PCRE_CONFIG(PCRE_CONFIG_STACKRECURSE, &rc); printf(" Match recursion uses %s", rc? "stack" : "heap"); if (showstore) { PCRE_EXEC(stack_size, NULL, NULL, NULL, -999, -999, 0, NULL, 0); printf(": %sframe size = %d bytes", rc? "approximate " : "", -stack_size); } printf("\n"); goto EXIT; } else if (strcmp(arg, "-help") == 0 || strcmp(arg, "--help") == 0) { usage(); goto EXIT; } else { BAD_ARG: printf("** Unknown or malformed option %s\n", arg); usage(); yield = 1; goto EXIT; } op++; argc--; } /* Get the store for the offsets vector, and remember what it was */ size_offsets_max = size_offsets; offsets = (int *)malloc(size_offsets_max * sizeof(int)); if (offsets == NULL) { printf("** Failed to get %d bytes of memory for offsets vector\n", (int)(size_offsets_max * sizeof(int))); yield = 1; goto EXIT; } /* Sort out the input and output files */ if (argc > 1) { infile = fopen(argv[op], INPUT_MODE); if (infile == NULL) { printf("** Failed to open %s\n", argv[op]); yield = 1; goto EXIT; } } if (argc > 2) { outfile = fopen(argv[op+1], OUTPUT_MODE); if (outfile == NULL) { printf("** Failed to open %s\n", argv[op+1]); yield = 1; goto EXIT; } } /* Set alternative malloc function */ #ifdef SUPPORT_PCRE8 pcre_malloc = new_malloc; pcre_free = new_free; pcre_stack_malloc = stack_malloc; pcre_stack_free = stack_free; #endif #ifdef SUPPORT_PCRE16 pcre16_malloc = new_malloc; pcre16_free = new_free; pcre16_stack_malloc = stack_malloc; pcre16_stack_free = stack_free; #endif #ifdef SUPPORT_PCRE32 pcre32_malloc = new_malloc; pcre32_free = new_free; pcre32_stack_malloc = stack_malloc; pcre32_stack_free = stack_free; #endif /* Heading line unless quiet */ if (!quiet) fprintf(outfile, "PCRE version %s\n\n", version); /* Main loop */ while (!done) { pcre *re = NULL; pcre_extra *extra = NULL; #if !defined NOPOSIX /* There are still compilers that require no indent */ regex_t preg = { NULL, 0, 0} ; int do_posix = 0; #endif const char *error; pcre_uint8 *markptr; pcre_uint8 *p, *pp, *ppp; pcre_uint8 *to_file = NULL; const pcre_uint8 *tables = NULL; unsigned long int get_options; unsigned long int true_size, true_study_size = 0; size_t size; int do_allcaps = 0; int do_mark = 0; int do_study = 0; int no_force_study = 0; int do_debug = debug; int do_G = 0; int do_g = 0; int do_showinfo = showinfo; int do_showrest = 0; int do_showcaprest = 0; int do_flip = 0; int erroroffset, len, delimiter, poffset; #if !defined NODFA int dfa_matched = 0; #endif use_utf = 0; debug_lengths = 1; SET_PCRE_STACK_GUARD(NULL); if (extend_inputline(infile, buffer, " re> ") == NULL) break; if (infile != stdin) fprintf(outfile, "%s", (char *)buffer); fflush(outfile); p = buffer; while (isspace(*p)) p++; if (*p == 0) continue; /* Handle option lock-out setting */ if (*p == '<' && p[1] == ' ') { p += 2; while (isspace(*p)) p++; if (strncmp((char *)p, "forbid ", 7) == 0) { p += 7; while (isspace(*p)) p++; pp = lockout; while (!isspace(*p) && pp < lockout + sizeof(lockout) - 1) *pp++ = *p++; *pp = 0; } else { printf("** Unrecognized special command '%s'\n", p); yield = 1; goto EXIT; } continue; } /* See if the pattern is to be loaded pre-compiled from a file. */ if (*p == '<' && strchr((char *)(p+1), '<') == NULL) { pcre_uint32 magic; pcre_uint8 sbuf[8]; FILE *f; p++; if (*p == '!') { do_debug = TRUE; do_showinfo = TRUE; p++; } pp = p + (int)strlen((char *)p); while (isspace(pp[-1])) pp--; *pp = 0; f = fopen((char *)p, "rb"); if (f == NULL) { fprintf(outfile, "Failed to open %s: %s\n", p, strerror(errno)); continue; } if (fread(sbuf, 1, 8, f) != 8) goto FAIL_READ; true_size = (sbuf[0] << 24) | (sbuf[1] << 16) | (sbuf[2] << 8) | sbuf[3]; true_study_size = (sbuf[4] << 24) | (sbuf[5] << 16) | (sbuf[6] << 8) | sbuf[7]; re = (pcre *)new_malloc(true_size); if (re == NULL) { printf("** Failed to get %d bytes of memory for pcre object\n", (int)true_size); yield = 1; goto EXIT; } if (fread(re, 1, true_size, f) != true_size) goto FAIL_READ; magic = REAL_PCRE_MAGIC(re); if (magic != MAGIC_NUMBER) { if (swap_uint32(magic) == MAGIC_NUMBER) { do_flip = 1; } else { fprintf(outfile, "Data in %s is not a compiled PCRE regex\n", p); new_free(re); fclose(f); continue; } } /* We hide the byte-invert info for little and big endian tests. */ fprintf(outfile, "Compiled pattern%s loaded from %s\n", do_flip && (p[-1] == '<') ? " (byte-inverted)" : "", p); /* Now see if there is any following study data. */ if (true_study_size != 0) { pcre_study_data *psd; extra = (pcre_extra *)new_malloc(sizeof(pcre_extra) + true_study_size); extra->flags = PCRE_EXTRA_STUDY_DATA; psd = (pcre_study_data *)(((char *)extra) + sizeof(pcre_extra)); extra->study_data = psd; if (fread(psd, 1, true_study_size, f) != true_study_size) { FAIL_READ: fprintf(outfile, "Failed to read data from %s\n", p); if (extra != NULL) { PCRE_FREE_STUDY(extra); } new_free(re); fclose(f); continue; } fprintf(outfile, "Study data loaded from %s\n", p); do_study = 1; /* To get the data output if requested */ } else fprintf(outfile, "No study data\n"); /* Flip the necessary bytes. */ if (do_flip) { int rc; PCRE_PATTERN_TO_HOST_BYTE_ORDER(rc, re, extra, NULL); if (rc == PCRE_ERROR_BADMODE) { pcre_uint32 flags_in_host_byte_order; if (REAL_PCRE_MAGIC(re) == MAGIC_NUMBER) flags_in_host_byte_order = REAL_PCRE_FLAGS(re); else flags_in_host_byte_order = swap_uint32(REAL_PCRE_FLAGS(re)); /* Simulate the result of the function call below. */ fprintf(outfile, "Error %d from pcre%s_fullinfo(%d)\n", rc, pcre_mode == PCRE32_MODE ? "32" : pcre_mode == PCRE16_MODE ? "16" : "", PCRE_INFO_OPTIONS); fprintf(outfile, "Running in %d-bit mode but pattern was compiled in " "%d-bit mode\n", 8 * CHAR_SIZE, 8 * (flags_in_host_byte_order & PCRE_MODE_MASK)); new_free(re); fclose(f); continue; } } /* Need to know if UTF-8 for printing data strings. */ if (new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options) < 0) { new_free(re); fclose(f); continue; } use_utf = (get_options & PCRE_UTF8) != 0; fclose(f); goto SHOW_INFO; } /* In-line pattern (the usual case). Get the delimiter and seek the end of the pattern; if it isn't complete, read more. */ delimiter = *p++; if (isalnum(delimiter) || delimiter == '\\') { fprintf(outfile, "** Delimiter must not be alphanumeric or \\\n"); goto SKIP_DATA; } pp = p; poffset = (int)(p - buffer); for(;;) { while (*pp != 0) { if (*pp == '\\' && pp[1] != 0) pp++; else if (*pp == delimiter) break; pp++; } if (*pp != 0) break; if ((pp = extend_inputline(infile, pp, " > ")) == NULL) { fprintf(outfile, "** Unexpected EOF\n"); done = 1; goto CONTINUE; } if (infile != stdin) fprintf(outfile, "%s", (char *)pp); } /* The buffer may have moved while being extended; reset the start of data pointer to the correct relative point in the buffer. */ p = buffer + poffset; /* If the first character after the delimiter is backslash, make the pattern end with backslash. This is purely to provide a way of testing for the error message when a pattern ends with backslash. */ if (pp[1] == '\\') *pp++ = '\\'; /* Terminate the pattern at the delimiter, and save a copy of the pattern for callouts. */ *pp++ = 0; strcpy((char *)pbuffer, (char *)p); /* Look for modifiers and options after the final delimiter. */ options = default_options; study_options = force_study_options; log_store = showstore; /* default from command line */ while (*pp != 0) { /* Check to see whether this modifier has been locked out for this file. This is complicated for the multi-character options that begin with '<'. If there is no '>' in the lockout string, all multi-character modifiers are locked out. */ if (strchr((char *)lockout, *pp) != NULL) { if (*pp == '<' && strchr((char *)lockout, '>') != NULL) { int x = check_mc_option(pp+1, outfile, FALSE, "modifier"); if (x == 0) goto SKIP_DATA; for (ppp = lockout; *ppp != 0; ppp++) { if (*ppp == '<') { int y = check_mc_option(ppp+1, outfile, FALSE, "modifier"); if (y == 0) { printf("** Error in modifier forbid data - giving up.\n"); yield = 1; goto EXIT; } if (x == y) { ppp = pp; while (*ppp != '>') ppp++; printf("** The %.*s modifier is locked out - giving up.\n", (int)(ppp - pp + 1), pp); yield = 1; goto EXIT; } } } } /* The single-character modifiers are straightforward. */ else { printf("** The /%c modifier is locked out - giving up.\n", *pp); yield = 1; goto EXIT; } } /* The modifier is not locked out; handle it. */ switch (*pp++) { case 'f': options |= PCRE_FIRSTLINE; break; case 'g': do_g = 1; break; case 'i': options |= PCRE_CASELESS; break; case 'm': options |= PCRE_MULTILINE; break; case 's': options |= PCRE_DOTALL; break; case 'x': options |= PCRE_EXTENDED; break; case '+': if (do_showrest) do_showcaprest = 1; else do_showrest = 1; break; case '=': do_allcaps = 1; break; case 'A': options |= PCRE_ANCHORED; break; case 'B': do_debug = 1; break; case 'C': options |= PCRE_AUTO_CALLOUT; break; case 'D': do_debug = do_showinfo = 1; break; case 'E': options |= PCRE_DOLLAR_ENDONLY; break; case 'F': do_flip = 1; break; case 'G': do_G = 1; break; case 'I': do_showinfo = 1; break; case 'J': options |= PCRE_DUPNAMES; break; case 'K': do_mark = 1; break; case 'M': log_store = 1; break; case 'N': options |= PCRE_NO_AUTO_CAPTURE; break; case 'O': options |= PCRE_NO_AUTO_POSSESS; break; #if !defined NOPOSIX case 'P': do_posix = 1; break; #endif case 'Q': switch (*pp) { case '0': case '1': stack_guard_return = *pp++ - '0'; break; default: fprintf(outfile, "** Missing 0 or 1 after /Q\n"); goto SKIP_DATA; } SET_PCRE_STACK_GUARD(stack_guard); break; case 'S': do_study = 1; for (;;) { switch (*pp++) { case 'S': do_study = 0; no_force_study = 1; break; case '!': study_options |= PCRE_STUDY_EXTRA_NEEDED; break; case '+': if (*pp == '+') { verify_jit = TRUE; pp++; } if (*pp >= '1' && *pp <= '7') study_options |= jit_study_bits[*pp++ - '1']; else study_options |= jit_study_bits[6]; break; case '-': study_options &= ~PCRE_STUDY_ALLJIT; break; default: pp--; goto ENDLOOP; } } ENDLOOP: break; case 'U': options |= PCRE_UNGREEDY; break; case 'W': options |= PCRE_UCP; break; case 'X': options |= PCRE_EXTRA; break; case 'Y': options |= PCRE_NO_START_OPTIMISE; break; case 'Z': debug_lengths = 0; break; case '8': options |= PCRE_UTF8; use_utf = 1; break; case '9': options |= PCRE_NEVER_UTF; break; case '?': options |= PCRE_NO_UTF8_CHECK; break; case 'T': switch (*pp++) { case '0': tables = tables0; break; case '1': tables = tables1; break; case '\r': case '\n': case ' ': case 0: fprintf(outfile, "** Missing table number after /T\n"); goto SKIP_DATA; default: fprintf(outfile, "** Bad table number \"%c\" after /T\n", pp[-1]); goto SKIP_DATA; } break; case 'L': ppp = pp; /* The '\r' test here is so that it works on Windows. */ /* The '0' test is just in case this is an unterminated line. */ while (*ppp != 0 && *ppp != '\n' && *ppp != '\r' && *ppp != ' ') ppp++; *ppp = 0; if (setlocale(LC_CTYPE, (const char *)pp) == NULL) { fprintf(outfile, "** Failed to set locale \"%s\"\n", pp); goto SKIP_DATA; } locale_set = 1; tables = PCRE_MAKETABLES; pp = ppp; break; case '>': to_file = pp; while (*pp != 0) pp++; while (isspace(pp[-1])) pp--; *pp = 0; break; case '<': { int x = check_mc_option(pp, outfile, FALSE, "modifier"); if (x == 0) goto SKIP_DATA; options |= x; while (*pp++ != '>'); } break; case '\r': /* So that it works in Windows */ case '\n': case ' ': break; default: fprintf(outfile, "** Unknown modifier '%c'\n", pp[-1]); goto SKIP_DATA; } } /* Handle compiling via the POSIX interface, which doesn't support the timing, showing, or debugging options, nor the ability to pass over local character tables. Neither does it have 16-bit support. */ #if !defined NOPOSIX if (posix || do_posix) { int rc; int cflags = 0; if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE; if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE; if ((options & PCRE_DOTALL) != 0) cflags |= REG_DOTALL; if ((options & PCRE_NO_AUTO_CAPTURE) != 0) cflags |= REG_NOSUB; if ((options & PCRE_UTF8) != 0) cflags |= REG_UTF8; if ((options & PCRE_UCP) != 0) cflags |= REG_UCP; if ((options & PCRE_UNGREEDY) != 0) cflags |= REG_UNGREEDY; rc = regcomp(&preg, (char *)p, cflags); /* Compilation failed; go back for another re, skipping to blank line if non-interactive. */ if (rc != 0) { (void)regerror(rc, &preg, (char *)buffer, buffer_size); fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer); goto SKIP_DATA; } } /* Handle compiling via the native interface */ else #endif /* !defined NOPOSIX */ { /* In 16- or 32-bit mode, convert the input. */ #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) { switch(to16(FALSE, p, options & PCRE_UTF8, (int)strlen((char *)p))) { case -1: fprintf(outfile, "**Failed: invalid UTF-8 string cannot be " "converted to UTF-16\n"); goto SKIP_DATA; case -2: fprintf(outfile, "**Failed: character value greater than 0x10ffff " "cannot be converted to UTF-16\n"); goto SKIP_DATA; case -3: /* "Impossible error" when to16 is called arg1 FALSE */ fprintf(outfile, "**Failed: character value greater than 0xffff " "cannot be converted to 16-bit in non-UTF mode\n"); goto SKIP_DATA; default: break; } p = (pcre_uint8 *)buffer16; } #endif #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) { switch(to32(FALSE, p, options & PCRE_UTF32, (int)strlen((char *)p))) { case -1: fprintf(outfile, "**Failed: invalid UTF-8 string cannot be " "converted to UTF-32\n"); goto SKIP_DATA; case -2: fprintf(outfile, "**Failed: character value greater than 0x10ffff " "cannot be converted to UTF-32\n"); goto SKIP_DATA; case -3: fprintf(outfile, "**Failed: character value is ill-formed UTF-32\n"); goto SKIP_DATA; default: break; } p = (pcre_uint8 *)buffer32; } #endif /* Compile many times when timing */ if (timeit > 0) { register int i; clock_t time_taken; clock_t start_time = clock(); for (i = 0; i < timeit; i++) { PCRE_COMPILE(re, p, options, &error, &erroroffset, tables); if (re != NULL) free(re); } total_compile_time += (time_taken = clock() - start_time); fprintf(outfile, "Compile time %.4f milliseconds\n", (((double)time_taken * 1000.0) / (double)timeit) / (double)CLOCKS_PER_SEC); } PCRE_COMPILE(re, p, options, &error, &erroroffset, tables); /* Compilation failed; go back for another re, skipping to blank line if non-interactive. */ if (re == NULL) { fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset); SKIP_DATA: if (infile != stdin) { for (;;) { if (extend_inputline(infile, buffer, NULL) == NULL) { done = 1; goto CONTINUE; } len = (int)strlen((char *)buffer); while (len > 0 && isspace(buffer[len-1])) len--; if (len == 0) break; } fprintf(outfile, "\n"); } goto CONTINUE; } /* Compilation succeeded. It is now possible to set the UTF-8 option from within the regex; check for this so that we know how to process the data lines. */ if (new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options) < 0) goto SKIP_DATA; if ((get_options & PCRE_UTF8) != 0) use_utf = 1; /* Extract the size for possible writing before possibly flipping it, and remember the store that was got. */ true_size = REAL_PCRE_SIZE(re); /* Output code size information if requested */ if (log_store) { int name_count, name_entry_size, real_pcre_size; new_info(re, NULL, PCRE_INFO_NAMECOUNT, &name_count); new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size); real_pcre_size = 0; #ifdef SUPPORT_PCRE8 if (REAL_PCRE_FLAGS(re) & PCRE_MODE8) real_pcre_size = sizeof(real_pcre); #endif #ifdef SUPPORT_PCRE16 if (REAL_PCRE_FLAGS(re) & PCRE_MODE16) real_pcre_size = sizeof(real_pcre16); #endif #ifdef SUPPORT_PCRE32 if (REAL_PCRE_FLAGS(re) & PCRE_MODE32) real_pcre_size = sizeof(real_pcre32); #endif new_info(re, NULL, PCRE_INFO_SIZE, &size); fprintf(outfile, "Memory allocation (code space): %d\n", (int)(size - real_pcre_size - name_count * name_entry_size)); } /* If -s or /S was present, study the regex to generate additional info to help with the matching, unless the pattern has the SS option, which suppresses the effect of /S (used for a few test patterns where studying is never sensible). */ if (do_study || (force_study >= 0 && !no_force_study)) { if (timeit > 0) { register int i; clock_t time_taken; clock_t start_time = clock(); for (i = 0; i < timeit; i++) { PCRE_STUDY(extra, re, study_options, &error); } total_study_time = (time_taken = clock() - start_time); if (extra != NULL) { PCRE_FREE_STUDY(extra); } fprintf(outfile, " Study time %.4f milliseconds\n", (((double)time_taken * 1000.0) / (double)timeit) / (double)CLOCKS_PER_SEC); } PCRE_STUDY(extra, re, study_options, &error); if (error != NULL) fprintf(outfile, "Failed to study: %s\n", error); else if (extra != NULL) { true_study_size = ((pcre_study_data *)(extra->study_data))->size; if (log_store) { size_t jitsize; if (new_info(re, extra, PCRE_INFO_JITSIZE, &jitsize) == 0 && jitsize != 0) fprintf(outfile, "Memory allocation (JIT code): %d\n", (int)jitsize); } } } /* If /K was present, we set up for handling MARK data. */ if (do_mark) { if (extra == NULL) { extra = (pcre_extra *)malloc(sizeof(pcre_extra)); extra->flags = 0; } extra->mark = &markptr; extra->flags |= PCRE_EXTRA_MARK; } /* Extract and display information from the compiled data if required. */ SHOW_INFO: if (do_debug) { fprintf(outfile, "------------------------------------------------------------------\n"); PCRE_PRINTINT(re, outfile, debug_lengths); } /* We already have the options in get_options (see above) */ if (do_showinfo) { unsigned long int all_options; pcre_uint32 first_char, need_char; pcre_uint32 match_limit, recursion_limit; int count, backrefmax, first_char_set, need_char_set, okpartial, jchanged, hascrorlf, maxlookbehind, match_empty; int nameentrysize, namecount; const pcre_uint8 *nametable; if (new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count) + new_info(re, NULL, PCRE_INFO_BACKREFMAX, &backrefmax) + new_info(re, NULL, PCRE_INFO_FIRSTCHARACTER, &first_char) + new_info(re, NULL, PCRE_INFO_FIRSTCHARACTERFLAGS, &first_char_set) + new_info(re, NULL, PCRE_INFO_REQUIREDCHAR, &need_char) + new_info(re, NULL, PCRE_INFO_REQUIREDCHARFLAGS, &need_char_set) + new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize) + new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount) + new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable) + new_info(re, NULL, PCRE_INFO_OKPARTIAL, &okpartial) + new_info(re, NULL, PCRE_INFO_JCHANGED, &jchanged) + new_info(re, NULL, PCRE_INFO_HASCRORLF, &hascrorlf) + new_info(re, NULL, PCRE_INFO_MATCH_EMPTY, &match_empty) + new_info(re, NULL, PCRE_INFO_MAXLOOKBEHIND, &maxlookbehind) != 0) goto SKIP_DATA; fprintf(outfile, "Capturing subpattern count = %d\n", count); if (backrefmax > 0) fprintf(outfile, "Max back reference = %d\n", backrefmax); if (maxlookbehind > 0) fprintf(outfile, "Max lookbehind = %d\n", maxlookbehind); if (new_info(re, NULL, PCRE_INFO_MATCHLIMIT, &match_limit) == 0) fprintf(outfile, "Match limit = %u\n", match_limit); if (new_info(re, NULL, PCRE_INFO_RECURSIONLIMIT, &recursion_limit) == 0) fprintf(outfile, "Recursion limit = %u\n", recursion_limit); if (namecount > 0) { fprintf(outfile, "Named capturing subpatterns:\n"); while (namecount-- > 0) { int imm2_size = pcre_mode == PCRE8_MODE ? 2 : 1; int length = (int)STRLEN(nametable + imm2_size); fprintf(outfile, " "); PCHARSV(nametable, imm2_size, length, outfile); while (length++ < nameentrysize - imm2_size) putc(' ', outfile); #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) fprintf(outfile, "%3d\n", (int)(((PCRE_SPTR32)nametable)[0])); #endif #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) fprintf(outfile, "%3d\n", (int)(((PCRE_SPTR16)nametable)[0])); #endif #ifdef SUPPORT_PCRE8 if (pcre_mode == PCRE8_MODE) fprintf(outfile, "%3d\n", ((int)nametable[0] << 8) | (int)nametable[1]); #endif nametable += nameentrysize * CHAR_SIZE; } } if (!okpartial) fprintf(outfile, "Partial matching not supported\n"); if (hascrorlf) fprintf(outfile, "Contains explicit CR or LF match\n"); if (match_empty) fprintf(outfile, "May match empty string\n"); all_options = REAL_PCRE_OPTIONS(re); if (do_flip) all_options = swap_uint32(all_options); if (get_options == 0) fprintf(outfile, "No options\n"); else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "", ((get_options & PCRE_CASELESS) != 0)? " caseless" : "", ((get_options & PCRE_EXTENDED) != 0)? " extended" : "", ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "", ((get_options & PCRE_FIRSTLINE) != 0)? " firstline" : "", ((get_options & PCRE_DOTALL) != 0)? " dotall" : "", ((get_options & PCRE_BSR_ANYCRLF) != 0)? " bsr_anycrlf" : "", ((get_options & PCRE_BSR_UNICODE) != 0)? " bsr_unicode" : "", ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "", ((get_options & PCRE_EXTRA) != 0)? " extra" : "", ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "", ((get_options & PCRE_NO_AUTO_CAPTURE) != 0)? " no_auto_capture" : "", ((get_options & PCRE_NO_AUTO_POSSESS) != 0)? " no_auto_possessify" : "", ((get_options & PCRE_UTF8) != 0)? " utf" : "", ((get_options & PCRE_UCP) != 0)? " ucp" : "", ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf_check" : "", ((get_options & PCRE_NO_START_OPTIMIZE) != 0)? " no_start_optimize" : "", ((get_options & PCRE_DUPNAMES) != 0)? " dupnames" : "", ((get_options & PCRE_NEVER_UTF) != 0)? " never_utf" : ""); if (jchanged) fprintf(outfile, "Duplicate name status changes\n"); switch (get_options & PCRE_NEWLINE_BITS) { case PCRE_NEWLINE_CR: fprintf(outfile, "Forced newline sequence: CR\n"); break; case PCRE_NEWLINE_LF: fprintf(outfile, "Forced newline sequence: LF\n"); break; case PCRE_NEWLINE_CRLF: fprintf(outfile, "Forced newline sequence: CRLF\n"); break; case PCRE_NEWLINE_ANYCRLF: fprintf(outfile, "Forced newline sequence: ANYCRLF\n"); break; case PCRE_NEWLINE_ANY: fprintf(outfile, "Forced newline sequence: ANY\n"); break; default: break; } if (first_char_set == 2) { fprintf(outfile, "First char at start or follows newline\n"); } else if (first_char_set == 1) { const char *caseless = ((REAL_PCRE_FLAGS(re) & PCRE_FCH_CASELESS) == 0)? "" : " (caseless)"; if (PRINTOK(first_char)) fprintf(outfile, "First char = \'%c\'%s\n", first_char, caseless); else { fprintf(outfile, "First char = "); pchar(first_char, outfile); fprintf(outfile, "%s\n", caseless); } } else { fprintf(outfile, "No first char\n"); } if (need_char_set == 0) { fprintf(outfile, "No need char\n"); } else { const char *caseless = ((REAL_PCRE_FLAGS(re) & PCRE_RCH_CASELESS) == 0)? "" : " (caseless)"; if (PRINTOK(need_char)) fprintf(outfile, "Need char = \'%c\'%s\n", need_char, caseless); else { fprintf(outfile, "Need char = "); pchar(need_char, outfile); fprintf(outfile, "%s\n", caseless); } } /* Don't output study size; at present it is in any case a fixed value, but it varies, depending on the computer architecture, and so messes up the test suite. (And with the /F option, it might be flipped.) If study was forced by an external -s, don't show this information unless -i or -d was also present. This means that, except when auto-callouts are involved, the output from runs with and without -s should be identical. */ if (do_study || (force_study >= 0 && showinfo && !no_force_study)) { if (extra == NULL) fprintf(outfile, "Study returned NULL\n"); else { pcre_uint8 *start_bits = NULL; int minlength; if (new_info(re, extra, PCRE_INFO_MINLENGTH, &minlength) == 0) fprintf(outfile, "Subject length lower bound = %d\n", minlength); if (new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits) == 0) { if (start_bits == NULL) fprintf(outfile, "No starting char list\n"); else { int i; int c = 24; fprintf(outfile, "Starting chars: "); for (i = 0; i < 256; i++) { if ((start_bits[i/8] & (1<<(i&7))) != 0) { if (c > 75) { fprintf(outfile, "\n "); c = 2; } if (PRINTOK(i) && i != ' ') { fprintf(outfile, "%c ", i); c += 2; } else { fprintf(outfile, "\\x%02x ", i); c += 5; } } } fprintf(outfile, "\n"); } } } /* Show this only if the JIT was set by /S, not by -s. */ if ((study_options & PCRE_STUDY_ALLJIT) != 0 && (force_study_options & PCRE_STUDY_ALLJIT) == 0) { int jit; if (new_info(re, extra, PCRE_INFO_JIT, &jit) == 0) { if (jit) fprintf(outfile, "JIT study was successful\n"); else #ifdef SUPPORT_JIT fprintf(outfile, "JIT study was not successful\n"); #else fprintf(outfile, "JIT support is not available in this version of PCRE\n"); #endif } } } } /* If the '>' option was present, we write out the regex to a file, and that is all. The first 8 bytes of the file are the regex length and then the study length, in big-endian order. */ if (to_file != NULL) { FILE *f = fopen((char *)to_file, "wb"); if (f == NULL) { fprintf(outfile, "Unable to open %s: %s\n", to_file, strerror(errno)); } else { pcre_uint8 sbuf[8]; if (do_flip) regexflip(re, extra); sbuf[0] = (pcre_uint8)((true_size >> 24) & 255); sbuf[1] = (pcre_uint8)((true_size >> 16) & 255); sbuf[2] = (pcre_uint8)((true_size >> 8) & 255); sbuf[3] = (pcre_uint8)((true_size) & 255); sbuf[4] = (pcre_uint8)((true_study_size >> 24) & 255); sbuf[5] = (pcre_uint8)((true_study_size >> 16) & 255); sbuf[6] = (pcre_uint8)((true_study_size >> 8) & 255); sbuf[7] = (pcre_uint8)((true_study_size) & 255); if (fwrite(sbuf, 1, 8, f) < 8 || fwrite(re, 1, true_size, f) < true_size) { fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno)); } else { fprintf(outfile, "Compiled pattern written to %s\n", to_file); /* If there is study data, write it. */ if (extra != NULL) { if (fwrite(extra->study_data, 1, true_study_size, f) < true_study_size) { fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno)); } else fprintf(outfile, "Study data written to %s\n", to_file); } } fclose(f); } new_free(re); if (extra != NULL) { PCRE_FREE_STUDY(extra); } if (locale_set) { new_free((void *)tables); setlocale(LC_CTYPE, "C"); locale_set = 0; } continue; /* With next regex */ } } /* End of non-POSIX compile */ /* Read data lines and test them */ for (;;) { #ifdef SUPPORT_PCRE8 pcre_uint8 *q8; #endif #ifdef SUPPORT_PCRE16 pcre_uint16 *q16; #endif #ifdef SUPPORT_PCRE32 pcre_uint32 *q32; #endif pcre_uint8 *bptr; int *use_offsets = offsets; int use_size_offsets = size_offsets; int callout_data = 0; int callout_data_set = 0; int count; pcre_uint32 c; int copystrings = 0; int find_match_limit = default_find_match_limit; int getstrings = 0; int getlist = 0; int gmatched = 0; int start_offset = 0; int start_offset_sign = 1; int g_notempty = 0; int use_dfa = 0; *copynames = 0; *getnames = 0; #ifdef SUPPORT_PCRE32 cn32ptr = copynames; gn32ptr = getnames; #endif #ifdef SUPPORT_PCRE16 cn16ptr = copynames16; gn16ptr = getnames16; #endif #ifdef SUPPORT_PCRE8 cn8ptr = copynames8; gn8ptr = getnames8; #endif SET_PCRE_CALLOUT(callout); first_callout = 1; last_callout_mark = NULL; callout_extra = 0; callout_count = 0; callout_fail_count = 999999; callout_fail_id = -1; show_malloc = 0; options = 0; if (extra != NULL) extra->flags &= ~(PCRE_EXTRA_MATCH_LIMIT|PCRE_EXTRA_MATCH_LIMIT_RECURSION); len = 0; for (;;) { if (extend_inputline(infile, buffer + len, "data> ") == NULL) { if (len > 0) /* Reached EOF without hitting a newline */ { fprintf(outfile, "\n"); break; } done = 1; goto CONTINUE; } if (infile != stdin) fprintf(outfile, "%s", (char *)buffer); len = (int)strlen((char *)buffer); if (buffer[len-1] == '\n') break; } while (len > 0 && isspace(buffer[len-1])) len--; buffer[len] = 0; if (len == 0) break; p = buffer; while (isspace(*p)) p++; #ifndef NOUTF /* Check that the data is well-formed UTF-8 if we're in UTF mode. To create invalid input to pcre_exec, you must use \x?? or \x{} sequences. */ if (use_utf) { pcre_uint8 *q; pcre_uint32 cc; int n = 1; for (q = p; n > 0 && *q; q += n) n = utf82ord(q, &cc); if (n <= 0) { fprintf(outfile, "**Failed: invalid UTF-8 string cannot be used as input in UTF mode\n"); goto NEXT_DATA; } } #endif #ifdef SUPPORT_VALGRIND /* Mark the dbuffer as addressable but undefined again. */ if (dbuffer != NULL) { VALGRIND_MAKE_MEM_UNDEFINED(dbuffer, dbuffer_size * CHAR_SIZE); } #endif /* Allocate a buffer to hold the data line; len+1 is an upper bound on the number of pcre_uchar units that will be needed. */ while (dbuffer == NULL || (size_t)len >= dbuffer_size) { dbuffer_size *= 2; dbuffer = (pcre_uint8 *)realloc(dbuffer, dbuffer_size * CHAR_SIZE); if (dbuffer == NULL) { fprintf(stderr, "pcretest: realloc(%d) failed\n", (int)dbuffer_size); exit(1); } } #ifdef SUPPORT_PCRE8 q8 = (pcre_uint8 *) dbuffer; #endif #ifdef SUPPORT_PCRE16 q16 = (pcre_uint16 *) dbuffer; #endif #ifdef SUPPORT_PCRE32 q32 = (pcre_uint32 *) dbuffer; #endif while ((c = *p++) != 0) { int i = 0; int n = 0; /* In UTF mode, input can be UTF-8, so just copy all non-backslash bytes. In non-UTF mode, allow the value of the byte to fall through to later, where values greater than 127 are turned into UTF-8 when running in 16-bit or 32-bit mode. */ if (c != '\\') { #ifndef NOUTF if (use_utf && HASUTF8EXTRALEN(c)) { GETUTF8INC(c, p); } #endif } /* Handle backslash escapes */ else switch ((c = *p++)) { case 'a': c = CHAR_BEL; break; case 'b': c = '\b'; break; case 'e': c = CHAR_ESC; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c -= '0'; while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9') c = c * 8 + *p++ - '0'; break; case 'o': if (*p == '{') { pcre_uint8 *pt = p; c = 0; for (pt++; isdigit(*pt) && *pt != '8' && *pt != '9'; pt++) { if (++i == 12) fprintf(outfile, "** Too many octal digits in \\o{...} item; " "using only the first twelve.\n"); else c = c * 8 + *pt - '0'; } if (*pt == '}') p = pt + 1; else fprintf(outfile, "** Missing } after \\o{ (assumed)\n"); } break; case 'x': if (*p == '{') { pcre_uint8 *pt = p; c = 0; /* We used to have "while (isxdigit(*(++pt)))" here, but it fails when isxdigit() is a macro that refers to its argument more than once. This is banned by the C Standard, but apparently happens in at least one MacOS environment. */ for (pt++; isxdigit(*pt); pt++) { if (++i == 9) fprintf(outfile, "** Too many hex digits in \\x{...} item; " "using only the first eight.\n"); else c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'a' - 10); } if (*pt == '}') { p = pt + 1; break; } /* Not correct form for \x{...}; fall through */ } /* \x without {} always defines just one byte in 8-bit mode. This allows UTF-8 characters to be constructed byte by byte, and also allows invalid UTF-8 sequences to be made. Just copy the byte in UTF mode. Otherwise, pass it down to later code so that it can be turned into UTF-8 when running in 16/32-bit mode. */ c = 0; while (i++ < 2 && isxdigit(*p)) { c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'a' - 10); p++; } #if !defined NOUTF && defined SUPPORT_PCRE8 if (use_utf && (pcre_mode == PCRE8_MODE)) { *q8++ = c; continue; } #endif break; case 0: /* \ followed by EOF allows for an empty line */ p--; continue; case '>': if (*p == '-') { start_offset_sign = -1; p++; } while(isdigit(*p)) start_offset = start_offset * 10 + *p++ - '0'; start_offset *= start_offset_sign; continue; case 'A': /* Option setting */ options |= PCRE_ANCHORED; continue; case 'B': options |= PCRE_NOTBOL; continue; case 'C': if (isdigit(*p)) /* Set copy string */ { while(isdigit(*p)) n = n * 10 + *p++ - '0'; copystrings |= 1 << n; } else if (isalnum(*p)) { READ_CAPTURE_NAME(p, &cn8ptr, &cn16ptr, &cn32ptr, re); } else if (*p == '+') { callout_extra = 1; p++; } else if (*p == '-') { SET_PCRE_CALLOUT(NULL); p++; } else if (*p == '!') { callout_fail_id = 0; p++; while(isdigit(*p)) callout_fail_id = callout_fail_id * 10 + *p++ - '0'; callout_fail_count = 0; if (*p == '!') { p++; while(isdigit(*p)) callout_fail_count = callout_fail_count * 10 + *p++ - '0'; } } else if (*p == '*') { int sign = 1; callout_data = 0; if (*(++p) == '-') { sign = -1; p++; } while(isdigit(*p)) callout_data = callout_data * 10 + *p++ - '0'; callout_data *= sign; callout_data_set = 1; } continue; #if !defined NODFA case 'D': #if !defined NOPOSIX if (posix || do_posix) printf("** Can't use dfa matching in POSIX mode: \\D ignored\n"); else #endif use_dfa = 1; continue; #endif #if !defined NODFA case 'F': options |= PCRE_DFA_SHORTEST; continue; #endif case 'G': if (isdigit(*p)) { while(isdigit(*p)) n = n * 10 + *p++ - '0'; getstrings |= 1 << n; } else if (isalnum(*p)) { READ_CAPTURE_NAME(p, &gn8ptr, &gn16ptr, &gn32ptr, re); } continue; case 'J': while(isdigit(*p)) n = n * 10 + *p++ - '0'; if (extra != NULL && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL) { if (jit_stack != NULL) { PCRE_JIT_STACK_FREE(jit_stack); } jit_stack = PCRE_JIT_STACK_ALLOC(1, n * 1024); PCRE_ASSIGN_JIT_STACK(extra, jit_callback, jit_stack); } continue; case 'L': getlist = 1; continue; case 'M': find_match_limit = 1; continue; case 'N': if ((options & PCRE_NOTEMPTY) != 0) options = (options & ~PCRE_NOTEMPTY) | PCRE_NOTEMPTY_ATSTART; else options |= PCRE_NOTEMPTY; continue; case 'O': while(isdigit(*p)) { if (n > (INT_MAX-10)/10) /* Hack to stop fuzzers */ { printf("** \\O argument is too big\n"); yield = 1; goto EXIT; } n = n * 10 + *p++ - '0'; } if (n > size_offsets_max) { size_offsets_max = n; free(offsets); use_offsets = offsets = (int *)malloc(size_offsets_max * sizeof(int)); if (offsets == NULL) { printf("** Failed to get %d bytes of memory for offsets vector\n", (int)(size_offsets_max * sizeof(int))); yield = 1; goto EXIT; } } use_size_offsets = n; if (n == 0) use_offsets = NULL; /* Ensures it can't write to it */ else use_offsets = offsets + size_offsets_max - n; /* To catch overruns */ continue; case 'P': options |= ((options & PCRE_PARTIAL_SOFT) == 0)? PCRE_PARTIAL_SOFT : PCRE_PARTIAL_HARD; continue; case 'Q': while(isdigit(*p)) n = n * 10 + *p++ - '0'; if (extra == NULL) { extra = (pcre_extra *)malloc(sizeof(pcre_extra)); extra->flags = 0; } extra->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION; extra->match_limit_recursion = n; continue; case 'q': while(isdigit(*p)) n = n * 10 + *p++ - '0'; if (extra == NULL) { extra = (pcre_extra *)malloc(sizeof(pcre_extra)); extra->flags = 0; } extra->flags |= PCRE_EXTRA_MATCH_LIMIT; extra->match_limit = n; continue; #if !defined NODFA case 'R': options |= PCRE_DFA_RESTART; continue; #endif case 'S': show_malloc = 1; continue; case 'Y': options |= PCRE_NO_START_OPTIMIZE; continue; case 'Z': options |= PCRE_NOTEOL; continue; case '?': options |= PCRE_NO_UTF8_CHECK; continue; case '<': { int x = check_mc_option(p, outfile, TRUE, "escape sequence"); if (x == 0) goto NEXT_DATA; options |= x; while (*p++ != '>'); } continue; } /* We now have a character value in c that may be greater than 255. In 8-bit mode we convert to UTF-8 if we are in UTF mode. Values greater than 127 in UTF mode must have come from \x{...} or octal constructs because values from \x.. get this far only in non-UTF mode. */ #ifdef SUPPORT_PCRE8 if (pcre_mode == PCRE8_MODE) { #ifndef NOUTF if (use_utf) { if (c > 0x7fffffff) { fprintf(outfile, "** Character \\x{%x} is greater than 0x7fffffff " "and so cannot be converted to UTF-8\n", c); goto NEXT_DATA; } q8 += ord2utf8(c, q8); } else #endif { if (c > 0xffu) { fprintf(outfile, "** Character \\x{%x} is greater than 255 " "and UTF-8 mode is not enabled.\n", c); fprintf(outfile, "** Truncation will probably give the wrong " "result.\n"); } *q8++ = c; } } #endif #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) { #ifndef NOUTF if (use_utf) { if (c > 0x10ffffu) { fprintf(outfile, "** Failed: character \\x{%x} is greater than " "0x10ffff and so cannot be converted to UTF-16\n", c); goto NEXT_DATA; } else if (c >= 0x10000u) { c-= 0x10000u; *q16++ = 0xD800 | (c >> 10); *q16++ = 0xDC00 | (c & 0x3ff); } else *q16++ = c; } else #endif { if (c > 0xffffu) { fprintf(outfile, "** Character \\x{%x} is greater than 0xffff " "and UTF-16 mode is not enabled.\n", c); fprintf(outfile, "** Truncation will probably give the wrong " "result.\n"); } *q16++ = c; } } #endif #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) { *q32++ = c; } #endif } /* Reached end of subject string */ #ifdef SUPPORT_PCRE8 if (pcre_mode == PCRE8_MODE) { *q8 = 0; len = (int)(q8 - (pcre_uint8 *)dbuffer); } #endif #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) { *q16 = 0; len = (int)(q16 - (pcre_uint16 *)dbuffer); } #endif #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) { *q32 = 0; len = (int)(q32 - (pcre_uint32 *)dbuffer); } #endif /* If we're compiling with explicit valgrind support, Mark the data from after its end to the end of the buffer as unaddressable, so that a read over the end of the buffer will be seen by valgrind, even if it doesn't cause a crash. If we're not building with valgrind support, at least move the data to the end of the buffer so that it might at least cause a crash. If we are using the POSIX interface, we must include the terminating zero. */ bptr = dbuffer; #if !defined NOPOSIX if (posix || do_posix) { #ifdef SUPPORT_VALGRIND VALGRIND_MAKE_MEM_NOACCESS(dbuffer + len + 1, dbuffer_size - (len + 1)); #else memmove(bptr + dbuffer_size - len - 1, bptr, len + 1); bptr += dbuffer_size - len - 1; #endif } else #endif { #ifdef SUPPORT_VALGRIND VALGRIND_MAKE_MEM_NOACCESS(dbuffer + len * CHAR_SIZE, (dbuffer_size - len) * CHAR_SIZE); #else bptr = memmove(bptr + (dbuffer_size - len) * CHAR_SIZE, bptr, len * CHAR_SIZE); #endif } if ((all_use_dfa || use_dfa) && find_match_limit) { printf("** Match limit not relevant for DFA matching: ignored\n"); find_match_limit = 0; } /* Handle matching via the POSIX interface, which does not support timing or playing with the match limit or callout data. */ #if !defined NOPOSIX if (posix || do_posix) { int rc; int eflags = 0; regmatch_t *pmatch = NULL; if (use_size_offsets > 0) pmatch = (regmatch_t *)malloc(sizeof(regmatch_t) * use_size_offsets); if ((options & PCRE_NOTBOL) != 0) eflags |= REG_NOTBOL; if ((options & PCRE_NOTEOL) != 0) eflags |= REG_NOTEOL; if ((options & PCRE_NOTEMPTY) != 0) eflags |= REG_NOTEMPTY; rc = regexec(&preg, (const char *)bptr, use_size_offsets, pmatch, eflags); if (rc != 0) { (void)regerror(rc, &preg, (char *)buffer, buffer_size); fprintf(outfile, "No match: POSIX code %d: %s\n", rc, buffer); } else if ((REAL_PCRE_OPTIONS(preg.re_pcre) & PCRE_NO_AUTO_CAPTURE) != 0) { fprintf(outfile, "Matched with REG_NOSUB\n"); } else { size_t i; for (i = 0; i < (size_t)use_size_offsets; i++) { if (pmatch[i].rm_so >= 0) { fprintf(outfile, "%2d: ", (int)i); PCHARSV(dbuffer, pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so, outfile); fprintf(outfile, "\n"); if (do_showcaprest || (i == 0 && do_showrest)) { fprintf(outfile, "%2d+ ", (int)i); PCHARSV(dbuffer, pmatch[i].rm_eo, len - pmatch[i].rm_eo, outfile); fprintf(outfile, "\n"); } } } } free(pmatch); goto NEXT_DATA; } #endif /* !defined NOPOSIX */ /* Handle matching via the native interface - repeats for /g and /G */ /* Ensure that there is a JIT callback if we want to verify that JIT was actually used. If jit_stack == NULL, no stack has yet been assigned. */ if (verify_jit && jit_stack == NULL && extra != NULL) { PCRE_ASSIGN_JIT_STACK(extra, jit_callback, jit_stack); } for (;; gmatched++) /* Loop for /g or /G */ { markptr = NULL; jit_was_used = FALSE; if (timeitm > 0) { register int i; clock_t time_taken; clock_t start_time = clock(); #if !defined NODFA if (all_use_dfa || use_dfa) { if ((options & PCRE_DFA_RESTART) != 0) { fprintf(outfile, "Timing DFA restarts is not supported\n"); break; } if (dfa_workspace == NULL) dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int)); for (i = 0; i < timeitm; i++) { PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset, (options | g_notempty), use_offsets, use_size_offsets, dfa_workspace, DFA_WS_DIMENSION); } } else #endif for (i = 0; i < timeitm; i++) { PCRE_EXEC(count, re, extra, bptr, len, start_offset, (options | g_notempty), use_offsets, use_size_offsets); } total_match_time += (time_taken = clock() - start_time); fprintf(outfile, "Execute time %.4f milliseconds\n", (((double)time_taken * 1000.0) / (double)timeitm) / (double)CLOCKS_PER_SEC); } /* If find_match_limit is set, we want to do repeated matches with varying limits in order to find the minimum value for the match limit and for the recursion limit. The match limits are relevant only to the normal running of pcre_exec(), so disable the JIT optimization. This makes it possible to run the same set of tests with and without JIT externally requested. */ if (find_match_limit) { if (extra != NULL) { PCRE_FREE_STUDY(extra); } extra = (pcre_extra *)malloc(sizeof(pcre_extra)); extra->flags = 0; (void)check_match_limit(re, extra, bptr, len, start_offset, options|g_notempty, use_offsets, use_size_offsets, PCRE_EXTRA_MATCH_LIMIT, &(extra->match_limit), PCRE_ERROR_MATCHLIMIT, "match()"); count = check_match_limit(re, extra, bptr, len, start_offset, options|g_notempty, use_offsets, use_size_offsets, PCRE_EXTRA_MATCH_LIMIT_RECURSION, &(extra->match_limit_recursion), PCRE_ERROR_RECURSIONLIMIT, "match() recursion"); } /* If callout_data is set, use the interface with additional data */ else if (callout_data_set) { if (extra == NULL) { extra = (pcre_extra *)malloc(sizeof(pcre_extra)); extra->flags = 0; } extra->flags |= PCRE_EXTRA_CALLOUT_DATA; extra->callout_data = &callout_data; PCRE_EXEC(count, re, extra, bptr, len, start_offset, options | g_notempty, use_offsets, use_size_offsets); extra->flags &= ~PCRE_EXTRA_CALLOUT_DATA; } /* The normal case is just to do the match once, with the default value of match_limit. */ #if !defined NODFA else if (all_use_dfa || use_dfa) { if (dfa_workspace == NULL) dfa_workspace = (int *)malloc(DFA_WS_DIMENSION*sizeof(int)); if (dfa_matched++ == 0) dfa_workspace[0] = -1; /* To catch bad restart */ PCRE_DFA_EXEC(count, re, extra, bptr, len, start_offset, (options | g_notempty), use_offsets, use_size_offsets, dfa_workspace, DFA_WS_DIMENSION); if (count == 0) { fprintf(outfile, "Matched, but offsets vector is too small to show all matches\n"); count = use_size_offsets/2; } } #endif else { PCRE_EXEC(count, re, extra, bptr, len, start_offset, options | g_notempty, use_offsets, use_size_offsets); if (count == 0) { fprintf(outfile, "Matched, but too many substrings\n"); /* 2 is a special case; match can be returned */ count = (use_size_offsets == 2)? 1 : use_size_offsets/3; } } /* Matched */ if (count >= 0) { int i, maxcount; void *cnptr, *gnptr; #if !defined NODFA if (all_use_dfa || use_dfa) maxcount = use_size_offsets/2; else #endif /* 2 is a special case; match can be returned */ maxcount = (use_size_offsets == 2)? 1 : use_size_offsets/3; /* This is a check against a lunatic return value. */ if (count > maxcount) { fprintf(outfile, "** PCRE error: returned count %d is too big for offset size %d\n", count, use_size_offsets); count = use_size_offsets/3; if (do_g || do_G) { fprintf(outfile, "** /%c loop abandoned\n", do_g? 'g' : 'G'); do_g = do_G = FALSE; /* Break g/G loop */ } } /* do_allcaps requests showing of all captures in the pattern, to check unset ones at the end. */ if (do_allcaps) { if (all_use_dfa || use_dfa) { fprintf(outfile, "** Show all captures ignored after DFA matching\n"); } else { if (new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count) < 0) goto SKIP_DATA; count++; /* Allow for full match */ if (count * 2 > use_size_offsets) count = use_size_offsets/2; } } /* Output the captured substrings. Note that, for the matched string, the use of \K in an assertion can make the start later than the end. */ for (i = 0; i < count * 2; i += 2) { if (use_offsets[i] < 0) { if (use_offsets[i] != -1) fprintf(outfile, "ERROR: bad negative value %d for offset %d\n", use_offsets[i], i); if (use_offsets[i+1] != -1) fprintf(outfile, "ERROR: bad negative value %d for offset %d\n", use_offsets[i+1], i+1); fprintf(outfile, "%2d: \n", i/2); } else { int start = use_offsets[i]; int end = use_offsets[i+1]; if (start > end) { start = use_offsets[i+1]; end = use_offsets[i]; fprintf(outfile, "Start of matched string is beyond its end - " "displaying from end to start.\n"); } fprintf(outfile, "%2d: ", i/2); PCHARSV(bptr, start, end - start, outfile); if (verify_jit && jit_was_used) fprintf(outfile, " (JIT)"); fprintf(outfile, "\n"); /* Note: don't use the start/end variables here because we want to show the text from what is reported as the end. */ if (do_showcaprest || (i == 0 && do_showrest)) { fprintf(outfile, "%2d+ ", i/2); PCHARSV(bptr, use_offsets[i+1], len - use_offsets[i+1], outfile); fprintf(outfile, "\n"); } } } if (markptr != NULL) { fprintf(outfile, "MK: "); PCHARSV(markptr, 0, -1, outfile); fprintf(outfile, "\n"); } for (i = 0; i < 32; i++) { if ((copystrings & (1 << i)) != 0) { int rc; char copybuffer[256]; PCRE_COPY_SUBSTRING(rc, bptr, use_offsets, count, i, copybuffer, sizeof(copybuffer)); if (rc < 0) fprintf(outfile, "copy substring %d failed %d\n", i, rc); else { fprintf(outfile, "%2dC ", i); PCHARSV(copybuffer, 0, rc, outfile); fprintf(outfile, " (%d)\n", rc); } } } cnptr = copynames; for (;;) { int rc; char copybuffer[256]; #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) { if (*(pcre_uint32 *)cnptr == 0) break; } #endif #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) { if (*(pcre_uint16 *)cnptr == 0) break; } #endif #ifdef SUPPORT_PCRE8 if (pcre_mode == PCRE8_MODE) { if (*(pcre_uint8 *)cnptr == 0) break; } #endif PCRE_COPY_NAMED_SUBSTRING(rc, re, bptr, use_offsets, count, cnptr, copybuffer, sizeof(copybuffer)); if (rc < 0) { fprintf(outfile, "copy substring "); PCHARSV(cnptr, 0, -1, outfile); fprintf(outfile, " failed %d\n", rc); } else { fprintf(outfile, " C "); PCHARSV(copybuffer, 0, rc, outfile); fprintf(outfile, " (%d) ", rc); PCHARSV(cnptr, 0, -1, outfile); putc('\n', outfile); } cnptr = (char *)cnptr + (STRLEN(cnptr) + 1) * CHAR_SIZE; } for (i = 0; i < 32; i++) { if ((getstrings & (1 << i)) != 0) { int rc; const char *substring; PCRE_GET_SUBSTRING(rc, bptr, use_offsets, count, i, &substring); if (rc < 0) fprintf(outfile, "get substring %d failed %d\n", i, rc); else { fprintf(outfile, "%2dG ", i); PCHARSV(substring, 0, rc, outfile); fprintf(outfile, " (%d)\n", rc); PCRE_FREE_SUBSTRING(substring); } } } gnptr = getnames; for (;;) { int rc; const char *substring; #ifdef SUPPORT_PCRE32 if (pcre_mode == PCRE32_MODE) { if (*(pcre_uint32 *)gnptr == 0) break; } #endif #ifdef SUPPORT_PCRE16 if (pcre_mode == PCRE16_MODE) { if (*(pcre_uint16 *)gnptr == 0) break; } #endif #ifdef SUPPORT_PCRE8 if (pcre_mode == PCRE8_MODE) { if (*(pcre_uint8 *)gnptr == 0) break; } #endif PCRE_GET_NAMED_SUBSTRING(rc, re, bptr, use_offsets, count, gnptr, &substring); if (rc < 0) { fprintf(outfile, "get substring "); PCHARSV(gnptr, 0, -1, outfile); fprintf(outfile, " failed %d\n", rc); } else { fprintf(outfile, " G "); PCHARSV(substring, 0, rc, outfile); fprintf(outfile, " (%d) ", rc); PCHARSV(gnptr, 0, -1, outfile); PCRE_FREE_SUBSTRING(substring); putc('\n', outfile); } gnptr = (char *)gnptr + (STRLEN(gnptr) + 1) * CHAR_SIZE; } if (getlist) { int rc; const char **stringlist; PCRE_GET_SUBSTRING_LIST(rc, bptr, use_offsets, count, &stringlist); if (rc < 0) fprintf(outfile, "get substring list failed %d\n", rc); else { for (i = 0; i < count; i++) { fprintf(outfile, "%2dL ", i); PCHARSV(stringlist[i], 0, -1, outfile); putc('\n', outfile); } if (stringlist[i] != NULL) fprintf(outfile, "string list not terminated by NULL\n"); PCRE_FREE_SUBSTRING_LIST(stringlist); } } } /* There was a partial match. If the bumpalong point is not the same as the first inspected character, show the offset explicitly. */ else if (count == PCRE_ERROR_PARTIAL) { fprintf(outfile, "Partial match"); if (use_size_offsets > 2 && use_offsets[0] != use_offsets[2]) fprintf(outfile, " at offset %d", use_offsets[2]); if (markptr != NULL) { fprintf(outfile, ", mark="); PCHARSV(markptr, 0, -1, outfile); } if (use_size_offsets > 1) { fprintf(outfile, ": "); PCHARSV(bptr, use_offsets[0], use_offsets[1] - use_offsets[0], outfile); } if (verify_jit && jit_was_used) fprintf(outfile, " (JIT)"); fprintf(outfile, "\n"); break; /* Out of the /g loop */ } /* Failed to match. If this is a /g or /G loop and we previously set g_notempty after a null match, this is not necessarily the end. We want to advance the start offset, and continue. We won't be at the end of the string - that was checked before setting g_notempty. Complication arises in the case when the newline convention is "any", "crlf", or "anycrlf". If the previous match was at the end of a line terminated by CRLF, an advance of one character just passes the \r, whereas we should prefer the longer newline sequence, as does the code in pcre_exec(). Fudge the offset value to achieve this. We check for a newline setting in the pattern; if none was set, use PCRE_CONFIG() to find the default. Otherwise, in the case of UTF-8 matching, the advance must be one character, not one byte. */ else { if (g_notempty != 0) { int onechar = 1; unsigned int obits = REAL_PCRE_OPTIONS(re); use_offsets[0] = start_offset; if ((obits & PCRE_NEWLINE_BITS) == 0) { int d; (void)PCRE_CONFIG(PCRE_CONFIG_NEWLINE, &d); /* Note that these values are always the ASCII ones, even in EBCDIC environments. CR = 13, NL = 10. */ obits = (d == 13)? PCRE_NEWLINE_CR : (d == 10)? PCRE_NEWLINE_LF : (d == (13<<8 | 10))? PCRE_NEWLINE_CRLF : (d == -2)? PCRE_NEWLINE_ANYCRLF : (d == -1)? PCRE_NEWLINE_ANY : 0; } if (((obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANY || (obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_CRLF || (obits & PCRE_NEWLINE_BITS) == PCRE_NEWLINE_ANYCRLF) && start_offset < len - 1 && ( #ifdef SUPPORT_PCRE8 (pcre_mode == PCRE8_MODE && bptr[start_offset] == '\r' && bptr[start_offset + 1] == '\n') || #endif #ifdef SUPPORT_PCRE16 (pcre_mode == PCRE16_MODE && ((PCRE_SPTR16)bptr)[start_offset] == '\r' && ((PCRE_SPTR16)bptr)[start_offset + 1] == '\n') || #endif #ifdef SUPPORT_PCRE32 (pcre_mode == PCRE32_MODE && ((PCRE_SPTR32)bptr)[start_offset] == '\r' && ((PCRE_SPTR32)bptr)[start_offset + 1] == '\n') || #endif 0)) onechar++; else if (use_utf) { while (start_offset + onechar < len) { if ((bptr[start_offset+onechar] & 0xc0) != 0x80) break; onechar++; } } use_offsets[1] = start_offset + onechar; } else { switch(count) { case PCRE_ERROR_NOMATCH: if (gmatched == 0) { if (markptr == NULL) { fprintf(outfile, "No match"); } else { fprintf(outfile, "No match, mark = "); PCHARSV(markptr, 0, -1, outfile); } if (verify_jit && jit_was_used) fprintf(outfile, " (JIT)"); putc('\n', outfile); } break; case PCRE_ERROR_BADUTF8: case PCRE_ERROR_SHORTUTF8: fprintf(outfile, "Error %d (%s UTF-%d string)", count, (count == PCRE_ERROR_BADUTF8)? "bad" : "short", 8 * CHAR_SIZE); if (use_size_offsets >= 2) fprintf(outfile, " offset=%d reason=%d", use_offsets[0], use_offsets[1]); fprintf(outfile, "\n"); break; case PCRE_ERROR_BADUTF8_OFFSET: fprintf(outfile, "Error %d (bad UTF-%d offset)\n", count, 8 * CHAR_SIZE); break; default: if (count < 0 && (-count) < (int)(sizeof(errtexts)/sizeof(const char *))) fprintf(outfile, "Error %d (%s)\n", count, errtexts[-count]); else fprintf(outfile, "Error %d (Unexpected value)\n", count); break; } break; /* Out of the /g loop */ } } /* If not /g or /G we are done */ if (!do_g && !do_G) break; if (use_offsets == NULL) { fprintf(outfile, "Cannot do global matching without an ovector\n"); break; } if (use_size_offsets < 2) { fprintf(outfile, "Cannot do global matching with an ovector size < 2\n"); break; } /* If we have matched an empty string, first check to see if we are at the end of the subject. If so, the /g loop is over. Otherwise, mimic what Perl's /g options does. This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and PCRE_ANCHORED and try the match again at the same point. If this fails (picked up above) we advance to the next character. */ g_notempty = 0; if (use_offsets[0] == use_offsets[1]) { if (use_offsets[0] == len) break; g_notempty = PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED; } /* For /g, update the start offset, leaving the rest alone. There is a tricky case when \K is used in a positive lookbehind assertion. This can cause the end of the match to be less than or equal to the start offset. In this case we restart at one past the start offset. This may return the same match if the original start offset was bumped along during the match, but eventually the new start offset will hit the actual start offset. (In PCRE2 the true start offset is available, and this can be done better. It is not worth doing more than making sure we do not loop at this stage in the life of PCRE1.) */ if (do_g) { if (g_notempty == 0 && use_offsets[1] <= start_offset) { if (start_offset >= len) break; /* End of subject */ start_offset++; if (use_utf) { while (start_offset < len) { if ((bptr[start_offset] & 0xc0) != 0x80) break; start_offset++; } } } else start_offset = use_offsets[1]; } /* For /G, update the pointer and length */ else { bptr += use_offsets[1] * CHAR_SIZE; len -= use_offsets[1]; } } /* End of loop for /g and /G */ NEXT_DATA: continue; } /* End of loop for data lines */ CONTINUE: #if !defined NOPOSIX if ((posix || do_posix) && preg.re_pcre != 0) regfree(&preg); #endif if (re != NULL) new_free(re); if (extra != NULL) { PCRE_FREE_STUDY(extra); } if (locale_set) { new_free((void *)tables); setlocale(LC_CTYPE, "C"); locale_set = 0; } if (jit_stack != NULL) { PCRE_JIT_STACK_FREE(jit_stack); jit_stack = NULL; } } if (infile == stdin) fprintf(outfile, "\n"); if (showtotaltimes) { fprintf(outfile, "--------------------------------------\n"); if (timeit > 0) { fprintf(outfile, "Total compile time %.4f milliseconds\n", (((double)total_compile_time * 1000.0) / (double)timeit) / (double)CLOCKS_PER_SEC); fprintf(outfile, "Total study time %.4f milliseconds\n", (((double)total_study_time * 1000.0) / (double)timeit) / (double)CLOCKS_PER_SEC); } fprintf(outfile, "Total execute time %.4f milliseconds\n", (((double)total_match_time * 1000.0) / (double)timeitm) / (double)CLOCKS_PER_SEC); } EXIT: if (infile != NULL && infile != stdin) fclose(infile); if (outfile != NULL && outfile != stdout) fclose(outfile); free(buffer); free(dbuffer); free(pbuffer); free(offsets); #ifdef SUPPORT_PCRE16 if (buffer16 != NULL) free(buffer16); #endif #ifdef SUPPORT_PCRE32 if (buffer32 != NULL) free(buffer32); #endif #if !defined NODFA if (dfa_workspace != NULL) free(dfa_workspace); #endif #if defined(__VMS) yield = SS$_NORMAL; /* Return values via DCL symbols */ #endif return yield; } /* End of pcretest.c */ ================================================ FILE: src/pcre/perltest.pl ================================================ #! /usr/bin/env perl # Program for testing regular expressions with perl to check that PCRE handles # them the same. This version needs to have "use utf8" at the start for running # the UTF-8 tests, but *not* for the other tests. The only way I've found for # doing this is to cat this line in explicitly in the RunPerlTest script. I've # also used this method to supply "require Encode" for the UTF-8 tests, so that # the main test will still run where Encode is not installed. #use utf8; #require Encode; # Function for turning a string into a string of printing chars. sub pchars { my($t) = ""; if ($utf8) { @p = unpack('U*', $_[0]); foreach $c (@p) { if ($c >= 32 && $c < 127) { $t .= chr $c; } else { $t .= sprintf("\\x{%02x}", $c); } } } else { foreach $c (split(//, $_[0])) { if (ord $c >= 32 && ord $c < 127) { $t .= $c; } else { $t .= sprintf("\\x%02x", ord $c); } } } $t; } # Read lines from named file or stdin and write to named file or stdout; lines # consist of a regular expression, in delimiters and optionally followed by # options, followed by a set of test data, terminated by an empty line. # Sort out the input and output files if (@ARGV > 0) { open(INFILE, "<$ARGV[0]") || die "Failed to open $ARGV[0]\n"; $infile = "INFILE"; } else { $infile = "STDIN"; } if (@ARGV > 1) { open(OUTFILE, ">$ARGV[1]") || die "Failed to open $ARGV[1]\n"; $outfile = "OUTFILE"; } else { $outfile = "STDOUT"; } printf($outfile "Perl $] Regular Expressions\n\n"); # Main loop NEXT_RE: for (;;) { printf " re> " if $infile eq "STDIN"; last if ! ($_ = <$infile>); printf $outfile "$_" if $infile ne "STDIN"; next if ($_ =~ /^\s*$/ || $_ =~ /^< forbid/); $pattern = $_; while ($pattern !~ /^\s*(.).*\1/s) { printf " > " if $infile eq "STDIN"; last if ! ($_ = <$infile>); printf $outfile "$_" if $infile ne "STDIN"; $pattern .= $_; } chomp($pattern); $pattern =~ s/\s+$//; # The private /+ modifier means "print $' afterwards". $showrest = ($pattern =~ s/\+(?=[a-zA-Z]*$)//); # A doubled version is used by pcretest to print remainders after captures $pattern =~ s/\+(?=[a-zA-Z]*$)//; # Remove /8 from a UTF-8 pattern. $utf8 = $pattern =~ s/8(?=[a-zA-Z]*$)//; # Remove /J from a pattern with duplicate names. $pattern =~ s/J(?=[a-zA-Z]*$)//; # Remove /K from a pattern (asks pcretest to check MARK data) */ $pattern =~ s/K(?=[a-zA-Z]*$)//; # /W asks pcretest to set PCRE_UCP; change this to /u for Perl $pattern =~ s/W(?=[a-zA-Z]*$)/u/; # Remove /S or /SS from a pattern (asks pcretest to study or not to study) $pattern =~ s/S(?=[a-zA-Z]*$)//g; # Remove /Y and /O from a pattern (disable PCRE optimizations) $pattern =~ s/[YO](?=[a-zA-Z]*$)//; # Check that the pattern is valid eval "\$_ =~ ${pattern}"; if ($@) { printf $outfile "Error: $@"; if ($infile != "STDIN") { for (;;) { last if ! ($_ = <$infile>); last if $_ =~ /^\s*$/; } } next NEXT_RE; } # If the /g modifier is present, we want to put a loop round the matching; # otherwise just a single "if". $cmd = ($pattern =~ /g[a-z]*$/)? "while" : "if"; # If the pattern is actually the null string, Perl uses the most recently # executed (and successfully compiled) regex is used instead. This is a # nasty trap for the unwary! The PCRE test suite does contain null strings # in places - if they are allowed through here all sorts of weird and # unexpected effects happen. To avoid this, we replace such patterns with # a non-null pattern that has the same effect. $pattern = "/(?#)/$2" if ($pattern =~ /^(.)\1(.*)$/); # Read data lines and test them for (;;) { printf "data> " if $infile eq "STDIN"; last NEXT_RE if ! ($_ = <$infile>); chomp; printf $outfile "$_\n" if $infile ne "STDIN"; s/\s+$//; # Remove trailing space s/^\s+//; # Remove leading space s/\\Y//g; # Remove \Y (pcretest flag to set PCRE_NO_START_OPTIMIZE) last if ($_ eq ""); $x = eval "\"$_\""; # To get escapes processed # Empty array for holding results, ensure $REGERROR and $REGMARK are # unset, then do the matching. @subs = (); $pushes = "push \@subs,\$&;" . "push \@subs,\$1;" . "push \@subs,\$2;" . "push \@subs,\$3;" . "push \@subs,\$4;" . "push \@subs,\$5;" . "push \@subs,\$6;" . "push \@subs,\$7;" . "push \@subs,\$8;" . "push \@subs,\$9;" . "push \@subs,\$10;" . "push \@subs,\$11;" . "push \@subs,\$12;" . "push \@subs,\$13;" . "push \@subs,\$14;" . "push \@subs,\$15;" . "push \@subs,\$16;" . "push \@subs,\$'; }"; undef $REGERROR; undef $REGMARK; eval "${cmd} (\$x =~ ${pattern}) {" . $pushes; if ($@) { printf $outfile "Error: $@\n"; next NEXT_RE; } elsif (scalar(@subs) == 0) { printf $outfile "No match"; if (defined $REGERROR && $REGERROR != 1) { printf $outfile (", mark = %s", &pchars($REGERROR)); } printf $outfile "\n"; } else { while (scalar(@subs) != 0) { printf $outfile (" 0: %s\n", &pchars($subs[0])); printf $outfile (" 0+ %s\n", &pchars($subs[17])) if $showrest; $last_printed = 0; for ($i = 1; $i <= 16; $i++) { if (defined $subs[$i]) { while ($last_printed++ < $i-1) { printf $outfile ("%2d: \n", $last_printed); } printf $outfile ("%2d: %s\n", $i, &pchars($subs[$i])); $last_printed = $i; } } splice(@subs, 0, 18); } # It seems that $REGMARK is not marked as UTF-8 even when use utf8 is # set and the input pattern was a UTF-8 string. We can, however, force # it to be so marked. if (defined $REGMARK && $REGMARK != 1) { $xx = $REGMARK; $xx = Encode::decode_utf8($xx) if $utf8; printf $outfile ("MK: %s\n", &pchars($xx)); } } } } # printf $outfile "\n"; # End ================================================ FILE: src/pcre/sljit/sljitConfig.h ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 _SLJIT_CONFIG_H_ #define _SLJIT_CONFIG_H_ /* --------------------------------------------------------------------- */ /* Custom defines */ /* --------------------------------------------------------------------- */ /* Put your custom defines here. This empty section will never change which helps maintaining patches (with diff / patch utilities). */ /* --------------------------------------------------------------------- */ /* Architecture */ /* --------------------------------------------------------------------- */ /* Architecture selection. */ /* #define SLJIT_CONFIG_X86_32 1 */ /* #define SLJIT_CONFIG_X86_64 1 */ /* #define SLJIT_CONFIG_ARM_V5 1 */ /* #define SLJIT_CONFIG_ARM_V7 1 */ /* #define SLJIT_CONFIG_ARM_THUMB2 1 */ /* #define SLJIT_CONFIG_ARM_64 1 */ /* #define SLJIT_CONFIG_PPC_32 1 */ /* #define SLJIT_CONFIG_PPC_64 1 */ /* #define SLJIT_CONFIG_MIPS_32 1 */ /* #define SLJIT_CONFIG_MIPS_64 1 */ /* #define SLJIT_CONFIG_SPARC_32 1 */ /* #define SLJIT_CONFIG_TILEGX 1 */ /* #define SLJIT_CONFIG_AUTO 1 */ /* #define SLJIT_CONFIG_UNSUPPORTED 1 */ /* --------------------------------------------------------------------- */ /* Utilities */ /* --------------------------------------------------------------------- */ /* Useful for thread-safe compiling of global functions. */ #ifndef SLJIT_UTIL_GLOBAL_LOCK /* Enabled by default */ #define SLJIT_UTIL_GLOBAL_LOCK 1 #endif /* Implements a stack like data structure (by using mmap / VirtualAlloc). */ #ifndef SLJIT_UTIL_STACK /* Enabled by default */ #define SLJIT_UTIL_STACK 1 #endif /* Single threaded application. Does not require any locks. */ #ifndef SLJIT_SINGLE_THREADED /* Disabled by default. */ #define SLJIT_SINGLE_THREADED 0 #endif /* --------------------------------------------------------------------- */ /* Configuration */ /* --------------------------------------------------------------------- */ /* If SLJIT_STD_MACROS_DEFINED is not defined, the application should define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */ #ifndef SLJIT_STD_MACROS_DEFINED /* Disabled by default. */ #define SLJIT_STD_MACROS_DEFINED 0 #endif /* Executable code allocation: If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */ #ifndef SLJIT_EXECUTABLE_ALLOCATOR /* Enabled by default. */ #define SLJIT_EXECUTABLE_ALLOCATOR 1 /* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an allocator which does not set writable and executable permission flags at the same time. The trade-of is increased memory consumption and disabled dynamic code modifications. */ #ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR /* Disabled by default. */ #define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0 #endif #endif /* Force cdecl calling convention even if a better calling convention (e.g. fastcall) is supported by the C compiler. If this option is disabled (this is the default), functions called from JIT should be defined with SLJIT_FUNC attribute. Standard C functions can still be called by using the SLJIT_CALL_CDECL jump type. */ #ifndef SLJIT_USE_CDECL_CALLING_CONVENTION /* Disabled by default */ #define SLJIT_USE_CDECL_CALLING_CONVENTION 0 #endif /* Return with error when an invalid argument is passed. */ #ifndef SLJIT_ARGUMENT_CHECKS /* Disabled by default */ #define SLJIT_ARGUMENT_CHECKS 0 #endif /* Debug checks (assertions, etc.). */ #ifndef SLJIT_DEBUG /* Enabled by default */ #define SLJIT_DEBUG 1 #endif /* Verbose operations. */ #ifndef SLJIT_VERBOSE /* Enabled by default */ #define SLJIT_VERBOSE 1 #endif /* SLJIT_IS_FPU_AVAILABLE The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE. zero value - FPU is NOT present. nonzero value - FPU is present. */ /* For further configurations, see the beginning of sljitConfigInternal.h */ #endif ================================================ FILE: src/pcre/sljit/sljitConfigInternal.h ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 _SLJIT_CONFIG_INTERNAL_H_ #define _SLJIT_CONFIG_INTERNAL_H_ /* SLJIT defines the following architecture dependent types and macros: Types: sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer sljit_p : unsgined pointer value (usually the same as sljit_uw, but some 64 bit ABIs may use 32 bit pointers) sljit_f32 : 32 bit single precision floating point value sljit_f64 : 64 bit double precision floating point value Macros for feature detection (boolean): SLJIT_32BIT_ARCHITECTURE : 32 bit architecture SLJIT_64BIT_ARCHITECTURE : 64 bit architecture SLJIT_LITTLE_ENDIAN : little endian architecture SLJIT_BIG_ENDIAN : big endian architecture SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!) SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information Constants: SLJIT_NUMBER_OF_REGISTERS : number of available registers SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index SLJIT_F32_SHIFT : the shift required to apply when accessing a single precision floating point array by index SLJIT_F64_SHIFT : the shift required to apply when accessing a double precision floating point array by index SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register the scratch register index of ecx is stored in this variable SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET) SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address Other macros: SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper) */ /*****************/ /* Sanity check. */ /*****************/ #if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ || (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ || (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \ || (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ || (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)) #error "An architecture must be selected" #endif #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \ + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ + (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2 #error "Multiple architectures are selected" #endif /********************************************************/ /* Automatic CPU detection (requires compiler support). */ /********************************************************/ #if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) #ifndef _WIN32 #if defined(__i386__) || defined(__i386) #define SLJIT_CONFIG_X86_32 1 #elif defined(__x86_64__) #define SLJIT_CONFIG_X86_64 1 #elif defined(__arm__) || defined(__ARM__) #ifdef __thumb2__ #define SLJIT_CONFIG_ARM_THUMB2 1 #elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) #define SLJIT_CONFIG_ARM_V7 1 #else #define SLJIT_CONFIG_ARM_V5 1 #endif #elif defined (__aarch64__) #define SLJIT_CONFIG_ARM_64 1 #elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__)) #define SLJIT_CONFIG_PPC_64 1 #elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER) #define SLJIT_CONFIG_PPC_32 1 #elif defined(__mips__) && !defined(_LP64) #define SLJIT_CONFIG_MIPS_32 1 #elif defined(__mips64) #define SLJIT_CONFIG_MIPS_64 1 #elif defined(__sparc__) || defined(__sparc) #define SLJIT_CONFIG_SPARC_32 1 #elif defined(__tilegx__) #define SLJIT_CONFIG_TILEGX 1 #else /* Unsupported architecture */ #define SLJIT_CONFIG_UNSUPPORTED 1 #endif #else /* _WIN32 */ #if defined(_M_X64) || defined(__x86_64__) #define SLJIT_CONFIG_X86_64 1 #elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__) #define SLJIT_CONFIG_ARM_THUMB2 1 #elif (defined(_M_ARM) && _M_ARM >= 7) #define SLJIT_CONFIG_ARM_V7 1 #elif defined(_ARM_) #define SLJIT_CONFIG_ARM_V5 1 #elif defined(_M_ARM64) || defined(__aarch64__) #define SLJIT_CONFIG_ARM_64 1 #else #define SLJIT_CONFIG_X86_32 1 #endif #endif /* !_WIN32 */ #endif /* SLJIT_CONFIG_AUTO */ #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #undef SLJIT_EXECUTABLE_ALLOCATOR #endif /******************************/ /* CPU family type detection. */ /******************************/ #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) #define SLJIT_CONFIG_ARM_32 1 #endif #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #define SLJIT_CONFIG_X86 1 #elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) #define SLJIT_CONFIG_ARM 1 #elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define SLJIT_CONFIG_PPC 1 #elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) #define SLJIT_CONFIG_MIPS 1 #elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) || (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64) #define SLJIT_CONFIG_SPARC 1 #endif /**********************************/ /* External function definitions. */ /**********************************/ /* General macros: Note: SLJIT is designed to be independent from them as possible. In release mode (SLJIT_DEBUG is not defined) only the following external functions are needed: */ #ifndef SLJIT_MALLOC #define SLJIT_MALLOC(size, allocator_data) malloc(size) #endif #ifndef SLJIT_FREE #define SLJIT_FREE(ptr, allocator_data) free(ptr) #endif #ifndef SLJIT_MEMCPY #define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len) #endif #ifndef SLJIT_ZEROMEM #define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len) #endif /***************************/ /* Compiler helper macros. */ /***************************/ #if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) #if defined(__GNUC__) && (__GNUC__ >= 3) #define SLJIT_LIKELY(x) __builtin_expect((x), 1) #define SLJIT_UNLIKELY(x) __builtin_expect((x), 0) #else #define SLJIT_LIKELY(x) (x) #define SLJIT_UNLIKELY(x) (x) #endif #endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */ #ifndef SLJIT_INLINE /* Inline functions. Some old compilers do not support them. */ #if defined(__SUNPRO_C) && __SUNPRO_C <= 0x510 #define SLJIT_INLINE #else #define SLJIT_INLINE __inline #endif #endif /* !SLJIT_INLINE */ #ifndef SLJIT_NOINLINE /* Not inline functions. */ #if defined(__GNUC__) #define SLJIT_NOINLINE __attribute__ ((noinline)) #else #define SLJIT_NOINLINE #endif #endif /* !SLJIT_INLINE */ #ifndef SLJIT_UNUSED_ARG /* Unused arguments. */ #define SLJIT_UNUSED_ARG(arg) (void)arg #endif /*********************************/ /* Type of public API functions. */ /*********************************/ #if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) /* Static ABI functions. For all-in-one programs. */ #if defined(__GNUC__) /* Disable unused warnings in gcc. */ #define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused)) #else #define SLJIT_API_FUNC_ATTRIBUTE static #endif #else #define SLJIT_API_FUNC_ATTRIBUTE #endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */ /****************************/ /* Instruction cache flush. */ /****************************/ #if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) #if __has_builtin(__builtin___clear_cache) #define SLJIT_CACHE_FLUSH(from, to) \ __builtin___clear_cache((char*)from, (char*)to) #endif /* __has_builtin(__builtin___clear_cache) */ #endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */ #ifndef SLJIT_CACHE_FLUSH #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* Not required to implement on archs with unified caches. */ #define SLJIT_CACHE_FLUSH(from, to) #elif defined __APPLE__ /* Supported by all macs since Mac OS 10.5. However, it does not work on non-jailbroken iOS devices, although the compilation is successful. */ #define SLJIT_CACHE_FLUSH(from, to) \ sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from)) #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) /* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */ #define SLJIT_CACHE_FLUSH(from, to) \ ppc_cache_flush((from), (to)) #define SLJIT_CACHE_FLUSH_OWN_IMPL 1 #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) #define SLJIT_CACHE_FLUSH(from, to) \ __builtin___clear_cache((char*)from, (char*)to) #elif defined __ANDROID__ /* Android lacks __clear_cache; instead, cacheflush should be used. */ #define SLJIT_CACHE_FLUSH(from, to) \ cacheflush((long)(from), (long)(to), 0) #elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) /* The __clear_cache() implementation of GCC is a dummy function on Sparc. */ #define SLJIT_CACHE_FLUSH(from, to) \ sparc_cache_flush((from), (to)) #define SLJIT_CACHE_FLUSH_OWN_IMPL 1 #elif defined _WIN32 #define SLJIT_CACHE_FLUSH(from, to) \ FlushInstructionCache(GetCurrentProcess(), (char*)(from), (char*)(to) - (char*)(from)) #else /* Calls __ARM_NR_cacheflush on ARM-Linux. */ #define SLJIT_CACHE_FLUSH(from, to) \ __clear_cache((char*)(from), (char*)(to)) #endif #endif /* !SLJIT_CACHE_FLUSH */ /******************************************************/ /* Integer and floating point type definitions. */ /******************************************************/ /* 8 bit byte type. */ typedef unsigned char sljit_u8; typedef signed char sljit_s8; /* 16 bit half-word type. */ typedef unsigned short int sljit_u16; typedef signed short int sljit_s16; /* 32 bit integer type. */ typedef unsigned int sljit_u32; typedef signed int sljit_s32; /* Machine word type. Enough for storing a pointer. 32 bit for 32 bit machines. 64 bit for 64 bit machines. */ #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) /* Just to have something. */ #define SLJIT_WORD_SHIFT 0 typedef unsigned long int sljit_uw; typedef long int sljit_sw; #elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ && !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) #define SLJIT_32BIT_ARCHITECTURE 1 #define SLJIT_WORD_SHIFT 2 typedef unsigned int sljit_uw; typedef int sljit_sw; #else #define SLJIT_64BIT_ARCHITECTURE 1 #define SLJIT_WORD_SHIFT 3 #ifdef _WIN32 #ifdef __GNUC__ /* These types do not require windows.h */ typedef unsigned long long sljit_uw; typedef long long sljit_sw; #else typedef unsigned __int64 sljit_uw; typedef __int64 sljit_sw; #endif #else /* !_WIN32 */ typedef unsigned long int sljit_uw; typedef long int sljit_sw; #endif /* _WIN32 */ #endif typedef sljit_uw sljit_p; /* Floating point types. */ typedef float sljit_f32; typedef double sljit_f64; /* Shift for pointer sized data. */ #define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT /* Shift for double precision sized data. */ #define SLJIT_F32_SHIFT 2 #define SLJIT_F64_SHIFT 3 #ifndef SLJIT_W /* Defining long constants. */ #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define SLJIT_W(w) (w##l) #elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #define SLJIT_W(w) (w##ll) #else #define SLJIT_W(w) (w) #endif #endif /* !SLJIT_W */ /*************************/ /* Endianness detection. */ /*************************/ #if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) /* These macros are mostly useful for the applications. */ #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #ifdef __LITTLE_ENDIAN__ #define SLJIT_LITTLE_ENDIAN 1 #else #define SLJIT_BIG_ENDIAN 1 #endif #elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) #ifdef __MIPSEL__ #define SLJIT_LITTLE_ENDIAN 1 #else #define SLJIT_BIG_ENDIAN 1 #endif #elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) #define SLJIT_BIG_ENDIAN 1 #else #define SLJIT_LITTLE_ENDIAN 1 #endif #endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */ /* Sanity check. */ #if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) #error "Exactly one endianness must be selected" #endif #if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) #error "Exactly one endianness must be selected" #endif #ifndef SLJIT_UNALIGNED #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define SLJIT_UNALIGNED 1 #endif #endif /* !SLJIT_UNALIGNED */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) /* Auto detect SSE2 support using CPUID. On 64 bit x86 cpus, sse2 must be present. */ #define SLJIT_DETECT_SSE2 1 #endif /*****************************************************************************************/ /* Calling convention of functions generated by SLJIT or called from the generated code. */ /*****************************************************************************************/ #ifndef SLJIT_FUNC #if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) /* Force cdecl. */ #define SLJIT_FUNC #elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #if defined(__GNUC__) && !defined(__APPLE__) #define SLJIT_FUNC __attribute__ ((fastcall)) #define SLJIT_X86_32_FASTCALL 1 #elif defined(_MSC_VER) #define SLJIT_FUNC __fastcall #define SLJIT_X86_32_FASTCALL 1 #elif defined(__BORLANDC__) #define SLJIT_FUNC __msfastcall #define SLJIT_X86_32_FASTCALL 1 #else /* Unknown compiler. */ /* The cdecl attribute is the default. */ #define SLJIT_FUNC #endif #else /* Non x86-32 architectures. */ #define SLJIT_FUNC #endif /* SLJIT_CONFIG_X86_32 */ #endif /* !SLJIT_FUNC */ #ifndef SLJIT_INDIRECT_CALL #if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \ || ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX) /* It seems certain ppc compilers use an indirect addressing for functions which makes things complicated. */ #define SLJIT_INDIRECT_CALL 1 #endif #endif /* SLJIT_INDIRECT_CALL */ /* The offset which needs to be substracted from the return address to determine the next executed instruction after return. */ #ifndef SLJIT_RETURN_ADDRESS_OFFSET #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) #define SLJIT_RETURN_ADDRESS_OFFSET 8 #else #define SLJIT_RETURN_ADDRESS_OFFSET 0 #endif #endif /* SLJIT_RETURN_ADDRESS_OFFSET */ /***************************************************/ /* Functions of the built-in executable allocator. */ /***************************************************/ #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size); SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr); SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size) #define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr) #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr) #else #define SLJIT_EXEC_OFFSET(ptr) 0 #endif #endif /**********************************************/ /* Registers and locals offset determination. */ /**********************************************/ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 9 #define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset) #define SLJIT_PREF_SHIFT_REG SLJIT_R2 #elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #define SLJIT_NUMBER_OF_REGISTERS 13 #ifndef _WIN64 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 6 #define SLJIT_LOCALS_OFFSET_BASE 0 #else /* _WIN64 */ #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset) #endif /* !_WIN64 */ #define SLJIT_PREF_SHIFT_REG SLJIT_R3 #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) #define SLJIT_NUMBER_OF_REGISTERS 12 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) #define SLJIT_NUMBER_OF_REGISTERS 26 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 10 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) #define SLJIT_NUMBER_OF_REGISTERS 23 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 17 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX) #define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw)) #elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) /* Add +1 for double alignment. */ #define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * sizeof(sljit_sw)) #else #define SLJIT_LOCALS_OFFSET_BASE (3 * sizeof(sljit_sw)) #endif /* SLJIT_CONFIG_PPC_64 || _AIX */ #elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) #define SLJIT_NUMBER_OF_REGISTERS 21 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw)) #else #define SLJIT_LOCALS_OFFSET_BASE 0 #endif #elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) #define SLJIT_NUMBER_OF_REGISTERS 18 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 14 #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) /* saved registers (16), return struct pointer (1), space for 6 argument words (1), 4th double arg (2), double alignment (1). */ #define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * sizeof(sljit_sw)) #endif #elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) #define SLJIT_NUMBER_OF_REGISTERS 10 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 5 #define SLJIT_LOCALS_OFFSET_BASE 0 #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define SLJIT_NUMBER_OF_REGISTERS 0 #define SLJIT_NUMBER_OF_SAVED_REGISTERS 0 #define SLJIT_LOCALS_OFFSET_BASE 0 #endif #define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE) #define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \ (SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS) #define SLJIT_NUMBER_OF_FLOAT_REGISTERS 6 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && (defined _WIN64) #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 1 #else #define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0 #endif #define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS) /*************************************/ /* Debug and verbose related macros. */ /*************************************/ #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) #include #endif #if (defined SLJIT_DEBUG && SLJIT_DEBUG) #if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) /* SLJIT_HALT_PROCESS must halt the process. */ #ifndef SLJIT_HALT_PROCESS #include #define SLJIT_HALT_PROCESS() \ abort(); #endif /* !SLJIT_HALT_PROCESS */ #include #endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */ /* Feel free to redefine these two macros. */ #ifndef SLJIT_ASSERT #define SLJIT_ASSERT(x) \ do { \ if (SLJIT_UNLIKELY(!(x))) { \ printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \ SLJIT_HALT_PROCESS(); \ } \ } while (0) #endif /* !SLJIT_ASSERT */ #ifndef SLJIT_UNREACHABLE #define SLJIT_UNREACHABLE() \ do { \ printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \ SLJIT_HALT_PROCESS(); \ } while (0) #endif /* !SLJIT_UNREACHABLE */ #else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */ /* Forcing empty, but valid statements. */ #undef SLJIT_ASSERT #undef SLJIT_UNREACHABLE #define SLJIT_ASSERT(x) \ do { } while (0) #define SLJIT_UNREACHABLE() \ do { } while (0) #endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */ #ifndef SLJIT_COMPILE_ASSERT #define SLJIT_COMPILE_ASSERT(x, description) \ switch(0) { case 0: case ((x) ? 1 : 0): break; } #endif /* !SLJIT_COMPILE_ASSERT */ #endif ================================================ FILE: src/pcre/sljit/sljitExecAllocator.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* This file contains a simple executable memory allocator It is assumed, that executable code blocks are usually medium (or sometimes large) memory blocks, and the allocator is not too frequently called (less optimized than other allocators). Thus, using it as a generic allocator is not suggested. How does it work: Memory is allocated in continuous memory areas called chunks by alloc_chunk() Chunk format: [ block ][ block ] ... [ block ][ block terminator ] All blocks and the block terminator is started with block_header. The block header contains the size of the previous and the next block. These sizes can also contain special values. Block size: 0 - The block is a free_block, with a different size member. 1 - The block is a block terminator. n - The block is used at the moment, and the value contains its size. Previous block size: 0 - This is the first block of the memory chunk. n - The size of the previous block. Using these size values we can go forward or backward on the block chain. The unused blocks are stored in a chain list pointed by free_blocks. This list is useful if we need to find a suitable memory area when the allocator is called. When a block is freed, the new free block is connected to its adjacent free blocks if possible. [ free block ][ used block ][ free block ] and "used block" is freed, the three blocks are connected together: [ one big free block ] */ /* --------------------------------------------------------------------- */ /* System (OS) functions */ /* --------------------------------------------------------------------- */ /* 64 KByte. */ #define CHUNK_SIZE 0x10000 /* alloc_chunk / free_chunk : * allocate executable system memory chunks * the size is always divisible by CHUNK_SIZE allocator_grab_lock / allocator_release_lock : * make the allocator thread safe * can be empty if the OS (or the application) does not support threading * only the allocator requires this lock, sljit is fully thread safe as it only uses local variables */ #ifdef _WIN32 static SLJIT_INLINE void* alloc_chunk(sljit_uw size) { return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); } static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) { SLJIT_UNUSED_ARG(size); VirtualFree(chunk, 0, MEM_RELEASE); } #else #ifdef __APPLE__ /* Configures TARGET_OS_OSX when appropriate */ #include #if TARGET_OS_OSX && defined(MAP_JIT) #include #endif /* TARGET_OS_OSX && MAP_JIT */ #ifdef MAP_JIT static SLJIT_INLINE int get_map_jit_flag() { #if TARGET_OS_OSX /* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version of macOS where it's OK to have more than one JIT block. On non-macOS systems, returns MAP_JIT if it is defined. */ static int map_jit_flag = -1; /* The following code is thread safe because multiple initialization sets map_jit_flag to the same value and the code has no side-effects. Changing the kernel version witout system restart is (very) unlikely. */ if (map_jit_flag == -1) { struct utsname name; uname(&name); /* Kernel version for 10.14.0 (Mojave) */ map_jit_flag = (atoi(name.release) >= 18) ? MAP_JIT : 0; } return map_jit_flag; #else /* !TARGET_OS_OSX */ return MAP_JIT; #endif /* TARGET_OS_OSX */ } #endif /* MAP_JIT */ #endif /* __APPLE__ */ static SLJIT_INLINE void* alloc_chunk(sljit_uw size) { void *retval; #ifdef MAP_ANON int flags = MAP_PRIVATE | MAP_ANON; #ifdef MAP_JIT flags |= get_map_jit_flag(); #endif retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, flags, -1, 0); #else /* !MAP_ANON */ if (dev_zero < 0) { if (open_dev_zero()) return NULL; } retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0); #endif /* MAP_ANON */ return (retval != MAP_FAILED) ? retval : NULL; } static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) { munmap(chunk, size); } #endif /* --------------------------------------------------------------------- */ /* Common functions */ /* --------------------------------------------------------------------- */ #define CHUNK_MASK (~(CHUNK_SIZE - 1)) struct block_header { sljit_uw size; sljit_uw prev_size; }; struct free_block { struct block_header header; struct free_block *next; struct free_block *prev; sljit_uw size; }; #define AS_BLOCK_HEADER(base, offset) \ ((struct block_header*)(((sljit_u8*)base) + offset)) #define AS_FREE_BLOCK(base, offset) \ ((struct free_block*)(((sljit_u8*)base) + offset)) #define MEM_START(base) ((void*)(((sljit_u8*)base) + sizeof(struct block_header))) #define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7) static struct free_block* free_blocks; static sljit_uw allocated_size; static sljit_uw total_size; static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size) { free_block->header.size = 0; free_block->size = size; free_block->next = free_blocks; free_block->prev = NULL; if (free_blocks) free_blocks->prev = free_block; free_blocks = free_block; } static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block) { if (free_block->next) free_block->next->prev = free_block->prev; if (free_block->prev) free_block->prev->next = free_block->next; else { SLJIT_ASSERT(free_blocks == free_block); free_blocks = free_block->next; } } SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) { struct block_header *header; struct block_header *next_header; struct free_block *free_block; sljit_uw chunk_size; allocator_grab_lock(); if (size < (64 - sizeof(struct block_header))) size = (64 - sizeof(struct block_header)); size = ALIGN_SIZE(size); free_block = free_blocks; while (free_block) { if (free_block->size >= size) { chunk_size = free_block->size; if (chunk_size > size + 64) { /* We just cut a block from the end of the free block. */ chunk_size -= size; free_block->size = chunk_size; header = AS_BLOCK_HEADER(free_block, chunk_size); header->prev_size = chunk_size; AS_BLOCK_HEADER(header, size)->prev_size = size; } else { sljit_remove_free_block(free_block); header = (struct block_header*)free_block; size = chunk_size; } allocated_size += size; header->size = size; allocator_release_lock(); return MEM_START(header); } free_block = free_block->next; } chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK; header = (struct block_header*)alloc_chunk(chunk_size); if (!header) { allocator_release_lock(); return NULL; } chunk_size -= sizeof(struct block_header); total_size += chunk_size; header->prev_size = 0; if (chunk_size > size + 64) { /* Cut the allocated space into a free and a used block. */ allocated_size += size; header->size = size; chunk_size -= size; free_block = AS_FREE_BLOCK(header, size); free_block->header.prev_size = size; sljit_insert_free_block(free_block, chunk_size); next_header = AS_BLOCK_HEADER(free_block, chunk_size); } else { /* All space belongs to this allocation. */ allocated_size += chunk_size; header->size = chunk_size; next_header = AS_BLOCK_HEADER(header, chunk_size); } next_header->size = 1; next_header->prev_size = chunk_size; allocator_release_lock(); return MEM_START(header); } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) { struct block_header *header; struct free_block* free_block; allocator_grab_lock(); header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); allocated_size -= header->size; /* Connecting free blocks together if possible. */ /* If header->prev_size == 0, free_block will equal to header. In this case, free_block->header.size will be > 0. */ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size); if (SLJIT_UNLIKELY(!free_block->header.size)) { free_block->size += header->size; header = AS_BLOCK_HEADER(free_block, free_block->size); header->prev_size = free_block->size; } else { free_block = (struct free_block*)header; sljit_insert_free_block(free_block, header->size); } header = AS_BLOCK_HEADER(free_block, free_block->size); if (SLJIT_UNLIKELY(!header->size)) { free_block->size += ((struct free_block*)header)->size; sljit_remove_free_block((struct free_block*)header); header = AS_BLOCK_HEADER(free_block, free_block->size); header->prev_size = free_block->size; } /* The whole chunk is free. */ if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) { /* If this block is freed, we still have (allocated_size / 2) free space. */ if (total_size - free_block->size > (allocated_size * 3 / 2)) { total_size -= free_block->size; sljit_remove_free_block(free_block); free_chunk(free_block, free_block->size + sizeof(struct block_header)); } } allocator_release_lock(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) { struct free_block* free_block; struct free_block* next_free_block; allocator_grab_lock(); free_block = free_blocks; while (free_block) { next_free_block = free_block->next; if (!free_block->header.prev_size && AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { total_size -= free_block->size; sljit_remove_free_block(free_block); free_chunk(free_block, free_block->size + sizeof(struct block_header)); } free_block = next_free_block; } SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks)); allocator_release_lock(); } ================================================ FILE: src/pcre/sljit/sljitLir.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 "sljitLir.h" #ifdef _WIN32 /* For SLJIT_CACHE_FLUSH, which can expand to FlushInstructionCache. */ #include #endif /* _WIN32 */ #if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED) /* These libraries are needed for the macros below. */ #include #include #endif /* SLJIT_STD_MACROS_DEFINED */ #define CHECK_ERROR() \ do { \ if (SLJIT_UNLIKELY(compiler->error)) \ return compiler->error; \ } while (0) #define CHECK_ERROR_PTR() \ do { \ if (SLJIT_UNLIKELY(compiler->error)) \ return NULL; \ } while (0) #define FAIL_IF(expr) \ do { \ if (SLJIT_UNLIKELY(expr)) \ return compiler->error; \ } while (0) #define PTR_FAIL_IF(expr) \ do { \ if (SLJIT_UNLIKELY(expr)) \ return NULL; \ } while (0) #define FAIL_IF_NULL(ptr) \ do { \ if (SLJIT_UNLIKELY(!(ptr))) { \ compiler->error = SLJIT_ERR_ALLOC_FAILED; \ return SLJIT_ERR_ALLOC_FAILED; \ } \ } while (0) #define PTR_FAIL_IF_NULL(ptr) \ do { \ if (SLJIT_UNLIKELY(!(ptr))) { \ compiler->error = SLJIT_ERR_ALLOC_FAILED; \ return NULL; \ } \ } while (0) #define PTR_FAIL_WITH_EXEC_IF(ptr) \ do { \ if (SLJIT_UNLIKELY(!(ptr))) { \ compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \ return NULL; \ } \ } while (0) #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define VARIABLE_FLAG_SHIFT (10) #define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT) #define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT) #define GET_OPCODE(op) \ ((op) & ~(SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) #define HAS_FLAGS(op) \ ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) #define GET_ALL_FLAGS(op) \ ((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #define TYPE_CAST_NEEDED(op) \ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32) #else #define TYPE_CAST_NEEDED(op) \ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16) #endif #define BUF_SIZE 4096 #if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) #define ABUF_SIZE 2048 #else #define ABUF_SIZE 4096 #endif /* Parameter parsing. */ #define REG_MASK 0x3f #define OFFS_REG(reg) (((reg) >> 8) & REG_MASK) #define OFFS_REG_MASK (REG_MASK << 8) #define TO_OFFS_REG(reg) ((reg) << 8) /* When reg cannot be unused. */ #define FAST_IS_REG(reg) ((reg) <= REG_MASK) /* When reg can be unused. */ #define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK) /* Mask for argument types. */ #define SLJIT_DEF_MASK ((1 << SLJIT_DEF_SHIFT) - 1) /* Jump flags. */ #define JUMP_LABEL 0x1 #define JUMP_ADDR 0x2 /* SLJIT_REWRITABLE_JUMP is 0x1000. */ #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) # define PATCH_MB 0x4 # define PATCH_MW 0x8 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) # define PATCH_MD 0x10 #endif #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) # define IS_BL 0x4 # define PATCH_B 0x8 #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) # define CPOOL_SIZE 512 #endif #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) # define IS_COND 0x04 # define IS_BL 0x08 /* conditional + imm8 */ # define PATCH_TYPE1 0x10 /* conditional + imm20 */ # define PATCH_TYPE2 0x20 /* IT + imm24 */ # define PATCH_TYPE3 0x30 /* imm11 */ # define PATCH_TYPE4 0x40 /* imm24 */ # define PATCH_TYPE5 0x50 /* BL + imm24 */ # define PATCH_BL 0x60 /* 0xf00 cc code for branches */ #endif #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) # define IS_COND 0x004 # define IS_CBZ 0x008 # define IS_BL 0x010 # define PATCH_B 0x020 # define PATCH_COND 0x040 # define PATCH_ABS48 0x080 # define PATCH_ABS64 0x100 #endif #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) # define IS_COND 0x004 # define IS_CALL 0x008 # define PATCH_B 0x010 # define PATCH_ABS_B 0x020 #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) # define PATCH_ABS32 0x040 # define PATCH_ABS48 0x080 #endif # define REMOVE_COND 0x100 #endif #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) # define IS_MOVABLE 0x004 # define IS_JAL 0x008 # define IS_CALL 0x010 # define IS_BIT26_COND 0x020 # define IS_BIT16_COND 0x040 # define IS_COND (IS_BIT26_COND | IS_BIT16_COND) # define PATCH_B 0x080 # define PATCH_J 0x100 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) # define PATCH_ABS32 0x200 # define PATCH_ABS48 0x400 #endif /* instruction types */ # define MOVABLE_INS 0 /* 1 - 31 last destination register */ /* no destination (i.e: store) */ # define UNMOVABLE_INS 32 /* FPU status register */ # define FCSR_FCC 33 #endif #if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) # define IS_JAL 0x04 # define IS_COND 0x08 # define PATCH_B 0x10 # define PATCH_J 0x20 #endif #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) # define IS_MOVABLE 0x04 # define IS_COND 0x08 # define IS_CALL 0x10 # define PATCH_B 0x20 # define PATCH_CALL 0x40 /* instruction types */ # define MOVABLE_INS 0 /* 1 - 31 last destination register */ /* no destination (i.e: store) */ # define UNMOVABLE_INS 32 # define DST_INS_MASK 0xff /* ICC_SET is the same as SET_FLAGS. */ # define ICC_IS_SET (1 << 23) # define FCC_IS_SET (1 << 24) #endif /* Stack management. */ #define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \ (((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \ (saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? saveds : SLJIT_NUMBER_OF_SAVED_REGISTERS) + \ extra) * sizeof(sljit_sw)) #define ADJUST_LOCAL_OFFSET(p, i) \ if ((p) == (SLJIT_MEM1(SLJIT_SP))) \ (i) += SLJIT_LOCALS_OFFSET; #endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */ /* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */ #include "sljitUtils.c" #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) #include "sljitProtExecAllocator.c" #else #include "sljitExecAllocator.c" #endif #endif #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset)) #else #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr)) #endif /* Argument checking features. */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) /* Returns with error when an invalid argument is passed. */ #define CHECK_ARGUMENT(x) \ do { \ if (SLJIT_UNLIKELY(!(x))) \ return 1; \ } while (0) #define CHECK_RETURN_TYPE sljit_s32 #define CHECK_RETURN_OK return 0 #define CHECK(x) \ do { \ if (SLJIT_UNLIKELY(x)) { \ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \ return SLJIT_ERR_BAD_ARGUMENT; \ } \ } while (0) #define CHECK_PTR(x) \ do { \ if (SLJIT_UNLIKELY(x)) { \ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \ return NULL; \ } \ } while (0) #define CHECK_REG_INDEX(x) \ do { \ if (SLJIT_UNLIKELY(x)) { \ return -2; \ } \ } while (0) #elif (defined SLJIT_DEBUG && SLJIT_DEBUG) /* Assertion failure occures if an invalid argument is passed. */ #undef SLJIT_ARGUMENT_CHECKS #define SLJIT_ARGUMENT_CHECKS 1 #define CHECK_ARGUMENT(x) SLJIT_ASSERT(x) #define CHECK_RETURN_TYPE void #define CHECK_RETURN_OK return #define CHECK(x) x #define CHECK_PTR(x) x #define CHECK_REG_INDEX(x) x #elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE) /* Arguments are not checked. */ #define CHECK_RETURN_TYPE void #define CHECK_RETURN_OK return #define CHECK(x) x #define CHECK_PTR(x) x #define CHECK_REG_INDEX(x) x #else /* Arguments are not checked. */ #define CHECK(x) #define CHECK_PTR(x) #define CHECK_REG_INDEX(x) #endif /* SLJIT_ARGUMENT_CHECKS */ /* --------------------------------------------------------------------- */ /* Public functions */ /* --------------------------------------------------------------------- */ #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) #define SLJIT_NEEDS_COMPILER_INIT 1 static sljit_s32 compiler_initialized = 0; /* A thread safe initialization. */ static void init_compiler(void); #endif SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data) { struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data); if (!compiler) return NULL; SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler)); SLJIT_COMPILE_ASSERT( sizeof(sljit_s8) == 1 && sizeof(sljit_u8) == 1 && sizeof(sljit_s16) == 2 && sizeof(sljit_u16) == 2 && sizeof(sljit_s32) == 4 && sizeof(sljit_u32) == 4 && (sizeof(sljit_p) == 4 || sizeof(sljit_p) == 8) && sizeof(sljit_p) <= sizeof(sljit_sw) && (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8) && (sizeof(sljit_uw) == 4 || sizeof(sljit_uw) == 8), invalid_integer_types); SLJIT_COMPILE_ASSERT(SLJIT_I32_OP == SLJIT_F32_OP, int_op_and_single_op_must_be_the_same); SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_F32_OP, rewritable_jump_and_single_op_must_not_be_the_same); SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1), conditional_flags_must_be_even_numbers); /* Only the non-zero members must be set. */ compiler->error = SLJIT_SUCCESS; compiler->allocator_data = allocator_data; compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data); compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data); if (!compiler->buf || !compiler->abuf) { if (compiler->buf) SLJIT_FREE(compiler->buf, allocator_data); if (compiler->abuf) SLJIT_FREE(compiler->abuf, allocator_data); SLJIT_FREE(compiler, allocator_data); return NULL; } compiler->buf->next = NULL; compiler->buf->used_size = 0; compiler->abuf->next = NULL; compiler->abuf->used_size = 0; compiler->scratches = -1; compiler->saveds = -1; compiler->fscratches = -1; compiler->fsaveds = -1; compiler->local_size = -1; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) compiler->args = -1; #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw) + CPOOL_SIZE * sizeof(sljit_u8), allocator_data); if (!compiler->cpool) { SLJIT_FREE(compiler->buf, allocator_data); SLJIT_FREE(compiler->abuf, allocator_data); SLJIT_FREE(compiler, allocator_data); return NULL; } compiler->cpool_unique = (sljit_u8*)(compiler->cpool + CPOOL_SIZE); compiler->cpool_diff = 0xffffffff; #endif #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) compiler->delay_slot = UNMOVABLE_INS; #endif #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) compiler->delay_slot = UNMOVABLE_INS; #endif #if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT) if (!compiler_initialized) { init_compiler(); compiler_initialized = 1; } #endif return compiler; } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; struct sljit_memory_fragment *curr; void *allocator_data = compiler->allocator_data; SLJIT_UNUSED_ARG(allocator_data); buf = compiler->buf; while (buf) { curr = buf; buf = buf->next; SLJIT_FREE(curr, allocator_data); } buf = compiler->abuf; while (buf) { curr = buf; buf = buf->next; SLJIT_FREE(curr, allocator_data); } #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) SLJIT_FREE(compiler->cpool, allocator_data); #endif SLJIT_FREE(compiler, allocator_data); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler) { if (compiler->error == SLJIT_SUCCESS) compiler->error = SLJIT_ERR_ALLOC_FAILED; } #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) { /* Remove thumb mode flag. */ SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1)); } #elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) { /* Resolve indirection. */ code = (void*)(*(sljit_uw*)code); SLJIT_FREE_EXEC(code); } #else SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) { SLJIT_FREE_EXEC(code); } #endif SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label) { if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) { jump->flags &= ~JUMP_ADDR; jump->flags |= JUMP_LABEL; jump->u.label = label; } } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) { if (SLJIT_LIKELY(!!jump)) { jump->flags &= ~JUMP_LABEL; jump->flags |= JUMP_ADDR; jump->u.target = target; } } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(current_flags); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_I32_OP | SLJIT_SET_Z)) == 0) { compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z)); } #endif } /* --------------------------------------------------------------------- */ /* Private functions */ /* --------------------------------------------------------------------- */ static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size) { sljit_u8 *ret; struct sljit_memory_fragment *new_frag; SLJIT_ASSERT(size <= 256); if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) { ret = compiler->buf->memory + compiler->buf->used_size; compiler->buf->used_size += size; return ret; } new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, compiler->allocator_data); PTR_FAIL_IF_NULL(new_frag); new_frag->next = compiler->buf; compiler->buf = new_frag; new_frag->used_size = size; return new_frag->memory; } static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size) { sljit_u8 *ret; struct sljit_memory_fragment *new_frag; SLJIT_ASSERT(size <= 256); if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) { ret = compiler->abuf->memory + compiler->abuf->used_size; compiler->abuf->used_size += size; return ret; } new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, compiler->allocator_data); PTR_FAIL_IF_NULL(new_frag); new_frag->next = compiler->abuf; compiler->abuf = new_frag; new_frag->used_size = size; return new_frag->memory; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size) { CHECK_ERROR_PTR(); #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) if (size <= 0 || size > 128) return NULL; size = (size + 7) & ~7; #else if (size <= 0 || size > 64) return NULL; size = (size + 3) & ~3; #endif return ensure_abuf(compiler, size); } static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf = compiler->buf; struct sljit_memory_fragment *prev = NULL; struct sljit_memory_fragment *tmp; do { tmp = buf->next; buf->next = prev; prev = buf; buf = tmp; } while (buf != NULL); compiler->buf = prev; } static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types) { sljit_s32 arg_count = 0; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { arg_count++; arg_types >>= SLJIT_DEF_SHIFT; } return arg_count; } static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(args); SLJIT_UNUSED_ARG(local_size); compiler->options = options; compiler->scratches = scratches; compiler->saveds = saveds; compiler->fscratches = fscratches; compiler->fsaveds = fsaveds; #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->logical_local_size = local_size; #endif } static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(args); SLJIT_UNUSED_ARG(local_size); compiler->options = options; compiler->scratches = scratches; compiler->saveds = saveds; compiler->fscratches = fscratches; compiler->fsaveds = fsaveds; #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->logical_local_size = local_size; #endif } static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler) { label->next = NULL; label->size = compiler->size; if (compiler->last_label) compiler->last_label->next = label; else compiler->labels = label; compiler->last_label = label; } static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_s32 flags) { jump->next = NULL; jump->flags = flags; if (compiler->last_jump) compiler->last_jump->next = jump; else compiler->jumps = jump; compiler->last_jump = jump; } static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler) { const_->next = NULL; const_->addr = compiler->size; if (compiler->last_const) compiler->last_const->next = const_; else compiler->consts = const_; compiler->last_const = const_; } #define ADDRESSING_DEPENDS_ON(exp, reg) \ (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg)) #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) #define FUNCTION_CHECK_IS_REG(r) \ (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \ || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0)) #define FUNCTION_CHECK_IS_FREG(fr) \ (((fr) >= SLJIT_FR0 && (fr) < (SLJIT_FR0 + compiler->fscratches)) \ || ((fr) > (SLJIT_FS0 - compiler->fsaveds) && (fr) <= SLJIT_FS0)) #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8) #else #define CHECK_IF_VIRTUAL_REGISTER(p) 0 #endif static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { if (compiler->scratches == -1 || compiler->saveds == -1) return 0; if (!(p & SLJIT_MEM)) return 0; if (!((p & REG_MASK) == SLJIT_UNUSED || FUNCTION_CHECK_IS_REG(p & REG_MASK))) return 0; if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK)) return 0; if (p & OFFS_REG_MASK) { if ((p & REG_MASK) == SLJIT_UNUSED) return 0; if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p)))) return 0; if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p))) return 0; if ((i & ~0x3) != 0) return 0; } return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0; } #define FUNCTION_CHECK_SRC_MEM(p, i) \ CHECK_ARGUMENT(function_check_src_mem(compiler, p, i)); static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { if (compiler->scratches == -1 || compiler->saveds == -1) return 0; if (FUNCTION_CHECK_IS_REG(p)) return (i == 0); if (p == SLJIT_IMM) return 1; if (p == SLJIT_MEM1(SLJIT_SP)) return (i >= 0 && i < compiler->logical_local_size); return function_check_src_mem(compiler, p, i); } #define FUNCTION_CHECK_SRC(p, i) \ CHECK_ARGUMENT(function_check_src(compiler, p, i)); static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 unused) { if (compiler->scratches == -1 || compiler->saveds == -1) return 0; if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED)) return (i == 0); if (p == SLJIT_MEM1(SLJIT_SP)) return (i >= 0 && i < compiler->logical_local_size); return function_check_src_mem(compiler, p, i); } #define FUNCTION_CHECK_DST(p, i, unused) \ CHECK_ARGUMENT(function_check_dst(compiler, p, i, unused)); static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { if (compiler->scratches == -1 || compiler->saveds == -1) return 0; if (FUNCTION_CHECK_IS_FREG(p)) return (i == 0); if (p == SLJIT_MEM1(SLJIT_SP)) return (i >= 0 && i < compiler->logical_local_size); return function_check_src_mem(compiler, p, i); } #define FUNCTION_FCHECK(p, i) \ CHECK_ARGUMENT(function_fcheck(compiler, p, i)); #endif /* SLJIT_ARGUMENT_CHECKS */ #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose) { compiler->verbose = verbose; } #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #ifdef _WIN64 # define SLJIT_PRINT_D "I64" #else # define SLJIT_PRINT_D "l" #endif #else # define SLJIT_PRINT_D "" #endif static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r) { if (r < (SLJIT_R0 + compiler->scratches)) fprintf(compiler->verbose, "r%d", r - SLJIT_R0); else if (r != SLJIT_SP) fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r); else fprintf(compiler->verbose, "sp"); } static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r) { if (r < (SLJIT_FR0 + compiler->fscratches)) fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0); else fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r); } static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { if ((p) & SLJIT_IMM) fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); else if ((p) & SLJIT_MEM) { if ((p) & REG_MASK) { fputc('[', compiler->verbose); sljit_verbose_reg(compiler, (p) & REG_MASK); if ((p) & OFFS_REG_MASK) { fprintf(compiler->verbose, " + "); sljit_verbose_reg(compiler, OFFS_REG(p)); if (i) fprintf(compiler->verbose, " * %d", 1 << (i)); } else if (i) fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); fputc(']', compiler->verbose); } else fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); } else if (p) sljit_verbose_reg(compiler, p); else fprintf(compiler->verbose, "unused"); } static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i) { if ((p) & SLJIT_MEM) { if ((p) & REG_MASK) { fputc('[', compiler->verbose); sljit_verbose_reg(compiler, (p) & REG_MASK); if ((p) & OFFS_REG_MASK) { fprintf(compiler->verbose, " + "); sljit_verbose_reg(compiler, OFFS_REG(p)); if (i) fprintf(compiler->verbose, "%d", 1 << (i)); } else if (i) fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i)); fputc(']', compiler->verbose); } else fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i)); } else sljit_verbose_freg(compiler, p); } static const char* op0_names[] = { (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw", (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s" }; static const char* op1_names[] = { (char*)"", (char*)".u8", (char*)".s8", (char*)".u16", (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p", (char*)"", (char*)".u8", (char*)".s8", (char*)".u16", (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p", (char*)"not", (char*)"neg", (char*)"clz", }; static const char* op2_names[] = { (char*)"add", (char*)"addc", (char*)"sub", (char*)"subc", (char*)"mul", (char*)"and", (char*)"or", (char*)"xor", (char*)"shl", (char*)"lshr", (char*)"ashr", }; static const char* fop1_names[] = { (char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv", (char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg", (char*)"abs", }; static const char* fop2_names[] = { (char*)"add", (char*)"sub", (char*)"mul", (char*)"div" }; #define JUMP_POSTFIX(type) \ ((type & 0xff) <= SLJIT_MUL_NOT_OVERFLOW ? ((type & SLJIT_I32_OP) ? "32" : "") \ : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_F32_OP) ? ".f32" : ".f64") : "")) static char* jump_names[] = { (char*)"equal", (char*)"not_equal", (char*)"less", (char*)"greater_equal", (char*)"greater", (char*)"less_equal", (char*)"sig_less", (char*)"sig_greater_equal", (char*)"sig_greater", (char*)"sig_less_equal", (char*)"overflow", (char*)"not_overflow", (char*)"mul_overflow", (char*)"mul_not_overflow", (char*)"carry", (char*)"", (char*)"equal", (char*)"not_equal", (char*)"less", (char*)"greater_equal", (char*)"greater", (char*)"less_equal", (char*)"unordered", (char*)"ordered", (char*)"jump", (char*)"fast_call", (char*)"call", (char*)"call.cdecl" }; static char* call_arg_names[] = { (char*)"void", (char*)"sw", (char*)"uw", (char*)"s32", (char*)"u32", (char*)"f32", (char*)"f64" }; #endif /* SLJIT_VERBOSE */ /* --------------------------------------------------------------------- */ /* Arch dependent */ /* --------------------------------------------------------------------- */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) struct sljit_jump *jump; #endif SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(compiler->size > 0); jump = compiler->jumps; while (jump) { /* All jumps have target. */ CHECK_ARGUMENT(jump->flags & (JUMP_LABEL | JUMP_ADDR)); jump = jump->next; } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) sljit_s32 types, arg_count, curr_type; #endif SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT)); CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); CHECK_ARGUMENT((arg_types & SLJIT_DEF_MASK) == 0); types = (arg_types >> SLJIT_DEF_SHIFT); arg_count = 0; while (types != 0 && arg_count < 3) { curr_type = (types & SLJIT_DEF_MASK); CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW); arg_count++; types >>= SLJIT_DEF_SHIFT; } CHECK_ARGUMENT(arg_count <= saveds && types == 0); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " enter options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : ""); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); arg_types >>= SLJIT_DEF_SHIFT; if (arg_types) fprintf(compiler->verbose, ","); } fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n", scratches, saveds, fscratches, fsaveds, local_size); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) sljit_s32 types, arg_count, curr_type; #endif SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT)); CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS); CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); types = (arg_types >> SLJIT_DEF_SHIFT); arg_count = 0; while (types != 0 && arg_count < 3) { curr_type = (types & SLJIT_DEF_MASK); CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW); arg_count++; types >>= SLJIT_DEF_SHIFT; } CHECK_ARGUMENT(arg_count <= saveds && types == 0); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " set_context options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : ""); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); arg_types >>= SLJIT_DEF_SHIFT; if (arg_types) fprintf(compiler->verbose, ","); } fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n", scratches, saveds, fscratches, fsaveds, local_size); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(compiler->scratches >= 0); if (op != SLJIT_UNUSED) { CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_P); FUNCTION_CHECK_SRC(src, srcw); } else CHECK_ARGUMENT(src == 0 && srcw == 0); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (op == SLJIT_UNUSED) fprintf(compiler->verbose, " return\n"); else { fprintf(compiler->verbose, " return%s ", op1_names[op - SLJIT_OP1_BASE]); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw, 0); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fast_enter "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_SRC(src, srcw); CHECK_ARGUMENT(src != SLJIT_IMM); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fast_return "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW) || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)); CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2); if (op >= SLJIT_LMUL_UW) compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]); if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW) { fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w"); } fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ); switch (GET_OPCODE(op)) { case SLJIT_NOT: /* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); break; case SLJIT_NEG: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW); break; case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_P: /* Nothing allowed */ CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))); break; default: /* Only SLJIT_I32_OP is allowed. */ CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); break; } FUNCTION_CHECK_DST(dst, dstw, 1); FUNCTION_CHECK_SRC(src, srcw); if (GET_OPCODE(op) >= SLJIT_NOT) { CHECK_ARGUMENT(src != SLJIT_IMM); compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (GET_OPCODE(op) <= SLJIT_MOV_P) { fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_I32_OP) ? "" : "32", (op != SLJIT_MOV32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ""); } else { fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32", !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".", !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]); } sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR); switch (GET_OPCODE(op)) { case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); break; case SLJIT_MUL: CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW); break; case SLJIT_ADD: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY) || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW); break; case SLJIT_SUB: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); break; case SLJIT_ADDC: case SLJIT_SUBC: CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)); CHECK_ARGUMENT((op & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP)); break; default: SLJIT_UNREACHABLE(); break; } FUNCTION_CHECK_DST(dst, dstw, 1); FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32", !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".", !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg) { SLJIT_UNUSED_ARG(reg); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS); #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit_s32 reg) { SLJIT_UNUSED_ARG(reg); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS); #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) int i; #endif SLJIT_UNUSED_ARG(compiler); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(instruction); #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) CHECK_ARGUMENT(size > 0 && size < 16); #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0) || (size == 4 && (((sljit_sw)instruction) & 0x3) == 0)); #else CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0); #endif compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " op_custom"); for (i = 0; i < size; i++) fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_MOV_F64 && GET_OPCODE(op) <= SLJIT_ABS_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src, srcw); FUNCTION_FCHECK(dst, dstw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32.from.f64" : ".f64.from.f32"); else fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64"); sljit_verbose_fparam(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); #endif if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) == SLJIT_CMP_F64); CHECK_ARGUMENT(!(op & SLJIT_SET_Z)); CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK) || (GET_FLAG_TYPE(op) >= SLJIT_EQUAL_F64 && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_F64)); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64"); if (op & VARIABLE_FLAG_MASK) { fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]); } fprintf(compiler->verbose, " "); sljit_verbose_fparam(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src, srcw); FUNCTION_CHECK_DST(dst, dstw, 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? ".s32" : ".sw", (op & SLJIT_F32_OP) ? ".f32" : ".f64"); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_SW && GET_OPCODE(op) <= SLJIT_CONV_F64_FROM_S32); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_CHECK_SRC(src, srcw); FUNCTION_FCHECK(dst, dstw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64", (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? ".s32" : ".sw"); sljit_verbose_fparam(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_ADD_F64 && GET_OPCODE(op) <= SLJIT_DIV_F64); CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); FUNCTION_FCHECK(dst, dstw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64"); sljit_verbose_fparam(compiler, dst, dstw); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) fprintf(compiler->verbose, "label:\n"); #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP))); CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1)); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL); CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP)); if ((type & 0xff) < SLJIT_JUMP) { if ((type & 0xff) <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW)); CHECK_ARGUMENT((type & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP)); } #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) fprintf(compiler->verbose, " jump%s %s%s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff], JUMP_POSTFIX(type)); #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) sljit_s32 i, types, curr_type, scratches, fscratches; CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP))); CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL); types = arg_types; scratches = 0; fscratches = 0; for (i = 0; i < 5; i++) { curr_type = (types & SLJIT_DEF_MASK); CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64); if (i > 0) { if (curr_type == 0) { break; } if (curr_type >= SLJIT_ARG_TYPE_F32) fscratches++; else scratches++; } else { if (curr_type >= SLJIT_ARG_TYPE_F32) { CHECK_ARGUMENT(compiler->fscratches > 0); } else if (curr_type >= SLJIT_ARG_TYPE_SW) { CHECK_ARGUMENT(compiler->scratches > 0); } } types >>= SLJIT_DEF_SHIFT; } CHECK_ARGUMENT(compiler->scratches >= scratches); CHECK_ARGUMENT(compiler->fscratches >= fscratches); CHECK_ARGUMENT(types == 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s%s ret[%s", jump_names[type & 0xff], !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]); arg_types >>= SLJIT_DEF_SHIFT; if (arg_types) { fprintf(compiler->verbose, "], args["); do { fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); arg_types >>= SLJIT_DEF_SHIFT; if (arg_types) fprintf(compiler->verbose, ","); } while (arg_types); } fprintf(compiler->verbose, "]\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL); FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " cmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff], (type & SLJIT_I32_OP) ? "32" : ""); sljit_verbose_param(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU)); CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64); FUNCTION_FCHECK(src1, src1w); FUNCTION_FCHECK(src2, src2w); compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " fcmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff], (type & SLJIT_F32_OP) ? ".f32" : ".f64"); sljit_verbose_fparam(compiler, src1, src1w); fprintf(compiler->verbose, ", "); sljit_verbose_fparam(compiler, src2, src2w); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { if (SLJIT_UNLIKELY(compiler->skip_checks)) { compiler->skip_checks = 0; CHECK_RETURN_OK; } #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL); FUNCTION_CHECK_SRC(src, srcw); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " ijump.%s ", jump_names[type]); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) sljit_s32 i, types, curr_type, scratches, fscratches; CHECK_ARGUMENT(type == SLJIT_CALL || type == SLJIT_CALL_CDECL); FUNCTION_CHECK_SRC(src, srcw); types = arg_types; scratches = 0; fscratches = 0; for (i = 0; i < 5; i++) { curr_type = (types & SLJIT_DEF_MASK); CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64); if (i > 0) { if (curr_type == 0) { break; } if (curr_type >= SLJIT_ARG_TYPE_F32) fscratches++; else scratches++; } else { if (curr_type >= SLJIT_ARG_TYPE_F32) { CHECK_ARGUMENT(compiler->fscratches > 0); } else if (curr_type >= SLJIT_ARG_TYPE_SW) { CHECK_ARGUMENT(compiler->scratches > 0); } } types >>= SLJIT_DEF_SHIFT; } CHECK_ARGUMENT(compiler->scratches >= scratches); CHECK_ARGUMENT(compiler->fscratches >= fscratches); CHECK_ARGUMENT(types == 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff], !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]); arg_types >>= SLJIT_DEF_SHIFT; if (arg_types) { fprintf(compiler->verbose, "], args["); do { fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]); arg_types >>= SLJIT_DEF_SHIFT; if (arg_types) fprintf(compiler->verbose, ","); } while (arg_types); } fprintf(compiler->verbose, "], "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1)); CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32 || (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR)); CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)); if ((type & 0xff) <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW)); FUNCTION_CHECK_DST(dst, dstw, 0); if (GET_OPCODE(op) >= SLJIT_ADD) compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " flags%s %s%s, ", !(op & SLJIT_SET_Z) ? "" : ".z", GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_I32_OP) ? "32" : "")); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type)); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP))); CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64); CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP)); if (src != SLJIT_IMM) { CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src)); CHECK_ARGUMENT(srcw == 0); } if ((type & 0xff) <= SLJIT_NOT_ZERO) CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z); else CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff) || ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW) || ((type & 0xff) == SLJIT_MUL_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_MUL_OVERFLOW)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " cmov%s %s%s, ", !(dst_reg & SLJIT_I32_OP) ? "" : "32", jump_names[type & 0xff], JUMP_POSTFIX(type)); sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, src, srcw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P); CHECK_ARGUMENT(!(type & SLJIT_I32_OP) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P)); CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); FUNCTION_CHECK_SRC_MEM(mem, memw); CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg)); CHECK_ARGUMENT((mem & REG_MASK) != SLJIT_UNUSED && (mem & REG_MASK) != reg); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) { if (sljit_emit_mem(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) fprintf(compiler->verbose, " //"); fprintf(compiler->verbose, " mem%s.%s%s%s ", !(type & SLJIT_I32_OP) ? "" : "32", (type & SLJIT_MEM_STORE) ? "st" : "ld", op1_names[(type & 0xff) - SLJIT_OP1_BASE], (type & SLJIT_MEM_PRE) ? ".pre" : ".post"); sljit_verbose_reg(compiler, reg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, mem, memw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64); CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST)); CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST)); CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0); FUNCTION_CHECK_SRC_MEM(mem, memw); CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) { if (sljit_emit_fmem(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) fprintf(compiler->verbose, " //"); fprintf(compiler->verbose, " fmem.%s%s%s ", (type & SLJIT_MEM_STORE) ? "st" : "ld", !(type & SLJIT_I32_OP) ? ".f64" : ".f32", (type & SLJIT_MEM_PRE) ? ".pre" : ".post"); sljit_verbose_freg(compiler, freg); fprintf(compiler->verbose, ", "); sljit_verbose_param(compiler, mem, memw); fprintf(compiler->verbose, "\n"); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { /* Any offset is allowed. */ SLJIT_UNUSED_ARG(offset); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw, 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " local_base "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset); } #endif CHECK_RETURN_OK; } static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { SLJIT_UNUSED_ARG(init_value); #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw, 0); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " const "); sljit_verbose_param(compiler, dst, dstw); fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value); } #endif CHECK_RETURN_OK; } #endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */ #define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \ SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1), \ invalid_float_opcodes); \ if (GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CMP_F64) { \ if (GET_OPCODE(op) == SLJIT_CMP_F64) { \ CHECK(check_sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw)); \ ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); \ return sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \ } \ if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_S32_FROM_F64) { \ CHECK(check_sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw)); \ ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); \ return sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \ } \ CHECK(check_sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw)); \ ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); \ return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \ } \ CHECK(check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw)); \ ADJUST_LOCAL_OFFSET(dst, dstw); \ ADJUST_LOCAL_OFFSET(src, srcw); static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { /* Return if don't need to do anything. */ if (op == SLJIT_UNUSED) return SLJIT_SUCCESS; #if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P)) return SLJIT_SUCCESS; #else if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P)) return SLJIT_SUCCESS; #endif #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) compiler->skip_checks = 1; #endif return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); } #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)) static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { struct sljit_label *label; struct sljit_jump *jump; sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV; #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif jump = sljit_emit_jump(compiler, type ^ 0x1); FAIL_IF(!jump); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif label = sljit_emit_label(compiler); FAIL_IF(!label); sljit_set_label(jump, label); return SLJIT_SUCCESS; } #endif /* CPU description section */ #if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) #define SLJIT_CPUINFO_PART1 " 32bit (" #elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) #define SLJIT_CPUINFO_PART1 " 64bit (" #else #error "Internal error: CPU type info missing" #endif #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) #define SLJIT_CPUINFO_PART2 "little endian + " #elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) #define SLJIT_CPUINFO_PART2 "big endian + " #else #error "Internal error: CPU type info missing" #endif #if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) #define SLJIT_CPUINFO_PART3 "unaligned)" #else #define SLJIT_CPUINFO_PART3 "aligned)" #endif #define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) # include "sljitNativeX86_common.c" #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) # include "sljitNativeARM_32.c" #elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) # include "sljitNativeARM_32.c" #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) # include "sljitNativeARM_T2_32.c" #elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) # include "sljitNativeARM_64.c" #elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) # include "sljitNativePPC_common.c" #elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) # include "sljitNativeMIPS_common.c" #elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) # include "sljitNativeSPARC_common.c" #elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) # include "sljitNativeTILEGX_64.c" #endif #if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* Default compare for most architectures. */ sljit_s32 flags, tmp_src, condition; sljit_sw tmp_srcw; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w)); condition = type & 0xff; #if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) { if ((src1 & SLJIT_IMM) && !src1w) { src1 = src2; src1w = src2w; src2 = SLJIT_IMM; src2w = 0; } if ((src2 & SLJIT_IMM) && !src2w) return emit_cmp_to0(compiler, type, src1, src1w); } #endif if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) { /* Immediate is prefered as second argument by most architectures. */ switch (condition) { case SLJIT_LESS: condition = SLJIT_GREATER; break; case SLJIT_GREATER_EQUAL: condition = SLJIT_LESS_EQUAL; break; case SLJIT_GREATER: condition = SLJIT_LESS; break; case SLJIT_LESS_EQUAL: condition = SLJIT_GREATER_EQUAL; break; case SLJIT_SIG_LESS: condition = SLJIT_SIG_GREATER; break; case SLJIT_SIG_GREATER_EQUAL: condition = SLJIT_SIG_LESS_EQUAL; break; case SLJIT_SIG_GREATER: condition = SLJIT_SIG_LESS; break; case SLJIT_SIG_LESS_EQUAL: condition = SLJIT_SIG_GREATER_EQUAL; break; } type = condition | (type & (SLJIT_I32_OP | SLJIT_REWRITABLE_JUMP)); tmp_src = src1; src1 = src2; src2 = tmp_src; tmp_srcw = src1w; src1w = src2w; src2w = tmp_srcw; } if (condition <= SLJIT_NOT_ZERO) flags = SLJIT_SET_Z; else flags = condition << VARIABLE_FLAG_SHIFT; #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_I32_OP), SLJIT_UNUSED, 0, src1, src1w, src2, src2w)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP))); } #endif SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_I32_OP), src1, src1w, src2, src2w); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); } #if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(reg); SLJIT_UNUSED_ARG(mem); SLJIT_UNUSED_ARG(memw); CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); return SLJIT_ERR_UNSUPPORTED; } #endif #if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(mem); SLJIT_UNUSED_ARG(memw); CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); return SLJIT_ERR_UNSUPPORTED; } #endif #if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { CHECK_ERROR(); CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif if (offset != 0) return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0); } #endif #else /* SLJIT_CONFIG_UNSUPPORTED */ /* Empty function bodies for those machines, which are not (yet) supported. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { return "unsupported"; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data) { SLJIT_UNUSED_ARG(allocator_data); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(size); SLJIT_UNREACHABLE(); return NULL; } #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(verbose); SLJIT_UNREACHABLE(); } #endif SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { SLJIT_UNUSED_ARG(feature_type); SLJIT_UNREACHABLE(); return 0; } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) { SLJIT_UNUSED_ARG(code); SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(options); SLJIT_UNUSED_ARG(arg_types); SLJIT_UNUSED_ARG(scratches); SLJIT_UNUSED_ARG(saveds); SLJIT_UNUSED_ARG(fscratches); SLJIT_UNUSED_ARG(fsaveds); SLJIT_UNUSED_ARG(local_size); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(options); SLJIT_UNUSED_ARG(arg_types); SLJIT_UNUSED_ARG(scratches); SLJIT_UNUSED_ARG(saveds); SLJIT_UNUSED_ARG(fscratches); SLJIT_UNUSED_ARG(fsaveds); SLJIT_UNUSED_ARG(local_size); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(src1); SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { SLJIT_UNREACHABLE(); return reg; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(instruction); SLJIT_UNUSED_ARG(size); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(current_flags); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(src1); SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(arg_types); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(src1); SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(src1); SLJIT_UNUSED_ARG(src1w); SLJIT_UNUSED_ARG(src2); SLJIT_UNUSED_ARG(src2w); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label) { SLJIT_UNUSED_ARG(jump); SLJIT_UNUSED_ARG(label); SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) { SLJIT_UNUSED_ARG(jump); SLJIT_UNUSED_ARG(target); SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(arg_types); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(op); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(type); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(dst_reg); SLJIT_UNUSED_ARG(src); SLJIT_UNUSED_ARG(srcw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(reg); SLJIT_UNUSED_ARG(mem); SLJIT_UNUSED_ARG(memw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(type); SLJIT_UNUSED_ARG(freg); SLJIT_UNUSED_ARG(mem); SLJIT_UNUSED_ARG(memw); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(offset); SLJIT_UNREACHABLE(); return SLJIT_ERR_UNSUPPORTED; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw initval) { SLJIT_UNUSED_ARG(compiler); SLJIT_UNUSED_ARG(dst); SLJIT_UNUSED_ARG(dstw); SLJIT_UNUSED_ARG(initval); SLJIT_UNREACHABLE(); return NULL; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { SLJIT_UNUSED_ARG(addr); SLJIT_UNUSED_ARG(new_target); SLJIT_UNUSED_ARG(executable_offset); SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { SLJIT_UNUSED_ARG(addr); SLJIT_UNUSED_ARG(new_constant); SLJIT_UNUSED_ARG(executable_offset); SLJIT_UNREACHABLE(); } #endif ================================================ FILE: src/pcre/sljit/sljitLir.h ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 _SLJIT_LIR_H_ #define _SLJIT_LIR_H_ /* ------------------------------------------------------------------------ Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC) ------------------------------------------------------------------------ Short description Advantages: - The execution can be continued from any LIR instruction. In other words, it is possible to jump to any label from anywhere, even from a code fragment, which is compiled later, if both compiled code shares the same context. See sljit_emit_enter for more details - Supports self modifying code: target of (conditional) jump and call instructions and some constant values can be dynamically modified during runtime - although it is not suggested to do it frequently - can be used for inline caching: save an important value once in the instruction stream - since this feature limits the optimization possibilities, a special flag must be passed at compile time when these instructions are emitted - A fixed stack space can be allocated for local variables - The compiler is thread-safe - The compiler is highly configurable through preprocessor macros. You can disable unneeded features (multithreading in single threaded applications), and you can use your own system functions (including memory allocators). See sljitConfig.h Disadvantages: - No automatic register allocation, and temporary results are not stored on the stack. (hence the name comes) In practice: - This approach is very effective for interpreters - One of the saved registers typically points to a stack interface - It can jump to any exception handler anytime (even if it belongs to another function) - Hot paths can be modified during runtime reflecting the changes of the fastest execution path of the dynamic language - SLJIT supports complex memory addressing modes - mainly position and context independent code (except some cases) For valgrind users: - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code" */ #if !(defined SLJIT_NO_DEFAULT_CONFIG && SLJIT_NO_DEFAULT_CONFIG) #include "sljitConfig.h" #endif /* The following header file defines useful macros for fine tuning sljit based code generators. They are listed in the beginning of sljitConfigInternal.h */ #include "sljitConfigInternal.h" /* --------------------------------------------------------------------- */ /* Error codes */ /* --------------------------------------------------------------------- */ /* Indicates no error. */ #define SLJIT_SUCCESS 0 /* After the call of sljit_generate_code(), the error code of the compiler is set to this value to avoid future sljit calls (in debug mode at least). The complier should be freed after sljit_generate_code(). */ #define SLJIT_ERR_COMPILED 1 /* Cannot allocate non executable memory. */ #define SLJIT_ERR_ALLOC_FAILED 2 /* Cannot allocate executable memory. Only for sljit_generate_code() */ #define SLJIT_ERR_EX_ALLOC_FAILED 3 /* Return value for SLJIT_CONFIG_UNSUPPORTED placeholder architecture. */ #define SLJIT_ERR_UNSUPPORTED 4 /* An ivalid argument is passed to any SLJIT function. */ #define SLJIT_ERR_BAD_ARGUMENT 5 /* Dynamic code modification is not enabled. */ #define SLJIT_ERR_DYN_CODE_MOD 6 /* --------------------------------------------------------------------- */ /* Registers */ /* --------------------------------------------------------------------- */ /* Scratch (R) registers: registers whose may not preserve their values across function calls. Saved (S) registers: registers whose preserve their values across function calls. The scratch and saved register sets are overlap. The last scratch register is the first saved register, the one before the last is the second saved register, and so on. If an architecture provides two scratch and three saved registers, its scratch and saved register sets are the following: R0 | | R0 is always a scratch register R1 | | R1 is always a scratch register [R2] | S2 | R2 and S2 represent the same physical register [R3] | S1 | R3 and S1 represent the same physical register [R4] | S0 | R4 and S0 represent the same physical register Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS would be 2 and SLJIT_NUMBER_OF_SAVED_REGISTERS would be 3 for this architecture. Note: On all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12 and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers are virtual on x86-32. See below. The purpose of this definition is convenience: saved registers can be used as extra scratch registers. For example four registers can be specified as scratch registers and the fifth one as saved register on the CPU above and any user code which requires four scratch registers can run unmodified. The SLJIT compiler automatically saves the content of the two extra scratch register on the stack. Scratch registers can also be preserved by saving their value on the stack but this needs to be done manually. Note: To emphasize that registers assigned to R2-R4 are saved registers, they are enclosed by square brackets. Note: sljit_emit_enter and sljit_set_context defines whether a register is S or R register. E.g: when 3 scratches and 1 saved is mapped by sljit_emit_enter, the allowed register set will be: R0-R2 and S0. Although S2 is mapped to the same position as R2, it does not available in the current configuration. Furthermore the S1 register is not available at all. */ /* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 or sljit_emit_op2 operations the result is discarded. If no status flags are set, no instructions are emitted for these operations. Data prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT operations do not support SLJIT_UNUSED as a destination operand. */ #define SLJIT_UNUSED 0 /* Scratch registers. */ #define SLJIT_R0 1 #define SLJIT_R1 2 #define SLJIT_R2 3 /* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they are allocated on the stack). These registers are called virtual and cannot be used for memory addressing (cannot be part of any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such limitation on other CPUs. See sljit_get_register_index(). */ #define SLJIT_R3 4 #define SLJIT_R4 5 #define SLJIT_R5 6 #define SLJIT_R6 7 #define SLJIT_R7 8 #define SLJIT_R8 9 #define SLJIT_R9 10 /* All R registers provided by the architecture can be accessed by SLJIT_R(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */ #define SLJIT_R(i) (1 + (i)) /* Saved registers. */ #define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS) #define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1) #define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2) /* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they are allocated on the stack). These registers are called virtual and cannot be used for memory addressing (cannot be part of any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such limitation on other CPUs. See sljit_get_register_index(). */ #define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3) #define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4) #define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5) #define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6) #define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7) #define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8) #define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9) /* All S registers provided by the architecture can be accessed by SLJIT_S(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */ #define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i)) /* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */ #define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1) /* The SLJIT_SP provides direct access to the linear stack space allocated by sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP). The immediate offset is extended by the relative stack offset automatically. The sljit_get_local_base can be used to obtain the absolute offset. */ #define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1) /* Return with machine word. */ #define SLJIT_RETURN_REG SLJIT_R0 /* --------------------------------------------------------------------- */ /* Floating point registers */ /* --------------------------------------------------------------------- */ /* Each floating point register can store a 32 or a 64 bit precision value. The FR and FS register sets are overlap in the same way as R and S register sets. See above. */ /* Note: SLJIT_UNUSED as destination is not valid for floating point operations, since they cannot be used for setting flags. */ /* Floating point scratch registers. */ #define SLJIT_FR0 1 #define SLJIT_FR1 2 #define SLJIT_FR2 3 #define SLJIT_FR3 4 #define SLJIT_FR4 5 #define SLJIT_FR5 6 /* All FR registers provided by the architecture can be accessed by SLJIT_FR(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */ #define SLJIT_FR(i) (1 + (i)) /* Floating point saved registers. */ #define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS) #define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1) #define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2) #define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3) #define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4) #define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5) /* All S registers provided by the architecture can be accessed by SLJIT_FS(i) The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */ #define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i)) /* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */ #define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1) /* --------------------------------------------------------------------- */ /* Argument type definitions */ /* --------------------------------------------------------------------- */ /* Argument type definitions. Used by SLJIT_[DEF_]ARGx and SLJIT_[DEF]_RET macros. */ #define SLJIT_ARG_TYPE_VOID 0 #define SLJIT_ARG_TYPE_SW 1 #define SLJIT_ARG_TYPE_UW 2 #define SLJIT_ARG_TYPE_S32 3 #define SLJIT_ARG_TYPE_U32 4 #define SLJIT_ARG_TYPE_F32 5 #define SLJIT_ARG_TYPE_F64 6 /* The following argument type definitions are used by sljit_emit_enter, sljit_set_context, sljit_emit_call, and sljit_emit_icall functions. The following return type definitions are used by sljit_emit_call and sljit_emit_icall functions. When a function is called, the first integer argument must be placed in SLJIT_R0, the second in SLJIT_R1, and so on. Similarly the first floating point argument must be placed in SLJIT_FR0, the second in SLJIT_FR1, and so on. Example function definition: sljit_f32 SLJIT_FUNC example_c_callback(sljit_sw arg_a, sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d); Argument type definition: SLJIT_DEF_RET(SLJIT_ARG_TYPE_F32) | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F64) | SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_U32) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F32) Short form of argument type definition: SLJIT_RET(F32) | SLJIT_ARG1(SW) | SLJIT_ARG2(F64) | SLJIT_ARG3(S32) | SLJIT_ARG4(F32) Argument passing: arg_a must be placed in SLJIT_R0 arg_c must be placed in SLJIT_R1 arg_b must be placed in SLJIT_FR0 arg_d must be placed in SLJIT_FR1 Note: The SLJIT_ARG_TYPE_VOID type is only supported by SLJIT_DEF_RET, and SLJIT_ARG_TYPE_VOID is also the default value when SLJIT_DEF_RET is not specified. */ #define SLJIT_DEF_SHIFT 4 #define SLJIT_DEF_RET(type) (type) #define SLJIT_DEF_ARG1(type) ((type) << SLJIT_DEF_SHIFT) #define SLJIT_DEF_ARG2(type) ((type) << (2 * SLJIT_DEF_SHIFT)) #define SLJIT_DEF_ARG3(type) ((type) << (3 * SLJIT_DEF_SHIFT)) #define SLJIT_DEF_ARG4(type) ((type) << (4 * SLJIT_DEF_SHIFT)) /* Short form of the macros above. For example the following definition: SLJIT_DEF_RET(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_F32) can be shortened to: SLJIT_RET(SW) | SLJIT_ARG1(F32) Note: The VOID type is only supported by SLJIT_RET, and VOID is also the default value when SLJIT_RET is not specified. */ #define SLJIT_RET(type) SLJIT_DEF_RET(SLJIT_ARG_TYPE_ ## type) #define SLJIT_ARG1(type) SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_ ## type) #define SLJIT_ARG2(type) SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_ ## type) #define SLJIT_ARG3(type) SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_ ## type) #define SLJIT_ARG4(type) SLJIT_DEF_ARG4(SLJIT_ARG_TYPE_ ## type) /* --------------------------------------------------------------------- */ /* Main structures and functions */ /* --------------------------------------------------------------------- */ /* The following structures are private, and can be changed in the future. Keeping them here allows code inlining. */ struct sljit_memory_fragment { struct sljit_memory_fragment *next; sljit_uw used_size; /* Must be aligned to sljit_sw. */ sljit_u8 memory[1]; }; struct sljit_label { struct sljit_label *next; sljit_uw addr; /* The maximum size difference. */ sljit_uw size; }; struct sljit_jump { struct sljit_jump *next; sljit_uw addr; sljit_sw flags; union { sljit_uw target; struct sljit_label* label; } u; }; struct sljit_const { struct sljit_const *next; sljit_uw addr; }; struct sljit_compiler { sljit_s32 error; sljit_s32 options; struct sljit_label *labels; struct sljit_jump *jumps; struct sljit_const *consts; struct sljit_label *last_label; struct sljit_jump *last_jump; struct sljit_const *last_const; void *allocator_data; struct sljit_memory_fragment *buf; struct sljit_memory_fragment *abuf; /* Used scratch registers. */ sljit_s32 scratches; /* Used saved registers. */ sljit_s32 saveds; /* Used float scratch registers. */ sljit_s32 fscratches; /* Used float saved registers. */ sljit_s32 fsaveds; /* Local stack size. */ sljit_s32 local_size; /* Code size. */ sljit_uw size; /* Relative offset of the executable mapping from the writable mapping. */ sljit_uw executable_offset; /* Executable size for statistical purposes. */ sljit_uw executable_size; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 args; sljit_s32 locals_offset; sljit_s32 saveds_offset; sljit_s32 stack_tmp_size; #endif #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 mode32; #ifdef _WIN64 sljit_s32 locals_offset; #endif #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) /* Constant pool handling. */ sljit_uw *cpool; sljit_u8 *cpool_unique; sljit_uw cpool_diff; sljit_uw cpool_fill; /* Other members. */ /* Contains pointer, "ldr pc, [...]" pairs. */ sljit_uw patches; #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) /* Temporary fields. */ sljit_uw shift_imm; #endif #if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) sljit_sw imm; #endif #if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) sljit_s32 delay_slot; sljit_s32 cache_arg; sljit_sw cache_argw; #endif #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) sljit_s32 delay_slot; sljit_s32 cache_arg; sljit_sw cache_argw; #endif #if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) sljit_s32 cache_arg; sljit_sw cache_argw; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) FILE* verbose; #endif #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) /* Flags specified by the last arithmetic instruction. It contains the type of the variable flag. */ sljit_s32 last_flags; /* Local size passed to the functions. */ sljit_s32 logical_local_size; #endif #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) /* Trust arguments when the API function is called. */ sljit_s32 skip_checks; #endif }; /* --------------------------------------------------------------------- */ /* Main functions */ /* --------------------------------------------------------------------- */ /* Creates an sljit compiler. The allocator_data is required by some custom memory managers. This pointer is passed to SLJIT_MALLOC and SLJIT_FREE macros. Most allocators (including the default one) ignores this value, and it is recommended to pass NULL as a dummy value for allocator_data. Returns NULL if failed. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data); /* Frees everything except the compiled machine code. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); /* Returns the current error code. If an error is occurred, future sljit calls which uses the same compiler argument returns early with the same error code. Thus there is no need for checking the error after every call, it is enough to do it before the code is compiled. Removing these checks increases the performance of the compiling process. */ static SLJIT_INLINE sljit_s32 sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } /* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except if an error was detected before. After the error code is set the compiler behaves as if the allocation failure happened during an sljit function call. This can greatly simplify error checking, since only the compiler status needs to be checked after the compilation. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler); /* Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler, and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_sw) aligned. Excellent for allocating small blocks during the compiling, and no need to worry about freeing them. The size is enough to contain at most 16 pointers. If the size is outside of the range, the function will return with NULL. However, this return value does not indicate that there is no more memory (does not set the current error code of the compiler to out-of-memory status). */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) /* Passing NULL disables verbose. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose); #endif /* Create executable code from the sljit instruction stream. This is the final step of the code generation so no more instructions can be added after this call. */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler); /* Free executable code. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code); /* When the protected executable allocator is used the JIT code is mapped twice. The first mapping has read/write and the second mapping has read/exec permissions. This function returns with the relative offset of the executable mapping using the writable mapping as the base after the machine code is successfully generated. The returned value is always 0 for the normal executable allocator, since it uses only one mapping with read/write/exec permissions. Dynamic code modifications requires this value. Before a successful code generation, this function returns with 0. */ static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *compiler) { return compiler->executable_offset; } /* The executable memory consumption of the generated code can be retrieved by this function. The returned value can be used for statistical purposes. Before a successful code generation, this function returns with 0. */ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } /* Returns with non-zero if the feature or limitation type passed as its argument is present on the current CPU. Some features (e.g. floating point operations) require hardware (CPU) support while others (e.g. move with update) are emulated if not available. However even if a feature is emulated, specialized code paths can be faster than the emulation. Some limitations are emulated as well so their general case is supported but it has extra performance costs. */ /* [Not emulated] Floating-point support is available. */ #define SLJIT_HAS_FPU 0 /* [Limitation] Some registers are virtual registers. */ #define SLJIT_HAS_VIRTUAL_REGISTERS 1 /* [Emulated] Count leading zero is supported. */ #define SLJIT_HAS_CLZ 2 /* [Emulated] Conditional move is supported. */ #define SLJIT_HAS_CMOV 3 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* [Not emulated] SSE2 support is available on x86. */ #define SLJIT_HAS_SSE2 100 #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type); /* Instruction generation. Returns with any error code. If there is no error, they return with SLJIT_SUCCESS. */ /* The executable code is a function from the viewpoint of the C language. The function calls must obey to the ABI (Application Binary Interface) of the platform, which specify the purpose of machine registers and stack handling among other things. The sljit_emit_enter function emits the necessary instructions for setting up a new context for the executable code and moves function arguments to the saved registers. Furthermore the options argument can be used to pass configuration options to the compiler. The available options are listed before sljit_emit_enter. The function argument list is the combination of SLJIT_ARGx (SLJIT_DEF_ARG1) macros. Currently maximum 3 SW / UW (SLJIT_ARG_TYPE_SW / LJIT_ARG_TYPE_UW) arguments are supported. The first argument goes to SLJIT_S0, the second goes to SLJIT_S1 and so on. The register set used by the function must be declared as well. The number of scratch and saved registers used by the function must be passed to sljit_emit_enter. Only R registers between R0 and "scratches" argument can be used later. E.g. if "scratches" is set to 2, the scratch register set will be limited to SLJIT_R0 and SLJIT_R1. The S registers and the floating point registers ("fscratches" and "fsaveds") are specified in a similar manner. The sljit_emit_enter is also capable of allocating a stack space for local variables. The "local_size" argument contains the size in bytes of this local area and its staring address is stored in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and SLJIT_SP + local_size (exclusive) can be modified freely until the function returns. The stack space is not initialized. Note: the following conditions must met: 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS 0 <= saveds <= SLJIT_NUMBER_OF_REGISTERS scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS 0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS 0 <= fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS Note: every call of sljit_emit_enter and sljit_set_context overwrites the previous context. */ /* The absolute address returned by sljit_get_local_base with offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */ #define SLJIT_F64_ALIGNMENT 0x00000001 /* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */ #define SLJIT_MAX_LOCAL_SIZE 65536 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); /* The machine code has a context (which contains the local stack space size, number of used registers, etc.) which initialized by sljit_emit_enter. Several functions (like sljit_emit_return) requres this context to be able to generate the appropriate code. However, some code fragments (like inline cache) may have no normal entry point so their context is unknown for the compiler. Their context can be provided to the compiler by the sljit_set_context function. Note: every call of sljit_emit_enter and sljit_set_context overwrites the previous context. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size); /* Return from machine code. The op argument can be SLJIT_UNUSED which means the function does not return with anything or any opcode between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op is SLJIT_UNUSED, otherwise see below the description about source and destination arguments. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw); /* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL). Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the values of all registers and stack frame. The return address is stored in the dst argument of sljit_emit_fast_enter, and this return address can be passed to sljit_emit_fast_return to continue the execution after the fast call. Fast calls are cheap operations (usually only a single call instruction is emitted) but they do not preserve any registers. However the callee function can freely use / update any registers and stack values which can be efficiently exploited by various optimizations. Registers can be saved manually by the callee function if needed. Although returning to different address by sljit_emit_fast_return is possible, this address usually cannot be predicted by the return address predictor of modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump to return is also inefficient since return address prediction is usually triggered by a specific form of ijump. Flags: - (does not modify flags). */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw); /* Source and destination operands for arithmetical instructions imm - a simple immediate value (cannot be used as a destination) reg - any of the registers (immediate argument must be 0) [imm] - absolute immediate memory address [reg+imm] - indirect memory address [reg+(reg<addr; } static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; } static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; } /* Only the address and executable offset are required to perform dynamic code modifications. See sljit_get_executable_offset function. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset); SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset); /* --------------------------------------------------------------------- */ /* Miscellaneous utility functions */ /* --------------------------------------------------------------------- */ #define SLJIT_MAJOR_VERSION 0 #define SLJIT_MINOR_VERSION 94 /* Get the human readable name of the platform. Can be useful on platforms like ARM, where ARM and Thumb2 functions can be mixed, and it is useful to know the type of the code generator. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void); /* Portable helper function to get an offset of a member. */ #define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10) #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) /* This global lock is useful to compile common functions. */ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void); SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void); #endif #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) /* The sljit_stack structure and its manipulation functions provides an implementation for a top-down stack. The stack top is stored in the end field of the sljit_stack structure and the stack goes down to the min_start field, so the memory region reserved for this stack is between min_start (inclusive) and end (exclusive) fields. However the application can only use the region between start (inclusive) and end (exclusive) fields. The sljit_stack_resize function can be used to extend this region up to min_start. This feature uses the "address space reserve" feature of modern operating systems. Instead of allocating a large memory block applications can allocate a small memory region and extend it later without moving the content of the memory area. Therefore after a successful resize by sljit_stack_resize all pointers into this region are still valid. Note: this structure may not be supported by all operating systems. end and max_limit fields are aligned to PAGE_SIZE bytes (usually 4 Kbyte or more). stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */ struct sljit_stack { /* User data, anything can be stored here. Initialized to the same value as the end field. */ sljit_u8 *top; /* These members are read only. */ /* End address of the stack */ sljit_u8 *end; /* Current start address of the stack. */ sljit_u8 *start; /* Lowest start address of the stack. */ sljit_u8 *min_start; }; /* Allocates a new stack. Returns NULL if unsuccessful. Note: see sljit_create_compiler for the explanation of allocator_data. */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data); SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data); /* Can be used to increase (extend) or decrease (shrink) the stack memory area. Returns with new_start if successful and NULL otherwise. It always fails if new_start is less than min_start or greater or equal than end fields. The fields of the stack are not changed if the returned value is NULL (the current memory content is never lost). */ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start); #endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */ #if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) /* Get the entry address of a given function. */ #define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)func_name) #else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ /* All JIT related code should be placed in the same context (library, binary, etc.). */ #define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(void*)func_name) /* For powerpc64, the function pointers point to a context descriptor. */ struct sljit_function_context { sljit_sw addr; sljit_sw r2; sljit_sw r11; }; /* Fill the context arguments using the addr and the function. If func_ptr is NULL, it will not be set to the address of context If addr is NULL, the function address also comes from the func pointer. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func); #endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) /* Free unused executable memory. The allocator keeps some free memory around to reduce the number of OS executable memory allocations. This improves performance since these calls are costly. However it is sometimes desired to free all unused memory regions, e.g. before the application terminates. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #endif /* --------------------------------------------------------------------- */ /* CPU specific functions */ /* --------------------------------------------------------------------- */ /* The following function is a helper function for sljit_emit_op_custom. It returns with the real machine register index ( >=0 ) of any SLJIT_R, SLJIT_S and SLJIT_SP registers. Note: it returns with -1 for virtual registers (only on x86-32). */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg); /* The following function is a helper function for sljit_emit_op_custom. It returns with the real machine register index of any SLJIT_FLOAT register. Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg); /* Any instruction can be inserted into the instruction stream by sljit_emit_op_custom. It has a similar purpose as inline assembly. The size parameter must match to the instruction size of the target architecture: x86: 0 < size <= 15. The instruction argument can be byte aligned. Thumb2: if size == 2, the instruction argument must be 2 byte aligned. if size == 4, the instruction argument must be 4 byte aligned. Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size); /* Define the currently available CPU status flags. It is usually used after an sljit_emit_op_custom call to define which flags are set. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags); #endif /* _SLJIT_LIR_H_ */ ================================================ FILE: src/pcre/sljit/sljitNativeARM_32.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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 __SOFTFP__ #define ARM_ABI_INFO " ABI:softfp" #else #define ARM_ABI_INFO " ABI:hardfp" #endif SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO; #elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) return "ARMv5" SLJIT_CPUINFO ARM_ABI_INFO; #else #error "Internal error: Unknown ARM architecture" #endif } /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4) #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) /* In ARM instruction words. Cache lines are usually 32 byte aligned. */ #define CONST_POOL_ALIGNMENT 8 #define CONST_POOL_EMPTY 0xffffffff #define ALIGN_INSTRUCTION(ptr) \ (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1)) #define MAX_DIFFERENCE(max_diff) \ (((max_diff) / (sljit_s32)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1)) /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 }; static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 0, 1, 2, 3, 4, 5, 6, 7 }; #define RM(rm) (reg_map[rm]) #define RD(rd) (reg_map[rd] << 12) #define RN(rn) (reg_map[rn] << 16) /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ /* The instruction includes the AL condition. INST_NAME - CONDITIONAL remove this flag. */ #define COND_MASK 0xf0000000 #define CONDITIONAL 0xe0000000 #define PUSH_POOL 0xff000000 #define ADC 0xe0a00000 #define ADD 0xe0800000 #define AND 0xe0000000 #define B 0xea000000 #define BIC 0xe1c00000 #define BL 0xeb000000 #define BLX 0xe12fff30 #define BX 0xe12fff10 #define CLZ 0xe16f0f10 #define CMN 0xe1600000 #define CMP 0xe1400000 #define BKPT 0xe1200070 #define EOR 0xe0200000 #define MOV 0xe1a00000 #define MUL 0xe0000090 #define MVN 0xe1e00000 #define NOP 0xe1a00000 #define ORR 0xe1800000 #define PUSH 0xe92d0000 #define POP 0xe8bd0000 #define RSB 0xe0600000 #define RSC 0xe0e00000 #define SBC 0xe0c00000 #define SMULL 0xe0c00090 #define SUB 0xe0400000 #define UMULL 0xe0800090 #define VABS_F32 0xeeb00ac0 #define VADD_F32 0xee300a00 #define VCMP_F32 0xeeb40a40 #define VCVT_F32_S32 0xeeb80ac0 #define VCVT_F64_F32 0xeeb70ac0 #define VCVT_S32_F32 0xeebd0ac0 #define VDIV_F32 0xee800a00 #define VMOV_F32 0xeeb00a40 #define VMOV 0xee000a10 #define VMOV2 0xec400a10 #define VMRS 0xeef1fa10 #define VMUL_F32 0xee200a00 #define VNEG_F32 0xeeb10a40 #define VSTR_F32 0xed000a00 #define VSUB_F32 0xee300a40 #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) /* Arm v7 specific instructions. */ #define MOVW 0xe3000000 #define MOVT 0xe3400000 #define SXTB 0xe6af0070 #define SXTH 0xe6bf0070 #define UXTB 0xe6ef0070 #define UXTH 0xe6ff0070 #endif #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) static sljit_s32 push_cpool(struct sljit_compiler *compiler) { /* Pushing the constant pool into the instruction stream. */ sljit_uw* inst; sljit_uw* cpool_ptr; sljit_uw* cpool_end; sljit_s32 i; /* The label could point the address after the constant pool. */ if (compiler->last_label && compiler->last_label->size == compiler->size) compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1; SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE); inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!inst); compiler->size++; *inst = 0xff000000 | compiler->cpool_fill; for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) { inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!inst); compiler->size++; *inst = 0; } cpool_ptr = compiler->cpool; cpool_end = cpool_ptr + compiler->cpool_fill; while (cpool_ptr < cpool_end) { inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!inst); compiler->size++; *inst = *cpool_ptr++; } compiler->cpool_diff = CONST_POOL_EMPTY; compiler->cpool_fill = 0; return SLJIT_SUCCESS; } static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst) { sljit_uw* ptr; if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092))) FAIL_IF(push_cpool(compiler)); ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!ptr); compiler->size++; *ptr = inst; return SLJIT_SUCCESS; } static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) { sljit_uw* ptr; sljit_uw cpool_index = CPOOL_SIZE; sljit_uw* cpool_ptr; sljit_uw* cpool_end; sljit_u8* cpool_unique_ptr; if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092))) FAIL_IF(push_cpool(compiler)); else if (compiler->cpool_fill > 0) { cpool_ptr = compiler->cpool; cpool_end = cpool_ptr + compiler->cpool_fill; cpool_unique_ptr = compiler->cpool_unique; do { if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) { cpool_index = cpool_ptr - compiler->cpool; break; } cpool_ptr++; cpool_unique_ptr++; } while (cpool_ptr < cpool_end); } if (cpool_index == CPOOL_SIZE) { /* Must allocate a new entry in the literal pool. */ if (compiler->cpool_fill < CPOOL_SIZE) { cpool_index = compiler->cpool_fill; compiler->cpool_fill++; } else { FAIL_IF(push_cpool(compiler)); cpool_index = 0; compiler->cpool_fill = 1; } } SLJIT_ASSERT((inst & 0xfff) == 0); ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!ptr); compiler->size++; *ptr = inst | cpool_index; compiler->cpool[cpool_index] = literal; compiler->cpool_unique[cpool_index] = 0; if (compiler->cpool_diff == CONST_POOL_EMPTY) compiler->cpool_diff = compiler->size; return SLJIT_SUCCESS; } static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) { sljit_uw* ptr; if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE)) FAIL_IF(push_cpool(compiler)); SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0); ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!ptr); compiler->size++; *ptr = inst | compiler->cpool_fill; compiler->cpool[compiler->cpool_fill] = literal; compiler->cpool_unique[compiler->cpool_fill] = 1; compiler->cpool_fill++; if (compiler->cpool_diff == CONST_POOL_EMPTY) compiler->cpool_diff = compiler->size; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 prepare_blx(struct sljit_compiler *compiler) { /* Place for at least two instruction (doesn't matter whether the first has a literal). */ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088))) return push_cpool(compiler); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler) { /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */ SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092)); SLJIT_ASSERT(reg_map[TMP_REG1] != 14); return push_inst(compiler, BLX | RM(TMP_REG1)); } static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size) { sljit_uw diff; sljit_uw ind; sljit_uw counter = 0; sljit_uw* clear_const_pool = const_pool; sljit_uw* clear_const_pool_end = const_pool + cpool_size; SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT); /* Set unused flag for all literals in the constant pool. I.e.: unused literals can belong to branches, which can be encoded as B or BL. We can "compress" the constant pool by discarding these literals. */ while (clear_const_pool < clear_const_pool_end) *clear_const_pool++ = (sljit_uw)(-1); while (last_pc_patch < code_ptr) { /* Data transfer instruction with Rn == r15. */ if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) { diff = const_pool - last_pc_patch; ind = (*last_pc_patch) & 0xfff; /* Must be a load instruction with immediate offset. */ SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20))); if ((sljit_s32)const_pool[ind] < 0) { const_pool[ind] = counter; ind = counter; counter++; } else ind = const_pool[ind]; SLJIT_ASSERT(diff >= 1); if (diff >= 2 || ind > 0) { diff = (diff + ind - 2) << 2; SLJIT_ASSERT(diff <= 0xfff); *last_pc_patch = (*last_pc_patch & ~0xfff) | diff; } else *last_pc_patch = (*last_pc_patch & ~(0xfff | (1 << 23))) | 0x004; } last_pc_patch++; } return counter; } /* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */ struct future_patch { struct future_patch* next; sljit_s32 index; sljit_s32 value; }; static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr) { sljit_s32 value; struct future_patch *curr_patch, *prev_patch; SLJIT_UNUSED_ARG(compiler); /* Using the values generated by patch_pc_relative_loads. */ if (!*first_patch) value = (sljit_s32)cpool_start_address[cpool_current_index]; else { curr_patch = *first_patch; prev_patch = NULL; while (1) { if (!curr_patch) { value = (sljit_s32)cpool_start_address[cpool_current_index]; break; } if ((sljit_uw)curr_patch->index == cpool_current_index) { value = curr_patch->value; if (prev_patch) prev_patch->next = curr_patch->next; else *first_patch = curr_patch->next; SLJIT_FREE(curr_patch, compiler->allocator_data); break; } prev_patch = curr_patch; curr_patch = curr_patch->next; } } if (value >= 0) { if ((sljit_uw)value > cpool_current_index) { curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data); if (!curr_patch) { while (*first_patch) { curr_patch = *first_patch; *first_patch = (*first_patch)->next; SLJIT_FREE(curr_patch, compiler->allocator_data); } return SLJIT_ERR_ALLOC_FAILED; } curr_patch->next = *first_patch; curr_patch->index = value; curr_patch->value = cpool_start_address[value]; *first_patch = curr_patch; } cpool_start_address[value] = *buf_ptr; } return SLJIT_SUCCESS; } #else static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst) { sljit_uw* ptr; ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); FAIL_IF(!ptr); compiler->size++; *ptr = inst; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) { FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); } #endif static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset) { sljit_sw diff; if (jump->flags & SLJIT_REWRITABLE_JUMP) return 0; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (jump->flags & IS_BL) code_ptr--; if (jump->flags & JUMP_ADDR) diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset); else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)); } /* Branch to Thumb code has not been optimized yet. */ if (diff & 0x3) return 0; if (jump->flags & IS_BL) { if (diff <= 0x01ffffff && diff >= -0x02000000) { *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK); jump->flags |= PATCH_B; return 1; } } else { if (diff <= 0x01ffffff && diff >= -0x02000000) { *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK); jump->flags |= PATCH_B; } } #else if (jump->flags & JUMP_ADDR) diff = ((sljit_sw)jump->u.target - (sljit_sw)code_ptr - executable_offset); else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)code_ptr); } /* Branch to Thumb code has not been optimized yet. */ if (diff & 0x3) return 0; if (diff <= 0x01ffffff && diff >= -0x02000000) { code_ptr -= 2; *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK); jump->flags |= PATCH_B; return 1; } #endif return 0; } static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) sljit_uw *ptr = (sljit_uw *)jump_ptr; sljit_uw *inst = (sljit_uw *)ptr[0]; sljit_uw mov_pc = ptr[1]; sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC); sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2); if (diff <= 0x7fffff && diff >= -0x800000) { /* Turn to branch. */ if (!bl) { inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff); if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } else { inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff); inst[1] = NOP; if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } } } else { /* Get the position of the constant. */ if (mov_pc & (1 << 23)) ptr = inst + ((mov_pc & 0xfff) >> 2) + 2; else ptr = inst + 1; if (*inst != mov_pc) { inst[0] = mov_pc; if (!bl) { if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } else { inst[1] = BLX | RM(TMP_REG1); if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } } } *ptr = new_addr; } #else sljit_uw *inst = (sljit_uw*)jump_ptr; SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT); inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff); inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff); if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } #endif } static sljit_uw get_imm(sljit_uw imm); static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_sw new_constant, sljit_s32 flush_cache) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) sljit_uw *ptr = (sljit_uw*)addr; sljit_uw *inst = (sljit_uw*)ptr[0]; sljit_uw ldr_literal = ptr[1]; sljit_uw src2; src2 = get_imm(new_constant); if (src2) { *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2; if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } return; } src2 = get_imm(~new_constant); if (src2) { *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2; if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } return; } if (ldr_literal & (1 << 23)) ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2; else ptr = inst + 1; if (*inst != ldr_literal) { *inst = ldr_literal; if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } *ptr = new_constant; #else sljit_uw *inst = (sljit_uw*)addr; SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT); inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff); inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff); if (flush_cache) { inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } #endif } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_uw *code; sljit_uw *code_ptr; sljit_uw *buf_ptr; sljit_uw *buf_end; sljit_uw size; sljit_uw word_count; sljit_sw executable_offset; sljit_sw jump_addr; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) sljit_uw cpool_size; sljit_uw cpool_skip_alignment; sljit_uw cpool_current_index; sljit_uw *cpool_start_address; sljit_uw *last_pc_patch; struct future_patch *first_patch; #endif struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); /* Second code generation pass. */ #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) size = compiler->size + (compiler->patches << 1); if (compiler->cpool_fill > 0) size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1; #else size = compiler->size; #endif code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) cpool_size = 0; cpool_skip_alignment = 0; cpool_current_index = 0; cpool_start_address = NULL; first_patch = NULL; last_pc_patch = code; #endif code_ptr = code; word_count = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; if (label && label->size == 0) { label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); label = label->next; } do { buf_ptr = (sljit_uw*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { word_count++; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (cpool_size > 0) { if (cpool_skip_alignment > 0) { buf_ptr++; cpool_skip_alignment--; } else { if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { SLJIT_FREE_EXEC(code); compiler->error = SLJIT_ERR_ALLOC_FAILED; return NULL; } buf_ptr++; if (++cpool_current_index >= cpool_size) { SLJIT_ASSERT(!first_patch); cpool_size = 0; if (label && label->size == word_count) { /* Points after the current instruction. */ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } } } } else if ((*buf_ptr & 0xff000000) != PUSH_POOL) { #endif *code_ptr = *buf_ptr++; /* These structures are ordered by their address. */ SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); if (jump && jump->addr == word_count) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (detect_jump_type(jump, code_ptr, code, executable_offset)) code_ptr--; jump->addr = (sljit_uw)code_ptr; #else jump->addr = (sljit_uw)(code_ptr - 2); if (detect_jump_type(jump, code_ptr, code, executable_offset)) code_ptr -= 2; #endif jump = jump->next; } if (label && label->size == word_count) { /* code_ptr can be affected above. */ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset); label->size = (code_ptr + 1) - code; label = label->next; } if (const_ && const_->addr == word_count) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) const_->addr = (sljit_uw)code_ptr; #else const_->addr = (sljit_uw)(code_ptr - 1); #endif const_ = const_->next; } code_ptr++; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) } else { /* Fortunately, no need to shift. */ cpool_size = *buf_ptr++ & ~PUSH_POOL; SLJIT_ASSERT(cpool_size > 0); cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1); cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size); if (cpool_current_index > 0) { /* Unconditional branch. */ *code_ptr = B | (((cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL); code_ptr = cpool_start_address + cpool_current_index; } cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1; cpool_current_index = 0; last_pc_patch = code_ptr; } #endif } while (buf_ptr < buf_end); buf = buf->next; } while (buf); SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) SLJIT_ASSERT(cpool_size == 0); if (compiler->cpool_fill > 0) { cpool_start_address = ALIGN_INSTRUCTION(code_ptr); cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill); if (cpool_current_index > 0) code_ptr = cpool_start_address + cpool_current_index; buf_ptr = compiler->cpool; buf_end = buf_ptr + compiler->cpool_fill; cpool_current_index = 0; while (buf_ptr < buf_end) { if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { SLJIT_FREE_EXEC(code); compiler->error = SLJIT_ERR_ALLOC_FAILED; return NULL; } buf_ptr++; cpool_current_index++; } SLJIT_ASSERT(!first_patch); } #endif jump = compiler->jumps; while (jump) { buf_ptr = (sljit_uw *)jump->addr; if (jump->flags & PATCH_B) { jump_addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset); if (!(jump->flags & JUMP_ADDR)) { SLJIT_ASSERT(jump->flags & JUMP_LABEL); SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - jump_addr) >= -0x02000000); *buf_ptr |= (((sljit_sw)jump->u.label->addr - jump_addr) >> 2) & 0x00ffffff; } else { SLJIT_ASSERT(((sljit_sw)jump->u.target - jump_addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - jump_addr) >= -0x02000000); *buf_ptr |= (((sljit_sw)jump->u.target - jump_addr) >> 2) & 0x00ffffff; } } else if (jump->flags & SLJIT_REWRITABLE_JUMP) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) jump->addr = (sljit_uw)code_ptr; code_ptr[0] = (sljit_uw)buf_ptr; code_ptr[1] = *buf_ptr; inline_set_jump_addr((sljit_uw)code_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); code_ptr += 2; #else inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); #endif } else { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (jump->flags & IS_BL) buf_ptr--; if (*buf_ptr & (1 << 23)) buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; else buf_ptr += 1; *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; #else inline_set_jump_addr((sljit_uw)buf_ptr, executable_offset, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); #endif } jump = jump->next; } #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) const_ = compiler->consts; while (const_) { buf_ptr = (sljit_uw*)const_->addr; const_->addr = (sljit_uw)code_ptr; code_ptr[0] = (sljit_uw)buf_ptr; code_ptr[1] = *buf_ptr; if (*buf_ptr & (1 << 23)) buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; else buf_ptr += 1; /* Set the value again (can be a simple constant). */ inline_set_const((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0); code_ptr += 2; const_ = const_->next; } #endif SLJIT_ASSERT(code_ptr - code <= (sljit_s32)size); compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw); code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #else /* Available by default. */ return 1; #endif case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: return 1; default: return 0; } } /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ /* Creates an index in data_transfer_insts array. */ #define WORD_SIZE 0x00 #define BYTE_SIZE 0x01 #define HALF_SIZE 0x02 #define PRELOAD 0x03 #define SIGNED 0x04 #define LOAD_DATA 0x08 /* Flag bits for emit_op. */ #define ALLOW_IMM 0x10 #define ALLOW_INV_IMM 0x20 #define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM) /* s/l - store/load (1 bit) u/s - signed/unsigned (1 bit) w/b/h/N - word/byte/half/NOT allowed (2 bit) Storing signed and unsigned values are the same operations. */ static const sljit_uw data_transfer_insts[16] = { /* s u w */ 0xe5000000 /* str */, /* s u b */ 0xe5400000 /* strb */, /* s u h */ 0xe10000b0 /* strh */, /* s u N */ 0x00000000 /* not allowed */, /* s s w */ 0xe5000000 /* str */, /* s s b */ 0xe5400000 /* strb */, /* s s h */ 0xe10000b0 /* strh */, /* s s N */ 0x00000000 /* not allowed */, /* l u w */ 0xe5100000 /* ldr */, /* l u b */ 0xe5500000 /* ldrb */, /* l u h */ 0xe11000b0 /* ldrh */, /* l u p */ 0xf5500000 /* preload */, /* l s w */ 0xe5100000 /* ldr */, /* l s b */ 0xe11000d0 /* ldrsb */, /* l s h */ 0xe11000f0 /* ldrsh */, /* l s N */ 0x00000000 /* not allowed */, }; #define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \ (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (arg)) /* Normal ldr/str instruction. Type2: ldrsb, ldrh, ldrsh */ #define IS_TYPE1_TRANSFER(type) \ (data_transfer_insts[(type) & 0xf] & 0x04000000) #define TYPE2_TRANSFER_IMM(imm) \ (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22)) static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args, size, i, tmp; sljit_uw push; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); /* Push saved registers, temporary registers stmdb sp!, {..., lr} */ push = PUSH | (1 << 14); tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) push |= 1 << reg_map[i]; for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) push |= 1 << reg_map[i]; FAIL_IF(push_inst(compiler, push)); /* Stack must be aligned to 8 bytes: */ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = ((size + local_size + 7) & ~7) - size; compiler->local_size = local_size; if (local_size > 0) FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size)); args = get_arg_count(arg_types); if (args >= 1) FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0) | RM(SLJIT_R0))); if (args >= 2) FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S1) | RM(SLJIT_R1))); if (args >= 3) FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S2) | RM(SLJIT_R2))); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 size; CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = ((size + local_size + 7) & ~7) - size; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 i, tmp; sljit_uw pop; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); if (compiler->local_size > 0) FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); /* Push saved registers, temporary registers ldmia sp!, {..., pc} */ pop = POP | (1 << 15); tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) pop |= 1 << reg_map[i]; for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) pop |= 1 << reg_map[i]; return push_inst(compiler, pop); } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ /* flags: */ /* Arguments are swapped. */ #define ARGS_SWAPPED 0x01 /* Inverted immediate. */ #define INV_IMM 0x02 /* Source and destination is register. */ #define MOVE_REG_CONV 0x04 /* Unused return value. */ #define UNUSED_RETURN 0x08 /* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */ #define SET_FLAGS (1 << 20) /* dst: reg src1: reg src2: reg or imm (if allowed) SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */ #define SRC2_IMM (1 << 25) #define EMIT_SHIFT_INS_AND_RETURN(opcode) \ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \ if (compiler->shift_imm != 0x20) { \ SLJIT_ASSERT(src1 == TMP_REG1); \ SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \ \ if (compiler->shift_imm != 0) \ return push_inst(compiler, MOV | (flags & SET_FLAGS) | \ RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \ } \ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | \ (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1)); static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { switch (GET_OPCODE(op)) { case SLJIT_MOV: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); if (dst != src2) { if (src2 & SRC2_IMM) { return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } return push_inst(compiler, MOV | RD(dst) | RM(src2)); } return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); if (flags & MOVE_REG_CONV) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (op == SLJIT_MOV_U8) return push_inst(compiler, AND | RD(dst) | RN(src2) | SRC2_IMM | 0xff); FAIL_IF(push_inst(compiler, MOV | RD(dst) | (24 << 7) | RM(src2))); return push_inst(compiler, MOV | RD(dst) | (24 << 7) | (op == SLJIT_MOV_U8 ? 0x20 : 0x40) | RM(dst)); #else return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2)); #endif } else if (dst != src2) { SLJIT_ASSERT(src2 & SRC2_IMM); return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); if (flags & MOVE_REG_CONV) { #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) FAIL_IF(push_inst(compiler, MOV | RD(dst) | (16 << 7) | RM(src2))); return push_inst(compiler, MOV | RD(dst) | (16 << 7) | (op == SLJIT_MOV_U16 ? 0x20 : 0x40) | RM(dst)); #else return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2)); #endif } else if (dst != src2) { SLJIT_ASSERT(src2 & SRC2_IMM); return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2); } return SLJIT_SUCCESS; case SLJIT_NOT: if (src2 & SRC2_IMM) { return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2); } return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2)); case SLJIT_CLZ: SLJIT_ASSERT(!(flags & INV_IMM)); SLJIT_ASSERT(!(src2 & SRC2_IMM)); FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); return SLJIT_SUCCESS; case SLJIT_ADD: SLJIT_ASSERT(!(flags & INV_IMM)); if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED)) return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_ADDC: SLJIT_ASSERT(!(flags & INV_IMM)); return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SUB: SLJIT_ASSERT(!(flags & INV_IMM)); if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED)) return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SUBC: SLJIT_ASSERT(!(flags & INV_IMM)); return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_MUL: SLJIT_ASSERT(!(flags & INV_IMM)); SLJIT_ASSERT(!(src2 & SRC2_IMM)); if (!HAS_FLAGS(op)) return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]); FAIL_IF(push_inst(compiler, SMULL | (reg_map[TMP_REG1] << 16) | (reg_map[dst] << 12) | (reg_map[src2] << 8) | reg_map[src1])); /* cmp TMP_REG1, dst asr #31. */ return push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | RM(dst) | 0xfc0); case SLJIT_AND: return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_OR: SLJIT_ASSERT(!(flags & INV_IMM)); return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_XOR: SLJIT_ASSERT(!(flags & INV_IMM)); return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2))); case SLJIT_SHL: EMIT_SHIFT_INS_AND_RETURN(0); case SLJIT_LSHR: EMIT_SHIFT_INS_AND_RETURN(1); case SLJIT_ASHR: EMIT_SHIFT_INS_AND_RETURN(2); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } #undef EMIT_SHIFT_INS_AND_RETURN /* Tests whether the immediate can be stored in the 12 bit imm field. Returns with 0 if not possible. */ static sljit_uw get_imm(sljit_uw imm) { sljit_s32 rol; if (imm <= 0xff) return SRC2_IMM | imm; if (!(imm & 0xff000000)) { imm <<= 8; rol = 8; } else { imm = (imm << 24) | (imm >> 8); rol = 0; } if (!(imm & 0xff000000)) { imm <<= 8; rol += 4; } if (!(imm & 0xf0000000)) { imm <<= 4; rol += 2; } if (!(imm & 0xc0000000)) { imm <<= 2; rol += 1; } if (!(imm & 0x00ffffff)) return SRC2_IMM | (imm >> 24) | (rol << 8); else return 0; } #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm, sljit_s32 positive) { sljit_uw mask; sljit_uw imm1; sljit_uw imm2; sljit_s32 rol; /* Step1: Search a zero byte (8 continous zero bit). */ mask = 0xff000000; rol = 8; while(1) { if (!(imm & mask)) { /* Rol imm by rol. */ imm = (imm << rol) | (imm >> (32 - rol)); /* Calculate arm rol. */ rol = 4 + (rol >> 1); break; } rol += 2; mask >>= 2; if (mask & 0x3) { /* rol by 8. */ imm = (imm << 8) | (imm >> 24); mask = 0xff00; rol = 24; while (1) { if (!(imm & mask)) { /* Rol imm by rol. */ imm = (imm << rol) | (imm >> (32 - rol)); /* Calculate arm rol. */ rol = (rol >> 1) - 8; break; } rol += 2; mask >>= 2; if (mask & 0x3) return 0; } break; } } /* The low 8 bit must be zero. */ SLJIT_ASSERT(!(imm & 0xff)); if (!(imm & 0xff000000)) { imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8); imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8); } else if (imm & 0xc0000000) { imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); imm <<= 8; rol += 4; if (!(imm & 0xff000000)) { imm <<= 8; rol += 4; } if (!(imm & 0xf0000000)) { imm <<= 4; rol += 2; } if (!(imm & 0xc0000000)) { imm <<= 2; rol += 1; } if (!(imm & 0x00ffffff)) imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); else return 0; } else { if (!(imm & 0xf0000000)) { imm <<= 4; rol += 2; } if (!(imm & 0xc0000000)) { imm <<= 2; rol += 1; } imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); imm <<= 8; rol += 4; if (!(imm & 0xf0000000)) { imm <<= 4; rol += 2; } if (!(imm & 0xc0000000)) { imm <<= 2; rol += 1; } if (!(imm & 0x00ffffff)) imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); else return 0; } FAIL_IF(push_inst(compiler, (positive ? MOV : MVN) | RD(reg) | imm1)); FAIL_IF(push_inst(compiler, (positive ? ORR : BIC) | RD(reg) | RN(reg) | imm2)); return 1; } #endif static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm) { sljit_uw tmp; #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) if (!(imm & ~0xffff)) return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)); #endif /* Create imm by 1 inst. */ tmp = get_imm(imm); if (tmp) return push_inst(compiler, MOV | RD(reg) | tmp); tmp = get_imm(~imm); if (tmp) return push_inst(compiler, MVN | RD(reg) | tmp); #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) /* Create imm by 2 inst. */ FAIL_IF(generate_int(compiler, reg, imm, 1)); FAIL_IF(generate_int(compiler, reg, ~imm, 0)); /* Load integer. */ return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm); #else FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); if (imm <= 0xffff) return SLJIT_SUCCESS; return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); #endif } static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_uw imm, offset_reg; sljit_uw is_type1_transfer = IS_TYPE1_TRANSFER(flags); SLJIT_ASSERT (arg & SLJIT_MEM); SLJIT_ASSERT((arg & REG_MASK) != tmp_reg); if ((arg & REG_MASK) == SLJIT_UNUSED) { if (is_type1_transfer) { FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff)); argw &= 0xfff; } else { FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xff)); argw &= 0xff; } return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, is_type1_transfer ? argw : TYPE2_TRANSFER_IMM(argw))); } if (arg & OFFS_REG_MASK) { offset_reg = OFFS_REG(arg); arg &= REG_MASK; argw &= 0x3; if (argw != 0 && !is_type1_transfer) { FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | (argw << 7))); return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0))); } /* Bit 25: RM is offset. */ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7))); } arg &= REG_MASK; if (is_type1_transfer) { if (argw > 0xfff) { imm = get_imm(argw & ~0xfff); if (imm) { FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); argw = argw & 0xfff; arg = tmp_reg; } } else if (argw < -0xfff) { imm = get_imm(-argw & ~0xfff); if (imm) { FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); argw = -(-argw & 0xfff); arg = tmp_reg; } } if (argw >= 0 && argw <= 0xfff) return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw)); if (argw < 0 && argw >= -0xfff) return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, -argw)); } else { if (argw > 0xff) { imm = get_imm(argw & ~0xff); if (imm) { FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm)); argw = argw & 0xff; arg = tmp_reg; } } else if (argw < -0xff) { imm = get_imm(-argw & ~0xff); if (imm) { FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm)); argw = -(-argw & 0xff); arg = tmp_reg; } } if (argw >= 0 && argw <= 0xff) return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, TYPE2_TRANSFER_IMM(argw))); if (argw < 0 && argw >= -0xff) { argw = -argw; return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, TYPE2_TRANSFER_IMM(argw))); } } FAIL_IF(load_immediate(compiler, tmp_reg, argw)); return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0))); } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* src1 is reg or TMP_REG1 src2 is reg, TMP_REG2, or imm result goes to TMP_REG2, so put result can use TMP_REG1. */ /* We prefers register and simple consts. */ sljit_s32 dst_reg; sljit_s32 src1_reg; sljit_s32 src2_reg; sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; /* Destination check. */ if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) flags |= UNUSED_RETURN; SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM)); src2_reg = 0; do { if (!(inp_flags & ALLOW_IMM)) break; if (src2 & SLJIT_IMM) { src2_reg = get_imm(src2w); if (src2_reg) break; if (inp_flags & ALLOW_INV_IMM) { src2_reg = get_imm(~src2w); if (src2_reg) { flags |= INV_IMM; break; } } if (GET_OPCODE(op) == SLJIT_ADD) { src2_reg = get_imm(-src2w); if (src2_reg) { op = SLJIT_SUB | GET_ALL_FLAGS(op); break; } } if (GET_OPCODE(op) == SLJIT_SUB) { src2_reg = get_imm(-src2w); if (src2_reg) { op = SLJIT_ADD | GET_ALL_FLAGS(op); break; } } } if (src1 & SLJIT_IMM) { src2_reg = get_imm(src1w); if (src2_reg) { flags |= ARGS_SWAPPED; src1 = src2; src1w = src2w; break; } if (inp_flags & ALLOW_INV_IMM) { src2_reg = get_imm(~src1w); if (src2_reg) { flags |= ARGS_SWAPPED | INV_IMM; src1 = src2; src1w = src2w; break; } } if (GET_OPCODE(op) == SLJIT_ADD) { src2_reg = get_imm(-src1w); if (src2_reg) { /* Note: add is commutative operation. */ src1 = src2; src1w = src2w; op = SLJIT_SUB | GET_ALL_FLAGS(op); break; } } } } while(0); /* Source 1. */ if (FAST_IS_REG(src1)) src1_reg = src1; else if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1)); src1_reg = TMP_REG1; } else { FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); src1_reg = TMP_REG1; } /* Destination. */ dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; if (op <= SLJIT_MOV_P) { if (dst & SLJIT_MEM) { if (inp_flags & BYTE_SIZE) inp_flags &= ~SIGNED; if (FAST_IS_REG(src2)) return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG2); } if (FAST_IS_REG(src2) && dst_reg != TMP_REG2) flags |= MOVE_REG_CONV; } /* Source 2. */ if (src2_reg == 0) { src2_reg = (op <= SLJIT_MOV_P) ? dst_reg : TMP_REG2; if (FAST_IS_REG(src2)) src2_reg = src2; else if (src2 & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2)); else FAIL_IF(load_immediate(compiler, src2_reg, src2w)); } FAIL_IF(emit_single_op(compiler, op, flags, dst_reg, src1_reg, src2_reg)); if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1); } #ifdef __cplusplus extern "C" { #endif #if defined(__GNUC__) extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator); extern int __aeabi_idivmod(int numerator, int denominator); #else #error "Software divmod functions are needed" #endif #ifdef __cplusplus } #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { sljit_sw saved_reg_list[3]; sljit_sw saved_reg_count; CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: FAIL_IF(push_inst(compiler, BKPT)); break; case SLJIT_NOP: FAIL_IF(push_inst(compiler, NOP)); break; case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL) | (reg_map[SLJIT_R1] << 16) | (reg_map[SLJIT_R0] << 12) | (reg_map[SLJIT_R0] << 8) | reg_map[SLJIT_R1]); case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3); saved_reg_count = 0; if (compiler->scratches >= 4) saved_reg_list[saved_reg_count++] = 3; if (compiler->scratches >= 3) saved_reg_list[saved_reg_count++] = 2; if (op >= SLJIT_DIV_UW) saved_reg_list[saved_reg_count++] = 1; if (saved_reg_count > 0) { FAIL_IF(push_inst(compiler, 0xe52d0000 | (saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); if (saved_reg_count >= 2) { SLJIT_ASSERT(saved_reg_list[1] < 8); FAIL_IF(push_inst(compiler, 0xe58d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */)); } if (saved_reg_count >= 3) { SLJIT_ASSERT(saved_reg_list[2] < 8); FAIL_IF(push_inst(compiler, 0xe58d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */)); } } #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif if (saved_reg_count > 0) { if (saved_reg_count >= 3) { SLJIT_ASSERT(saved_reg_list[2] < 8); FAIL_IF(push_inst(compiler, 0xe59d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */)); } if (saved_reg_count >= 2) { SLJIT_ASSERT(saved_reg_list[1] < 8); FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */)); } return push_inst(compiler, 0xe49d0000 | (saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } return SLJIT_SUCCESS; } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); #endif return SLJIT_SUCCESS; } switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U8: return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_NOT: return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_NEG: #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_op2(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw); case SLJIT_CLZ: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; switch (GET_OPCODE(op)) { case SLJIT_ADD: case SLJIT_ADDC: case SLJIT_SUB: case SLJIT_SUBC: case SLJIT_OR: case SLJIT_XOR: return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: if (src2 & SLJIT_IMM) { compiler->shift_imm = src2w & 0x1f; return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w); } else { compiler->shift_imm = 0x20; return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); } } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return (freg_map[reg] << 1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); return push_inst(compiler, *(sljit_uw*)instruction); } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ #define FPU_LOAD (1 << 20) #define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \ ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg_map[freg] << 12) | (offs)) #define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \ ((opcode) | (mode) | (freg_map[dst] << 12) | freg_map[src1] | (freg_map[src2] << 16)) static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { sljit_uw imm; sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD)); SLJIT_ASSERT(arg & SLJIT_MEM); arg &= ~SLJIT_MEM; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((argw & 0x3) << 7))); arg = TMP_REG2; argw = 0; } /* Fast loads and stores. */ if (arg) { if (!(argw & ~0x3fc)) return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2)); if (!(-argw & ~0x3fc)) return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2)); imm = get_imm(argw & ~0x3fc); if (imm) { FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | imm)); return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2)); } imm = get_imm(-argw & ~0x3fc); if (imm) { argw = -argw; FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG2) | RN(arg & REG_MASK) | imm)); return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG2, reg, (argw & 0x3fc) >> 2)); } } if (arg) { FAIL_IF(load_immediate(compiler, TMP_REG2, argw)); FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(TMP_REG2))); } else FAIL_IF(load_immediate(compiler, TMP_REG2, argw)); return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { op ^= SLJIT_F32_OP; if (src & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw)); src = TMP_FREG1; } FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_F32_OP, TMP_FREG1, src, 0))); if (FAST_IS_REG(dst)) return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (freg_map[TMP_FREG1] << 16)); /* Store the integer value from a VFP register. */ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; op ^= SLJIT_F32_OP; if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, VMOV | RD(src) | (freg_map[TMP_FREG1] << 16))); else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw)); } else { FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (freg_map[TMP_FREG1] << 16))); } FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_F32_OP, dst_r, TMP_FREG1, 0))); if (dst & SLJIT_MEM) return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { op ^= SLJIT_F32_OP; if (src1 & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w)); src2 = TMP_FREG2; } FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_F32_OP, src1, src2, 0))); return push_inst(compiler, VMRS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; CHECK_ERROR(); SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; if (src & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw)); src = dst_r; } switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_F32_OP, dst_r, src, 0))); else dst_r = src; } break; case SLJIT_NEG_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_F32_OP, dst_r, src, 0))); break; case SLJIT_ABS_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_F32_OP, dst_r, src, 0))); break; case SLJIT_CONV_F64_FROM_F32: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_F32_OP, dst_r, src, 0))); op ^= SLJIT_F32_OP; break; } if (dst & SLJIT_MEM) return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src2 & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w)); src2 = TMP_FREG2; } if (src1 & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w)); src1 = TMP_FREG1; } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_F32_OP, dst_r, src2, src1))); break; case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_F32_OP, dst_r, src2, src1))); break; case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_F32_OP, dst_r, src2, src1))); break; case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_F32_OP, dst_r, src2, src1))); break; } if (dst_r == TMP_FREG1) FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw)); return SLJIT_SUCCESS; } #undef FPU_LOAD #undef EMIT_FPU_DATA_TRANSFER /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); SLJIT_ASSERT(reg_map[TMP_REG2] == 14); if (FAST_IS_REG(dst)) return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2)); /* Memory. */ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); SLJIT_ASSERT(reg_map[TMP_REG2] == 14); if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src))); else FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1)); return push_inst(compiler, BX | RM(TMP_REG2)); } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ static sljit_uw get_cc(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: case SLJIT_MUL_NOT_OVERFLOW: case SLJIT_EQUAL_F64: return 0x00000000; case SLJIT_NOT_EQUAL: case SLJIT_MUL_OVERFLOW: case SLJIT_NOT_EQUAL_F64: return 0x10000000; case SLJIT_LESS: case SLJIT_LESS_F64: return 0x30000000; case SLJIT_GREATER_EQUAL: case SLJIT_GREATER_EQUAL_F64: return 0x20000000; case SLJIT_GREATER: case SLJIT_GREATER_F64: return 0x80000000; case SLJIT_LESS_EQUAL: case SLJIT_LESS_EQUAL_F64: return 0x90000000; case SLJIT_SIG_LESS: return 0xb0000000; case SLJIT_SIG_GREATER_EQUAL: return 0xa0000000; case SLJIT_SIG_GREATER: return 0xc0000000; case SLJIT_SIG_LESS_EQUAL: return 0xd0000000; case SLJIT_OVERFLOW: case SLJIT_UNORDERED_F64: return 0x60000000; case SLJIT_NOT_OVERFLOW: case SLJIT_ORDERED_F64: return 0x70000000; default: SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL); return 0xe0000000; } } SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); return label; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; SLJIT_ASSERT(reg_map[TMP_REG1] != 14); #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (type >= SLJIT_FAST_CALL) PTR_FAIL_IF(prepare_blx(compiler)); PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0)); if (jump->flags & SLJIT_REWRITABLE_JUMP) { jump->addr = compiler->size; compiler->patches++; } if (type >= SLJIT_FAST_CALL) { jump->flags |= IS_BL; PTR_FAIL_IF(emit_blx(compiler)); } if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) jump->addr = compiler->size; #else if (type >= SLJIT_FAST_CALL) jump->flags |= IS_BL; PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0)); PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type))); jump->addr = compiler->size; #endif return jump; } #ifdef __SOFTFP__ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) { sljit_s32 stack_offset = 0; sljit_s32 arg_count = 0; sljit_s32 word_arg_offset = 0; sljit_s32 float_arg_count = 0; sljit_s32 types = 0; sljit_s32 src_offset = 4 * sizeof(sljit_sw); sljit_u8 offsets[4]; if (src && FAST_IS_REG(*src)) src_offset = reg_map[*src] * sizeof(sljit_sw); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_f32); arg_count++; float_arg_count++; break; case SLJIT_ARG_TYPE_F64: if (stack_offset & 0x7) stack_offset += sizeof(sljit_sw); offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_f64); arg_count++; float_arg_count++; break; default: offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_sw); arg_count++; word_arg_offset += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } if (stack_offset > 16) FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_offset - 16) + 0x7) & ~0x7))); /* Process arguments in reversed direction. */ while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: arg_count--; float_arg_count--; stack_offset = offsets[arg_count]; if (stack_offset < 16) { if (src_offset == stack_offset) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2))); *src = TMP_REG1; } FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10))); } else FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); break; case SLJIT_ARG_TYPE_F64: arg_count--; float_arg_count--; stack_offset = offsets[arg_count]; SLJIT_ASSERT((stack_offset & 0x7) == 0); if (stack_offset < 16) { if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2))); *src = TMP_REG1; } FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count)); } else FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); break; default: arg_count--; word_arg_offset -= sizeof(sljit_sw); stack_offset = offsets[arg_count]; SLJIT_ASSERT(stack_offset >= word_arg_offset); if (stack_offset != word_arg_offset) { if (stack_offset < 16) { if (src_offset == stack_offset) { FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2))); *src = TMP_REG1; } else if (src_offset == word_arg_offset) { *src = 1 + (stack_offset >> 2); src_offset = stack_offset; } FAIL_IF(push_inst(compiler, MOV | (stack_offset << 10) | (word_arg_offset >> 2))); } else FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (stack_offset - 16))); } break; } types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) { sljit_s32 stack_size = 0; if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12))); if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0)); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: stack_size += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: if (stack_size & 0x7) stack_size += sizeof(sljit_sw); stack_size += sizeof(sljit_f64); break; default: stack_size += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } if (stack_size <= 16) return SLJIT_SUCCESS; return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_size - 16) + 0x7) & ~0x7)); } #else /* !__SOFTFP__ */ static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) { sljit_u32 remap = 0; sljit_u32 offset = 0; sljit_u32 new_offset, mask; /* Remove return value. */ arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) { new_offset = 0; mask = 1; while (remap & mask) { new_offset++; mask <<= 1; } remap |= mask; if (offset != new_offset) FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, 0, (new_offset >> 1) + 1, (offset >> 1) + 1, 0) | ((new_offset & 0x1) ? 0x400000 : 0))); offset += 2; } else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) { new_offset = 0; mask = 3; while (remap & mask) { new_offset += 2; mask <<= 2; } remap |= mask; if (offset != new_offset) FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, SLJIT_F32_OP, (new_offset >> 1) + 1, (offset >> 1) + 1, 0))); offset += 2; } arg_types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } #endif /* __SOFTFP__ */ #undef EMIT_FPU_OPERATION SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { #ifdef __SOFTFP__ struct sljit_jump *jump; #endif CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #ifdef __SOFTFP__ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif jump = sljit_emit_jump(compiler, type); PTR_FAIL_IF(jump == NULL); PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); return jump; #else /* !__SOFTFP__ */ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); #endif /* __SOFTFP__ */ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); SLJIT_ASSERT(reg_map[TMP_REG1] != 14); if (!(src & SLJIT_IMM)) { if (FAST_IS_REG(src)) { SLJIT_ASSERT(reg_map[src] != 14); return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src)); } SLJIT_ASSERT(src & SLJIT_MEM); FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)); } /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); jump->u.target = srcw; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) if (type >= SLJIT_FAST_CALL) FAIL_IF(prepare_blx(compiler)); FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0)); if (type >= SLJIT_FAST_CALL) FAIL_IF(emit_blx(compiler)); #else FAIL_IF(emit_imm(compiler, TMP_REG1, 0)); FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1))); #endif jump->addr = compiler->size; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); #ifdef __SOFTFP__ if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); return softfloat_post_call_with_args(compiler, arg_types); #else /* !__SOFTFP__ */ FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_ijump(compiler, type, src, srcw); #endif /* __SOFTFP__ */ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op); sljit_uw cc, ins; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); op = GET_OPCODE(op); cc = get_cc(type & 0xff); dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1; if (op < SLJIT_ADD) { FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0)); FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc)); if (dst & SLJIT_MEM) return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR)); if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2)); FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc)); if (op == SLJIT_AND) FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000))); if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2)); if (flags & SLJIT_SET_Z) return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg)); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { sljit_uw cc, tmp; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); dst_reg &= ~SLJIT_I32_OP; cc = get_cc(type & 0xff); if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { tmp = get_imm(srcw); if (tmp) return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc); tmp = get_imm(~srcw); if (tmp) return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc); #if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) tmp = (sljit_uw) srcw; FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff))); if (tmp <= 0xffff) return SLJIT_SUCCESS; return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff)); #else FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; #endif } return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src)) & ~COND_MASK) | cc); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { sljit_s32 flags; sljit_uw is_type1_transfer, inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); is_type1_transfer = 1; switch (type & 0xff) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: flags = WORD_SIZE; break; case SLJIT_MOV_U8: flags = BYTE_SIZE; break; case SLJIT_MOV_S8: if (!(type & SLJIT_MEM_STORE)) is_type1_transfer = 0; flags = BYTE_SIZE | SIGNED; break; case SLJIT_MOV_U16: is_type1_transfer = 0; flags = HALF_SIZE; break; case SLJIT_MOV_S16: is_type1_transfer = 0; flags = HALF_SIZE | SIGNED; break; default: SLJIT_UNREACHABLE(); flags = WORD_SIZE; break; } if (!(type & SLJIT_MEM_STORE)) flags |= LOAD_DATA; SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags)); if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { if (!is_type1_transfer && memw != 0) return SLJIT_ERR_UNSUPPORTED; } else { if (is_type1_transfer) { if (memw > 4095 && memw < -4095) return SLJIT_ERR_UNSUPPORTED; } else { if (memw > 255 && memw < -255) return SLJIT_ERR_UNSUPPORTED; } } if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { memw &= 0x3; inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | (memw << 7)); if (is_type1_transfer) inst |= (1 << 25); if (type & SLJIT_MEM_PRE) inst |= (1 << 21); else inst ^= (1 << 24); return push_inst(compiler, inst); } inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0); if (type & SLJIT_MEM_PRE) inst |= (1 << 21); else inst ^= (1 << 24); if (is_type1_transfer) { if (memw >= 0) inst |= (1 << 23); else memw = -memw; return push_inst(compiler, inst | memw); } if (memw >= 0) inst |= (1 << 23); else memw = -memw; return push_inst(compiler, inst | TYPE2_TRANSFER_IMM(memw)); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; sljit_s32 reg; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); reg = SLOW_IS_REG(dst) ? dst : TMP_REG2; #if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), init_value)); compiler->patches++; #else PTR_FAIL_IF(emit_imm(compiler, reg, init_value)); #endif set_const(const_, compiler); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1)); return const_; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { inline_set_jump_addr(addr, executable_offset, new_target, 1); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { inline_set_const(addr, executable_offset, new_constant, 1); } ================================================ FILE: src/pcre/sljit/sljitNativeARM_64.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { return "ARM-64" SLJIT_CPUINFO; } /* Length of an instruction word */ typedef sljit_u32 sljit_ins; #define TMP_ZERO (0) #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4) #define TMP_FP (SLJIT_NUMBER_OF_REGISTERS + 5) #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) /* r18 - platform register, currently not used */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = { 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 31, 9, 10, 30, 29 }; static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 0, 1, 2, 3, 4, 5, 6, 7 }; #define W_OP (1u << 31) #define RD(rd) (reg_map[rd]) #define RT(rt) (reg_map[rt]) #define RN(rn) (reg_map[rn] << 5) #define RT2(rt2) (reg_map[rt2] << 10) #define RM(rm) (reg_map[rm] << 16) #define VD(vd) (freg_map[vd]) #define VT(vt) (freg_map[vt]) #define VN(vn) (freg_map[vn] << 5) #define VM(vm) (freg_map[vm] << 16) /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ #define ADC 0x9a000000 #define ADD 0x8b000000 #define ADDE 0x8b200000 #define ADDI 0x91000000 #define AND 0x8a000000 #define ANDI 0x92000000 #define ASRV 0x9ac02800 #define B 0x14000000 #define B_CC 0x54000000 #define BL 0x94000000 #define BLR 0xd63f0000 #define BR 0xd61f0000 #define BRK 0xd4200000 #define CBZ 0xb4000000 #define CLZ 0xdac01000 #define CSEL 0x9a800000 #define CSINC 0x9a800400 #define EOR 0xca000000 #define EORI 0xd2000000 #define FABS 0x1e60c000 #define FADD 0x1e602800 #define FCMP 0x1e602000 #define FCVT 0x1e224000 #define FCVTZS 0x9e780000 #define FDIV 0x1e601800 #define FMOV 0x1e604000 #define FMUL 0x1e600800 #define FNEG 0x1e614000 #define FSUB 0x1e603800 #define LDRI 0xf9400000 #define LDP 0xa9400000 #define LDP_PRE 0xa9c00000 #define LDR_PRE 0xf8400c00 #define LSLV 0x9ac02000 #define LSRV 0x9ac02400 #define MADD 0x9b000000 #define MOVK 0xf2800000 #define MOVN 0x92800000 #define MOVZ 0xd2800000 #define NOP 0xd503201f #define ORN 0xaa200000 #define ORR 0xaa000000 #define ORRI 0xb2000000 #define RET 0xd65f0000 #define SBC 0xda000000 #define SBFM 0x93000000 #define SCVTF 0x9e620000 #define SDIV 0x9ac00c00 #define SMADDL 0x9b200000 #define SMULH 0x9b403c00 #define STP 0xa9000000 #define STP_PRE 0xa9800000 #define STRB 0x38206800 #define STRBI 0x39000000 #define STRI 0xf9000000 #define STR_FI 0x3d000000 #define STR_FR 0x3c206800 #define STUR_FI 0x3c000000 #define STURBI 0x38000000 #define SUB 0xcb000000 #define SUBI 0xd1000000 #define SUBS 0xeb000000 #define UBFM 0xd3000000 #define UDIV 0x9ac00800 #define UMULH 0x9bc03c00 /* dest_reg is the absolute name of the register Useful for reordering instructions in the delay slot. */ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm) { FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5))); FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 16) & 0xffff) << 5) | (1 << 21))); FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 32) & 0xffff) << 5) | (2 << 21))); return push_inst(compiler, MOVK | RD(dst) | ((imm >> 48) << 5) | (3 << 21)); } static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm) { sljit_s32 dst = inst[0] & 0x1f; SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21))); inst[0] = MOVZ | dst | ((new_imm & 0xffff) << 5); inst[1] = MOVK | dst | (((new_imm >> 16) & 0xffff) << 5) | (1 << 21); inst[2] = MOVK | dst | (((new_imm >> 32) & 0xffff) << 5) | (2 << 21); inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21); } static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; if (jump->flags & SLJIT_REWRITABLE_JUMP) { jump->flags |= PATCH_ABS64; return 0; } if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset; if (jump->flags & IS_COND) { diff += sizeof(sljit_ins); if (diff <= 0xfffff && diff >= -0x100000) { code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1; jump->addr -= sizeof(sljit_ins); jump->flags |= PATCH_COND; return 5; } diff -= sizeof(sljit_ins); } if (diff <= 0x7ffffff && diff >= -0x8000000) { jump->flags |= PATCH_B; return 4; } if (target_addr <= 0xffffffffl) { if (jump->flags & IS_COND) code_ptr[-5] -= (2 << 5); code_ptr[-2] = code_ptr[0]; return 2; } if (target_addr <= 0xffffffffffffl) { if (jump->flags & IS_COND) code_ptr[-5] -= (1 << 5); jump->flags |= PATCH_ABS48; code_ptr[-1] = code_ptr[0]; return 1; } jump->flags |= PATCH_ABS64; return 0; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_ins *code; sljit_ins *code_ptr; sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; sljit_sw executable_offset; sljit_uw addr; sljit_s32 dst; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; word_count = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; /* These structures are ordered by their address. */ SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); if (label && label->size == word_count) { label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } if (jump && jump->addr == word_count) { jump->addr = (sljit_uw)(code_ptr - 4); code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset); jump = jump->next; } if (const_ && const_->addr == word_count) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; } code_ptr ++; word_count ++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); if (label && label->size == word_count) { label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { do { addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; buf_ptr = (sljit_ins *)jump->addr; if (jump->flags & PATCH_B) { addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000); buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff); if (jump->flags & IS_COND) buf_ptr[-1] -= (4 << 5); break; } if (jump->flags & PATCH_COND) { addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000); buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5); break; } SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || addr <= 0xffffffffl); SLJIT_ASSERT((jump->flags & PATCH_ABS64) || addr <= 0xffffffffffffl); dst = buf_ptr[0] & 0x1f; buf_ptr[0] = MOVZ | dst | ((addr & 0xffff) << 5); buf_ptr[1] = MOVK | dst | (((addr >> 16) & 0xffff) << 5) | (1 << 21); if (jump->flags & (PATCH_ABS48 | PATCH_ABS64)) buf_ptr[2] = MOVK | dst | (((addr >> 32) & 0xffff) << 5) | (2 << 21); if (jump->flags & PATCH_ABS64) buf_ptr[3] = MOVK | dst | (((addr >> 48) & 0xffff) << 5) | (3 << 21); } while (0); jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #else /* Available by default. */ return 1; #endif case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: return 1; default: return 0; } } /* --------------------------------------------------------------------- */ /* Core code generator functions. */ /* --------------------------------------------------------------------- */ #define COUNT_TRAILING_ZERO(value, result) \ result = 0; \ if (!(value & 0xffffffff)) { \ result += 32; \ value >>= 32; \ } \ if (!(value & 0xffff)) { \ result += 16; \ value >>= 16; \ } \ if (!(value & 0xff)) { \ result += 8; \ value >>= 8; \ } \ if (!(value & 0xf)) { \ result += 4; \ value >>= 4; \ } \ if (!(value & 0x3)) { \ result += 2; \ value >>= 2; \ } \ if (!(value & 0x1)) { \ result += 1; \ value >>= 1; \ } #define LOGICAL_IMM_CHECK 0x100 static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len) { sljit_s32 negated, ones, right; sljit_uw mask, uimm; sljit_ins ins; if (len & LOGICAL_IMM_CHECK) { len &= ~LOGICAL_IMM_CHECK; if (len == 32 && (imm == 0 || imm == -1)) return 0; if (len == 16 && ((sljit_s32)imm == 0 || (sljit_s32)imm == -1)) return 0; } SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1) || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1)); uimm = (sljit_uw)imm; while (1) { if (len <= 0) { SLJIT_UNREACHABLE(); return 0; } mask = ((sljit_uw)1 << len) - 1; if ((uimm & mask) != ((uimm >> len) & mask)) break; len >>= 1; } len <<= 1; negated = 0; if (uimm & 0x1) { negated = 1; uimm = ~uimm; } if (len < 64) uimm &= ((sljit_uw)1 << len) - 1; /* Unsigned right shift. */ COUNT_TRAILING_ZERO(uimm, right); /* Signed shift. We also know that the highest bit is set. */ imm = (sljit_sw)~uimm; SLJIT_ASSERT(imm < 0); COUNT_TRAILING_ZERO(imm, ones); if (~imm) return 0; if (len == 64) ins = 1 << 22; else ins = (0x3f - ((len << 1) - 1)) << 10; if (negated) return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16); return ins | ((ones - 1) << 10) | ((len - right) << 16); } #undef COUNT_TRAILING_ZERO static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm) { sljit_uw imm = (sljit_uw)simm; sljit_s32 i, zeros, ones, first; sljit_ins bitmask; /* Handling simple immediates first. */ if (imm <= 0xffff) return push_inst(compiler, MOVZ | RD(dst) | (imm << 5)); if (simm < 0 && simm >= -0x10000) return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5)); if (imm <= 0xffffffffl) { if ((imm & 0xffff) == 0) return push_inst(compiler, MOVZ | RD(dst) | ((imm >> 16) << 5) | (1 << 21)); if ((imm & 0xffff0000l) == 0xffff0000) return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff) << 5)); if ((imm & 0xffff) == 0xffff) return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); bitmask = logical_imm(simm, 16); if (bitmask != 0) return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask); FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5))); return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); } bitmask = logical_imm(simm, 32); if (bitmask != 0) return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask); if (simm < 0 && simm >= -0x100000000l) { if ((imm & 0xffff) == 0xffff) return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5))); return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21)); } /* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */ zeros = 0; ones = 0; for (i = 4; i > 0; i--) { if ((simm & 0xffff) == 0) zeros++; if ((simm & 0xffff) == 0xffff) ones++; simm >>= 16; } simm = (sljit_sw)imm; first = 1; if (ones > zeros) { simm = ~simm; for (i = 0; i < 4; i++) { if (!(simm & 0xffff)) { simm >>= 16; continue; } if (first) { first = 0; FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((simm & 0xffff) << 5) | (i << 21))); } else FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((~simm & 0xffff) << 5) | (i << 21))); simm >>= 16; } return SLJIT_SUCCESS; } for (i = 0; i < 4; i++) { if (!(simm & 0xffff)) { simm >>= 16; continue; } if (first) { first = 0; FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((simm & 0xffff) << 5) | (i << 21))); } else FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((simm & 0xffff) << 5) | (i << 21))); simm >>= 16; } return SLJIT_SUCCESS; } #define ARG1_IMM 0x0010000 #define ARG2_IMM 0x0020000 #define INT_OP 0x0040000 #define SET_FLAGS 0x0080000 #define UNUSED_RETURN 0x0100000 #define CHECK_FLAGS(flag_bits) \ if (flags & SET_FLAGS) { \ inv_bits |= flag_bits; \ if (flags & UNUSED_RETURN) \ dst = TMP_ZERO; \ } static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_sw arg1, sljit_sw arg2) { /* dst must be register, TMP_REG1 arg1 must be register, TMP_REG1, imm arg2 must be register, TMP_REG2, imm */ sljit_ins inv_bits = (flags & INT_OP) ? W_OP : 0; sljit_ins inst_bits; sljit_s32 op = (flags & 0xffff); sljit_s32 reg; sljit_sw imm, nimm; if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { /* Both are immediates. */ flags &= ~ARG1_IMM; if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB) arg1 = TMP_ZERO; else { FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); arg1 = TMP_REG1; } } if (flags & (ARG1_IMM | ARG2_IMM)) { reg = (flags & ARG2_IMM) ? arg1 : arg2; imm = (flags & ARG2_IMM) ? arg2 : arg1; switch (op) { case SLJIT_MUL: case SLJIT_NEG: case SLJIT_CLZ: case SLJIT_ADDC: case SLJIT_SUBC: /* No form with immediate operand (except imm 0, which is represented by a ZERO register). */ break; case SLJIT_MOV: SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1); return load_immediate(compiler, dst, imm); case SLJIT_NOT: SLJIT_ASSERT(flags & ARG2_IMM); FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm)); goto set_flags; case SLJIT_SUB: if (flags & ARG1_IMM) break; imm = -imm; /* Fall through. */ case SLJIT_ADD: if (imm == 0) { CHECK_FLAGS(1 << 29); return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg)); } if (imm > 0 && imm <= 0xfff) { CHECK_FLAGS(1 << 29); return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (imm << 10)); } nimm = -imm; if (nimm > 0 && nimm <= 0xfff) { CHECK_FLAGS(1 << 29); return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (nimm << 10)); } if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) { CHECK_FLAGS(1 << 29); return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22)); } if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) { CHECK_FLAGS(1 << 29); return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22)); } if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) { FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22))); return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | ((imm & 0xfff) << 10)); } if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) { FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22))); return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | ((nimm & 0xfff) << 10)); } break; case SLJIT_AND: inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32)); if (!inst_bits) break; CHECK_FLAGS(3 << 29); return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits); case SLJIT_OR: case SLJIT_XOR: inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32)); if (!inst_bits) break; if (op == SLJIT_OR) inst_bits |= ORRI; else inst_bits |= EORI; FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg))); goto set_flags; case SLJIT_SHL: if (flags & ARG1_IMM) break; if (flags & INT_OP) { imm &= 0x1f; FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | ((-imm & 0x1f) << 16) | ((31 - imm) << 10))); } else { imm &= 0x3f; FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | ((-imm & 0x3f) << 16) | ((63 - imm) << 10))); } goto set_flags; case SLJIT_LSHR: case SLJIT_ASHR: if (flags & ARG1_IMM) break; if (op == SLJIT_ASHR) inv_bits |= 1 << 30; if (flags & INT_OP) { imm &= 0x1f; FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (imm << 16) | (31 << 10))); } else { imm &= 0x3f; FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | (imm << 16) | (63 << 10))); } goto set_flags; default: SLJIT_UNREACHABLE(); break; } if (flags & ARG2_IMM) { if (arg2 == 0) arg2 = TMP_ZERO; else { FAIL_IF(load_immediate(compiler, TMP_REG2, arg2)); arg2 = TMP_REG2; } } else { if (arg1 == 0) arg1 = TMP_ZERO; else { FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); arg1 = TMP_REG1; } } } /* Both arguments are registers. */ switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (dst == arg2) return SLJIT_SUCCESS; return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(arg2)); case SLJIT_MOV_U8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (7 << 10)); case SLJIT_MOV_S8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (!(flags & INT_OP)) inv_bits |= 1 << 22; return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10)); case SLJIT_MOV_U16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); return push_inst(compiler, (UBFM ^ W_OP) | RD(dst) | RN(arg2) | (15 << 10)); case SLJIT_MOV_S16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if (!(flags & INT_OP)) inv_bits |= 1 << 22; return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10)); case SLJIT_MOV_U32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if ((flags & INT_OP) && dst == arg2) return SLJIT_SUCCESS; return push_inst(compiler, (ORR ^ W_OP) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); case SLJIT_MOV_S32: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); if ((flags & INT_OP) && dst == arg2) return SLJIT_SUCCESS; return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10)); case SLJIT_NOT: SLJIT_ASSERT(arg1 == TMP_REG1); FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2))); break; /* Set flags. */ case SLJIT_NEG: SLJIT_ASSERT(arg1 == TMP_REG1); if (flags & SET_FLAGS) inv_bits |= 1 << 29; return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)); case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG1); return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2)); case SLJIT_ADD: CHECK_FLAGS(1 << 29); return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); case SLJIT_ADDC: CHECK_FLAGS(1 << 29); return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); case SLJIT_SUB: CHECK_FLAGS(1 << 29); return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); case SLJIT_SUBC: CHECK_FLAGS(1 << 29); return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); case SLJIT_MUL: if (!(flags & SET_FLAGS)) return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)); if (flags & INT_OP) { FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10))); FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10))); return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10)); } FAIL_IF(push_inst(compiler, SMULH | RD(TMP_LR) | RN(arg1) | RM(arg2))); FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO))); return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10)); case SLJIT_AND: CHECK_FLAGS(3 << 29); return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)); case SLJIT_OR: FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_XOR: FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_SHL: FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_LSHR: FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ case SLJIT_ASHR: FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2))); break; /* Set flags. */ default: SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } set_flags: if (flags & SET_FLAGS) return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO)); return SLJIT_SUCCESS; } #define STORE 0x10 #define SIGNED 0x20 #define BYTE_SIZE 0x0 #define HALF_SIZE 0x1 #define INT_SIZE 0x2 #define WORD_SIZE 0x3 #define MEM_SIZE_SHIFT(flags) ((flags) & 0x3) static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_u32 shift = MEM_SIZE_SHIFT(flags); sljit_u32 type = (shift << 30); if (!(flags & STORE)) type |= (flags & SIGNED) ? 0x00800000 : 0x00400000; SLJIT_ASSERT(arg & SLJIT_MEM); if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; if (argw == 0 || argw == shift) return push_inst(compiler, STRB | type | RT(reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0)); FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10))); return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg)); } arg &= REG_MASK; if (arg == SLJIT_UNUSED) { FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift))); argw = (argw >> shift) & 0xfff; return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10)); } if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) { if ((argw >> shift) <= 0xfff) { return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | (argw << (10 - shift))); } if (argw <= 0xffffff) { FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | ((argw >> 12) << 10))); argw = ((argw & 0xfff) >> shift); return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10)); } } if (argw <= 255 && argw >= -256) return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12)); FAIL_IF(load_immediate(compiler, tmp_reg, argw)); return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg)); } /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args, i, tmp, offs, prev, saved_regs_size; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); if (saved_regs_size & 0x8) saved_regs_size += sizeof(sljit_sw); local_size = (local_size + 15) & ~0xf; compiler->local_size = local_size + saved_regs_size; FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP) | ((-(saved_regs_size >> 3) & 0x7f) << 15))); #ifdef _WIN32 if (local_size >= 4096) FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (1 << 10) | (1 << 22))); else if (local_size > 256) FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (local_size << 10))); #endif tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; prev = -1; offs = 2 << 15; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { prev = i; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs)); offs += 2 << 15; prev = -1; } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { prev = i; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs)); offs += 2 << 15; prev = -1; } if (prev != -1) FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5))); FAIL_IF(push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10))); args = get_arg_count(arg_types); if (args >= 1) FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0))); if (args >= 2) FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S1) | RN(TMP_ZERO) | RM(SLJIT_R1))); if (args >= 3) FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2))); #ifdef _WIN32 if (local_size >= 4096) { if (local_size < 4 * 4096) { /* No need for a loop. */ if (local_size >= 2 * 4096) { FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22))); local_size -= 4096; } if (local_size >= 2 * 4096) { FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22))); local_size -= 4096; } FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); local_size -= 4096; } else { FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG2) | (((local_size >> 12) - 1) << 5))); FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22))); FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG2) | RN(TMP_REG2) | (1 << 10))); FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */)); FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); local_size &= 0xfff; } if (local_size > 256) { FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (local_size << 10))); FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); } else if (local_size > 0) FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(TMP_REG1) | ((-local_size & 0x1ff) << 12))); FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10))); } else if (local_size > 256) { FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1))); FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10))); } else if (local_size > 0) FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(SLJIT_SP) | ((-local_size & 0x1ff) << 12))); #else /* !_WIN32 */ /* The local_size does not include saved registers size. */ if (local_size > 0xfff) { FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22))); local_size &= 0xfff; } if (local_size != 0) FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10))); #endif /* _WIN32 */ return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 saved_regs_size; CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2); if (saved_regs_size & 0x8) saved_regs_size += sizeof(sljit_sw); compiler->local_size = saved_regs_size + ((local_size + 15) & ~0xf); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 local_size; sljit_s32 i, tmp, offs, prev, saved_regs_size; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 2); if (saved_regs_size & 0x8) saved_regs_size += sizeof(sljit_sw); local_size = compiler->local_size - saved_regs_size; /* Load LR as early as possible. */ if (local_size == 0) FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP))); else if (local_size < 63 * sizeof(sljit_sw)) { FAIL_IF(push_inst(compiler, LDP_PRE | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP) | (local_size << (15 - 3)))); } else { if (local_size > 0xfff) { FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22))); local_size &= 0xfff; } if (local_size) FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10))); FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP))); } tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; prev = -1; offs = 2 << 15; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { prev = i; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs)); offs += 2 << 15; prev = -1; } for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { prev = i; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs)); offs += 2 << 15; prev = -1; } if (prev != -1) FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5))); /* These two can be executed in parallel. */ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (saved_regs_size << 10))); return push_inst(compiler, RET | RN(TMP_LR)); } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { sljit_ins inv_bits = (op & SLJIT_I32_OP) ? W_OP : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: return push_inst(compiler, BRK); case SLJIT_NOP: return push_inst(compiler, NOP); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, ((op == SLJIT_DIVMOD_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); case SLJIT_DIV_UW: case SLJIT_DIV_SW: return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r, flags, mem_flags; sljit_s32 op_flags = GET_ALL_FLAGS(op); CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) { SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4); if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) dst = 5; else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) dst = 3; else dst = 1; /* Signed word sized load is the prefetch instruction. */ return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw, TMP_REG1); } return SLJIT_SUCCESS; } dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; op = GET_OPCODE(op); if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { /* Both operands are registers. */ if (dst_r != TMP_REG1 && FAST_IS_REG(src)) return emit_op_imm(compiler, op | ((op_flags & SLJIT_I32_OP) ? INT_OP : 0), dst_r, TMP_REG1, src); switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: mem_flags = WORD_SIZE; break; case SLJIT_MOV_U8: mem_flags = BYTE_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u8)srcw; break; case SLJIT_MOV_S8: mem_flags = BYTE_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s8)srcw; break; case SLJIT_MOV_U16: mem_flags = HALF_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u16)srcw; break; case SLJIT_MOV_S16: mem_flags = HALF_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s16)srcw; break; case SLJIT_MOV_U32: mem_flags = INT_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u32)srcw; break; case SLJIT_MOV_S32: mem_flags = INT_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s32)srcw; break; default: SLJIT_UNREACHABLE(); mem_flags = 0; break; } if (src & SLJIT_IMM) FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw)); else if (!(src & SLJIT_MEM)) dst_r = src; else FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, src, srcw, TMP_REG1)); if (dst & SLJIT_MEM) return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0; mem_flags = WORD_SIZE; if (op_flags & SLJIT_I32_OP) { flags |= INT_OP; mem_flags = INT_SIZE; } if (dst == SLJIT_UNUSED) flags |= UNUSED_RETURN; if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2)); src = TMP_REG2; } emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, src); if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r, flags, mem_flags; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; flags = HAS_FLAGS(op) ? SET_FLAGS : 0; mem_flags = WORD_SIZE; if (op & SLJIT_I32_OP) { flags |= INT_OP; mem_flags = INT_SIZE; } if (dst == SLJIT_UNUSED) flags |= UNUSED_RETURN; if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, src1, src1w, TMP_REG1)); src1 = TMP_REG1; } if (src2 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src2, src2w, TMP_REG2)); src2 = TMP_REG2; } if (src1 & SLJIT_IMM) flags |= ARG1_IMM; else src1w = src1; if (src2 & SLJIT_IMM) flags |= ARG2_IMM; else src2w = src2; emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w); if (dst & SLJIT_MEM) return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); return push_inst(compiler, *(sljit_ins*)instruction); } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { sljit_u32 shift = MEM_SIZE_SHIFT(flags); sljit_ins type = (shift << 30); SLJIT_ASSERT(arg & SLJIT_MEM); if (!(flags & STORE)) type |= 0x00400000; if (arg & OFFS_REG_MASK) { argw &= 3; if (argw == 0 || argw == shift) return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0)); FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10))); return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1)); } arg &= REG_MASK; if (arg == SLJIT_UNUSED) { FAIL_IF(load_immediate(compiler, TMP_REG1, argw & ~(0xfff << shift))); argw = (argw >> shift) & 0xfff; return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10)); } if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) { if ((argw >> shift) <= 0xfff) return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | (argw << (10 - shift))); if (argw <= 0xffffff) { FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG1) | RN(arg) | ((argw >> 12) << 10))); argw = ((argw & 0xfff) >> shift); return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10)); } } if (argw <= 255 && argw >= -256) return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12)); FAIL_IF(load_immediate(compiler, TMP_REG1, argw)); return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG1)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) inv_bits |= W_OP; if (src & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw); src = TMP_FREG1; } FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src))); if (dst & SLJIT_MEM) return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) inv_bits |= W_OP; if (src & SLJIT_MEM) { emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? INT_SIZE : WORD_SIZE), TMP_REG1, src, srcw, TMP_REG1); src = TMP_REG1; } else if (src & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src))); if (dst & SLJIT_MEM) return emit_fop_mem(compiler, ((op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE; sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; if (src1 & SLJIT_MEM) { emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w); src2 = TMP_FREG2; } return push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE; sljit_ins inv_bits; CHECK_ERROR(); SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw); src = dst_r; } switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src))); else dst_r = src; } break; case SLJIT_NEG_F64: FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src))); break; case SLJIT_ABS_F64: FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src))); break; case SLJIT_CONV_F64_FROM_F32: FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_F32_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src))); break; } if (dst & SLJIT_MEM) return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE; sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src1 & SLJIT_MEM) { emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w); src2 = TMP_FREG2; } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); break; case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); break; case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); break; case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2))); break; } if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw); } /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) return push_inst(compiler, ORR | RD(dst) | RN(TMP_ZERO) | RM(TMP_LR)); /* Memory. */ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); else FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); return push_inst(compiler, RET | RN(TMP_LR)); } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ static sljit_uw get_cc(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: case SLJIT_MUL_NOT_OVERFLOW: case SLJIT_EQUAL_F64: return 0x1; case SLJIT_NOT_EQUAL: case SLJIT_MUL_OVERFLOW: case SLJIT_NOT_EQUAL_F64: return 0x0; case SLJIT_LESS: case SLJIT_LESS_F64: return 0x2; case SLJIT_GREATER_EQUAL: case SLJIT_GREATER_EQUAL_F64: return 0x3; case SLJIT_GREATER: case SLJIT_GREATER_F64: return 0x9; case SLJIT_LESS_EQUAL: case SLJIT_LESS_EQUAL_F64: return 0x8; case SLJIT_SIG_LESS: return 0xa; case SLJIT_SIG_GREATER_EQUAL: return 0xb; case SLJIT_SIG_GREATER: return 0xd; case SLJIT_SIG_LESS_EQUAL: return 0xc; case SLJIT_OVERFLOW: case SLJIT_UNORDERED_F64: return 0x7; case SLJIT_NOT_OVERFLOW: case SLJIT_ORDERED_F64: return 0x6; default: SLJIT_UNREACHABLE(); return 0xe; } } SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); return label; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; if (type < SLJIT_JUMP) { jump->flags |= IS_COND; PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(type))); } else if (type >= SLJIT_FAST_CALL) jump->flags |= IS_BL; PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1))); return jump; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); } static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump; sljit_ins inv_bits = (type & SLJIT_I32_OP) ? W_OP : 0; SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL); ADJUST_LOCAL_OFFSET(src, srcw); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); jump->flags |= IS_CBZ | IS_COND; if (src & SLJIT_MEM) { PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } else if (src & SLJIT_IMM) { PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } SLJIT_ASSERT(FAST_IS_REG(src)); if ((type & 0xff) == SLJIT_EQUAL) inv_bits |= 1 << 24; PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src))); PTR_FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG1))); return jump; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (!(src & SLJIT_IMM)) { if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src)); } /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); jump->u.target = srcw; FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG1)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_ijump(compiler, type, src, srcw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_s32 dst_r, src_r, flags, mem_flags; sljit_ins cc; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); cc = get_cc(type & 0xff); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (GET_OPCODE(op) < SLJIT_ADD) { FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO))); if (dst_r == TMP_REG1) { mem_flags = (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE; return emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG2); } return SLJIT_SUCCESS; } flags = HAS_FLAGS(op) ? SET_FLAGS : 0; mem_flags = WORD_SIZE; if (op & SLJIT_I32_OP) { flags |= INT_OP; mem_flags = INT_SIZE; } src_r = dst; if (dst & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG1)); src_r = TMP_REG1; } FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO))); emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src_r, TMP_REG2); if (dst & SLJIT_MEM) return emit_op_mem(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? W_OP : 0; sljit_ins cc; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { if (dst_reg & SLJIT_I32_OP) srcw = (sljit_s32)srcw; FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; srcw = 0; } cc = get_cc(type & 0xff); dst_reg &= ~SLJIT_I32_OP; return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { sljit_u32 sign = 0, inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256)) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; switch (type & 0xff) { case SLJIT_MOV: case SLJIT_MOV_P: inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; break; case SLJIT_MOV_S8: sign = 1; case SLJIT_MOV_U8: inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400; break; case SLJIT_MOV_S16: sign = 1; case SLJIT_MOV_U16: inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400; break; case SLJIT_MOV_S32: sign = 1; case SLJIT_MOV_U32: inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400; break; default: SLJIT_UNREACHABLE(); inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400; break; } if (!(type & SLJIT_MEM_STORE)) inst |= sign ? 0x00800000 : 0x00400000; if (type & SLJIT_MEM_PRE) inst |= 0x800; return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { sljit_u32 inst; CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256)) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; inst = STUR_FI | 0x80000400; if (!(type & SLJIT_F32_OP)) inst |= 0x40000000; if (!(type & SLJIT_MEM_STORE)) inst |= 0x00400000; if (type & SLJIT_MEM_PRE) inst |= 0x800; return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { sljit_s32 dst_reg; sljit_ins ins; CHECK_ERROR(); CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); SLJIT_ASSERT (SLJIT_LOCALS_OFFSET_BASE == 0); dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1; if (offset <= 0xffffff && offset >= -0xffffff) { ins = ADDI; if (offset < 0) { offset = -offset; ins = SUBI; } if (offset <= 0xfff) FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (offset << 10))); else { FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | ((offset & 0xfff000) >> (12 - 10)) | (1 << 22))); offset &= 0xfff; if (offset != 0) FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (offset << 10))); } } else { FAIL_IF(load_immediate (compiler, dst_reg, offset)); /* Add extended register form. */ FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg))); } if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; sljit_s32 dst_r; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value)); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); return const_; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins* inst = (sljit_ins*)addr; modify_imm64_const(inst, new_target); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 4); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_ins* inst = (sljit_ins*)addr; modify_imm64_const(inst, new_constant); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 4); } ================================================ FILE: src/pcre/sljit/sljitNativeARM_T2_32.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { #ifdef __SOFTFP__ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp"; #else return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp"; #endif } /* Length of an instruction word. */ typedef sljit_u32 sljit_ins; /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4) #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) /* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15 }; static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 0, 1, 2, 3, 4, 5, 6, 7 }; #define COPY_BITS(src, from, to, bits) \ ((from >= to ? (src >> (from - to)) : (src << (to - from))) & (((1 << bits) - 1) << to)) /* Thumb16 encodings. */ #define RD3(rd) (reg_map[rd]) #define RN3(rn) (reg_map[rn] << 3) #define RM3(rm) (reg_map[rm] << 6) #define RDN3(rdn) (reg_map[rdn] << 8) #define IMM3(imm) (imm << 6) #define IMM8(imm) (imm) /* Thumb16 helpers. */ #define SET_REGS44(rd, rn) \ ((reg_map[rn] << 3) | (reg_map[rd] & 0x7) | ((reg_map[rd] & 0x8) << 4)) #define IS_2_LO_REGS(reg1, reg2) \ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7) #define IS_3_LO_REGS(reg1, reg2, reg3) \ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7) /* Thumb32 encodings. */ #define RD4(rd) (reg_map[rd] << 8) #define RN4(rn) (reg_map[rn] << 16) #define RM4(rm) (reg_map[rm]) #define RT4(rt) (reg_map[rt] << 12) #define DD4(dd) (freg_map[dd] << 12) #define DN4(dn) (freg_map[dn] << 16) #define DM4(dm) (freg_map[dm]) #define IMM5(imm) \ (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6)) #define IMM12(imm) \ (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)) /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ /* dot '.' changed to _ I immediate form (possibly followed by number of immediate bits). */ #define ADCI 0xf1400000 #define ADCS 0x4140 #define ADC_W 0xeb400000 #define ADD 0x4400 #define ADDS 0x1800 #define ADDSI3 0x1c00 #define ADDSI8 0x3000 #define ADD_W 0xeb000000 #define ADDWI 0xf2000000 #define ADD_SP 0xb000 #define ADD_W 0xeb000000 #define ADD_WI 0xf1000000 #define ANDI 0xf0000000 #define ANDS 0x4000 #define AND_W 0xea000000 #define ASRS 0x4100 #define ASRSI 0x1000 #define ASR_W 0xfa40f000 #define ASR_WI 0xea4f0020 #define BCC 0xd000 #define BICI 0xf0200000 #define BKPT 0xbe00 #define BLX 0x4780 #define BX 0x4700 #define CLZ 0xfab0f080 #define CMNI_W 0xf1100f00 #define CMP 0x4280 #define CMPI 0x2800 #define CMPI_W 0xf1b00f00 #define CMP_X 0x4500 #define CMP_W 0xebb00f00 #define EORI 0xf0800000 #define EORS 0x4040 #define EOR_W 0xea800000 #define IT 0xbf00 #define LDRI 0xf8500800 #define LSLS 0x4080 #define LSLSI 0x0000 #define LSL_W 0xfa00f000 #define LSL_WI 0xea4f0000 #define LSRS 0x40c0 #define LSRSI 0x0800 #define LSR_W 0xfa20f000 #define LSR_WI 0xea4f0010 #define MOV 0x4600 #define MOVS 0x0000 #define MOVSI 0x2000 #define MOVT 0xf2c00000 #define MOVW 0xf2400000 #define MOV_W 0xea4f0000 #define MOV_WI 0xf04f0000 #define MUL 0xfb00f000 #define MVNS 0x43c0 #define MVN_W 0xea6f0000 #define MVN_WI 0xf06f0000 #define NOP 0xbf00 #define ORNI 0xf0600000 #define ORRI 0xf0400000 #define ORRS 0x4300 #define ORR_W 0xea400000 #define POP 0xbc00 #define POP_W 0xe8bd0000 #define PUSH 0xb400 #define PUSH_W 0xe92d0000 #define RSB_WI 0xf1c00000 #define RSBSI 0x4240 #define SBCI 0xf1600000 #define SBCS 0x4180 #define SBC_W 0xeb600000 #define SDIV 0xfb90f0f0 #define SMULL 0xfb800000 #define STR_SP 0x9000 #define SUBS 0x1a00 #define SUBSI3 0x1e00 #define SUBSI8 0x3800 #define SUB_W 0xeba00000 #define SUBWI 0xf2a00000 #define SUB_SP 0xb080 #define SUB_WI 0xf1a00000 #define SXTB 0xb240 #define SXTB_W 0xfa4ff080 #define SXTH 0xb200 #define SXTH_W 0xfa0ff080 #define TST 0x4200 #define UDIV 0xfbb0f0f0 #define UMULL 0xfba00000 #define UXTB 0xb2c0 #define UXTB_W 0xfa5ff080 #define UXTH 0xb280 #define UXTH_W 0xfa1ff080 #define VABS_F32 0xeeb00ac0 #define VADD_F32 0xee300a00 #define VCMP_F32 0xeeb40a40 #define VCVT_F32_S32 0xeeb80ac0 #define VCVT_F64_F32 0xeeb70ac0 #define VCVT_S32_F32 0xeebd0ac0 #define VDIV_F32 0xee800a00 #define VMOV_F32 0xeeb00a40 #define VMOV 0xee000a10 #define VMOV2 0xec400a10 #define VMRS 0xeef1fa10 #define VMUL_F32 0xee200a00 #define VNEG_F32 0xeeb10a40 #define VSTR_F32 0xed000a00 #define VSUB_F32 0xee300a40 static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst) { sljit_u16 *ptr; SLJIT_ASSERT(!(inst & 0xffff0000)); ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16)); FAIL_IF(!ptr); *ptr = inst; compiler->size++; return SLJIT_SUCCESS; } static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst) { sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr++ = inst >> 16; *ptr = inst; compiler->size += 2; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm) { FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); return push_inst32(compiler, MOVT | RD4(dst) | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); } static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm) { sljit_s32 dst = inst[1] & 0x0f00; SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00)); inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1); inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff); inst[2] = (MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1); inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16); } static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset) { sljit_sw diff; if (jump->flags & SLJIT_REWRITABLE_JUMP) return 0; if (jump->flags & JUMP_ADDR) { /* Branch to ARM code is not optimized yet. */ if (!(jump->u.target & 0x1)) return 0; diff = ((sljit_sw)jump->u.target - (sljit_sw)(code_ptr + 2) - executable_offset) >> 1; } else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); diff = ((sljit_sw)(code + jump->u.label->size) - (sljit_sw)(code_ptr + 2)) >> 1; } if (jump->flags & IS_COND) { SLJIT_ASSERT(!(jump->flags & IS_BL)); if (diff <= 127 && diff >= -128) { jump->flags |= PATCH_TYPE1; return 5; } if (diff <= 524287 && diff >= -524288) { jump->flags |= PATCH_TYPE2; return 4; } /* +1 comes from the prefix IT instruction. */ diff--; if (diff <= 8388607 && diff >= -8388608) { jump->flags |= PATCH_TYPE3; return 3; } } else if (jump->flags & IS_BL) { if (diff <= 8388607 && diff >= -8388608) { jump->flags |= PATCH_BL; return 3; } } else { if (diff <= 1023 && diff >= -1024) { jump->flags |= PATCH_TYPE4; return 4; } if (diff <= 8388607 && diff >= -8388608) { jump->flags |= PATCH_TYPE5; return 3; } } return 0; } static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw executable_offset) { sljit_s32 type = (jump->flags >> 4) & 0xf; sljit_sw diff; sljit_u16 *jump_inst; sljit_s32 s, j1, j2; if (SLJIT_UNLIKELY(type == 0)) { modify_imm32_const((sljit_u16*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target); return; } if (jump->flags & JUMP_ADDR) { SLJIT_ASSERT(jump->u.target & 0x1); diff = ((sljit_sw)jump->u.target - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1; } else { SLJIT_ASSERT(jump->u.label->addr & 0x1); diff = ((sljit_sw)(jump->u.label->addr) - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1; } jump_inst = (sljit_u16*)jump->addr; switch (type) { case 1: /* Encoding T1 of 'B' instruction */ SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND)); jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff); return; case 2: /* Encoding T3 of 'B' instruction */ SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND)); jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1); jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff); return; case 3: SLJIT_ASSERT(jump->flags & IS_COND); *jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8; diff--; type = 5; break; case 4: /* Encoding T2 of 'B' instruction */ SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND)); jump_inst[0] = 0xe000 | (diff & 0x7ff); return; } SLJIT_ASSERT(diff <= 8388607 && diff >= -8388608); /* Really complex instruction form for branches. */ s = (diff >> 23) & 0x1; j1 = (~(diff >> 22) ^ s) & 0x1; j2 = (~(diff >> 21) ^ s) & 0x1; jump_inst[0] = 0xf000 | (s << 10) | COPY_BITS(diff, 11, 0, 10); jump_inst[1] = (j1 << 13) | (j2 << 11) | (diff & 0x7ff); /* The others have a common form. */ if (type == 5) /* Encoding T4 of 'B' instruction */ jump_inst[1] |= 0x9000; else if (type == 6) /* Encoding T1 of 'BL' instruction */ jump_inst[1] |= 0xd000; else SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_u16 *code; sljit_u16 *code_ptr; sljit_u16 *buf_ptr; sljit_u16 *buf_end; sljit_uw half_count; sljit_sw executable_offset; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; half_count = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; do { buf_ptr = (sljit_u16*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 1); do { *code_ptr = *buf_ptr++; /* These structures are ordered by their address. */ SLJIT_ASSERT(!label || label->size >= half_count); SLJIT_ASSERT(!jump || jump->addr >= half_count); SLJIT_ASSERT(!const_ || const_->addr >= half_count); if (label && label->size == half_count) { label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1; label->size = code_ptr - code; label = label->next; } if (jump && jump->addr == half_count) { jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_COND) ? 10 : 8); code_ptr -= detect_jump_type(jump, code_ptr, code, executable_offset); jump = jump->next; } if (const_ && const_->addr == half_count) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; } code_ptr ++; half_count ++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); if (label && label->size == half_count) { label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1; label->size = code_ptr - code; label = label->next; } SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { set_jump_instruction(jump, executable_offset); jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16); code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); /* Set thumb mode flag. */ return (void*)((sljit_uw)code | 0x1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #else /* Available by default. */ return 1; #endif case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: return 1; default: return 0; } } /* --------------------------------------------------------------------- */ /* Core code generator functions. */ /* --------------------------------------------------------------------- */ #define INVALID_IMM 0x80000000 static sljit_uw get_imm(sljit_uw imm) { /* Thumb immediate form. */ sljit_s32 counter; if (imm <= 0xff) return imm; if ((imm & 0xffff) == (imm >> 16)) { /* Some special cases. */ if (!(imm & 0xff00)) return (1 << 12) | (imm & 0xff); if (!(imm & 0xff)) return (2 << 12) | ((imm >> 8) & 0xff); if ((imm & 0xff00) == ((imm & 0xff) << 8)) return (3 << 12) | (imm & 0xff); } /* Assembly optimization: count leading zeroes? */ counter = 8; if (!(imm & 0xffff0000)) { counter += 16; imm <<= 16; } if (!(imm & 0xff000000)) { counter += 8; imm <<= 8; } if (!(imm & 0xf0000000)) { counter += 4; imm <<= 4; } if (!(imm & 0xc0000000)) { counter += 2; imm <<= 2; } if (!(imm & 0x80000000)) { counter += 1; imm <<= 1; } /* Since imm >= 128, this must be true. */ SLJIT_ASSERT(counter <= 31); if (imm & 0x00ffffff) return INVALID_IMM; /* Cannot be encoded. */ return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1); } static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm) { sljit_uw tmp; /* MOVS cannot be used since it destroy flags. */ if (imm >= 0x10000) { tmp = get_imm(imm); if (tmp != INVALID_IMM) return push_inst32(compiler, MOV_WI | RD4(dst) | tmp); tmp = get_imm(~imm); if (tmp != INVALID_IMM) return push_inst32(compiler, MVN_WI | RD4(dst) | tmp); } /* set low 16 bits, set hi 16 bits to 0. */ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); /* set hi 16 bit if needed. */ if (imm >= 0x10000) return push_inst32(compiler, MOVT | RD4(dst) | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); return SLJIT_SUCCESS; } #define ARG1_IMM 0x0010000 #define ARG2_IMM 0x0020000 /* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */ #define SET_FLAGS 0x0100000 #define UNUSED_RETURN 0x0200000 static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_uw arg1, sljit_uw arg2) { /* dst must be register, TMP_REG1 arg1 must be register, imm arg2 must be register, imm */ sljit_s32 reg; sljit_uw imm, nimm; if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { /* Both are immediates, no temporaries are used. */ flags &= ~ARG1_IMM; FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); arg1 = TMP_REG1; } if (flags & (ARG1_IMM | ARG2_IMM)) { reg = (flags & ARG2_IMM) ? arg1 : arg2; imm = (flags & ARG2_IMM) ? arg2 : arg1; switch (flags & 0xffff) { case SLJIT_CLZ: case SLJIT_MUL: /* No form with immediate operand. */ break; case SLJIT_MOV: SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2); return load_immediate(compiler, dst, imm); case SLJIT_NOT: if (!(flags & SET_FLAGS)) return load_immediate(compiler, dst, ~imm); /* Since the flags should be set, we just fallback to the register mode. Although some clever things could be done here, "NOT IMM" does not worth the efforts. */ break; case SLJIT_ADD: nimm = -imm; if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); if (nimm <= 0x7) return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg)); if (reg == dst) { if (imm <= 0xff) return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst)); if (nimm <= 0xff) return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst)); } } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm)); if (nimm <= 0xfff) return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm)); } nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); nimm = get_imm(-imm); if (nimm != INVALID_IMM) return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); break; case SLJIT_ADDC: imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SUB: /* SUB operation can be replaced by ADD because of the negative carry flag. */ if (flags & ARG1_IMM) { if (imm == 0 && IS_2_LO_REGS(reg, dst)) return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg)); imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; } if (flags & UNUSED_RETURN) { if (imm <= 0xff && reg_map[reg] <= 7) return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, CMPI_W | RN4(reg) | nimm); nimm = get_imm(-imm); if (nimm != INVALID_IMM) return push_inst32(compiler, CMNI_W | RN4(reg) | nimm); } nimm = -imm; if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); if (nimm <= 0x7) return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg)); if (reg == dst) { if (imm <= 0xff) return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst)); if (nimm <= 0xff) return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst)); } } if (!(flags & SET_FLAGS)) { if (imm <= 0xfff) return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm)); if (nimm <= 0xfff) return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm)); } nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); nimm = get_imm(-imm); if (nimm != INVALID_IMM) return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); break; case SLJIT_SUBC: if (flags & ARG1_IMM) break; imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_AND: nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_OR: nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_XOR: imm = get_imm(imm); if (imm != INVALID_IMM) return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); break; case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: if (flags & ARG1_IMM) break; imm &= 0x1f; if (imm == 0) { if (!(flags & SET_FLAGS)) return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); } switch (flags & 0xffff) { case SLJIT_SHL: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); case SLJIT_LSHR: if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); default: /* SLJIT_ASHR */ if (IS_2_LO_REGS(dst, reg)) return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); } default: SLJIT_UNREACHABLE(); break; } if (flags & ARG2_IMM) { imm = arg2; arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1; FAIL_IF(load_immediate(compiler, arg2, imm)); } else { imm = arg1; arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1; FAIL_IF(load_immediate(compiler, arg1, imm)); } SLJIT_ASSERT(arg1 != arg2); } /* Both arguments are registers. */ switch (flags & 0xffff) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (dst == arg2) return SLJIT_SUCCESS; return push_inst16(compiler, MOV | SET_REGS44(dst, arg2)); case SLJIT_MOV_U8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2)); return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2)); case SLJIT_MOV_S8: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2)); case SLJIT_MOV_U16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2)); return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2)); case SLJIT_MOV_S16: SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2)); case SLJIT_NOT: SLJIT_ASSERT(arg1 == TMP_REG2); if (IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2)); case SLJIT_CLZ: SLJIT_ASSERT(arg1 == TMP_REG2); FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2))); return SLJIT_SUCCESS; case SLJIT_ADD: if (IS_3_LO_REGS(dst, arg1, arg2)) return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2)); if (dst == arg1 && !(flags & SET_FLAGS)) return push_inst16(compiler, ADD | SET_REGS44(dst, arg2)); return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_ADDC: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_SUB: if (flags & UNUSED_RETURN) { if (IS_2_LO_REGS(arg1, arg2)) return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2)); return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2)); } if (IS_3_LO_REGS(dst, arg1, arg2)) return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2)); return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_SUBC: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_MUL: if (!(flags & SET_FLAGS)) return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2)); SLJIT_ASSERT(dst != TMP_REG2); FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2))); /* cmp TMP_REG2, dst asr #31. */ return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst)); case SLJIT_AND: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2)); if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2)) return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2)); return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_OR: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_XOR: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_SHL: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_LSHR: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); case SLJIT_ASHR: if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2)); return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } #define STORE 0x01 #define SIGNED 0x02 #define WORD_SIZE 0x00 #define BYTE_SIZE 0x04 #define HALF_SIZE 0x08 #define PRELOAD 0x0c #define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE))) #define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift))) /* 1st letter: w = word b = byte h = half 2nd letter: s = signed u = unsigned 3rd letter: l = load s = store */ static const sljit_ins sljit_mem16[12] = { /* w u l */ 0x5800 /* ldr */, /* w u s */ 0x5000 /* str */, /* w s l */ 0x5800 /* ldr */, /* w s s */ 0x5000 /* str */, /* b u l */ 0x5c00 /* ldrb */, /* b u s */ 0x5400 /* strb */, /* b s l */ 0x5600 /* ldrsb */, /* b s s */ 0x5400 /* strb */, /* h u l */ 0x5a00 /* ldrh */, /* h u s */ 0x5200 /* strh */, /* h s l */ 0x5e00 /* ldrsh */, /* h s s */ 0x5200 /* strh */, }; static const sljit_ins sljit_mem16_imm5[12] = { /* w u l */ 0x6800 /* ldr imm5 */, /* w u s */ 0x6000 /* str imm5 */, /* w s l */ 0x6800 /* ldr imm5 */, /* w s s */ 0x6000 /* str imm5 */, /* b u l */ 0x7800 /* ldrb imm5 */, /* b u s */ 0x7000 /* strb imm5 */, /* b s l */ 0x0000 /* not allowed */, /* b s s */ 0x7000 /* strb imm5 */, /* h u l */ 0x8800 /* ldrh imm5 */, /* h u s */ 0x8000 /* strh imm5 */, /* h s l */ 0x0000 /* not allowed */, /* h s s */ 0x8000 /* strh imm5 */, }; #define MEM_IMM8 0xc00 #define MEM_IMM12 0x800000 static const sljit_ins sljit_mem32[13] = { /* w u l */ 0xf8500000 /* ldr.w */, /* w u s */ 0xf8400000 /* str.w */, /* w s l */ 0xf8500000 /* ldr.w */, /* w s s */ 0xf8400000 /* str.w */, /* b u l */ 0xf8100000 /* ldrb.w */, /* b u s */ 0xf8000000 /* strb.w */, /* b s l */ 0xf9100000 /* ldrsb.w */, /* b s s */ 0xf8000000 /* strb.w */, /* h u l */ 0xf8300000 /* ldrh.w */, /* h u s */ 0xf8200000 /* strsh.w */, /* h s l */ 0xf9300000 /* ldrsh.w */, /* h s s */ 0xf8200000 /* strsh.w */, /* p u l */ 0xf8100000 /* pld */, }; /* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value) { if (value >= 0) { if (value <= 0xfff) return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value)); value = get_imm(value); if (value != INVALID_IMM) return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | value); } else { value = -value; if (value <= 0xfff) return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value)); value = get_imm(value); if (value != INVALID_IMM) return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | value); } return SLJIT_ERR_UNSUPPORTED; } static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_s32 other_r; sljit_uw tmp; SLJIT_ASSERT(arg & SLJIT_MEM); SLJIT_ASSERT((arg & REG_MASK) != tmp_reg); arg &= ~SLJIT_MEM; if (SLJIT_UNLIKELY(!(arg & REG_MASK))) { tmp = get_imm(argw & ~0xfff); if (tmp != INVALID_IMM) { FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp)); return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff)); } FAIL_IF(load_immediate(compiler, tmp_reg, argw)); if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags]) return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg)); return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg)); } if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; other_r = OFFS_REG(arg); arg &= 0xf; if (!argw && IS_3_LO_REGS(reg, arg, other_r)) return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)); return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)); } if (argw > 0xfff) { tmp = get_imm(argw & ~0xfff); if (tmp != INVALID_IMM) { push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp); arg = tmp_reg; argw = argw & 0xfff; } } else if (argw < -0xff) { tmp = get_imm(-argw & ~0xff); if (tmp != INVALID_IMM) { push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp); arg = tmp_reg; argw = -(-argw & 0xff); } } if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) { tmp = 3; if (IS_WORD_SIZE(flags)) { if (OFFSET_CHECK(0x1f, 2)) tmp = 2; } else if (flags & BYTE_SIZE) { if (OFFSET_CHECK(0x1f, 0)) tmp = 0; } else { SLJIT_ASSERT(flags & HALF_SIZE); if (OFFSET_CHECK(0x1f, 1)) tmp = 1; } if (tmp < 3) return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp))); } else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) { /* SP based immediate. */ return push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2)); } if (argw >= 0 && argw <= 0xfff) return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw); else if (argw < 0 && argw >= -0xff) return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw); SLJIT_ASSERT(arg != tmp_reg); FAIL_IF(load_immediate(compiler, tmp_reg, argw)); if (IS_3_LO_REGS(reg, arg, tmp_reg)) return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg)); return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg)); } /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args, size, i, tmp; sljit_ins push = 0; #ifdef _WIN32 sljit_uw imm; #endif CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) push |= 1 << reg_map[i]; for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) push |= 1 << reg_map[i]; FAIL_IF((push & 0xff00) ? push_inst32(compiler, PUSH_W | (1 << 14) | push) : push_inst16(compiler, PUSH | (1 << 8) | push)); /* Stack must be aligned to 8 bytes: (LR, R4) */ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = ((size + local_size + 7) & ~7) - size; compiler->local_size = local_size; #ifdef _WIN32 if (local_size >= 256) { if (local_size > 4096) imm = get_imm(4096); else imm = get_imm(local_size & ~0xff); SLJIT_ASSERT(imm != INVALID_IMM); FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(SLJIT_SP) | imm)); } #else if (local_size > 0) { if (local_size <= (127 << 2)) FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2))); else FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size)); } #endif args = get_arg_count(arg_types); if (args >= 1) FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0))); if (args >= 2) FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S1, SLJIT_R1))); if (args >= 3) FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S2, SLJIT_R2))); #ifdef _WIN32 if (local_size >= 256) { if (local_size > 4096) { imm = get_imm(4096); SLJIT_ASSERT(imm != INVALID_IMM); if (local_size < 4 * 4096) { if (local_size > 2 * 4096) { FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1))); FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm)); local_size -= 4096; } if (local_size > 2 * 4096) { FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1))); FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm)); local_size -= 4096; } FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1))); local_size -= 4096; SLJIT_ASSERT(local_size > 0); } else { FAIL_IF(load_immediate(compiler, SLJIT_R3, (local_size >> 12) - 1)); FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1))); FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm)); SLJIT_ASSERT(reg_map[SLJIT_R3] < 7); FAIL_IF(push_inst16(compiler, SUBSI8 | RDN3(SLJIT_R3) | 1)); FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-7 & 0xff))); local_size &= 0xfff; if (local_size != 0) FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1))); } if (local_size >= 256) { imm = get_imm(local_size & ~0xff); SLJIT_ASSERT(imm != INVALID_IMM); FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm)); } } local_size &= 0xff; FAIL_IF(push_inst32(compiler, LDRI | 0x400 | (local_size > 0 ? 0x100 : 0) | RT4(TMP_REG2) | RN4(TMP_REG1) | local_size)); FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SP, TMP_REG1))); } else if (local_size > 0) FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | local_size)); #endif return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 size; CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = ((size + local_size + 7) & ~7) - size; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 i, tmp; sljit_ins pop = 0; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); if (compiler->local_size > 0) { if (compiler->local_size <= (127 << 2)) FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2))); else FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size)); } tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) pop |= 1 << reg_map[i]; for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) pop |= 1 << reg_map[i]; return (pop & 0xff00) ? push_inst32(compiler, POP_W | (1 << 15) | pop) : push_inst16(compiler, POP | (1 << 8) | pop); } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ #if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__) #ifdef __cplusplus extern "C" { #endif #ifdef _WIN32 extern unsigned long long __rt_udiv(unsigned int denominator, unsigned int numerator); extern long long __rt_sdiv(int denominator, int numerator); #elif defined(__GNUC__) extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator); extern int __aeabi_idivmod(int numerator, int denominator); #else #error "Software divmod functions are needed" #endif #ifdef __cplusplus } #endif #endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__) sljit_sw saved_reg_list[3]; sljit_sw saved_reg_count; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: return push_inst16(compiler, BKPT); case SLJIT_NOP: return push_inst16(compiler, NOP); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL) | (reg_map[SLJIT_R1] << 8) | (reg_map[SLJIT_R0] << 12) | (reg_map[SLJIT_R0] << 16) | reg_map[SLJIT_R1]); #if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__) case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0))); FAIL_IF(push_inst32(compiler, (op == SLJIT_DIVMOD_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1))); FAIL_IF(push_inst32(compiler, MUL | RD4(SLJIT_R1) | RN4(SLJIT_R0) | RM4(SLJIT_R1))); return push_inst32(compiler, SUB_W | RD4(SLJIT_R1) | RN4(TMP_REG1) | RM4(SLJIT_R1)); case SLJIT_DIV_UW: case SLJIT_DIV_SW: return push_inst32(compiler, (op == SLJIT_DIV_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1)); #else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */ case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3); saved_reg_count = 0; if (compiler->scratches >= 4) saved_reg_list[saved_reg_count++] = 3; if (compiler->scratches >= 3) saved_reg_list[saved_reg_count++] = 2; if (op >= SLJIT_DIV_UW) saved_reg_list[saved_reg_count++] = 1; if (saved_reg_count > 0) { FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); if (saved_reg_count >= 2) { SLJIT_ASSERT(saved_reg_list[1] < 8); FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */)); } if (saved_reg_count >= 3) { SLJIT_ASSERT(saved_reg_list[2] < 8); FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */)); } } #ifdef _WIN32 FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0))); FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1))); FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1))); FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__rt_udiv) : SLJIT_FUNC_OFFSET(__rt_sdiv)))); #elif defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif if (saved_reg_count > 0) { if (saved_reg_count >= 3) { SLJIT_ASSERT(saved_reg_list[2] < 8); FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */)); } if (saved_reg_count >= 2) { SLJIT_ASSERT(saved_reg_list[1] < 8); FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */)); } return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8) | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } return SLJIT_SUCCESS; #endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */ } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r, flags; sljit_s32 op_flags = GET_ALL_FLAGS(op); CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { /* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */ if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1); return SLJIT_SUCCESS; } dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; op = GET_OPCODE(op); if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: flags = WORD_SIZE; break; case SLJIT_MOV_U8: flags = BYTE_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u8)srcw; break; case SLJIT_MOV_S8: flags = BYTE_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s8)srcw; break; case SLJIT_MOV_U16: flags = HALF_SIZE; if (src & SLJIT_IMM) srcw = (sljit_u16)srcw; break; case SLJIT_MOV_S16: flags = HALF_SIZE | SIGNED; if (src & SLJIT_IMM) srcw = (sljit_s16)srcw; break; default: SLJIT_UNREACHABLE(); flags = 0; break; } if (src & SLJIT_IMM) FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw)); else if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1)); } else { if (dst_r != TMP_REG1) return emit_op_imm(compiler, op, dst_r, TMP_REG2, src); dst_r = src; } if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2); } if (op == SLJIT_NEG) { #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw); } flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0; if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, src); if (SLJIT_UNLIKELY(dst & SLJIT_MEM)) return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_reg, flags, src2_reg; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG1; flags = HAS_FLAGS(op) ? SET_FLAGS : 0; if (src1 & SLJIT_IMM) flags |= ARG1_IMM; else if (src1 & SLJIT_MEM) { emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1); src1w = TMP_REG1; } else src1w = src1; if (src2 & SLJIT_IMM) flags |= ARG2_IMM; else if (src2 & SLJIT_MEM) { src2_reg = (!(flags & ARG1_IMM) && (src1w == TMP_REG1)) ? TMP_REG2 : TMP_REG1; emit_op_mem(compiler, WORD_SIZE, src2_reg, src2, src2w, src2_reg); src2w = src2_reg; } else src2w = src2; if (dst == SLJIT_UNUSED) flags |= UNUSED_RETURN; emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, src1w, src2w); if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return (freg_map[reg] << 1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); if (size == 2) return push_inst16(compiler, *(sljit_u16*)instruction); return push_inst32(compiler, *(sljit_ins*)instruction); } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ #define FPU_LOAD (1 << 20) static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { sljit_uw imm; sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD)); SLJIT_ASSERT(arg & SLJIT_MEM); /* Fast loads and stores. */ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6))); arg = SLJIT_MEM | TMP_REG1; argw = 0; } if ((arg & REG_MASK) && (argw & 0x3) == 0) { if (!(argw & ~0x3fc)) return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | (argw >> 2)); if (!(-argw & ~0x3fc)) return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2)); } if (arg & REG_MASK) { if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) { FAIL_IF(compiler->error); return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg)); } imm = get_imm(argw & ~0x3fc); if (imm != INVALID_IMM) { FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm)); return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2)); } imm = get_imm(-argw & ~0x3fc); if (imm != INVALID_IMM) { argw = -argw; FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm)); return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2)); } } FAIL_IF(load_immediate(compiler, TMP_REG1, argw)); if (arg & REG_MASK) FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK)))); return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { op ^= SLJIT_F32_OP; if (src & SLJIT_MEM) { FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw)); src = TMP_FREG1; } FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_F32_OP) | DD4(TMP_FREG1) | DM4(src))); if (FAST_IS_REG(dst)) return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1)); /* Store the integer value from a VFP register. */ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; op ^= SLJIT_F32_OP; if (FAST_IS_REG(src)) FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1))); else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw)); } else { FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1))); } FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(TMP_FREG1))); if (dst & SLJIT_MEM) return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { op ^= SLJIT_F32_OP; if (src1 & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w); src2 = TMP_FREG2; } FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_F32_OP) | DD4(src1) | DM4(src2))); return push_inst32(compiler, VMRS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; CHECK_ERROR(); SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; if (src & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw); src = dst_r; } switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src))); else dst_r = src; } break; case SLJIT_NEG_F64: FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src))); break; case SLJIT_ABS_F64: FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src))); break; case SLJIT_CONV_F64_FROM_F32: FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src))); op ^= SLJIT_F32_OP; break; } if (dst & SLJIT_MEM) return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src1 & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w); src2 = TMP_FREG2; } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); break; case SLJIT_SUB_F64: FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); break; case SLJIT_MUL_F64: FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); break; case SLJIT_DIV_F64: FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2))); break; } if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw); } #undef FPU_LOAD /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); SLJIT_ASSERT(reg_map[TMP_REG2] == 14); if (FAST_IS_REG(dst)) return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); /* Memory. */ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); SLJIT_ASSERT(reg_map[TMP_REG2] == 14); if (FAST_IS_REG(src)) FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src))); else FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2)); return push_inst16(compiler, BX | RN3(TMP_REG2)); } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ static sljit_uw get_cc(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: case SLJIT_MUL_NOT_OVERFLOW: case SLJIT_EQUAL_F64: return 0x0; case SLJIT_NOT_EQUAL: case SLJIT_MUL_OVERFLOW: case SLJIT_NOT_EQUAL_F64: return 0x1; case SLJIT_LESS: case SLJIT_LESS_F64: return 0x3; case SLJIT_GREATER_EQUAL: case SLJIT_GREATER_EQUAL_F64: return 0x2; case SLJIT_GREATER: case SLJIT_GREATER_F64: return 0x8; case SLJIT_LESS_EQUAL: case SLJIT_LESS_EQUAL_F64: return 0x9; case SLJIT_SIG_LESS: return 0xb; case SLJIT_SIG_GREATER_EQUAL: return 0xa; case SLJIT_SIG_GREATER: return 0xc; case SLJIT_SIG_LESS_EQUAL: return 0xd; case SLJIT_OVERFLOW: case SLJIT_UNORDERED_F64: return 0x6; case SLJIT_NOT_OVERFLOW: case SLJIT_ORDERED_F64: return 0x7; default: /* SLJIT_JUMP */ SLJIT_UNREACHABLE(); return 0xe; } } SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); return label; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; sljit_ins cc; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); if (type < SLJIT_JUMP) { jump->flags |= IS_COND; cc = get_cc(type); jump->flags |= cc << 8; PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); } jump->addr = compiler->size; if (type <= SLJIT_JUMP) PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1))); else { jump->flags |= IS_BL; PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1))); } return jump; } #ifdef __SOFTFP__ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) { sljit_s32 stack_offset = 0; sljit_s32 arg_count = 0; sljit_s32 word_arg_offset = 0; sljit_s32 float_arg_count = 0; sljit_s32 types = 0; sljit_s32 src_offset = 4 * sizeof(sljit_sw); sljit_u8 offsets[4]; if (src && FAST_IS_REG(*src)) src_offset = reg_map[*src] * sizeof(sljit_sw); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_f32); arg_count++; float_arg_count++; break; case SLJIT_ARG_TYPE_F64: if (stack_offset & 0x7) stack_offset += sizeof(sljit_sw); offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_f64); arg_count++; float_arg_count++; break; default: offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_sw); arg_count++; word_arg_offset += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } if (stack_offset > 16) FAIL_IF(push_inst16(compiler, SUB_SP | (((stack_offset - 16) + 0x7) & ~0x7) >> 2)); SLJIT_ASSERT(reg_map[TMP_REG1] == 12); /* Process arguments in reversed direction. */ while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: arg_count--; float_arg_count--; stack_offset = offsets[arg_count]; if (stack_offset < 16) { if (src_offset == stack_offset) { FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7))); *src = TMP_REG1; } FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10))); } else FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); break; case SLJIT_ARG_TYPE_F64: arg_count--; float_arg_count--; stack_offset = offsets[arg_count]; SLJIT_ASSERT((stack_offset & 0x7) == 0); if (stack_offset < 16) { if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) { FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7))); *src = TMP_REG1; } FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count)); } else FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2))); break; default: arg_count--; word_arg_offset -= sizeof(sljit_sw); stack_offset = offsets[arg_count]; SLJIT_ASSERT(stack_offset >= word_arg_offset); if (stack_offset != word_arg_offset) { if (stack_offset < 16) { if (src_offset == stack_offset) { FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7))); *src = TMP_REG1; } else if (src_offset == word_arg_offset) { *src = 1 + (stack_offset >> 2); src_offset = stack_offset; } FAIL_IF(push_inst16(compiler, MOV | (stack_offset >> 2) | (word_arg_offset << 1))); } else FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((stack_offset - 16) >> 2))); } break; } types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) { sljit_s32 stack_size = 0; if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12))); if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0)); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: stack_size += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: if (stack_size & 0x7) stack_size += sizeof(sljit_sw); stack_size += sizeof(sljit_f64); break; default: stack_size += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } if (stack_size <= 16) return SLJIT_SUCCESS; return push_inst16(compiler, ADD_SP | ((((stack_size - 16) + 0x7) & ~0x7) >> 2)); } #else static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) { sljit_u32 remap = 0; sljit_u32 offset = 0; sljit_u32 new_offset, mask; /* Remove return value. */ arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) { new_offset = 0; mask = 1; while (remap & mask) { new_offset++; mask <<= 1; } remap |= mask; if (offset != new_offset) FAIL_IF(push_inst32(compiler, VMOV_F32 | DD4((new_offset >> 1) + 1) | ((new_offset & 0x1) ? 0x400000 : 0) | DM4((offset >> 1) + 1))); offset += 2; } else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) { new_offset = 0; mask = 3; while (remap & mask) { new_offset += 2; mask <<= 2; } remap |= mask; if (offset != new_offset) FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_F32_OP | DD4((new_offset >> 1) + 1) | DM4((offset >> 1) + 1))); offset += 2; } arg_types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } #endif SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { #ifdef __SOFTFP__ struct sljit_jump *jump; #endif CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #ifdef __SOFTFP__ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif jump = sljit_emit_jump(compiler, type); PTR_FAIL_IF(jump == NULL); PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types)); return jump; #else PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); #endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); SLJIT_ASSERT(reg_map[TMP_REG1] != 14); if (!(src & SLJIT_IMM)) { if (FAST_IS_REG(src)) { SLJIT_ASSERT(reg_map[src] != 14); return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src)); } FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1)); if (type >= SLJIT_FAST_CALL) return push_inst16(compiler, BLX | RN3(TMP_REG1)); } /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); jump->u.target = srcw; FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); jump->addr = compiler->size; return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); #ifdef __SOFTFP__ if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); return softfloat_post_call_with_args(compiler, arg_types); #else /* !__SOFTFP__ */ FAIL_IF(hardfloat_call_with_args(compiler, arg_types)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_ijump(compiler, type, src, srcw); #endif /* __SOFTFP__ */ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_s32 dst_r, flags = GET_ALL_FLAGS(op); sljit_ins cc; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); op = GET_OPCODE(op); cc = get_cc(type & 0xff); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (op < SLJIT_ADD) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); if (reg_map[dst_r] > 7) { FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1)); FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0)); } else { /* The movsi (immediate) instruction does not set flags in IT block. */ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1)); FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0)); } if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2); } if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2)); if (op == SLJIT_AND) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 1)); FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 0)); } else { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); FAIL_IF(push_inst32(compiler, ((op == SLJIT_OR) ? ORRI : EORI) | RN4(dst_r) | RD4(dst_r) | 1)); } if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2)); if (!(flags & SLJIT_SET_Z)) return SLJIT_SUCCESS; /* The condition must always be set, even if the ORR/EORI is not executed above. */ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { sljit_uw cc, tmp; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); dst_reg &= ~SLJIT_I32_OP; cc = get_cc(type & 0xff); if (!(src & SLJIT_IMM)) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src)); } tmp = (sljit_uw) srcw; if (tmp < 0x10000) { /* set low 16 bits, set hi 16 bits to 0. */ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); return push_inst32(compiler, MOVW | RD4(dst_reg) | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)); } tmp = get_imm(srcw); if (tmp != INVALID_IMM) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp); } tmp = get_imm(~srcw); if (tmp != INVALID_IMM) { FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp); } FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4)); tmp = (sljit_uw) srcw; FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg) | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff))); return push_inst32(compiler, MOVT | RD4(dst_reg) | COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { sljit_s32 flags; sljit_ins inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -255)) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; switch (type & 0xff) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: flags = WORD_SIZE; break; case SLJIT_MOV_U8: flags = BYTE_SIZE; break; case SLJIT_MOV_S8: flags = BYTE_SIZE | SIGNED; break; case SLJIT_MOV_U16: flags = HALF_SIZE; break; case SLJIT_MOV_S16: flags = HALF_SIZE | SIGNED; break; default: SLJIT_UNREACHABLE(); flags = WORD_SIZE; break; } if (type & SLJIT_MEM_STORE) flags |= STORE; inst = sljit_mem32[flags] | 0x900; if (type & SLJIT_MEM_PRE) inst |= 0x400; if (memw >= 0) inst |= 0x200; else memw = -memw; return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | memw); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; sljit_s32 dst_r; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value)); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2)); return const_; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_u16 *inst = (sljit_u16*)addr; modify_imm32_const(inst, new_target); inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 4); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_u16 *inst = (sljit_u16*)addr; modify_imm32_const(inst, new_constant); inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 4); } ================================================ FILE: src/pcre/sljit/sljitNativeMIPS_32.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* mips 32-bit arch dependent functions. */ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { if (!(imm & ~0xffff)) return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); if (imm < 0 && imm >= SIMM_MIN) return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar)); return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; } #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ } \ else { \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ } #define EMIT_SHIFT(op_imm, op_v) \ if (flags & SRC2_IMM) { \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ } \ else { \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \ } static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { sljit_s32 is_overflow, is_carry, is_handled; switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (dst != src2) return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst)); return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); #else FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); #endif } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); #else FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); #endif } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); return SLJIT_SUCCESS; case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); #else if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); } /* Nearly all instructions are unmovable in the following sequence. */ FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); /* Check zero. */ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst))); /* Loop for searching the highest bit. */ FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst))); FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); #endif return SLJIT_SUCCESS; case SLJIT_ADD: is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_overflow) { if (src2 >= 0) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); if (is_overflow || is_carry) { if (src2 >= 0) FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); else { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); } } /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { if (is_overflow) FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); } /* a + b >= a | b (otherwise, the carry should be set to 1). */ if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); if (!is_overflow) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_ADDC: is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_carry) { if (src2 >= 0) FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); else { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); } } FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { if (is_carry) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); } if (is_carry) FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); if (!is_carry) return SLJIT_SUCCESS; /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); /* Set carry flag. */ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_SUB: if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } is_handled = 0; if (flags & SRC2_IMM) { if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); is_handled = 1; } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); is_handled = 1; } } if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { is_handled = 1; if (flags & SRC2_IMM) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); } else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) { FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) { FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); } } if (is_handled) { if (flags & SRC2_IMM) { if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)); } else { if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)); } return SLJIT_SUCCESS; } is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_overflow) { if (src2 >= 0) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { if (is_overflow) FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); } if (!is_overflow) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_SUBC: if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_carry) FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { if (is_carry) FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); } if (is_carry) FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; case SLJIT_MUL: SLJIT_ASSERT(!(flags & SRC2_IMM)); if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); #else FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); return push_inst(compiler, MFLO | D(dst), DR(dst)); #endif } FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_AND: EMIT_LOGICAL(ANDI, AND); return SLJIT_SUCCESS; case SLJIT_OR: EMIT_LOGICAL(ORI, OR); return SLJIT_SUCCESS; case SLJIT_XOR: EMIT_LOGICAL(XORI, XOR); return SLJIT_SUCCESS; case SLJIT_SHL: EMIT_SHIFT(SLL, SLLV); return SLJIT_SUCCESS; case SLJIT_LSHR: EMIT_SHIFT(SRL, SRLV); return SLJIT_SUCCESS; case SLJIT_ASHR: EMIT_SHIFT(SRA, SRAV); return SLJIT_SUCCESS; } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) { FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst))); return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr) { sljit_s32 stack_offset = 0; sljit_s32 arg_count = 0; sljit_s32 float_arg_count = 0; sljit_s32 word_arg_count = 0; sljit_s32 types = 0; sljit_s32 arg_count_save, types_save; sljit_ins prev_ins = NOP; sljit_ins ins = NOP; sljit_u8 offsets[4]; SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: offsets[arg_count] = (sljit_u8)stack_offset; if (word_arg_count == 0 && arg_count <= 1) offsets[arg_count] = 254 + arg_count; stack_offset += sizeof(sljit_f32); arg_count++; float_arg_count++; break; case SLJIT_ARG_TYPE_F64: if (stack_offset & 0x7) stack_offset += sizeof(sljit_sw); offsets[arg_count] = (sljit_u8)stack_offset; if (word_arg_count == 0 && arg_count <= 1) offsets[arg_count] = 254 + arg_count; stack_offset += sizeof(sljit_f64); arg_count++; float_arg_count++; break; default: offsets[arg_count] = (sljit_u8)stack_offset; stack_offset += sizeof(sljit_sw); arg_count++; word_arg_count++; break; } arg_types >>= SLJIT_DEF_SHIFT; } /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */ if (stack_offset > 16) FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP))); types_save = types; arg_count_save = arg_count; while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: arg_count--; if (offsets[arg_count] < 254) ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]); float_arg_count--; break; case SLJIT_ARG_TYPE_F64: arg_count--; if (offsets[arg_count] < 254) ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]); float_arg_count--; break; default: if (offsets[arg_count - 1] >= 16) ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]); else if (arg_count != word_arg_count) ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2)); else if (arg_count == 1) ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4); arg_count--; word_arg_count--; break; } if (ins != NOP) { if (prev_ins != NOP) FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); prev_ins = ins; ins = NOP; } types >>= SLJIT_DEF_SHIFT; } types = types_save; arg_count = arg_count_save; while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: arg_count--; if (offsets[arg_count] == 254) ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1); else if (offsets[arg_count] < 16) ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]); break; case SLJIT_ARG_TYPE_F64: arg_count--; if (offsets[arg_count] == 254) ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1); else if (offsets[arg_count] < 16) { if (prev_ins != NOP) FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]); ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw)); } break; default: arg_count--; break; } if (ins != NOP) { if (prev_ins != NOP) FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); prev_ins = ins; ins = NOP; } types >>= SLJIT_DEF_SHIFT; } *ins_ptr = prev_ins; return SLJIT_SUCCESS; } static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types) { sljit_s32 stack_offset = 0; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: stack_offset += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: if (stack_offset & 0x7) stack_offset += sizeof(sljit_sw); stack_offset += sizeof(sljit_f64); break; default: stack_offset += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */ if (stack_offset > 16) return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP)); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { struct sljit_jump *jump; sljit_ins ins; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0)); jump->flags |= IS_JAL | IS_CALL; PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); PTR_FAIL_IF(post_call_with_args(compiler, arg_types)); return jump; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { sljit_ins ins; CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); if (src & SLJIT_IMM) FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); else if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); else if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); } FAIL_IF(call_with_args(compiler, arg_types, &ins)); /* Register input. */ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); return post_call_with_args(compiler, arg_types); } ================================================ FILE: src/pcre/sljit/sljitNativeMIPS_64.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* mips 64-bit arch dependent functions. */ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { sljit_s32 shift = 32; sljit_s32 shift2; sljit_s32 inv = 0; sljit_ins ins; sljit_uw uimm; if (!(imm & ~0xffff)) return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); if (imm < 0 && imm >= SIMM_MIN) return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); if (imm <= 0x7fffffffl && imm >= -0x80000000l) { FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar)); return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; } /* Zero extended number. */ uimm = imm; if (imm < 0) { uimm = ~imm; inv = 1; } while (!(uimm & 0xff00000000000000l)) { shift -= 8; uimm <<= 8; } if (!(uimm & 0xf000000000000000l)) { shift -= 4; uimm <<= 4; } if (!(uimm & 0xc000000000000000l)) { shift -= 2; uimm <<= 2; } if ((sljit_sw)uimm < 0) { uimm >>= 1; shift += 1; } SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32)); if (inv) uimm = ~uimm; FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar)); if (uimm & 0x0000ffff00000000l) FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar)); imm &= (1l << shift) - 1; if (!(imm & ~0xffff)) { ins = (shift == 32) ? DSLL32 : DSLL; if (shift < 32) ins |= SH_IMM(shift); FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar)); return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar); } /* Double shifts needs to be performed. */ uimm <<= 32; shift2 = shift - 16; while (!(uimm & 0xf000000000000000l)) { shift2 -= 4; uimm <<= 4; } if (!(uimm & 0xc000000000000000l)) { shift2 -= 2; uimm <<= 2; } if (!(uimm & 0x8000000000000000l)) { shift2--; uimm <<= 1; } SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16)); FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar)); FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar)); FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar)); imm &= (1l << shift2) - 1; return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar); } #define SELECT_OP(a, b) \ (!(op & SLJIT_I32_OP) ? a : b) #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ } \ else { \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ } #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \ if (flags & SRC2_IMM) { \ if (src2 >= 32) { \ SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \ ins = op_dimm32; \ src2 -= 32; \ } \ else \ ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ } \ else { \ ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \ if (op & SLJIT_SET_Z) \ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ if (!(flags & UNUSED_DEST)) \ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \ } static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { sljit_ins ins; sljit_s32 is_overflow, is_carry, is_handled; switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_P: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (dst != src2) return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst)); return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) { FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst))); return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst)); } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) { FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst)); } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U32: SLJIT_ASSERT(!(op & SLJIT_I32_OP)); FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst))); return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)); case SLJIT_MOV_S32: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst)); case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); return SLJIT_SUCCESS; case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); #else if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); } /* Nearly all instructions are unmovable in the following sequence. */ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); /* Check zero. */ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst))); /* Loop for searching the highest bit. */ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); #endif return SLJIT_SUCCESS; case SLJIT_ADD: is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_overflow) { if (src2 >= 0) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); if (is_overflow || is_carry) { if (src2 >= 0) FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); else { FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); } } /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { if (is_overflow) FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); } /* a + b >= a | b (otherwise, the carry should be set to 1). */ if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); if (!is_overflow) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_ADDC: is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_carry) { if (src2 >= 0) FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); else { FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); } } FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); } else { if (is_carry) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); } if (is_carry) FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); if (!is_carry) return SLJIT_SUCCESS; /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); /* Set carry flag. */ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_SUB: if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } is_handled = 0; if (flags & SRC2_IMM) { if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); is_handled = 1; } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); is_handled = 1; } } if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { is_handled = 1; if (flags & SRC2_IMM) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); } else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) { FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) { FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); } } if (is_handled) { if (flags & SRC2_IMM) { if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)); } else { if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)); } return SLJIT_SUCCESS; } is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW; is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_overflow) { if (src2 >= 0) FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); else FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); } else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { if (is_overflow) FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); else if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (is_overflow || is_carry) FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); /* dst may be the same as src1 or src2. */ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); } if (!is_overflow) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); case SLJIT_SUBC: if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); src2 = TMP_REG2; flags &= ~SRC2_IMM; } is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); if (flags & SRC2_IMM) { if (is_carry) FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); } else { if (is_carry) FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); /* dst may be the same as src1 or src2. */ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); } if (is_carry) FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; case SLJIT_MUL: SLJIT_ASSERT(!(flags & SRC2_IMM)); if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) if (op & SLJIT_I32_OP) return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); return push_inst(compiler, MFLO | D(dst), DR(dst)); #else FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); return push_inst(compiler, MFLO | D(dst), DR(dst)); #endif } FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); case SLJIT_AND: EMIT_LOGICAL(ANDI, AND); return SLJIT_SUCCESS; case SLJIT_OR: EMIT_LOGICAL(ORI, OR); return SLJIT_SUCCESS; case SLJIT_XOR: EMIT_LOGICAL(XORI, XOR); return SLJIT_SUCCESS; case SLJIT_SHL: EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV); return SLJIT_SUCCESS; case SLJIT_LSHR: EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV); return SLJIT_SUCCESS; case SLJIT_ASHR: EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV); return SLJIT_SUCCESS; } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) { FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst))); FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst))); FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst))); FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff); inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 6); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 6); } static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr) { sljit_s32 arg_count = 0; sljit_s32 word_arg_count = 0; sljit_s32 float_arg_count = 0; sljit_s32 types = 0; sljit_ins prev_ins = NOP; sljit_ins ins = NOP; SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12); arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: case SLJIT_ARG_TYPE_F64: arg_count++; float_arg_count++; break; default: arg_count++; word_arg_count++; break; } arg_types >>= SLJIT_DEF_SHIFT; } while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: if (arg_count != float_arg_count) ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count); else if (arg_count == 1) ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1); arg_count--; float_arg_count--; break; case SLJIT_ARG_TYPE_F64: if (arg_count != float_arg_count) ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count); else if (arg_count == 1) ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1); arg_count--; float_arg_count--; break; default: if (arg_count != word_arg_count) ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count); else if (arg_count == 1) ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4); arg_count--; word_arg_count--; break; } if (ins != NOP) { if (prev_ins != NOP) FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS)); prev_ins = ins; ins = NOP; } types >>= SLJIT_DEF_SHIFT; } *ins_ptr = prev_ins; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { struct sljit_jump *jump; sljit_ins ins; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins)); SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0)); jump->flags |= IS_JAL | IS_CALL; PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS)); return jump; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { sljit_ins ins; CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); if (src & SLJIT_IMM) FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); else if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG))); else if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw)); } FAIL_IF(call_with_args(compiler, arg_types, &ins)); /* Register input. */ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); return push_inst(compiler, ins, UNMOVABLE_INS); } ================================================ FILE: src/pcre/sljit/sljitNativeMIPS_common.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* Latest MIPS architecture. */ /* Automatically detect SLJIT_MIPS_R1 */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) return "MIPS32-R1" SLJIT_CPUINFO; #else return "MIPS64-R1" SLJIT_CPUINFO; #endif #else /* SLJIT_MIPS_R1 */ return "MIPS III" SLJIT_CPUINFO; #endif } /* Length of an instruction word Both for mips-32 and mips-64 */ typedef sljit_u32 sljit_ins; #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) /* For position independent code, t9 must contain the function address. */ #define PIC_ADDR_REG TMP_REG2 /* Floating point status register. */ #define FCSR_REG 31 /* Return address register. */ #define RETURN_ADDR_REG 31 /* Flags are kept in volatile registers. */ #define EQUAL_FLAG 3 #define OTHER_FLAG 1 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = { 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 4, 25, 31 }; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 0, 14, 2, 4, 6, 8, 12, 10 }; #else static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 0, 13, 14, 15, 16, 17, 12, 18 }; #endif /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ #define S(s) (reg_map[s] << 21) #define T(t) (reg_map[t] << 16) #define D(d) (reg_map[d] << 11) #define FT(t) (freg_map[t] << 16) #define FS(s) (freg_map[s] << 11) #define FD(d) (freg_map[d] << 6) /* Absolute registers. */ #define SA(s) ((s) << 21) #define TA(t) ((t) << 16) #define DA(d) ((d) << 11) #define IMM(imm) ((imm) & 0xffff) #define SH_IMM(imm) ((imm) << 6) #define DR(dr) (reg_map[dr]) #define FR(dr) (freg_map[dr]) #define HI(opcode) ((opcode) << 26) #define LO(opcode) (opcode) /* S = (16 << 21) D = (17 << 21) */ #define FMT_S (16 << 21) #define FMT_D (17 << 21) #define ABS_S (HI(17) | FMT_S | LO(5)) #define ADD_S (HI(17) | FMT_S | LO(0)) #define ADDIU (HI(9)) #define ADDU (HI(0) | LO(33)) #define AND (HI(0) | LO(36)) #define ANDI (HI(12)) #define B (HI(4)) #define BAL (HI(1) | (17 << 16)) #define BC1F (HI(17) | (8 << 21)) #define BC1T (HI(17) | (8 << 21) | (1 << 16)) #define BEQ (HI(4)) #define BGEZ (HI(1) | (1 << 16)) #define BGTZ (HI(7)) #define BLEZ (HI(6)) #define BLTZ (HI(1) | (0 << 16)) #define BNE (HI(5)) #define BREAK (HI(0) | LO(13)) #define CFC1 (HI(17) | (2 << 21)) #define C_UN_S (HI(17) | FMT_S | LO(49)) #define C_UEQ_S (HI(17) | FMT_S | LO(51)) #define C_ULE_S (HI(17) | FMT_S | LO(55)) #define C_ULT_S (HI(17) | FMT_S | LO(53)) #define CVT_S_S (HI(17) | FMT_S | LO(32)) #define DADDIU (HI(25)) #define DADDU (HI(0) | LO(45)) #define DDIV (HI(0) | LO(30)) #define DDIVU (HI(0) | LO(31)) #define DIV (HI(0) | LO(26)) #define DIVU (HI(0) | LO(27)) #define DIV_S (HI(17) | FMT_S | LO(3)) #define DMULT (HI(0) | LO(28)) #define DMULTU (HI(0) | LO(29)) #define DSLL (HI(0) | LO(56)) #define DSLL32 (HI(0) | LO(60)) #define DSLLV (HI(0) | LO(20)) #define DSRA (HI(0) | LO(59)) #define DSRA32 (HI(0) | LO(63)) #define DSRAV (HI(0) | LO(23)) #define DSRL (HI(0) | LO(58)) #define DSRL32 (HI(0) | LO(62)) #define DSRLV (HI(0) | LO(22)) #define DSUBU (HI(0) | LO(47)) #define J (HI(2)) #define JAL (HI(3)) #define JALR (HI(0) | LO(9)) #define JR (HI(0) | LO(8)) #define LD (HI(55)) #define LUI (HI(15)) #define LW (HI(35)) #define MFC1 (HI(17)) #define MFHI (HI(0) | LO(16)) #define MFLO (HI(0) | LO(18)) #define MOV_S (HI(17) | FMT_S | LO(6)) #define MTC1 (HI(17) | (4 << 21)) #define MUL_S (HI(17) | FMT_S | LO(2)) #define MULT (HI(0) | LO(24)) #define MULTU (HI(0) | LO(25)) #define NEG_S (HI(17) | FMT_S | LO(7)) #define NOP (HI(0) | LO(0)) #define NOR (HI(0) | LO(39)) #define OR (HI(0) | LO(37)) #define ORI (HI(13)) #define SD (HI(63)) #define SDC1 (HI(61)) #define SLT (HI(0) | LO(42)) #define SLTI (HI(10)) #define SLTIU (HI(11)) #define SLTU (HI(0) | LO(43)) #define SLL (HI(0) | LO(0)) #define SLLV (HI(0) | LO(4)) #define SRL (HI(0) | LO(2)) #define SRLV (HI(0) | LO(6)) #define SRA (HI(0) | LO(3)) #define SRAV (HI(0) | LO(7)) #define SUB_S (HI(17) | FMT_S | LO(1)) #define SUBU (HI(0) | LO(35)) #define SW (HI(43)) #define SWC1 (HI(57)) #define TRUNC_W_S (HI(17) | FMT_S | LO(13)) #define XOR (HI(0) | LO(38)) #define XORI (HI(14)) #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) #define CLZ (HI(28) | LO(32)) #define DCLZ (HI(28) | LO(36)) #define MOVF (HI(0) | (0 << 16) | LO(1)) #define MOVN (HI(0) | LO(11)) #define MOVT (HI(0) | (1 << 16) | LO(1)) #define MOVZ (HI(0) | LO(10)) #define MUL (HI(28) | LO(2)) #define PREF (HI(51)) #define PREFX (HI(19) | LO(15)) #define SEB (HI(31) | (16 << 6) | LO(32)) #define SEH (HI(31) | (24 << 6) | LO(32)) #endif #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define ADDU_W ADDU #define ADDIU_W ADDIU #define SLL_W SLL #define SUBU_W SUBU #else #define ADDU_W DADDU #define ADDIU_W DADDIU #define SLL_W DSLL #define SUBU_W DSUBU #endif #define SIMM_MAX (0x7fff) #define SIMM_MIN (-0x8000) #define UIMM_MAX (0xffff) /* dest_reg is the absolute name of the register Useful for reordering instructions in the delay slot. */ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot) { SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f)); sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; compiler->delay_slot = delay_slot; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags) { return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16); } static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; sljit_ins saved_inst; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL)) return code_ptr; #else if (jump->flags & SLJIT_REWRITABLE_JUMP) return code_ptr; #endif if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } inst = (sljit_ins *)jump->addr; if (jump->flags & IS_COND) inst--; #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (jump->flags & IS_CALL) goto keep_address; #endif /* B instructions. */ if (jump->flags & IS_MOVABLE) { diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2; if (diff <= SIMM_MAX && diff >= SIMM_MIN) { jump->flags |= PATCH_B; if (!(jump->flags & IS_COND)) { inst[0] = inst[-1]; inst[-1] = (jump->flags & IS_JAL) ? BAL : B; jump->addr -= sizeof(sljit_ins); return inst; } saved_inst = inst[0]; inst[0] = inst[-1]; inst[-1] = saved_inst ^ invert_branch(jump->flags); jump->addr -= 2 * sizeof(sljit_ins); return inst; } } else { diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2; if (diff <= SIMM_MAX && diff >= SIMM_MIN) { jump->flags |= PATCH_B; if (!(jump->flags & IS_COND)) { inst[0] = (jump->flags & IS_JAL) ? BAL : B; inst[1] = NOP; return inst + 1; } inst[0] = inst[0] ^ invert_branch(jump->flags); inst[1] = NOP; jump->addr -= sizeof(sljit_ins); return inst + 1; } } if (jump->flags & IS_COND) { if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~0xfffffff)) { jump->flags |= PATCH_J; saved_inst = inst[0]; inst[0] = inst[-1]; inst[-1] = (saved_inst & 0xffff0000) | 3; inst[1] = J; inst[2] = NOP; return inst + 2; } else if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) { jump->flags |= PATCH_J; inst[0] = (inst[0] & 0xffff0000) | 3; inst[1] = NOP; inst[2] = J; inst[3] = NOP; jump->addr += sizeof(sljit_ins); return inst + 3; } } else { /* J instuctions. */ if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) { jump->flags |= PATCH_J; inst[0] = inst[-1]; inst[-1] = (jump->flags & IS_JAL) ? JAL : J; jump->addr -= sizeof(sljit_ins); return inst; } if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) { jump->flags |= PATCH_J; inst[0] = (jump->flags & IS_JAL) ? JAL : J; inst[1] = NOP; return inst + 1; } } #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) keep_address: if (target_addr <= 0x7fffffff) { jump->flags |= PATCH_ABS32; if (jump->flags & IS_COND) { inst[0] -= 4; inst++; } inst[2] = inst[6]; inst[3] = inst[7]; return inst + 3; } if (target_addr <= 0x7fffffffffffl) { jump->flags |= PATCH_ABS48; if (jump->flags & IS_COND) { inst[0] -= 2; inst++; } inst[4] = inst[6]; inst[5] = inst[7]; return inst + 5; } #endif return code_ptr; } #ifdef __GNUC__ static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr) { SLJIT_CACHE_FLUSH(code, code_ptr); } #endif SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_ins *code; sljit_ins *code_ptr; sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; sljit_sw executable_offset; sljit_uw addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; word_count = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); /* These structures are ordered by their address. */ if (label && label->size == word_count) { label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } if (jump && jump->addr == word_count) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) jump->addr = (sljit_uw)(code_ptr - 3); #else jump->addr = (sljit_uw)(code_ptr - 7); #endif code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); jump = jump->next; } if (const_ && const_->addr == word_count) { /* Just recording the address. */ const_->addr = (sljit_uw)code_ptr; const_ = const_->next; } code_ptr ++; word_count ++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); if (label && label->size == word_count) { label->addr = (sljit_uw)code_ptr; label->size = code_ptr - code; label = label->next; } SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { do { addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; buf_ptr = (sljit_ins *)jump->addr; if (jump->flags & PATCH_B) { addr = (sljit_sw)(addr - ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins))) >> 2; SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN); buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff); break; } if (jump->flags & PATCH_J) { SLJIT_ASSERT((addr & ~0xfffffff) == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~0xfffffff)); buf_ptr[0] |= (addr >> 2) & 0x03ffffff; break; } /* Set the fields of immediate loads. */ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff); #else if (jump->flags & PATCH_ABS32) { SLJIT_ASSERT(addr <= 0x7fffffff); buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff); } else if (jump->flags & PATCH_ABS48) { SLJIT_ASSERT(addr <= 0x7fffffffffffl); buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff); } else { buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff); buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[5] = (buf_ptr[5] & 0xffff0000) | (addr & 0xffff); } #endif } while (0); jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); #ifndef __GNUC__ SLJIT_CACHE_FLUSH(code, code_ptr); #else /* GCC workaround for invalid code generation with -O2. */ sljit_cache_flush(code, code_ptr); #endif return code; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { sljit_sw fir = 0; switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #elif defined(__GNUC__) asm ("cfc1 %0, $0" : "=r"(fir)); return (fir >> 22) & 0x1; #else #error "FIR check is not implemented for this architecture" #endif #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: return 1; #endif default: return fir; } } /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ /* Creates an index in data_transfer_insts array. */ #define LOAD_DATA 0x01 #define WORD_DATA 0x00 #define BYTE_DATA 0x02 #define HALF_DATA 0x04 #define INT_DATA 0x06 #define SIGNED_DATA 0x08 /* Separates integer and floating point registers */ #define GPR_REG 0x0f #define DOUBLE_DATA 0x10 #define SINGLE_DATA 0x12 #define MEM_MASK 0x1f #define ARG_TEST 0x00020 #define ALT_KEEP_CACHE 0x00040 #define CUMULATIVE_OP 0x00080 #define LOGICAL_OP 0x00100 #define IMM_OP 0x00200 #define SRC2_IMM 0x00400 #define UNUSED_DEST 0x00800 #define REG_DEST 0x01000 #define REG1_SOURCE 0x02000 #define REG2_SOURCE 0x04000 #define SLOW_SRC1 0x08000 #define SLOW_SRC2 0x10000 #define SLOW_DEST 0x20000 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define STACK_STORE SW #define STACK_LOAD LW #else #define STACK_STORE SD #define STACK_LOAD LD #endif static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #include "sljitNativeMIPS_32.c" #else #include "sljitNativeMIPS_64.c" #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_ins base; sljit_s32 args, i, tmp, offs; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) local_size = (local_size + 15) & ~0xf; #else local_size = (local_size + 31) & ~0x1f; #endif compiler->local_size = local_size; if (local_size <= SIMM_MAX) { /* Frequent case. */ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP))); base = S(SLJIT_SP); offs = local_size - (sljit_sw)sizeof(sljit_sw); } else { FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size)); FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP))); base = S(TMP_REG2); local_size = 0; offs = -(sljit_sw)sizeof(sljit_sw); } FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS)); tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) { offs -= (sljit_s32)(sizeof(sljit_sw)); FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS)); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { offs -= (sljit_s32)(sizeof(sljit_sw)); FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS)); } args = get_arg_count(arg_types); if (args >= 1) FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_S0), DR(SLJIT_S0))); if (args >= 2) FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_S1), DR(SLJIT_S1))); if (args >= 3) FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_S2), DR(SLJIT_S2))); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) compiler->local_size = (local_size + 15) & ~0xf; #else compiler->local_size = (local_size + 31) & ~0x1f; #endif return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 local_size, i, tmp, offs; sljit_ins base; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); local_size = compiler->local_size; if (local_size <= SIMM_MAX) base = S(SLJIT_SP); else { FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size)); FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1))); base = S(TMP_REG1); local_size = 0; } FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_s32)sizeof(sljit_sw)), RETURN_ADDR_REG)); offs = local_size - (sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1); tmp = compiler->scratches; for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i))); offs += (sljit_s32)(sizeof(sljit_sw)); } tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; for (i = tmp; i <= SLJIT_S0; i++) { FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i))); offs += (sljit_s32)(sizeof(sljit_sw)); } SLJIT_ASSERT(offs == local_size - (sljit_sw)(sizeof(sljit_sw))); FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); if (compiler->local_size <= SIMM_MAX) return push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(compiler->local_size), UNMOVABLE_INS); else return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_SP), UNMOVABLE_INS); } #undef STACK_STORE #undef STACK_LOAD /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define ARCH_32_64(a, b) a #else #define ARCH_32_64(a, b) b #endif static const sljit_ins data_transfer_insts[16 + 4] = { /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */), /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */), /* u b s */ HI(40) /* sb */, /* u b l */ HI(36) /* lbu */, /* u h s */ HI(41) /* sh */, /* u h l */ HI(37) /* lhu */, /* u i s */ HI(43) /* sw */, /* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */), /* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */), /* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */), /* s b s */ HI(40) /* sb */, /* s b l */ HI(32) /* lb */, /* s h s */ HI(41) /* sh */, /* s h l */ HI(33) /* lh */, /* s i s */ HI(43) /* sw */, /* s i l */ HI(35) /* lw */, /* d s */ HI(61) /* sdc1 */, /* d l */ HI(53) /* ldc1 */, /* s s */ HI(57) /* swc1 */, /* s l */ HI(49) /* lwc1 */, }; #undef ARCH_32_64 /* reg_ar is an absoulute register! */ /* Can perform an operation using at most 1 instruction. */ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) { SLJIT_ASSERT(arg & SLJIT_MEM); if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) { /* Works for both absoulte and relative addresses. */ if (SLJIT_UNLIKELY(flags & ARG_TEST)) return 1; FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK) | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS)); return -1; } return 0; } /* See getput_arg below. Note: can_cache is called only for binary operators. Those operators always uses word arguments without write back. */ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); /* Simple operation except for updates. */ if (arg & OFFS_REG_MASK) { argw &= 0x3; next_argw &= 0x3; if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK))) return 1; return 0; } if (arg == next_arg) { if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)) return 1; return 0; } return 0; } /* Emit the necessary instructions. See can_cache above. */ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { sljit_s32 tmp_ar, base, delay_slot; SLJIT_ASSERT(arg & SLJIT_MEM); if (!(next_arg & SLJIT_MEM)) { next_arg = 0; next_argw = 0; } if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) { tmp_ar = reg_ar; delay_slot = reg_ar; } else { tmp_ar = DR(TMP_REG1); delay_slot = MOVABLE_INS; } base = arg & REG_MASK; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; /* Using the cache. */ if (argw == compiler->cache_argw) { if (arg == compiler->cache_arg) return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { if (arg == next_arg && argw == (next_argw & 0x3)) { compiler->cache_arg = arg; compiler->cache_argw = argw; FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); } FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } } if (SLJIT_UNLIKELY(argw)) { compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK); compiler->cache_argw = argw; FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3))); } if (arg == next_arg && argw == (next_argw & 0x3)) { compiler->cache_arg = arg; compiler->cache_argw = argw; FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); tmp_ar = DR(TMP_REG3); } else FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { if (argw != compiler->cache_argw) { FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); compiler->cache_argw = argw; } return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); } if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { if (argw != compiler->cache_argw) FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); } else { compiler->cache_arg = SLJIT_MEM; FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); } compiler->cache_argw = argw; if (!base) return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) { compiler->cache_arg = arg; FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3))); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot); } FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) { sljit_s32 tmp_ar, base, delay_slot; if (getput_arg_fast(compiler, flags, reg_ar, arg, argw)) return compiler->error; if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) { tmp_ar = reg_ar; delay_slot = reg_ar; } else { tmp_ar = DR(TMP_REG1); delay_slot = MOVABLE_INS; } base = arg & REG_MASK; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; if (SLJIT_UNLIKELY(argw)) { FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar)); FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar)); } else FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } FAIL_IF(load_immediate(compiler, tmp_ar, argw)); if (base != 0) FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar)); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot); } static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) { if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) return compiler->error; return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* arg1 goes to TMP_REG1 or src reg arg2 goes to TMP_REG2, imm or src reg TMP_REG3 can be used for caching result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ sljit_s32 dst_r = TMP_REG2; sljit_s32 src1_r; sljit_sw src2_r = 0; sljit_s32 sugg_src2_r = TMP_REG2; if (!(flags & ALT_KEEP_CACHE)) { compiler->cache_arg = 0; compiler->cache_argw = 0; } if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { SLJIT_ASSERT(HAS_FLAGS(op)); flags |= UNUSED_DEST; } else if (FAST_IS_REG(dst)) { dst_r = dst; flags |= REG_DEST; if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) sugg_src2_r = dst_r; } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw)) flags |= SLOW_DEST; if (flags & IMM_OP) { if ((src2 & SLJIT_IMM) && src2w) { if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN)) || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) { flags |= SRC2_IMM; src2_r = src2w; } } if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) { if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN)) || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) { flags |= SRC2_IMM; src2_r = src1w; /* And swap arguments. */ src1 = src2; src1w = src2w; src2 = SLJIT_IMM; /* src2w = src2_r unneeded. */ } } } /* Source 1. */ if (FAST_IS_REG(src1)) { src1_r = src1; flags |= REG1_SOURCE; } else if (src1 & SLJIT_IMM) { if (src1w) { FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); src1_r = TMP_REG1; } else src1_r = 0; } else { if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w)) FAIL_IF(compiler->error); else flags |= SLOW_SRC1; src1_r = TMP_REG1; } /* Source 2. */ if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { if (!(flags & SRC2_IMM)) { if (src2w) { FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w)); src2_r = sugg_src2_r; } else { src2_r = 0; if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM)) dst_r = 0; } } } else { if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w)) FAIL_IF(compiler->error); else flags |= SLOW_SRC2; src2_r = sugg_src2_r; } if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { SLJIT_ASSERT(src2_r == TMP_REG2); if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w)); FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw)); } else { FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w)); FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw)); } } else if (flags & SLOW_SRC1) FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw)); else if (flags & SLOW_SRC2) FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw)); FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); if (dst & SLJIT_MEM) { if (!(flags & SLOW_DEST)) { getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw); return compiler->error; } return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) sljit_s32 int_op = op & SLJIT_I32_OP; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: return push_inst(compiler, BREAK, UNMOVABLE_INS); case SLJIT_NOP: return push_inst(compiler, NOP, UNMOVABLE_INS); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #else FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); #if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); #endif #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (int_op) FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); else FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #else FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); } return SLJIT_SUCCESS; } #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { if (!(src & OFFS_REG_MASK)) { if (srcw <= SIMM_MAX && srcw >= SIMM_MIN) return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS); FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS); } srcw &= 0x3; if (SLJIT_UNLIKELY(srcw != 0)) { FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1))); return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS); } return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS); } #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # define flags 0 #else sljit_s32 flags = 0; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) return emit_prefetch(compiler, src, srcw); #endif return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) flags |= INT_DATA | SIGNED_DATA; #endif switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_P: return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U32: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); #else return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw); #endif case SLJIT_MOV_S32: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw); #else return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw); #endif case SLJIT_MOV_U8: return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_NOT: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_NEG: return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); case SLJIT_CLZ: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # undef flags #endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # define flags 0 #else sljit_s32 flags = 0; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (op & SLJIT_I32_OP) { flags |= INT_DATA | SIGNED_DATA; if (src1 & SLJIT_IMM) src1w = (sljit_s32)src1w; if (src2 & SLJIT_IMM) src2w = (sljit_s32)src2w; } #endif switch (GET_OPCODE(op)) { case SLJIT_ADD: case SLJIT_ADDC: return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: case SLJIT_SUBC: return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) if (src2 & SLJIT_IMM) src2w &= 0x1f; #else if (src2 & SLJIT_IMM) { if (op & SLJIT_I32_OP) src2w &= 0x1f; else src2w &= 0x3f; } #endif return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # undef flags #endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return FR(reg); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS); } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7)) #define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8)) static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # define flags 0 #else sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) << 21; #endif if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); src = TMP_FREG1; } FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS)); if (FAST_IS_REG(dst)) return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS); /* Store the integer value from a VFP register. */ return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0); #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # undef is_long #endif } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # define flags 0 #else sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21; #endif sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS)); else if (src & SLJIT_MEM) { /* Load the integer value into a VFP register. */ FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw)); } else { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS)); } FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS)); if (dst & SLJIT_MEM) return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0); return SLJIT_SUCCESS; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) # undef flags #endif } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_ins inst; if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0)); src2 = TMP_FREG2; } switch (GET_FLAG_TYPE(op)) { case SLJIT_EQUAL_F64: case SLJIT_NOT_EQUAL_F64: inst = C_UEQ_S; break; case SLJIT_LESS_F64: case SLJIT_GREATER_EQUAL_F64: inst = C_ULT_S; break; case SLJIT_GREATER_F64: case SLJIT_LESS_EQUAL_F64: inst = C_ULE_S; break; default: SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64); inst = C_UN_S; break; } return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1), UNMOVABLE_INS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; CHECK_ERROR(); compiler->cache_arg = 0; compiler->cache_argw = 0; SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw)); src = dst_r; } switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS)); else dst_r = src; } break; case SLJIT_NEG_F64: FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS)); break; case SLJIT_ABS_F64: FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS)); break; case SLJIT_CONV_F64_FROM_F32: FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_F32_OP) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS)); op ^= SLJIT_F32_OP; break; } if (dst & SLJIT_MEM) return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r, flags = 0; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); compiler->cache_arg = 0; compiler->cache_argw = 0; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; if (src1 & SLJIT_MEM) { if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) { FAIL_IF(compiler->error); src1 = TMP_FREG1; } else flags |= SLOW_SRC1; } if (src2 & SLJIT_MEM) { if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) { FAIL_IF(compiler->error); src2 = TMP_FREG2; } else flags |= SLOW_SRC2; } if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w)); FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw)); } else { FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w)); FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw)); } } else if (flags & SLOW_SRC1) FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw)); else if (flags & SLOW_SRC2) FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw)); if (flags & SLOW_SRC1) src1 = TMP_FREG1; if (flags & SLOW_SRC2) src2 = TMP_FREG2; switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS)); break; } if (dst_r == TMP_FREG2) FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0)); return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst)); /* Memory. */ return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); else FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); return push_inst(compiler, NOP, UNMOVABLE_INS); } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); compiler->delay_slot = UNMOVABLE_INS; return label; } #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define JUMP_LENGTH 4 #else #define JUMP_LENGTH 8 #endif #define BR_Z(src) \ inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \ flags = IS_BIT26_COND; \ delay_check = src; #define BR_NZ(src) \ inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \ flags = IS_BIT26_COND; \ delay_check = src; #define BR_T() \ inst = BC1T | JUMP_LENGTH; \ flags = IS_BIT16_COND; \ delay_check = FCSR_FCC; #define BR_F() \ inst = BC1F | JUMP_LENGTH; \ flags = IS_BIT16_COND; \ delay_check = FCSR_FCC; SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; sljit_ins inst; sljit_s32 flags = 0; sljit_s32 delay_check = UNMOVABLE_INS; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; switch (type) { case SLJIT_EQUAL: BR_NZ(EQUAL_FLAG); break; case SLJIT_NOT_EQUAL: BR_Z(EQUAL_FLAG); break; case SLJIT_LESS: case SLJIT_GREATER: case SLJIT_SIG_LESS: case SLJIT_SIG_GREATER: case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: BR_Z(OTHER_FLAG); break; case SLJIT_GREATER_EQUAL: case SLJIT_LESS_EQUAL: case SLJIT_SIG_GREATER_EQUAL: case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: BR_NZ(OTHER_FLAG); break; case SLJIT_NOT_EQUAL_F64: case SLJIT_GREATER_EQUAL_F64: case SLJIT_GREATER_F64: case SLJIT_ORDERED_F64: BR_T(); break; case SLJIT_EQUAL_F64: case SLJIT_LESS_F64: case SLJIT_LESS_EQUAL_F64: case SLJIT_UNORDERED_F64: BR_F(); break; default: /* Not conditional branch. */ inst = 0; break; } jump->flags |= flags; if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check)) jump->flags |= IS_MOVABLE; if (inst) PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS)); PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); if (type <= SLJIT_JUMP) PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); else { jump->flags |= IS_JAL; PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); } jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return jump; } #define RESOLVE_IMM1() \ if (src1 & SLJIT_IMM) { \ if (src1w) { \ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \ src1 = TMP_REG1; \ } \ else \ src1 = 0; \ } #define RESOLVE_IMM2() \ if (src2 & SLJIT_IMM) { \ if (src2w) { \ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \ src2 = TMP_REG2; \ } \ else \ src2 = 0; \ } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { struct sljit_jump *jump; sljit_s32 flags; sljit_ins inst; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); compiler->cache_arg = 0; compiler->cache_argw = 0; flags = ((type & SLJIT_I32_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA; if (src1 & SLJIT_MEM) { PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w)); src1 = TMP_REG1; } if (src2 & SLJIT_MEM) { PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0)); src2 = TMP_REG2; } jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; if (type <= SLJIT_NOT_EQUAL) { RESOLVE_IMM1(); RESOLVE_IMM2(); jump->flags |= IS_BIT26_COND; if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2))) jump->flags |= IS_MOVABLE; PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS)); } else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) { inst = NOP; if ((src1 & SLJIT_IMM) && (src1w == 0)) { RESOLVE_IMM2(); switch (type) { case SLJIT_SIG_LESS: inst = BLEZ; jump->flags |= IS_BIT26_COND; break; case SLJIT_SIG_GREATER_EQUAL: inst = BGTZ; jump->flags |= IS_BIT26_COND; break; case SLJIT_SIG_GREATER: inst = BGEZ; jump->flags |= IS_BIT16_COND; break; case SLJIT_SIG_LESS_EQUAL: inst = BLTZ; jump->flags |= IS_BIT16_COND; break; } src1 = src2; } else { RESOLVE_IMM1(); switch (type) { case SLJIT_SIG_LESS: inst = BGEZ; jump->flags |= IS_BIT16_COND; break; case SLJIT_SIG_GREATER_EQUAL: inst = BLTZ; jump->flags |= IS_BIT16_COND; break; case SLJIT_SIG_GREATER: inst = BLEZ; jump->flags |= IS_BIT26_COND; break; case SLJIT_SIG_LESS_EQUAL: inst = BGTZ; jump->flags |= IS_BIT26_COND; break; } } PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS)); } else { if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) { RESOLVE_IMM1(); if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN) PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1))); else { RESOLVE_IMM2(); PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1))); } type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL; } else { RESOLVE_IMM2(); if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN) PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1))); else { RESOLVE_IMM1(); PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1))); } type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL; } jump->flags |= IS_BIT26_COND; PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS)); } PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return jump; } #undef RESOLVE_IMM1 #undef RESOLVE_IMM2 #undef JUMP_LENGTH #undef BR_Z #undef BR_NZ #undef BR_T #undef BR_F #undef FLOAT_DATA #undef FMT SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump = NULL; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (src & SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0)); jump->u.target = srcw; if (compiler->delay_slot != UNMOVABLE_INS) jump->flags |= IS_MOVABLE; FAIL_IF(emit_const(compiler, TMP_REG2, 0)); src = TMP_REG2; } else if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw)); src = TMP_REG2; } FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS)); if (jump) jump->addr = compiler->size; FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_s32 src_ar, dst_ar; sljit_s32 saved_op = op; #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) sljit_s32 mem_type = WORD_DATA; #else sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); op = GET_OPCODE(op); #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (op == SLJIT_MOV_S32) mem_type = INT_DATA | SIGNED_DATA; #endif dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2); compiler->cache_arg = 0; compiler->cache_argw = 0; if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw)); switch (type & 0xff) { case SLJIT_EQUAL: case SLJIT_NOT_EQUAL: FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; break; case SLJIT_MUL_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; type ^= 0x1; /* Flip type bit for the XORI below. */ break; case SLJIT_GREATER_F64: case SLJIT_LESS_EQUAL_F64: type ^= 0x1; /* Flip type bit for the XORI below. */ case SLJIT_EQUAL_F64: case SLJIT_NOT_EQUAL_F64: case SLJIT_LESS_F64: case SLJIT_GREATER_EQUAL_F64: case SLJIT_UNORDERED_F64: case SLJIT_ORDERED_F64: FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar)); FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar)); FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; break; default: src_ar = OTHER_FLAG; break; } if (type & 0x1) { FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; } if (op < SLJIT_ADD) { if (dst & SLJIT_MEM) return emit_op_mem(compiler, mem_type, src_ar, dst, dstw); if (src_ar != dst_ar) return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar); return SLJIT_SUCCESS; } /* OTHER_FLAG cannot be specified as src2 argument at the moment. */ if (DR(TMP_REG2) != src_ar) FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE; if (dst & SLJIT_MEM) return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) sljit_ins ins; #endif CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (dst_reg & SLJIT_I32_OP) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw)); src = TMP_REG1; srcw = 0; } dst_reg &= ~SLJIT_I32_OP; switch (type & 0xff) { case SLJIT_EQUAL: ins = MOVZ | TA(EQUAL_FLAG); break; case SLJIT_NOT_EQUAL: ins = MOVN | TA(EQUAL_FLAG); break; case SLJIT_LESS: case SLJIT_GREATER: case SLJIT_SIG_LESS: case SLJIT_SIG_GREATER: case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: ins = MOVN | TA(OTHER_FLAG); break; case SLJIT_GREATER_EQUAL: case SLJIT_LESS_EQUAL: case SLJIT_SIG_GREATER_EQUAL: case SLJIT_SIG_LESS_EQUAL: case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: ins = MOVZ | TA(OTHER_FLAG); break; case SLJIT_EQUAL_F64: case SLJIT_LESS_F64: case SLJIT_LESS_EQUAL_F64: case SLJIT_UNORDERED_F64: ins = MOVT; break; case SLJIT_NOT_EQUAL_F64: case SLJIT_GREATER_EQUAL_F64: case SLJIT_GREATER_F64: case SLJIT_ORDERED_F64: ins = MOVF; break; default: ins = MOVZ | TA(OTHER_FLAG); SLJIT_UNREACHABLE(); break; } return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg)); #else return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); #endif } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; sljit_s32 reg; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const(compiler, reg, init_value)); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); return const_; } ================================================ FILE: src/pcre/sljit/sljitNativePPC_32.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* ppc 32-bit arch dependent functions. */ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) { if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); if (!(imm & ~0xffff)) return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm)); FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16))); return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } #define INS_CLEAR_LEFT(dst, src, from) \ (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1)) static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: SLJIT_ASSERT(src1 == TMP_REG1); if (dst != src2) return push_inst(compiler, OR | S(src2) | A(dst) | B(src2)); return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); } else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) return push_inst(compiler, EXTSH | S(src2) | A(dst)); return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1); return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); case SLJIT_NEG: SLJIT_ASSERT(src1 == TMP_REG1); /* Setting XER SO is not enough, CR SO is also needed. */ return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2)); case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); return push_inst(compiler, CNTLZW | S(src2) | A(dst)); case SLJIT_ADD: if (flags & ALT_FORM1) { /* Setting XER SO is not enough, CR SO is also needed. */ return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); } if (flags & ALT_FORM2) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); if (flags & ALT_FORM4) { FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); src1 = dst; } return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); if (flags & ALT_FORM4) return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2)); case SLJIT_ADDC: return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); case SLJIT_SUB: if (flags & ALT_FORM1) { if (flags & ALT_FORM2) { FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm)); if (!(flags & ALT_FORM3)) return SLJIT_SUCCESS; return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff)); } FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2))); if (!(flags & ALT_FORM3)) return SLJIT_SUCCESS; return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); } if (flags & ALT_FORM2) { /* Setting XER SO is not enough, CR SO is also needed. */ return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); } if (flags & ALT_FORM3) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); } if (flags & ALT_FORM4) { if (flags & ALT_FORM5) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm); } return push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)); } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); if (flags & ALT_FORM5) return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_SUBC: return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); case SLJIT_MUL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); } return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_AND: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM2) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); } return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_OR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM2) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_XOR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM2) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); compiler->imm &= 0x1f; return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); } return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); compiler->imm &= 0x1f; return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); } return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); compiler->imm &= 0x1f; return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); } return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } ================================================ FILE: src/pcre/sljit/sljitNativePPC_64.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* ppc 64-bit arch dependent functions. */ #if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM) #define ASM_SLJIT_CLZ(src, dst) \ __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) ) #elif defined(__xlc__) #error "Please enable GCC syntax for inline assembly statements" #else #error "Must implement count leading zeroes" #endif #define RLDI(dst, src, sh, mb, type) \ (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20)) #define PUSH_RLDICR(reg, shift) \ push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1)) static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) { sljit_uw tmp; sljit_uw shift; sljit_uw tmp2; sljit_uw shift2; if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); if (!(imm & ~0xffff)) return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm)); if (imm <= 0x7fffffffl && imm >= -0x80000000l) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16))); return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; } /* Count leading zeroes. */ tmp = (imm >= 0) ? imm : ~imm; ASM_SLJIT_CLZ(tmp, shift); SLJIT_ASSERT(shift > 0); shift--; tmp = (imm << shift); if ((tmp & ~0xffff000000000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); shift += 15; return PUSH_RLDICR(reg, shift); } if ((tmp & ~0xffffffff00000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32))); shift += 31; return PUSH_RLDICR(reg, shift); } /* Cut out the 16 bit from immediate. */ shift += 15; tmp2 = imm & ((1ul << (63 - shift)) - 1); if (tmp2 <= 0xffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); FAIL_IF(PUSH_RLDICR(reg, shift)); return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2); } if (tmp2 <= 0xffffffff) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); FAIL_IF(PUSH_RLDICR(reg, shift)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16))); return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS; } ASM_SLJIT_CLZ(tmp2, shift2); tmp2 <<= shift2; if ((tmp2 & ~0xffff000000000000ul) == 0) { FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); shift2 += 15; shift += (63 - shift2); FAIL_IF(PUSH_RLDICR(reg, shift)); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48))); return PUSH_RLDICR(reg, shift2); } /* The general version. */ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32))); FAIL_IF(PUSH_RLDICR(reg, 31)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)); } /* Simplified mnemonics: clrldi. */ #define INS_CLEAR_LEFT(dst, src, from) \ (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5)) /* Sign extension for integer operations. */ #define UN_EXTS() \ if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \ src2 = TMP_REG2; \ } #define BIN_EXTS() \ if (flags & ALT_SIGN_EXT) { \ if (flags & REG1_SOURCE) { \ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \ src1 = TMP_REG1; \ } \ if (flags & REG2_SOURCE) { \ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \ src2 = TMP_REG2; \ } \ } #define BIN_IMM_EXTS() \ if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \ src1 = TMP_REG1; \ } static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) { switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: SLJIT_ASSERT(src1 == TMP_REG1); if (dst != src2) return push_inst(compiler, OR | S(src2) | A(dst) | B(src2)); return SLJIT_SUCCESS; case SLJIT_MOV_U32: case SLJIT_MOV_S32: SLJIT_ASSERT(src1 == TMP_REG1); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S32) return push_inst(compiler, EXTSW | S(src2) | A(dst)); return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); } else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(src2) | A(dst)); else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) return push_inst(compiler, EXTSH | S(src2) | A(dst)); return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); } else { SLJIT_ASSERT(dst == src2); } return SLJIT_SUCCESS; case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1); UN_EXTS(); return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); case SLJIT_NEG: SLJIT_ASSERT(src1 == TMP_REG1); if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) { FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2))); return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); } UN_EXTS(); /* Setting XER SO is not enough, CR SO is also needed. */ return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2)); case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1); if (flags & ALT_FORM1) return push_inst(compiler, CNTLZW | S(src2) | A(dst)); return push_inst(compiler, CNTLZD | S(src2) | A(dst)); case SLJIT_ADD: if (flags & ALT_FORM1) { if (flags & ALT_SIGN_EXT) { FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); src1 = TMP_REG1; FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); src2 = TMP_REG2; } /* Setting XER SO is not enough, CR SO is also needed. */ FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2))); if (flags & ALT_SIGN_EXT) return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); return SLJIT_SUCCESS; } if (flags & ALT_FORM2) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); if (flags & ALT_FORM3) return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); if (flags & ALT_FORM4) { FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)))); src1 = dst; } return push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); BIN_IMM_EXTS(); return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); BIN_EXTS(); if (flags & ALT_FORM4) return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2)); case SLJIT_ADDC: BIN_EXTS(); return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); case SLJIT_SUB: if (flags & ALT_FORM1) { if (flags & ALT_FORM2) { FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm)); if (!(flags & ALT_FORM3)) return SLJIT_SUCCESS; return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff)); } FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); if (!(flags & ALT_FORM3)) return SLJIT_SUCCESS; return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); } if (flags & ALT_FORM2) { if (flags & ALT_SIGN_EXT) { FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1))); src1 = TMP_REG1; FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1))); src2 = TMP_REG2; } /* Setting XER SO is not enough, CR SO is also needed. */ FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1))); if (flags & ALT_SIGN_EXT) return push_inst(compiler, RLDI(dst, dst, 32, 32, 0)); return SLJIT_SUCCESS; } if (flags & ALT_FORM3) { /* Flags does not set: BIN_IMM_EXTS unnecessary. */ SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); } if (flags & ALT_FORM4) { if (flags & ALT_FORM5) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); } return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); } if (!(flags & ALT_SET_FLAGS)) return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); BIN_EXTS(); if (flags & ALT_FORM5) return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_SUBC: BIN_EXTS(); return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); case SLJIT_MUL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); } BIN_EXTS(); if (flags & ALT_FORM2) return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1)); return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1)); case SLJIT_AND: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM2) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); } return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_OR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM2) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); } return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_XOR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM2) { SLJIT_ASSERT(src2 == TMP_REG2); return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); } if (flags & ALT_FORM3) { SLJIT_ASSERT(src2 == TMP_REG2); FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); } return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_SHL: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); if (flags & ALT_FORM2) { compiler->imm &= 0x1f; return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); } compiler->imm &= 0x3f; return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); } return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_LSHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); if (flags & ALT_FORM2) { compiler->imm &= 0x1f; return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); } compiler->imm &= 0x3f; return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); } return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2)); case SLJIT_ASHR: if (flags & ALT_FORM1) { SLJIT_ASSERT(src2 == TMP_REG2); if (flags & ALT_FORM2) { compiler->imm &= 0x1f; return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); } compiler->imm &= 0x3f; return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)); } return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) { sljit_s32 arg_count = 0; sljit_s32 word_arg_count = 0; sljit_s32 types = 0; sljit_s32 reg = 0; if (src) reg = *src & REG_MASK; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: case SLJIT_ARG_TYPE_F64: arg_count++; break; default: arg_count++; word_arg_count++; if (arg_count != word_arg_count && arg_count == reg) { FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg))); *src = TMP_CALL_REG; } break; } arg_types >>= SLJIT_DEF_SHIFT; } while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: case SLJIT_ARG_TYPE_F64: arg_count--; break; default: if (arg_count != word_arg_count) FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count))); arg_count--; word_arg_count--; break; } types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value) { FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48))); FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32))); FAIL_IF(PUSH_RLDICR(reg, 31)); FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16))); return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins*)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff); inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 5); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins*)addr; inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 5); } ================================================ FILE: src/pcre/sljit/sljitNativePPC_common.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { return "PowerPC" SLJIT_CPUINFO; } /* Length of an instruction word. Both for ppc-32 and ppc-64. */ typedef sljit_u32 sljit_ins; #if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define SLJIT_PPC_STACK_FRAME_V2 1 #endif #ifdef _AIX #include #endif #if (defined _CALL_ELF && _CALL_ELF == 2) #define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1 #endif #if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) static void ppc_cache_flush(sljit_ins *from, sljit_ins *to) { #ifdef _AIX _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from)); #elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM) # if defined(_ARCH_PWR) || defined(_ARCH_PWR2) /* Cache flush for POWER architecture. */ while (from < to) { __asm__ volatile ( "clf 0, %0\n" "dcs\n" : : "r"(from) ); from++; } __asm__ volatile ( "ics" ); # elif defined(_ARCH_COM) && !defined(_ARCH_PPC) # error "Cache flush is not implemented for PowerPC/POWER common mode." # else /* Cache flush for PowerPC architecture. */ while (from < to) { __asm__ volatile ( "dcbf 0, %0\n" "sync\n" "icbi 0, %0\n" : : "r"(from) ); from++; } __asm__ volatile ( "isync" ); # endif # ifdef __xlc__ # warning "This file may fail to compile if -qfuncsect is used" # endif #elif defined(__xlc__) #error "Please enable GCC syntax for inline assembly statements with -qasm=gcc" #else #error "This platform requires a cache flush implementation." #endif /* _AIX */ } #endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4) #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) #define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5) #else #define TMP_CALL_REG TMP_REG2 #endif #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = { 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12 }; static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 1, 2, 3, 4, 5, 6, 0, 7 }; /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ #define D(d) (reg_map[d] << 21) #define S(s) (reg_map[s] << 21) #define A(a) (reg_map[a] << 16) #define B(b) (reg_map[b] << 11) #define C(c) (reg_map[c] << 6) #define FD(fd) (freg_map[fd] << 21) #define FS(fs) (freg_map[fs] << 21) #define FA(fa) (freg_map[fa] << 16) #define FB(fb) (freg_map[fb] << 11) #define FC(fc) (freg_map[fc] << 6) #define IMM(imm) ((imm) & 0xffff) #define CRD(d) ((d) << 21) /* Instruction bit sections. OE and Rc flag (see ALT_SET_FLAGS). */ #define OE(flags) ((flags) & ALT_SET_FLAGS) /* Rc flag (see ALT_SET_FLAGS). */ #define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10) #define HI(opcode) ((opcode) << 26) #define LO(opcode) ((opcode) << 1) #define ADD (HI(31) | LO(266)) #define ADDC (HI(31) | LO(10)) #define ADDE (HI(31) | LO(138)) #define ADDI (HI(14)) #define ADDIC (HI(13)) #define ADDIS (HI(15)) #define ADDME (HI(31) | LO(234)) #define AND (HI(31) | LO(28)) #define ANDI (HI(28)) #define ANDIS (HI(29)) #define Bx (HI(18)) #define BCx (HI(16)) #define BCCTR (HI(19) | LO(528) | (3 << 11)) #define BLR (HI(19) | LO(16) | (0x14 << 21)) #define CNTLZD (HI(31) | LO(58)) #define CNTLZW (HI(31) | LO(26)) #define CMP (HI(31) | LO(0)) #define CMPI (HI(11)) #define CMPL (HI(31) | LO(32)) #define CMPLI (HI(10)) #define CROR (HI(19) | LO(449)) #define DCBT (HI(31) | LO(278)) #define DIVD (HI(31) | LO(489)) #define DIVDU (HI(31) | LO(457)) #define DIVW (HI(31) | LO(491)) #define DIVWU (HI(31) | LO(459)) #define EXTSB (HI(31) | LO(954)) #define EXTSH (HI(31) | LO(922)) #define EXTSW (HI(31) | LO(986)) #define FABS (HI(63) | LO(264)) #define FADD (HI(63) | LO(21)) #define FADDS (HI(59) | LO(21)) #define FCFID (HI(63) | LO(846)) #define FCMPU (HI(63) | LO(0)) #define FCTIDZ (HI(63) | LO(815)) #define FCTIWZ (HI(63) | LO(15)) #define FDIV (HI(63) | LO(18)) #define FDIVS (HI(59) | LO(18)) #define FMR (HI(63) | LO(72)) #define FMUL (HI(63) | LO(25)) #define FMULS (HI(59) | LO(25)) #define FNEG (HI(63) | LO(40)) #define FRSP (HI(63) | LO(12)) #define FSUB (HI(63) | LO(20)) #define FSUBS (HI(59) | LO(20)) #define LD (HI(58) | 0) #define LWZ (HI(32)) #define MFCR (HI(31) | LO(19)) #define MFLR (HI(31) | LO(339) | 0x80000) #define MFXER (HI(31) | LO(339) | 0x10000) #define MTCTR (HI(31) | LO(467) | 0x90000) #define MTLR (HI(31) | LO(467) | 0x80000) #define MTXER (HI(31) | LO(467) | 0x10000) #define MULHD (HI(31) | LO(73)) #define MULHDU (HI(31) | LO(9)) #define MULHW (HI(31) | LO(75)) #define MULHWU (HI(31) | LO(11)) #define MULLD (HI(31) | LO(233)) #define MULLI (HI(7)) #define MULLW (HI(31) | LO(235)) #define NEG (HI(31) | LO(104)) #define NOP (HI(24)) #define NOR (HI(31) | LO(124)) #define OR (HI(31) | LO(444)) #define ORI (HI(24)) #define ORIS (HI(25)) #define RLDICL (HI(30)) #define RLWINM (HI(21)) #define SLD (HI(31) | LO(27)) #define SLW (HI(31) | LO(24)) #define SRAD (HI(31) | LO(794)) #define SRADI (HI(31) | LO(413 << 1)) #define SRAW (HI(31) | LO(792)) #define SRAWI (HI(31) | LO(824)) #define SRD (HI(31) | LO(539)) #define SRW (HI(31) | LO(536)) #define STD (HI(62) | 0) #define STDU (HI(62) | 1) #define STDUX (HI(31) | LO(181)) #define STFIWX (HI(31) | LO(983)) #define STW (HI(36)) #define STWU (HI(37)) #define STWUX (HI(31) | LO(183)) #define SUBF (HI(31) | LO(40)) #define SUBFC (HI(31) | LO(8)) #define SUBFE (HI(31) | LO(136)) #define SUBFIC (HI(8)) #define XOR (HI(31) | LO(316)) #define XORI (HI(26)) #define XORIS (HI(27)) #define SIMM_MAX (0x7fff) #define SIMM_MIN (-0x8000) #define UIMM_MAX (0xffff) #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func) { sljit_sw* ptrs; if (func_ptr) *func_ptr = (void*)context; ptrs = (sljit_sw*)func; context->addr = addr ? addr : ptrs[0]; context->r2 = ptrs[1]; context->r11 = ptrs[2]; } #endif static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; sljit_sw extra_jump_flags; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL)) return 0; #else if (jump->flags & SLJIT_REWRITABLE_JUMP) return 0; #endif if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (jump->flags & IS_CALL) goto keep_address; #endif diff = ((sljit_sw)target_addr - (sljit_sw)(code_ptr) - executable_offset) & ~0x3l; extra_jump_flags = 0; if (jump->flags & IS_COND) { if (diff <= 0x7fff && diff >= -0x8000) { jump->flags |= PATCH_B; return 1; } if (target_addr <= 0xffff) { jump->flags |= PATCH_B | PATCH_ABS_B; return 1; } extra_jump_flags = REMOVE_COND; diff -= sizeof(sljit_ins); } if (diff <= 0x01ffffff && diff >= -0x02000000) { jump->flags |= PATCH_B | extra_jump_flags; return 1; } if (target_addr <= 0x03ffffff) { jump->flags |= PATCH_B | PATCH_ABS_B | extra_jump_flags; return 1; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) keep_address: #endif if (target_addr <= 0x7fffffff) { jump->flags |= PATCH_ABS32; return 1; } if (target_addr <= 0x7fffffffffffl) { jump->flags |= PATCH_ABS48; return 1; } #endif return 0; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_ins *code; sljit_ins *code_ptr; sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; sljit_sw executable_offset; sljit_uw addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins)); #else compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins)); #endif #endif code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; word_count = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); /* These structures are ordered by their address. */ if (label && label->size == word_count) { /* Just recording the address. */ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } if (jump && jump->addr == word_count) { #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) jump->addr = (sljit_uw)(code_ptr - 3); #else jump->addr = (sljit_uw)(code_ptr - 6); #endif if (detect_jump_type(jump, code_ptr, code, executable_offset)) { #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) code_ptr[-3] = code_ptr[0]; code_ptr -= 3; #else if (jump->flags & PATCH_ABS32) { code_ptr -= 3; code_ptr[-1] = code_ptr[2]; code_ptr[0] = code_ptr[3]; } else if (jump->flags & PATCH_ABS48) { code_ptr--; code_ptr[-1] = code_ptr[0]; code_ptr[0] = code_ptr[1]; /* rldicr rX,rX,32,31 -> rX,rX,16,47 */ SLJIT_ASSERT((code_ptr[-3] & 0xfc00ffff) == 0x780007c6); code_ptr[-3] ^= 0x8422; /* oris -> ori */ code_ptr[-2] ^= 0x4000000; } else { code_ptr[-6] = code_ptr[0]; code_ptr -= 6; } #endif if (jump->flags & REMOVE_COND) { code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001); code_ptr++; jump->addr += sizeof(sljit_ins); code_ptr[0] = Bx; jump->flags -= IS_COND; } } jump = jump->next; } if (const_ && const_->addr == word_count) { const_->addr = (sljit_uw)code_ptr; const_ = const_->next; } code_ptr ++; word_count ++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); if (label && label->size == word_count) { label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))); #else SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); #endif jump = compiler->jumps; while (jump) { do { addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; buf_ptr = (sljit_ins *)jump->addr; if (jump->flags & PATCH_B) { if (jump->flags & IS_COND) { if (!(jump->flags & PATCH_ABS_B)) { addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000); *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001); } else { SLJIT_ASSERT(addr <= 0xffff); *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001); } } else { if (!(jump->flags & PATCH_ABS_B)) { addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset); SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000); *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1); } else { SLJIT_ASSERT(addr <= 0x03ffffff); *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1); } } break; } /* Set the fields of immediate loads. */ #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff); #else if (jump->flags & PATCH_ABS32) { SLJIT_ASSERT(addr <= 0x7fffffff); buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff); break; } if (jump->flags & PATCH_ABS48) { SLJIT_ASSERT(addr <= 0x7fffffffffff); buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff); break; } buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff); buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff); buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff); buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff); #endif } while (0); jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (((sljit_sw)code_ptr) & 0x4) code_ptr++; #endif sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code); #endif code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) return code_ptr; #else return code; #endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #else /* Available by default. */ return 1; #endif case SLJIT_HAS_CLZ: return 1; default: return 0; } } /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ /* inp_flags: */ /* Creates an index in data_transfer_insts array. */ #define LOAD_DATA 0x01 #define INDEXED 0x02 #define SIGNED_DATA 0x04 #define WORD_DATA 0x00 #define BYTE_DATA 0x08 #define HALF_DATA 0x10 #define INT_DATA 0x18 /* Separates integer and floating point registers */ #define GPR_REG 0x1f #define DOUBLE_DATA 0x20 #define MEM_MASK 0x7f /* Other inp_flags. */ /* Integer opertion and set flags -> requires exts on 64 bit systems. */ #define ALT_SIGN_EXT 0x000100 /* This flag affects the RC() and OERC() macros. */ #define ALT_SET_FLAGS 0x000400 #define ALT_FORM1 0x001000 #define ALT_FORM2 0x002000 #define ALT_FORM3 0x004000 #define ALT_FORM4 0x008000 #define ALT_FORM5 0x010000 /* Source and destination is register. */ #define REG_DEST 0x000001 #define REG1_SOURCE 0x000002 #define REG2_SOURCE 0x000004 /* ALT_SIGN_EXT 0x000100 ALT_SET_FLAGS 0x000200 ALT_FORM1 0x001000 ... ALT_FORM5 0x010000 */ #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #include "sljitNativePPC_32.c" #else #include "sljitNativePPC_64.c" #endif #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #define STACK_STORE STW #define STACK_LOAD LWZ #else #define STACK_STORE STD #define STACK_LOAD LD #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args, i, tmp, offs; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); FAIL_IF(push_inst(compiler, MFLR | D(0))); offs = -(sljit_s32)(sizeof(sljit_sw)); FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs))); tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) { offs -= (sljit_s32)(sizeof(sljit_sw)); FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs))); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { offs -= (sljit_s32)(sizeof(sljit_sw)); FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs))); } SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1)); #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2) FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw)))); #else FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw)))); #endif FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0)); args = get_arg_count(arg_types); if (args >= 1) FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0))); if (args >= 2) FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1))); if (args >= 3) FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2))); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; local_size = (local_size + 15) & ~0xf; compiler->local_size = local_size; #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) if (local_size <= SIMM_MAX) FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size))); else { FAIL_IF(load_immediate(compiler, 0, -local_size)); FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0))); } #else if (local_size <= SIMM_MAX) FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size))); else { FAIL_IF(load_immediate(compiler, 0, -local_size)); FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0))); } #endif return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET; compiler->local_size = (local_size + 15) & ~0xf; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 i, tmp, offs; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); if (compiler->local_size <= SIMM_MAX) FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size))); else { FAIL_IF(load_immediate(compiler, 0, compiler->local_size)); FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0))); } #if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2) FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw)))); #else FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw)))); #endif offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1); tmp = compiler->scratches; for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs))); offs += (sljit_s32)(sizeof(sljit_sw)); } tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; for (i = tmp; i <= SLJIT_S0; i++) { FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs))); offs += (sljit_s32)(sizeof(sljit_sw)); } FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs))); SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw))); FAIL_IF(push_inst(compiler, MTLR | S(0))); FAIL_IF(push_inst(compiler, BLR)); return SLJIT_SUCCESS; } #undef STACK_STORE #undef STACK_LOAD /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ /* s/l - store/load (1 bit) i/x - immediate/indexed form u/s - signed/unsigned (1 bit) w/b/h/i - word/byte/half/int allowed (2 bit) Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */ /* 64 bit only: [reg+imm] must be aligned to 4 bytes. */ #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define INT_ALIGNED 0x10000 #endif #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) #define ARCH_32_64(a, b) a #define INST_CODE_AND_DST(inst, flags, reg) \ ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))) #else #define ARCH_32_64(a, b) b #define INST_CODE_AND_DST(inst, flags, reg) \ (((inst) & ~INT_ALIGNED) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg))) #endif static const sljit_ins data_transfer_insts[64 + 16] = { /* -------- Integer -------- */ /* Word. */ /* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */), /* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */), /* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), /* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), /* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */), /* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */), /* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), /* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), /* Byte. */ /* b u i s */ HI(38) /* stb */, /* b u i l */ HI(34) /* lbz */, /* b u x s */ HI(31) | LO(215) /* stbx */, /* b u x l */ HI(31) | LO(87) /* lbzx */, /* b s i s */ HI(38) /* stb */, /* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */, /* b s x s */ HI(31) | LO(215) /* stbx */, /* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */, /* Half. */ /* h u i s */ HI(44) /* sth */, /* h u i l */ HI(40) /* lhz */, /* h u x s */ HI(31) | LO(407) /* sthx */, /* h u x l */ HI(31) | LO(279) /* lhzx */, /* h s i s */ HI(44) /* sth */, /* h s i l */ HI(42) /* lha */, /* h s x s */ HI(31) | LO(407) /* sthx */, /* h s x l */ HI(31) | LO(343) /* lhax */, /* Int. */ /* i u i s */ HI(36) /* stw */, /* i u i l */ HI(32) /* lwz */, /* i u x s */ HI(31) | LO(151) /* stwx */, /* i u x l */ HI(31) | LO(23) /* lwzx */, /* i s i s */ HI(36) /* stw */, /* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */), /* i s x s */ HI(31) | LO(151) /* stwx */, /* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */), /* -------- Floating point -------- */ /* d i s */ HI(54) /* stfd */, /* d i l */ HI(50) /* lfd */, /* d x s */ HI(31) | LO(727) /* stfdx */, /* d x l */ HI(31) | LO(599) /* lfdx */, /* s i s */ HI(52) /* stfs */, /* s i l */ HI(48) /* lfs */, /* s x s */ HI(31) | LO(663) /* stfsx */, /* s x l */ HI(31) | LO(535) /* lfsx */, }; static const sljit_ins updated_data_transfer_insts[64] = { /* -------- Integer -------- */ /* Word. */ /* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */), /* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */), /* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), /* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), /* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */), /* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */), /* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), /* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), /* Byte. */ /* b u i s */ HI(39) /* stbu */, /* b u i l */ HI(35) /* lbzu */, /* b u x s */ HI(31) | LO(247) /* stbux */, /* b u x l */ HI(31) | LO(119) /* lbzux */, /* b s i s */ HI(39) /* stbu */, /* b s i l */ 0 /* no such instruction */, /* b s x s */ HI(31) | LO(247) /* stbux */, /* b s x l */ 0 /* no such instruction */, /* Half. */ /* h u i s */ HI(45) /* sthu */, /* h u i l */ HI(41) /* lhzu */, /* h u x s */ HI(31) | LO(439) /* sthux */, /* h u x l */ HI(31) | LO(311) /* lhzux */, /* h s i s */ HI(45) /* sthu */, /* h s i l */ HI(43) /* lhau */, /* h s x s */ HI(31) | LO(439) /* sthux */, /* h s x l */ HI(31) | LO(375) /* lhaux */, /* Int. */ /* i u i s */ HI(37) /* stwu */, /* i u i l */ HI(33) /* lwzu */, /* i u x s */ HI(31) | LO(183) /* stwux */, /* i u x l */ HI(31) | LO(55) /* lwzux */, /* i s i s */ HI(37) /* stwu */, /* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */), /* i s x s */ HI(31) | LO(183) /* stwux */, /* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */), /* -------- Floating point -------- */ /* d i s */ HI(55) /* stfdu */, /* d i l */ HI(51) /* lfdu */, /* d x s */ HI(31) | LO(759) /* stfdux */, /* d x l */ HI(31) | LO(631) /* lfdux */, /* s i s */ HI(53) /* stfsu */, /* s i l */ HI(49) /* lfsu */, /* s x s */ HI(31) | LO(695) /* stfsux */, /* s x l */ HI(31) | LO(567) /* lfsux */, }; #undef ARCH_32_64 /* Simple cases, (no caching is required). */ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg) { sljit_ins inst; sljit_s32 offs_reg; sljit_sw high_short; /* Should work when (arg & REG_MASK) == 0. */ SLJIT_ASSERT(A(0) == 0); SLJIT_ASSERT(arg & SLJIT_MEM); if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; offs_reg = OFFS_REG(arg); if (argw != 0) { #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | (argw << 11) | ((31 - argw) << 1))); #else FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1))); #endif offs_reg = tmp_reg; } inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) SLJIT_ASSERT(!(inst & INT_ALIGNED)); #endif return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg)); } inst = data_transfer_insts[inp_flags & MEM_MASK]; arg &= REG_MASK; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) { FAIL_IF(load_immediate(compiler, tmp_reg, argw)); inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); } #endif if (argw <= SIMM_MAX && argw >= SIMM_MIN) return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (argw <= 0x7fff7fffl && argw >= -0x80000000l) { #endif high_short = (sljit_s32)(argw + ((argw & 0x8000) << 1)) & ~0xffff; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) SLJIT_ASSERT(high_short && high_short <= 0x7fffffffl && high_short >= -0x80000000l); #else SLJIT_ASSERT(high_short); #endif FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM(high_short >> 16))); return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) } /* The rest is PPC-64 only. */ FAIL_IF(load_immediate(compiler, tmp_reg, argw)); inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg)); #endif } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* arg1 goes to TMP_REG1 or src reg arg2 goes to TMP_REG2, imm or src reg result goes to TMP_REG2, so put result can use TMP_REG1. */ sljit_s32 dst_r = TMP_REG2; sljit_s32 src1_r; sljit_s32 src2_r; sljit_s32 sugg_src2_r = TMP_REG2; sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS); /* Destination check. */ if (SLOW_IS_REG(dst)) { dst_r = dst; flags |= REG_DEST; if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) sugg_src2_r = dst_r; } /* Source 1. */ if (FAST_IS_REG(src1)) { src1_r = src1; flags |= REG1_SOURCE; } else if (src1 & SLJIT_IMM) { FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); src1_r = TMP_REG1; } else { FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1)); src1_r = TMP_REG1; } /* Source 2. */ if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w)); src2_r = sugg_src2_r; } else { FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2)); src2_r = sugg_src2_r; } FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) sljit_s32 int_op = op & SLJIT_I32_OP; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: case SLJIT_NOP: return push_inst(compiler, NOP); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0))); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1)); #else FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1)); #endif case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0))); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); #else FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); #endif return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); case SLJIT_DIV_UW: case SLJIT_DIV_SW: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #else return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #endif } return SLJIT_SUCCESS; } static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { if (!(src & OFFS_REG_MASK)) { if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED) return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK)); FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); /* Works with SLJIT_MEM0() case as well. */ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); } srcw &= 0x3; if (srcw == 0) return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src))); #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1))); #else FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1))); #endif return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1)); } #define EMIT_MOV(type, type_flags, type_cast) \ emit_op(compiler, (src & SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? type_cast srcw : srcw) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0; sljit_s32 op_flags = GET_ALL_FLAGS(op); CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) return emit_prefetch(compiler, src, srcw); return SLJIT_SUCCESS; } op = GET_OPCODE(op); if ((src & SLJIT_IMM) && srcw == 0) src = TMP_ZERO; if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW) FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); if (op < SLJIT_NOT && FAST_IS_REG(src) && src == dst) { if (!TYPE_CAST_NEEDED(op)) return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op_flags & SLJIT_I32_OP) { if (op < SLJIT_NOT) { if (src & SLJIT_MEM) { if (op == SLJIT_MOV_S32) op = SLJIT_MOV_U32; } else if (src & SLJIT_IMM) { if (op == SLJIT_MOV_U32) op = SLJIT_MOV_S32; } } else { /* Most operations expect sign extended arguments. */ flags |= INT_DATA | SIGNED_DATA; if (HAS_FLAGS(op_flags)) flags |= ALT_SIGN_EXT; } } #endif switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) case SLJIT_MOV_U32: case SLJIT_MOV_S32: #endif return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) case SLJIT_MOV_U32: return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32)); case SLJIT_MOV_S32: return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32)); #endif case SLJIT_MOV_U8: return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8)); case SLJIT_MOV_S8: return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8)); case SLJIT_MOV_U16: return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16)); case SLJIT_MOV_S16: return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16)); case SLJIT_NOT: return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_NEG: return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_CLZ: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); #else return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw); #endif } return SLJIT_SUCCESS; } #undef EMIT_MOV #define TEST_SL_IMM(src, srcw) \ (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN) #define TEST_UL_IMM(src, srcw) \ (((src) & SLJIT_IMM) && !((srcw) & ~0xffff)) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define TEST_SH_IMM(src, srcw) \ (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l) #else #define TEST_SH_IMM(src, srcw) \ (((src) & SLJIT_IMM) && !((srcw) & 0xffff)) #endif #define TEST_UH_IMM(src, srcw) \ (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000)) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define TEST_ADD_IMM(src, srcw) \ (((src) & SLJIT_IMM) && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l) #else #define TEST_ADD_IMM(src, srcw) \ ((src) & SLJIT_IMM) #endif #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define TEST_UI_IMM(src, srcw) \ (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff)) #else #define TEST_UI_IMM(src, srcw) \ ((src) & SLJIT_IMM) #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; if ((src1 & SLJIT_IMM) && src1w == 0) src1 = TMP_ZERO; if ((src2 & SLJIT_IMM) && src2w == 0) src2 = TMP_ZERO; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_I32_OP) { /* Most operations expect sign extended arguments. */ flags |= INT_DATA | SIGNED_DATA; if (src1 & SLJIT_IMM) src1w = (sljit_s32)(src1w); if (src2 & SLJIT_IMM) src2w = (sljit_s32)(src2w); if (HAS_FLAGS(op)) flags |= ALT_SIGN_EXT; } #endif if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); switch (GET_OPCODE(op)) { case SLJIT_ADD: if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w); if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SL_IMM(src1, src1w)) { compiler->imm = src1w & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); } if (TEST_SH_IMM(src2, src2w)) { compiler->imm = (src2w >> 16) & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SH_IMM(src1, src1w)) { compiler->imm = (src1w >> 16) & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } /* Range between -1 and -32768 is covered above. */ if (TEST_ADD_IMM(src2, src2w)) { compiler->imm = src2w & 0xffffffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_ADD_IMM(src1, src1w)) { compiler->imm = src1w & 0xffffffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0); } } if (HAS_FLAGS(op)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SL_IMM(src1, src1w)) { compiler->imm = src1w & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } } return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM4 : 0), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ADDC: return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) { if (dst == SLJIT_UNUSED) { if (TEST_UL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w); } if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) { compiler->imm = src2w; return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w); } if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW) return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w); if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { if (TEST_SL_IMM(src2, -src2w)) { compiler->imm = (-src2w) & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SL_IMM(src1, src1w)) { compiler->imm = src1w & 0xffff; return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } if (TEST_SH_IMM(src2, -src2w)) { compiler->imm = ((-src2w) >> 16) & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } /* Range between -1 and -32768 is covered above. */ if (TEST_ADD_IMM(src2, -src2w)) { compiler->imm = -src2w & 0xffffffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); } } if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) != GET_FLAG_TYPE(SLJIT_SET_CARRY)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0); } return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w); } if (TEST_SL_IMM(src2, -src2w)) { compiler->imm = (-src2w) & 0xffff; return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */ return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUBC: return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_I32_OP) flags |= ALT_FORM2; #endif if (!HAS_FLAGS(op)) { if (TEST_SL_IMM(src2, src2w)) { compiler->imm = src2w & 0xffff; return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_SL_IMM(src1, src1w)) { compiler->imm = src1w & 0xffff; return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); } } else FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO))); return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: /* Commutative unsigned operations. */ if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) { if (TEST_UL_IMM(src2, src2w)) { compiler->imm = src2w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_UL_IMM(src1, src1w)) { compiler->imm = src1w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); } if (TEST_UH_IMM(src2, src2w)) { compiler->imm = (src2w >> 16) & 0xffff; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_UH_IMM(src1, src1w)) { compiler->imm = (src1w >> 16) & 0xffff; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); } } if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) { /* Unlike or and xor, and resets unwanted bits as well. */ if (TEST_UI_IMM(src2, src2w)) { compiler->imm = src2w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); } if (TEST_UI_IMM(src1, src1w)) { compiler->imm = src1w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); } } return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (op & SLJIT_I32_OP) flags |= ALT_FORM2; #endif if (src2 & SLJIT_IMM) { compiler->imm = src2w; return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); } return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); return push_inst(compiler, *(sljit_ins*)instruction); } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6)) #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double) #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) #define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw)) #else #define FLOAT_TMP_MEM_OFFSET (2 * sizeof(sljit_sw)) #if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) #define FLOAT_TMP_MEM_OFFSET_LOW (2 * sizeof(sljit_sw)) #define FLOAT_TMP_MEM_OFFSET_HI (3 * sizeof(sljit_sw)) #else #define FLOAT_TMP_MEM_OFFSET_LOW (3 * sizeof(sljit_sw)) #define FLOAT_TMP_MEM_OFFSET_HI (2 * sizeof(sljit_sw)) #endif #endif /* SLJIT_CONFIG_PPC_64 */ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { if (src & SLJIT_MEM) { /* We can ignore the temporary data store on the stack from caching point of view. */ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); src = TMP_FREG1; } #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) op = GET_OPCODE(op); FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src))); if (op == SLJIT_CONV_SW_FROM_F64) { if (FAST_IS_REG(dst)) { FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); return emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1); } return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1); } #else FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src))); #endif if (FAST_IS_REG(dst)) { FAIL_IF(load_immediate(compiler, TMP_REG1, FLOAT_TMP_MEM_OFFSET)); FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1))); return emit_op_mem(compiler, INT_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1); } SLJIT_ASSERT(dst & SLJIT_MEM); if (dst & OFFS_REG_MASK) { dstw &= 0x3; if (dstw) { #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1))); #else FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1))); #endif dstw = TMP_REG1; } else dstw = OFFS_REG(dst); } else { if ((dst & REG_MASK) && !dstw) { dstw = dst & REG_MASK; dst = 0; } else { /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */ FAIL_IF(load_immediate(compiler, TMP_REG1, dstw)); dstw = TMP_REG1; } } return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw)); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_IMM) { if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; } else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) { if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1))); else FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } if (FAST_IS_REG(src)) { FAIL_IF(emit_op_mem(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); } else FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1)); FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1))); if (dst & SLJIT_MEM) return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); if (op & SLJIT_F32_OP) return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); return SLJIT_SUCCESS; #else sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; sljit_s32 invert_sign = 1; if (src & SLJIT_IMM) { FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000)); src = TMP_REG1; invert_sign = 0; } else if (!FAST_IS_REG(src)) { FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1)); src = TMP_REG1; } /* First, a special double floating point value is constructed: (2^53 + (input xor (2^31))) The double precision format has exactly 53 bit precision, so the lower 32 bit represents the lower 32 bit of such value. The result of xor 2^31 is the same as adding 0x80000000 to the input, which shifts it into the 0 - 0xffffffff range. To get the converted floating point value, we need to substract 2^53 + 2^31 from the constructed value. */ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330)); if (invert_sign) FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000)); FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_HI, TMP_REG1)); FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2)); FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000)); FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET_LOW, TMP_REG2)); FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG2, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, TMP_REG1)); FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2))); if (dst & SLJIT_MEM) return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1); if (op & SLJIT_F32_OP) return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)); return SLJIT_SUCCESS; #endif } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2)); src2 = TMP_FREG2; } return push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; CHECK_ERROR(); SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1)); src = dst_r; } switch (GET_OPCODE(op)) { case SLJIT_CONV_F64_FROM_F32: op ^= SLJIT_F32_OP; if (op & SLJIT_F32_OP) { FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src))); break; } /* Fall through. */ case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src))); else dst_r = src; } break; case SLJIT_NEG_F64: FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src))); break; case SLJIT_ABS_F64: FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src))); break; } if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1)); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2)); src2 = TMP_FREG2; } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2))); break; case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2))); break; case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */)); break; case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2))); break; } if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1)); return SLJIT_SUCCESS; } #undef SELECT_FOP /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) return push_inst(compiler, MFLR | D(dst)); /* Memory. */ FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2))); return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, MTLR | S(src))); else { FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); } return push_inst(compiler, BLR); } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); return label; } static sljit_ins get_bo_bi_flags(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: return (12 << 21) | (2 << 16); case SLJIT_NOT_EQUAL: return (4 << 21) | (2 << 16); case SLJIT_LESS: case SLJIT_SIG_LESS: return (12 << 21) | (0 << 16); case SLJIT_GREATER_EQUAL: case SLJIT_SIG_GREATER_EQUAL: return (4 << 21) | (0 << 16); case SLJIT_GREATER: case SLJIT_SIG_GREATER: return (12 << 21) | (1 << 16); case SLJIT_LESS_EQUAL: case SLJIT_SIG_LESS_EQUAL: return (4 << 21) | (1 << 16); case SLJIT_LESS_F64: return (12 << 21) | ((4 + 0) << 16); case SLJIT_GREATER_EQUAL_F64: return (4 << 21) | ((4 + 0) << 16); case SLJIT_GREATER_F64: return (12 << 21) | ((4 + 1) << 16); case SLJIT_LESS_EQUAL_F64: return (4 << 21) | ((4 + 1) << 16); case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: return (12 << 21) | (3 << 16); case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: return (4 << 21) | (3 << 16); case SLJIT_EQUAL_F64: return (12 << 21) | ((4 + 2) << 16); case SLJIT_NOT_EQUAL_F64: return (4 << 21) | ((4 + 2) << 16); case SLJIT_UNORDERED_F64: return (12 << 21) | ((4 + 3) << 16); case SLJIT_ORDERED_F64: return (4 << 21) | ((4 + 3) << 16); default: SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_CDECL); return (20 << 21); } } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; sljit_ins bo_bi_flags; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); bo_bi_flags = get_bo_bi_flags(type & 0xff); if (!bo_bi_flags) return NULL; jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; /* In PPC, we don't need to touch the arguments. */ if (type < SLJIT_JUMP) jump->flags |= IS_COND; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) if (type >= SLJIT_CALL) jump->flags |= IS_CALL; #endif PTR_FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_CALL_REG))); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0))); return jump; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump = NULL; sljit_s32 src_r; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) if (type >= SLJIT_CALL) { FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src))); src_r = TMP_CALL_REG; } else src_r = src; #else src_r = src; #endif } else if (src & SLJIT_IMM) { /* These jumps are converted to jump/call instructions when possible. */ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR); jump->u.target = srcw; #if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) if (type >= SLJIT_CALL) jump->flags |= IS_CALL; #endif FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0)); src_r = TMP_CALL_REG; } else { FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); src_r = TMP_CALL_REG; } FAIL_IF(push_inst(compiler, MTCTR | S(src_r))); if (jump) jump->addr = compiler->size; return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw)); src = TMP_CALL_REG; } FAIL_IF(call_with_args(compiler, arg_types, &src)); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_ijump(compiler, type, src, srcw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_s32 reg, input_flags, cr_bit, invert; sljit_s32 saved_op = op; sljit_sw saved_dstw = dstw; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA; #else input_flags = WORD_DATA; #endif op = GET_OPCODE(op); reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1)); invert = 0; cr_bit = 0; switch (type & 0xff) { case SLJIT_LESS: case SLJIT_SIG_LESS: break; case SLJIT_GREATER_EQUAL: case SLJIT_SIG_GREATER_EQUAL: invert = 1; break; case SLJIT_GREATER: case SLJIT_SIG_GREATER: cr_bit = 1; break; case SLJIT_LESS_EQUAL: case SLJIT_SIG_LESS_EQUAL: cr_bit = 1; invert = 1; break; case SLJIT_EQUAL: cr_bit = 2; break; case SLJIT_NOT_EQUAL: cr_bit = 2; invert = 1; break; case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: cr_bit = 3; break; case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: cr_bit = 3; invert = 1; break; case SLJIT_LESS_F64: cr_bit = 4 + 0; break; case SLJIT_GREATER_EQUAL_F64: cr_bit = 4 + 0; invert = 1; break; case SLJIT_GREATER_F64: cr_bit = 4 + 1; break; case SLJIT_LESS_EQUAL_F64: cr_bit = 4 + 1; invert = 1; break; case SLJIT_EQUAL_F64: cr_bit = 4 + 2; break; case SLJIT_NOT_EQUAL_F64: cr_bit = 4 + 2; invert = 1; break; case SLJIT_UNORDERED_F64: cr_bit = 4 + 3; break; case SLJIT_ORDERED_F64: cr_bit = 4 + 3; invert = 1; break; default: SLJIT_UNREACHABLE(); break; } FAIL_IF(push_inst(compiler, MFCR | D(reg))); FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1))); if (invert) FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1)); if (op < SLJIT_ADD) { if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1); } #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif if (dst & SLJIT_MEM) return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0); return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 reg, sljit_s32 mem, sljit_sw memw) { sljit_s32 mem_flags; sljit_ins inst; CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); if (type & SLJIT_MEM_POST) return SLJIT_ERR_UNSUPPORTED; switch (type & 0xff) { case SLJIT_MOV: case SLJIT_MOV_P: #if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) case SLJIT_MOV_U32: case SLJIT_MOV_S32: #endif mem_flags = WORD_DATA; break; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) case SLJIT_MOV_U32: mem_flags = INT_DATA; break; case SLJIT_MOV_S32: mem_flags = INT_DATA; if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_I32_OP)) { if (mem & OFFS_REG_MASK) mem_flags |= SIGNED_DATA; else return SLJIT_ERR_UNSUPPORTED; } break; #endif case SLJIT_MOV_U8: case SLJIT_MOV_S8: mem_flags = BYTE_DATA; break; case SLJIT_MOV_U16: mem_flags = HALF_DATA; break; case SLJIT_MOV_S16: mem_flags = HALF_DATA | SIGNED_DATA; break; default: SLJIT_UNREACHABLE(); mem_flags = WORD_DATA; break; } if (!(type & SLJIT_MEM_STORE)) mem_flags |= LOAD_DATA; if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { if (memw != 0) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; inst = updated_data_transfer_insts[mem_flags | INDEXED]; FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem)))); } else { if (memw > SIMM_MAX || memw < SIMM_MIN) return SLJIT_ERR_UNSUPPORTED; inst = updated_data_transfer_insts[mem_flags]; #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) if ((inst & INT_ALIGNED) && (memw & 0x3) != 0) return SLJIT_ERR_UNSUPPORTED; #endif if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw))); } if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8) return push_inst(compiler, EXTSB | S(reg) | A(reg)); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 freg, sljit_s32 mem, sljit_sw memw) { sljit_s32 mem_flags; sljit_ins inst; CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); if (type & SLJIT_MEM_POST) return SLJIT_ERR_UNSUPPORTED; if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { if (memw != 0) return SLJIT_ERR_UNSUPPORTED; } else { if (memw > SIMM_MAX || memw < SIMM_MIN) return SLJIT_ERR_UNSUPPORTED; } if (type & SLJIT_MEM_SUPP) return SLJIT_SUCCESS; mem_flags = FLOAT_DATA(type); if (!(type & SLJIT_MEM_STORE)) mem_flags |= LOAD_DATA; if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) { inst = updated_data_transfer_insts[mem_flags | INDEXED]; return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem))); } inst = updated_data_transfer_insts[mem_flags]; return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw)); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; sljit_s32 reg; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const(compiler, reg, init_value)); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); return const_; } ================================================ FILE: src/pcre/sljit/sljitNativeSPARC_32.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw imm) { if (imm <= SIMM_MAX && imm >= SIMM_MIN) return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst)); FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst))); return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS; } #define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2)) static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same); switch (op) { case SLJIT_MOV: case SLJIT_MOV_U32: case SLJIT_MOV_S32: case SLJIT_MOV_P: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (dst != src2) return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst)); return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_U8) return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst)); FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst))); return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst)); } else if (dst != src2) SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst))); return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst)); } else if (dst != src2) SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS)); FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst))); /* Loop. */ FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS)); FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS)); return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS); case SLJIT_ADD: return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_ADDC: return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_SUB: return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_SUBC: return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_MUL: FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); if (!(flags & SET_FLAGS)) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK))); return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS); case SLJIT_AND: return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_OR: return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_XOR: return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); case SLJIT_SHL: FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); case SLJIT_LSHR: FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); case SLJIT_ASHR: FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src) { sljit_s32 reg_index = 8; sljit_s32 word_reg_index = 8; sljit_s32 float_arg_index = 1; sljit_s32 double_arg_count = 0; sljit_s32 float_offset = (16 + 6) * sizeof(sljit_sw); sljit_s32 types = 0; sljit_s32 reg = 0; sljit_s32 move_to_tmp2 = 0; if (src) reg = reg_map[*src & REG_MASK]; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: float_arg_index++; if (reg_index == reg) move_to_tmp2 = 1; reg_index++; break; case SLJIT_ARG_TYPE_F64: float_arg_index++; double_arg_count++; if (reg_index == reg || reg_index + 1 == reg) move_to_tmp2 = 1; reg_index += 2; break; default: if (reg_index != word_reg_index && reg_index < 14 && reg_index == reg) move_to_tmp2 = 1; reg_index++; word_reg_index++; break; } if (move_to_tmp2) { move_to_tmp2 = 0; if (reg < 14) FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1))); *src = TMP_REG1; } arg_types >>= SLJIT_DEF_SHIFT; } arg_types = types; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: float_arg_index--; FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS)); float_offset -= sizeof(sljit_f64); break; case SLJIT_ARG_TYPE_F64: float_arg_index--; if (float_arg_index == 4 && double_arg_count == 4) { FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS)); FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS)); } else FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS)); float_offset -= sizeof(sljit_f64); break; default: break; } arg_types >>= SLJIT_DEF_SHIFT; } float_offset = (16 + 6) * sizeof(sljit_sw); while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: reg_index--; if (reg_index < 14) FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index)); float_offset -= sizeof(sljit_f64); break; case SLJIT_ARG_TYPE_F64: reg_index -= 2; if (reg_index < 14) { if ((reg_index & 0x1) != 0) { FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index)); if (reg_index < 13) FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1)); } else FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index)); } float_offset -= sizeof(sljit_f64); break; default: reg_index--; word_reg_index--; if (reg_index != word_reg_index) { if (reg_index < 14) FAIL_IF(push_inst(compiler, OR | DA(reg_index) | S1(0) | S2A(word_reg_index), reg_index)); else FAIL_IF(push_inst(compiler, STW | DA(word_reg_index) | S1(SLJIT_SP) | IMM(92), word_reg_index)); } break; } types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) { FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst))); return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst)); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff); inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff); inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } ================================================ FILE: src/pcre/sljit/sljitNativeSPARC_common.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { return "SPARC" SLJIT_CPUINFO; } /* Length of an instruction word Both for sparc-32 and sparc-64 */ typedef sljit_u32 sljit_ins; #if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) static void sparc_cache_flush(sljit_ins *from, sljit_ins *to) { #if defined(__SUNPRO_C) && __SUNPRO_C < 0x590 __asm ( /* if (from == to) return */ "cmp %i0, %i1\n" "be .leave\n" "nop\n" /* loop until from >= to */ ".mainloop:\n" "flush %i0\n" "add %i0, 8, %i0\n" "cmp %i0, %i1\n" "bcs .mainloop\n" "nop\n" /* The comparison was done above. */ "bne .leave\n" /* nop is not necessary here, since the sub operation has no side effect. */ "sub %i0, 4, %i0\n" "flush %i0\n" ".leave:" ); #else if (SLJIT_UNLIKELY(from == to)) return; do { __asm__ volatile ( "flush %0\n" : : "r"(from) ); /* Operates at least on doubleword. */ from += 2; } while (from < to); if (from == to) { /* Flush the last word. */ from --; __asm__ volatile ( "flush %0\n" : : "r"(from) ); } #endif } #endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */ /* TMP_REG2 is not used by getput_arg */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) /* This register is modified by calls, which affects the instruction in the delay slot if it is used as a source register. */ #define TMP_LINK (SLJIT_NUMBER_OF_REGISTERS + 5) #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1) #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { 0, 8, 9, 10, 11, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 12, 13, 15 }; static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = { 0, 0, 2, 4, 6, 8, 10, 12, 14 }; /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ #define D(d) (reg_map[d] << 25) #define FD(d) (freg_map[d] << 25) #define FDN(d) ((freg_map[d] | 0x1) << 25) #define DA(d) ((d) << 25) #define S1(s1) (reg_map[s1] << 14) #define FS1(s1) (freg_map[s1] << 14) #define S1A(s1) ((s1) << 14) #define S2(s2) (reg_map[s2]) #define FS2(s2) (freg_map[s2]) #define FS2N(s2) (freg_map[s2] | 0x1) #define S2A(s2) (s2) #define IMM_ARG 0x2000 #define DOP(op) ((op) << 5) #define IMM(imm) (((imm) & 0x1fff) | IMM_ARG) #define DR(dr) (reg_map[dr]) #define OPC1(opcode) ((opcode) << 30) #define OPC2(opcode) ((opcode) << 22) #define OPC3(opcode) ((opcode) << 19) #define SET_FLAGS OPC3(0x10) #define ADD (OPC1(0x2) | OPC3(0x00)) #define ADDC (OPC1(0x2) | OPC3(0x08)) #define AND (OPC1(0x2) | OPC3(0x01)) #define ANDN (OPC1(0x2) | OPC3(0x05)) #define CALL (OPC1(0x1)) #define FABSS (OPC1(0x2) | OPC3(0x34) | DOP(0x09)) #define FADDD (OPC1(0x2) | OPC3(0x34) | DOP(0x42)) #define FADDS (OPC1(0x2) | OPC3(0x34) | DOP(0x41)) #define FCMPD (OPC1(0x2) | OPC3(0x35) | DOP(0x52)) #define FCMPS (OPC1(0x2) | OPC3(0x35) | DOP(0x51)) #define FDIVD (OPC1(0x2) | OPC3(0x34) | DOP(0x4e)) #define FDIVS (OPC1(0x2) | OPC3(0x34) | DOP(0x4d)) #define FDTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd2)) #define FDTOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc6)) #define FITOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc8)) #define FITOS (OPC1(0x2) | OPC3(0x34) | DOP(0xc4)) #define FMOVS (OPC1(0x2) | OPC3(0x34) | DOP(0x01)) #define FMULD (OPC1(0x2) | OPC3(0x34) | DOP(0x4a)) #define FMULS (OPC1(0x2) | OPC3(0x34) | DOP(0x49)) #define FNEGS (OPC1(0x2) | OPC3(0x34) | DOP(0x05)) #define FSTOD (OPC1(0x2) | OPC3(0x34) | DOP(0xc9)) #define FSTOI (OPC1(0x2) | OPC3(0x34) | DOP(0xd1)) #define FSUBD (OPC1(0x2) | OPC3(0x34) | DOP(0x46)) #define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45)) #define JMPL (OPC1(0x2) | OPC3(0x38)) #define LDD (OPC1(0x3) | OPC3(0x03)) #define LDUW (OPC1(0x3) | OPC3(0x00)) #define NOP (OPC1(0x0) | OPC2(0x04)) #define OR (OPC1(0x2) | OPC3(0x02)) #define ORN (OPC1(0x2) | OPC3(0x06)) #define RDY (OPC1(0x2) | OPC3(0x28) | S1A(0)) #define RESTORE (OPC1(0x2) | OPC3(0x3d)) #define SAVE (OPC1(0x2) | OPC3(0x3c)) #define SETHI (OPC1(0x0) | OPC2(0x04)) #define SLL (OPC1(0x2) | OPC3(0x25)) #define SLLX (OPC1(0x2) | OPC3(0x25) | (1 << 12)) #define SRA (OPC1(0x2) | OPC3(0x27)) #define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12)) #define SRL (OPC1(0x2) | OPC3(0x26)) #define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12)) #define STDF (OPC1(0x3) | OPC3(0x27)) #define STF (OPC1(0x3) | OPC3(0x24)) #define STW (OPC1(0x3) | OPC3(0x04)) #define SUB (OPC1(0x2) | OPC3(0x04)) #define SUBC (OPC1(0x2) | OPC3(0x0c)) #define TA (OPC1(0x2) | OPC3(0x3a) | (8 << 25)) #define WRY (OPC1(0x2) | OPC3(0x30) | DA(0)) #define XOR (OPC1(0x2) | OPC3(0x03)) #define XNOR (OPC1(0x2) | OPC3(0x07)) #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) #define MAX_DISP (0x1fffff) #define MIN_DISP (-0x200000) #define DISP_MASK (0x3fffff) #define BICC (OPC1(0x0) | OPC2(0x2)) #define FBFCC (OPC1(0x0) | OPC2(0x6)) #define SLL_W SLL #define SDIV (OPC1(0x2) | OPC3(0x0f)) #define SMUL (OPC1(0x2) | OPC3(0x0b)) #define UDIV (OPC1(0x2) | OPC3(0x0e)) #define UMUL (OPC1(0x2) | OPC3(0x0a)) #else #define SLL_W SLLX #endif #define SIMM_MAX (0x0fff) #define SIMM_MIN (-0x1000) /* dest_reg is the absolute name of the register Useful for reordering instructions in the delay slot. */ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot) { sljit_ins *ptr; SLJIT_ASSERT((delay_slot & DST_INS_MASK) == UNMOVABLE_INS || (delay_slot & DST_INS_MASK) == MOVABLE_INS || (delay_slot & DST_INS_MASK) == ((ins >> 25) & 0x1f)); ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; compiler->delay_slot = delay_slot; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; sljit_ins saved_inst; if (jump->flags & SLJIT_REWRITABLE_JUMP) return code_ptr; if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset; } inst = (sljit_ins*)jump->addr; #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) if (jump->flags & IS_CALL) { /* Call is always patchable on sparc 32. */ jump->flags |= PATCH_CALL; if (jump->flags & IS_MOVABLE) { inst[0] = inst[-1]; inst[-1] = CALL; jump->addr -= sizeof(sljit_ins); return inst; } inst[0] = CALL; inst[1] = NOP; return inst + 1; } #else /* Both calls and BPr instructions shall not pass this point. */ #error "Implementation required" #endif if (jump->flags & IS_COND) inst--; diff = ((sljit_sw)target_addr - (sljit_sw)(inst - 1) - executable_offset) >> 2; if (jump->flags & IS_MOVABLE) { if (diff <= MAX_DISP && diff >= MIN_DISP) { jump->flags |= PATCH_B; inst--; if (jump->flags & IS_COND) { saved_inst = inst[0]; inst[0] = inst[1] ^ (1 << 28); inst[1] = saved_inst; } else { inst[1] = inst[0]; inst[0] = BICC | DA(0x8); } jump->addr = (sljit_uw)inst; return inst + 1; } } diff += sizeof(sljit_ins); if (diff <= MAX_DISP && diff >= MIN_DISP) { jump->flags |= PATCH_B; if (jump->flags & IS_COND) inst[0] ^= (1 << 28); else inst[0] = BICC | DA(0x8); inst[1] = NOP; jump->addr = (sljit_uw)inst; return inst + 1; } return code_ptr; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_ins *code; sljit_ins *code_ptr; sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; sljit_sw executable_offset; sljit_uw addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; word_count = 0; executable_offset = SLJIT_EXEC_OFFSET(code); label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; do { buf_ptr = (sljit_ins*)buf->memory; buf_end = buf_ptr + (buf->used_size >> 2); do { *code_ptr = *buf_ptr++; SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); /* These structures are ordered by their address. */ if (label && label->size == word_count) { /* Just recording the address. */ label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } if (jump && jump->addr == word_count) { #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) jump->addr = (sljit_uw)(code_ptr - 3); #else jump->addr = (sljit_uw)(code_ptr - 6); #endif code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset); jump = jump->next; } if (const_ && const_->addr == word_count) { /* Just recording the address. */ const_->addr = (sljit_uw)code_ptr; const_ = const_->next; } code_ptr ++; word_count ++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); if (label && label->size == word_count) { label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; } SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size); jump = compiler->jumps; while (jump) { do { addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; buf_ptr = (sljit_ins *)jump->addr; if (jump->flags & PATCH_CALL) { addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000); buf_ptr[0] = CALL | (addr & 0x3fffffff); break; } if (jump->flags & PATCH_B) { addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2; SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP); buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK); break; } /* Set the fields of immediate loads. */ #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) buf_ptr[0] = (buf_ptr[0] & 0xffc00000) | ((addr >> 10) & 0x3fffff); buf_ptr[1] = (buf_ptr[1] & 0xfffffc00) | (addr & 0x3ff); #else #error "Implementation required" #endif } while (0); jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #else /* Available by default. */ return 1; #endif #if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64) case SLJIT_HAS_CMOV: return 1; #endif default: return 0; } } /* --------------------------------------------------------------------- */ /* Entry, exit */ /* --------------------------------------------------------------------- */ /* Creates an index in data_transfer_insts array. */ #define LOAD_DATA 0x01 #define WORD_DATA 0x00 #define BYTE_DATA 0x02 #define HALF_DATA 0x04 #define INT_DATA 0x06 #define SIGNED_DATA 0x08 /* Separates integer and floating point registers */ #define GPR_REG 0x0f #define DOUBLE_DATA 0x10 #define SINGLE_DATA 0x12 #define MEM_MASK 0x1f #define ARG_TEST 0x00020 #define ALT_KEEP_CACHE 0x00040 #define CUMULATIVE_OP 0x00080 #define IMM_OP 0x00100 #define SRC2_IMM 0x00200 #define REG_DEST 0x00400 #define REG2_SOURCE 0x00800 #define SLOW_SRC1 0x01000 #define SLOW_SRC2 0x02000 #define SLOW_DEST 0x04000 /* SET_FLAGS (0x10 << 19) also belong here! */ #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) #include "sljitNativeSPARC_32.c" #else #include "sljitNativeSPARC_64.c" #endif SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7; compiler->local_size = local_size; if (local_size <= SIMM_MAX) { FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | IMM(-local_size), UNMOVABLE_INS)); } else { FAIL_IF(load_immediate(compiler, TMP_REG1, -local_size)); FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | S2(TMP_REG1), UNMOVABLE_INS)); } /* Arguments are in their appropriate registers. */ return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); if (op != SLJIT_MOV || !FAST_IS_REG(src)) { FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); src = SLJIT_R0; } FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS)); return push_inst(compiler, RESTORE | D(SLJIT_R0) | S1(src) | S2(0), UNMOVABLE_INS); } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) #define ARCH_32_64(a, b) a #else #define ARCH_32_64(a, b) b #endif static const sljit_ins data_transfer_insts[16 + 4] = { /* u w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */), /* u w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */), /* u b s */ OPC1(3) | OPC3(0x05) /* stb */, /* u b l */ OPC1(3) | OPC3(0x01) /* ldub */, /* u h s */ OPC1(3) | OPC3(0x06) /* sth */, /* u h l */ OPC1(3) | OPC3(0x02) /* lduh */, /* u i s */ OPC1(3) | OPC3(0x04) /* stw */, /* u i l */ OPC1(3) | OPC3(0x00) /* lduw */, /* s w s */ ARCH_32_64(OPC1(3) | OPC3(0x04) /* stw */, OPC1(3) | OPC3(0x0e) /* stx */), /* s w l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x0b) /* ldx */), /* s b s */ OPC1(3) | OPC3(0x05) /* stb */, /* s b l */ OPC1(3) | OPC3(0x09) /* ldsb */, /* s h s */ OPC1(3) | OPC3(0x06) /* sth */, /* s h l */ OPC1(3) | OPC3(0x0a) /* ldsh */, /* s i s */ OPC1(3) | OPC3(0x04) /* stw */, /* s i l */ ARCH_32_64(OPC1(3) | OPC3(0x00) /* lduw */, OPC1(3) | OPC3(0x08) /* ldsw */), /* d s */ OPC1(3) | OPC3(0x27), /* d l */ OPC1(3) | OPC3(0x23), /* s s */ OPC1(3) | OPC3(0x24), /* s l */ OPC1(3) | OPC3(0x20), }; #undef ARCH_32_64 /* Can perform an operation using at most 1 instruction. */ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { SLJIT_ASSERT(arg & SLJIT_MEM); if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) || ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) { /* Works for both absoulte and relative addresses (immediate case). */ if (SLJIT_UNLIKELY(flags & ARG_TEST)) return 1; FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)) | S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS)); return -1; } return 0; } /* See getput_arg below. Note: can_cache is called only for binary operators. Those operators always uses word arguments without write back. */ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); /* Simple operation except for updates. */ if (arg & OFFS_REG_MASK) { argw &= 0x3; SLJIT_ASSERT(argw); next_argw &= 0x3; if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == next_argw) return 1; return 0; } if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)) return 1; return 0; } /* Emit the necessary instructions. See can_cache above. */ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { sljit_s32 base, arg2, delay_slot; sljit_ins dest; SLJIT_ASSERT(arg & SLJIT_MEM); if (!(next_arg & SLJIT_MEM)) { next_arg = 0; next_argw = 0; } base = arg & REG_MASK; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; /* Using the cache. */ if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw)) arg2 = TMP_REG3; else { if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) { compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK); compiler->cache_argw = argw; arg2 = TMP_REG3; } else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && reg != OFFS_REG(arg)) arg2 = reg; else /* It must be a mov operation, so tmp1 must be free to use. */ arg2 = TMP_REG1; FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | argw, DR(arg2))); } } else { /* Using the cache. */ if ((compiler->cache_arg == SLJIT_MEM) && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) { if (argw != compiler->cache_argw) { FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | S1(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); compiler->cache_argw = argw; } arg2 = TMP_REG3; } else { if ((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN) { compiler->cache_arg = SLJIT_MEM; compiler->cache_argw = argw; arg2 = TMP_REG3; } else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base) arg2 = reg; else /* It must be a mov operation, so tmp1 must be free to use. */ arg2 = TMP_REG1; FAIL_IF(load_immediate(compiler, arg2, argw)); } } dest = ((flags & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)); delay_slot = ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS; if (!base) return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(arg2) | IMM(0), delay_slot); return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot); } static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw) { if (getput_arg_fast(compiler, flags, reg, arg, argw)) return compiler->error; compiler->cache_arg = 0; compiler->cache_argw = 0; return getput_arg(compiler, flags, reg, arg, argw, 0, 0); } static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) { if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) return compiler->error; return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* arg1 goes to TMP_REG1 or src reg arg2 goes to TMP_REG2, imm or src reg TMP_REG3 can be used for caching result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ sljit_s32 dst_r = TMP_REG2; sljit_s32 src1_r; sljit_sw src2_r = 0; sljit_s32 sugg_src2_r = TMP_REG2; if (!(flags & ALT_KEEP_CACHE)) { compiler->cache_arg = 0; compiler->cache_argw = 0; } if (dst != SLJIT_UNUSED) { if (FAST_IS_REG(dst)) { dst_r = dst; flags |= REG_DEST; if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) sugg_src2_r = dst_r; } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw)) flags |= SLOW_DEST; } if (flags & IMM_OP) { if ((src2 & SLJIT_IMM) && src2w) { if (src2w <= SIMM_MAX && src2w >= SIMM_MIN) { flags |= SRC2_IMM; src2_r = src2w; } } if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) { if (src1w <= SIMM_MAX && src1w >= SIMM_MIN) { flags |= SRC2_IMM; src2_r = src1w; /* And swap arguments. */ src1 = src2; src1w = src2w; src2 = SLJIT_IMM; /* src2w = src2_r unneeded. */ } } } /* Source 1. */ if (FAST_IS_REG(src1)) src1_r = src1; else if (src1 & SLJIT_IMM) { if (src1w) { FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); src1_r = TMP_REG1; } else src1_r = 0; } else { if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w)) FAIL_IF(compiler->error); else flags |= SLOW_SRC1; src1_r = TMP_REG1; } /* Source 2. */ if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { if (!(flags & SRC2_IMM)) { if (src2w) { FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w)); src2_r = sugg_src2_r; } else { src2_r = 0; if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM)) dst_r = 0; } } } else { if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w)) FAIL_IF(compiler->error); else flags |= SLOW_SRC2; src2_r = sugg_src2_r; } if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { SLJIT_ASSERT(src2_r == TMP_REG2); if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w)); FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); } else { FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); } } else if (flags & SLOW_SRC1) FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); else if (flags & SLOW_SRC2) FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); if (dst & SLJIT_MEM) { if (!(flags & SLOW_DEST)) { getput_arg_fast(compiler, flags, dst_r, dst, dstw); return compiler->error; } return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_BREAKPOINT: return push_inst(compiler, TA, UNMOVABLE_INS); case SLJIT_NOP: return push_inst(compiler, NOP, UNMOVABLE_INS); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? UMUL : SMUL) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); return push_inst(compiler, RDY | D(SLJIT_R1), DR(SLJIT_R1)); #else #error "Implementation required" #endif case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) if ((op | 0x2) == SLJIT_DIV_UW) FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS)); else { FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS)); } if (op <= SLJIT_DIVMOD_SW) FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); if (op >= SLJIT_DIV_UW) return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1))); return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)); #else #error "Implementation required" #endif } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; op = GET_OPCODE(op); switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U32: return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_S32: return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U8: return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw); case SLJIT_MOV_S8: return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw); case SLJIT_MOV_U16: return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw); case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw); case SLJIT_NOT: case SLJIT_CLZ: return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_NEG: return emit_op(compiler, SLJIT_SUB, flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; op = GET_OPCODE(op); switch (op) { case SLJIT_ADD: case SLJIT_ADDC: case SLJIT_MUL: case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: case SLJIT_SUBC: return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) if (src2 & SLJIT_IMM) src2w &= 0x1f; #else SLJIT_UNREACHABLE(); #endif return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); return freg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS); } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7)) #define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double) #define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw)) static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); src = TMP_FREG1; } FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOI, FDTOI) | FD(TMP_FREG1) | FS2(src), MOVABLE_INS)); if (FAST_IS_REG(dst)) { FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); return emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, dst, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET); } /* Store the integer value from a VFP register. */ return emit_op_mem2(compiler, SINGLE_DATA, TMP_FREG1, dst, dstw, 0, 0); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; #endif FAIL_IF(load_immediate(compiler, TMP_REG1, srcw)); src = TMP_REG1; srcw = 0; } if (FAST_IS_REG(src)) { FAIL_IF(emit_op_mem2(compiler, WORD_DATA, src, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET, SLJIT_MEM1(SLJIT_SP), FLOAT_TMP_MEM_OFFSET)); src = SLJIT_MEM1(SLJIT_SP); srcw = FLOAT_TMP_MEM_OFFSET; } FAIL_IF(emit_op_mem2(compiler, SINGLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw)); FAIL_IF(push_inst(compiler, SELECT_FOP(op, FITOS, FITOD) | FD(dst_r) | FS2(TMP_FREG1), MOVABLE_INS)); if (dst & SLJIT_MEM) return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { if (src1 & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); src1 = TMP_FREG1; } if (src2 & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0)); src2 = TMP_FREG2; } return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | FS1(src1) | FS2(src2), FCC_IS_SET | MOVABLE_INS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; CHECK_ERROR(); compiler->cache_arg = 0; compiler->cache_argw = 0; SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) op ^= SLJIT_F32_OP; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1; if (src & SLJIT_MEM) { FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw)); src = dst_r; } switch (GET_OPCODE(op)) { case SLJIT_MOV_F64: if (src != dst_r) { if (dst_r != TMP_FREG1) { FAIL_IF(push_inst(compiler, FMOVS | FD(dst_r) | FS2(src), MOVABLE_INS)); if (!(op & SLJIT_F32_OP)) FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS)); } else dst_r = src; } break; case SLJIT_NEG_F64: FAIL_IF(push_inst(compiler, FNEGS | FD(dst_r) | FS2(src), MOVABLE_INS)); if (dst_r != src && !(op & SLJIT_F32_OP)) FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS)); break; case SLJIT_ABS_F64: FAIL_IF(push_inst(compiler, FABSS | FD(dst_r) | FS2(src), MOVABLE_INS)); if (dst_r != src && !(op & SLJIT_F32_OP)) FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS)); break; case SLJIT_CONV_F64_FROM_F32: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | FD(dst_r) | FS2(src), MOVABLE_INS)); op ^= SLJIT_F32_OP; break; } if (dst & SLJIT_MEM) FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0)); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r, flags = 0; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); compiler->cache_arg = 0; compiler->cache_argw = 0; dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2; if (src1 & SLJIT_MEM) { if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) { FAIL_IF(compiler->error); src1 = TMP_FREG1; } else flags |= SLOW_SRC1; } if (src2 & SLJIT_MEM) { if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) { FAIL_IF(compiler->error); src2 = TMP_FREG2; } else flags |= SLOW_SRC2; } if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w)); FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); } else { FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w)); FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); } } else if (flags & SLOW_SRC1) FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw)); else if (flags & SLOW_SRC2) FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw)); if (flags & SLOW_SRC1) src1 = TMP_FREG1; if (flags & SLOW_SRC2) src2 = TMP_FREG2; switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADDD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; case SLJIT_SUB_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUBD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; case SLJIT_MUL_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMULD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; case SLJIT_DIV_F64: FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIVD) | FD(dst_r) | FS1(src1) | FS2(src2), MOVABLE_INS)); break; } if (dst_r == TMP_FREG2) FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0)); return SLJIT_SUCCESS; } #undef FLOAT_DATA #undef SELECT_FOP /* --------------------------------------------------------------------- */ /* Other instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst)); /* Memory. */ return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK))); else FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw)); FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS)); return push_inst(compiler, NOP, UNMOVABLE_INS); } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); compiler->delay_slot = UNMOVABLE_INS; return label; } static sljit_ins get_cc(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: case SLJIT_MUL_NOT_OVERFLOW: case SLJIT_NOT_EQUAL_F64: /* Unordered. */ return DA(0x1); case SLJIT_NOT_EQUAL: case SLJIT_MUL_OVERFLOW: case SLJIT_EQUAL_F64: return DA(0x9); case SLJIT_LESS: case SLJIT_GREATER_F64: /* Unordered. */ return DA(0x5); case SLJIT_GREATER_EQUAL: case SLJIT_LESS_EQUAL_F64: return DA(0xd); case SLJIT_GREATER: case SLJIT_GREATER_EQUAL_F64: /* Unordered. */ return DA(0xc); case SLJIT_LESS_EQUAL: case SLJIT_LESS_F64: return DA(0x4); case SLJIT_SIG_LESS: return DA(0x3); case SLJIT_SIG_GREATER_EQUAL: return DA(0xb); case SLJIT_SIG_GREATER: return DA(0xa); case SLJIT_SIG_LESS_EQUAL: return DA(0x2); case SLJIT_OVERFLOW: case SLJIT_UNORDERED_F64: return DA(0x7); case SLJIT_NOT_OVERFLOW: case SLJIT_ORDERED_F64: return DA(0xf); default: SLJIT_UNREACHABLE(); return DA(0x8); } } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; if (type < SLJIT_EQUAL_F64) { jump->flags |= IS_COND; if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & ICC_IS_SET)) jump->flags |= IS_MOVABLE; #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) PTR_FAIL_IF(push_inst(compiler, BICC | get_cc(type ^ 1) | 5, UNMOVABLE_INS)); #else #error "Implementation required" #endif } else if (type < SLJIT_JUMP) { jump->flags |= IS_COND; if (((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) && !(compiler->delay_slot & FCC_IS_SET)) jump->flags |= IS_MOVABLE; #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) PTR_FAIL_IF(push_inst(compiler, FBFCC | get_cc(type ^ 1) | 5, UNMOVABLE_INS)); #else #error "Implementation required" #endif } else { if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) jump->flags |= IS_MOVABLE; if (type >= SLJIT_FAST_CALL) jump->flags |= IS_CALL; } PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0)); PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG1) | IMM(0), UNMOVABLE_INS)); jump->addr = compiler->size; PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); return jump; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { struct sljit_jump *jump = NULL; sljit_s32 src_r; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) src_r = src; else if (src & SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR); jump->u.target = srcw; if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS) jump->flags |= IS_MOVABLE; if (type >= SLJIT_FAST_CALL) jump->flags |= IS_CALL; FAIL_IF(emit_const(compiler, TMP_REG1, 0)); src_r = TMP_REG1; } else { FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); src_r = TMP_REG1; } FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS)); if (jump) jump->addr = compiler->size; return push_inst(compiler, NOP, UNMOVABLE_INS); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw)); src = TMP_REG1; } FAIL_IF(call_with_args(compiler, arg_types, &src)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_ijump(compiler, type, src, srcw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) op = GET_OPCODE(op); reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2; compiler->cache_arg = 0; compiler->cache_argw = 0; if (op >= SLJIT_ADD && (dst & SLJIT_MEM)) FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw)); type &= 0xff; if (type < SLJIT_EQUAL_F64) FAIL_IF(push_inst(compiler, BICC | get_cc(type) | 3, UNMOVABLE_INS)); else FAIL_IF(push_inst(compiler, FBFCC | get_cc(type) | 3, UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(1), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, OR | D(reg) | S1(0) | IMM(0), UNMOVABLE_INS)); if (op >= SLJIT_ADD) { flags |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE; if (dst & SLJIT_MEM) return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); return emit_op(compiler, op, flags, dst, 0, dst, 0, TMP_REG2, 0); } if (!(dst & SLJIT_MEM)) return SLJIT_SUCCESS; return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw); #else #error "Implementation required" #endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);; #else #error "Implementation required" #endif } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { sljit_s32 reg; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const(compiler, reg, init_value)); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw)); return const_; } ================================================ FILE: src/pcre/sljit/sljitNativeTILEGX-encoder.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved. * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* This code is owned by Tilera Corporation, and distributed as part of multiple projects. In sljit, the code is under BSD licence. */ #include #include #include #define BFD_RELOC(x) R_##x /* Special registers. */ #define TREG_LR 55 #define TREG_SN 56 #define TREG_ZERO 63 /* Canonical name of each register. */ const char *const tilegx_register_names[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", "r48", "r49", "r50", "r51", "r52", "tp", "sp", "lr", "sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero" }; enum { R_NONE = 0, R_TILEGX_NONE = 0, R_TILEGX_64 = 1, R_TILEGX_32 = 2, R_TILEGX_16 = 3, R_TILEGX_8 = 4, R_TILEGX_64_PCREL = 5, R_TILEGX_32_PCREL = 6, R_TILEGX_16_PCREL = 7, R_TILEGX_8_PCREL = 8, R_TILEGX_HW0 = 9, R_TILEGX_HW1 = 10, R_TILEGX_HW2 = 11, R_TILEGX_HW3 = 12, R_TILEGX_HW0_LAST = 13, R_TILEGX_HW1_LAST = 14, R_TILEGX_HW2_LAST = 15, R_TILEGX_COPY = 16, R_TILEGX_GLOB_DAT = 17, R_TILEGX_JMP_SLOT = 18, R_TILEGX_RELATIVE = 19, R_TILEGX_BROFF_X1 = 20, R_TILEGX_JUMPOFF_X1 = 21, R_TILEGX_JUMPOFF_X1_PLT = 22, R_TILEGX_IMM8_X0 = 23, R_TILEGX_IMM8_Y0 = 24, R_TILEGX_IMM8_X1 = 25, R_TILEGX_IMM8_Y1 = 26, R_TILEGX_DEST_IMM8_X1 = 27, R_TILEGX_MT_IMM14_X1 = 28, R_TILEGX_MF_IMM14_X1 = 29, R_TILEGX_MMSTART_X0 = 30, R_TILEGX_MMEND_X0 = 31, R_TILEGX_SHAMT_X0 = 32, R_TILEGX_SHAMT_X1 = 33, R_TILEGX_SHAMT_Y0 = 34, R_TILEGX_SHAMT_Y1 = 35, R_TILEGX_IMM16_X0_HW0 = 36, R_TILEGX_IMM16_X1_HW0 = 37, R_TILEGX_IMM16_X0_HW1 = 38, R_TILEGX_IMM16_X1_HW1 = 39, R_TILEGX_IMM16_X0_HW2 = 40, R_TILEGX_IMM16_X1_HW2 = 41, R_TILEGX_IMM16_X0_HW3 = 42, R_TILEGX_IMM16_X1_HW3 = 43, R_TILEGX_IMM16_X0_HW0_LAST = 44, R_TILEGX_IMM16_X1_HW0_LAST = 45, R_TILEGX_IMM16_X0_HW1_LAST = 46, R_TILEGX_IMM16_X1_HW1_LAST = 47, R_TILEGX_IMM16_X0_HW2_LAST = 48, R_TILEGX_IMM16_X1_HW2_LAST = 49, R_TILEGX_IMM16_X0_HW0_PCREL = 50, R_TILEGX_IMM16_X1_HW0_PCREL = 51, R_TILEGX_IMM16_X0_HW1_PCREL = 52, R_TILEGX_IMM16_X1_HW1_PCREL = 53, R_TILEGX_IMM16_X0_HW2_PCREL = 54, R_TILEGX_IMM16_X1_HW2_PCREL = 55, R_TILEGX_IMM16_X0_HW3_PCREL = 56, R_TILEGX_IMM16_X1_HW3_PCREL = 57, R_TILEGX_IMM16_X0_HW0_LAST_PCREL = 58, R_TILEGX_IMM16_X1_HW0_LAST_PCREL = 59, R_TILEGX_IMM16_X0_HW1_LAST_PCREL = 60, R_TILEGX_IMM16_X1_HW1_LAST_PCREL = 61, R_TILEGX_IMM16_X0_HW2_LAST_PCREL = 62, R_TILEGX_IMM16_X1_HW2_LAST_PCREL = 63, R_TILEGX_IMM16_X0_HW0_GOT = 64, R_TILEGX_IMM16_X1_HW0_GOT = 65, R_TILEGX_IMM16_X0_HW0_PLT_PCREL = 66, R_TILEGX_IMM16_X1_HW0_PLT_PCREL = 67, R_TILEGX_IMM16_X0_HW1_PLT_PCREL = 68, R_TILEGX_IMM16_X1_HW1_PLT_PCREL = 69, R_TILEGX_IMM16_X0_HW2_PLT_PCREL = 70, R_TILEGX_IMM16_X1_HW2_PLT_PCREL = 71, R_TILEGX_IMM16_X0_HW0_LAST_GOT = 72, R_TILEGX_IMM16_X1_HW0_LAST_GOT = 73, R_TILEGX_IMM16_X0_HW1_LAST_GOT = 74, R_TILEGX_IMM16_X1_HW1_LAST_GOT = 75, R_TILEGX_IMM16_X0_HW0_TLS_GD = 78, R_TILEGX_IMM16_X1_HW0_TLS_GD = 79, R_TILEGX_IMM16_X0_HW0_TLS_LE = 80, R_TILEGX_IMM16_X1_HW0_TLS_LE = 81, R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE = 82, R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE = 83, R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE = 84, R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE = 85, R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD = 86, R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD = 87, R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD = 88, R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD = 89, R_TILEGX_IMM16_X0_HW0_TLS_IE = 92, R_TILEGX_IMM16_X1_HW0_TLS_IE = 93, R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL = 94, R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL = 95, R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL = 96, R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL = 97, R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL = 98, R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL = 99, R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE = 100, R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE = 101, R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE = 102, R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE = 103, R_TILEGX_TLS_DTPMOD64 = 106, R_TILEGX_TLS_DTPOFF64 = 107, R_TILEGX_TLS_TPOFF64 = 108, R_TILEGX_TLS_DTPMOD32 = 109, R_TILEGX_TLS_DTPOFF32 = 110, R_TILEGX_TLS_TPOFF32 = 111, R_TILEGX_TLS_GD_CALL = 112, R_TILEGX_IMM8_X0_TLS_GD_ADD = 113, R_TILEGX_IMM8_X1_TLS_GD_ADD = 114, R_TILEGX_IMM8_Y0_TLS_GD_ADD = 115, R_TILEGX_IMM8_Y1_TLS_GD_ADD = 116, R_TILEGX_TLS_IE_LOAD = 117, R_TILEGX_IMM8_X0_TLS_ADD = 118, R_TILEGX_IMM8_X1_TLS_ADD = 119, R_TILEGX_IMM8_Y0_TLS_ADD = 120, R_TILEGX_IMM8_Y1_TLS_ADD = 121, R_TILEGX_GNU_VTINHERIT = 128, R_TILEGX_GNU_VTENTRY = 129, R_TILEGX_IRELATIVE = 130, R_TILEGX_NUM = 131 }; typedef enum { TILEGX_PIPELINE_X0, TILEGX_PIPELINE_X1, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, } tilegx_pipeline; typedef unsigned long long tilegx_bundle_bits; /* These are the bits that determine if a bundle is in the X encoding. */ #define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62) enum { /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */ TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3, /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */ TILEGX_NUM_PIPELINE_ENCODINGS = 5, /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */ TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3, /* Instructions take this many bytes. */ TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES, /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */ TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3, /* Bundles should be aligned modulo this number of bytes. */ TILEGX_BUNDLE_ALIGNMENT_IN_BYTES = (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES), /* Number of registers (some are magic, such as network I/O). */ TILEGX_NUM_REGISTERS = 64, }; /* Make a few "tile_" variables to simplify common code between architectures. */ typedef tilegx_bundle_bits tile_bundle_bits; #define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES #define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES #define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \ TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES /* 64-bit pattern for a { bpt ; nop } bundle. */ #define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL typedef enum { TILEGX_OP_TYPE_REGISTER, TILEGX_OP_TYPE_IMMEDIATE, TILEGX_OP_TYPE_ADDRESS, TILEGX_OP_TYPE_SPR } tilegx_operand_type; struct tilegx_operand { /* Is this operand a register, immediate or address? */ tilegx_operand_type type; /* The default relocation type for this operand. */ signed int default_reloc : 16; /* How many bits is this value? (used for range checking) */ unsigned int num_bits : 5; /* Is the value signed? (used for range checking) */ unsigned int is_signed : 1; /* Is this operand a source register? */ unsigned int is_src_reg : 1; /* Is this operand written? (i.e. is it a destination register) */ unsigned int is_dest_reg : 1; /* Is this operand PC-relative? */ unsigned int is_pc_relative : 1; /* By how many bits do we right shift the value before inserting? */ unsigned int rightshift : 2; /* Return the bits for this operand to be ORed into an existing bundle. */ tilegx_bundle_bits (*insert) (int op); /* Extract this operand and return it. */ unsigned int (*extract) (tilegx_bundle_bits bundle); }; typedef enum { TILEGX_OPC_BPT, TILEGX_OPC_INFO, TILEGX_OPC_INFOL, TILEGX_OPC_LD4S_TLS, TILEGX_OPC_LD_TLS, TILEGX_OPC_MOVE, TILEGX_OPC_MOVEI, TILEGX_OPC_MOVELI, TILEGX_OPC_PREFETCH, TILEGX_OPC_PREFETCH_ADD_L1, TILEGX_OPC_PREFETCH_ADD_L1_FAULT, TILEGX_OPC_PREFETCH_ADD_L2, TILEGX_OPC_PREFETCH_ADD_L2_FAULT, TILEGX_OPC_PREFETCH_ADD_L3, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_L1, TILEGX_OPC_PREFETCH_L1_FAULT, TILEGX_OPC_PREFETCH_L2, TILEGX_OPC_PREFETCH_L2_FAULT, TILEGX_OPC_PREFETCH_L3, TILEGX_OPC_PREFETCH_L3_FAULT, TILEGX_OPC_RAISE, TILEGX_OPC_ADD, TILEGX_OPC_ADDI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDX, TILEGX_OPC_ADDXI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXSC, TILEGX_OPC_AND, TILEGX_OPC_ANDI, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZT, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBCT, TILEGX_OPC_BLBS, TILEGX_OPC_BLBST, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZT, TILEGX_OPC_CLZ, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPEXCH, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTU, TILEGX_OPC_CMPLTUI, TILEGX_OPC_CMPNE, TILEGX_OPC_CMUL, TILEGX_OPC_CMULA, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULF, TILEGX_OPC_CMULFR, TILEGX_OPC_CMULH, TILEGX_OPC_CMULHR, TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_CTZ, TILEGX_OPC_DBLALIGN, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_EXCH, TILEGX_OPC_EXCH4, TILEGX_OPC_FDOUBLE_ADD_FLAGS, TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1, TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS, TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN, TILEGX_OPC_FETCHADD, TILEGX_OPC_FETCHADD4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHOR, TILEGX_OPC_FETCHOR4, TILEGX_OPC_FINV, TILEGX_OPC_FLUSH, TILEGX_OPC_FLUSHWB, TILEGX_OPC_FNOP, TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2, TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_FSINGLE_PACK2, TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_ICOH, TILEGX_OPC_ILL, TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_J, TILEGX_OPC_JAL, TILEGX_OPC_JALR, TILEGX_OPC_JALRP, TILEGX_OPC_JR, TILEGX_OPC_JRP, TILEGX_OPC_LD, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LDNA, TILEGX_OPC_LDNA_ADD, TILEGX_OPC_LDNT, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U, TILEGX_OPC_LDNT1U_ADD, TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2S_ADD, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U, TILEGX_OPC_LDNT4U_ADD, TILEGX_OPC_LDNT_ADD, TILEGX_OPC_LNK, TILEGX_OPC_MF, TILEGX_OPC_MFSPR, TILEGX_OPC_MM, TILEGX_OPC_MNZ, TILEGX_OPC_MTSPR, TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU, TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU, TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS, TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS, TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU, TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULAX, TILEGX_OPC_MULX, TILEGX_OPC_MZ, TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_NOR, TILEGX_OPC_OR, TILEGX_OPC_ORI, TILEGX_OPC_PCNT, TILEGX_OPC_REVBITS, TILEGX_OPC_REVBYTES, TILEGX_OPC_ROTL, TILEGX_OPC_ROTLI, TILEGX_OPC_SHL, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHLI, TILEGX_OPC_SHLX, TILEGX_OPC_SHLXI, TILEGX_OPC_SHRS, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRU, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRUXI, TILEGX_OPC_SHUFFLEBYTES, TILEGX_OPC_ST, TILEGX_OPC_ST1, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4, TILEGX_OPC_ST4_ADD, TILEGX_OPC_ST_ADD, TILEGX_OPC_STNT, TILEGX_OPC_STNT1, TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4, TILEGX_OPC_STNT4_ADD, TILEGX_OPC_STNT_ADD, TILEGX_OPC_SUB, TILEGX_OPC_SUBX, TILEGX_OPC_SUBXSC, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1, TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1, TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTSI, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1DDOTPU, TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DOTP, TILEGX_OPC_V1DOTPA, TILEGX_OPC_V1DOTPU, TILEGX_OPC_V1DOTPUA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MINUI, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULU, TILEGX_OPC_V1MULUS, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU, TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHLI, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V1SUB, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADDI, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS, TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MAXSI, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MINSI, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ, TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS, TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHLI, TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SHRUI, TILEGX_OPC_V2SUB, TILEGX_OPC_V2SUBSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4INT_H, TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHLSC, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUB, TILEGX_OPC_V4SUBSC, TILEGX_OPC_WH64, TILEGX_OPC_XOR, TILEGX_OPC_XORI, TILEGX_OPC_NONE } tilegx_mnemonic; enum { TILEGX_MAX_OPERANDS = 4 /* bfexts */ }; struct tilegx_opcode { /* The opcode mnemonic, e.g. "add" */ const char *name; /* The enum value for this mnemonic. */ tilegx_mnemonic mnemonic; /* A bit mask of which of the five pipes this instruction is compatible with: X0 0x01 X1 0x02 Y0 0x04 Y1 0x08 Y2 0x10 */ unsigned char pipes; /* How many operands are there? */ unsigned char num_operands; /* Which register does this write implicitly, or TREG_ZERO if none? */ unsigned char implicitly_written_register; /* Can this be bundled with other instructions (almost always true). */ unsigned char can_bundle; /* The description of the operands. Each of these is an * index into the tilegx_operands[] table. */ unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS]; /* A mask of which bits have predefined values for each pipeline. * This is useful for disassembly. */ tilegx_bundle_bits fixed_bit_masks[TILEGX_NUM_PIPELINE_ENCODINGS]; /* For each bit set in fixed_bit_masks, what the value is for this * instruction. */ tilegx_bundle_bits fixed_bit_values[TILEGX_NUM_PIPELINE_ENCODINGS]; }; /* Used for non-textual disassembly into structs. */ struct tilegx_decoded_instruction { const struct tilegx_opcode *opcode; const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS]; long long operand_values[TILEGX_MAX_OPERANDS]; }; enum { ADDI_IMM8_OPCODE_X0 = 1, ADDI_IMM8_OPCODE_X1 = 1, ADDI_OPCODE_Y0 = 0, ADDI_OPCODE_Y1 = 1, ADDLI_OPCODE_X0 = 1, ADDLI_OPCODE_X1 = 0, ADDXI_IMM8_OPCODE_X0 = 2, ADDXI_IMM8_OPCODE_X1 = 2, ADDXI_OPCODE_Y0 = 1, ADDXI_OPCODE_Y1 = 2, ADDXLI_OPCODE_X0 = 2, ADDXLI_OPCODE_X1 = 1, ADDXSC_RRR_0_OPCODE_X0 = 1, ADDXSC_RRR_0_OPCODE_X1 = 1, ADDX_RRR_0_OPCODE_X0 = 2, ADDX_RRR_0_OPCODE_X1 = 2, ADDX_RRR_0_OPCODE_Y0 = 0, ADDX_SPECIAL_0_OPCODE_Y1 = 0, ADD_RRR_0_OPCODE_X0 = 3, ADD_RRR_0_OPCODE_X1 = 3, ADD_RRR_0_OPCODE_Y0 = 1, ADD_SPECIAL_0_OPCODE_Y1 = 1, ANDI_IMM8_OPCODE_X0 = 3, ANDI_IMM8_OPCODE_X1 = 3, ANDI_OPCODE_Y0 = 2, ANDI_OPCODE_Y1 = 3, AND_RRR_0_OPCODE_X0 = 4, AND_RRR_0_OPCODE_X1 = 4, AND_RRR_5_OPCODE_Y0 = 0, AND_RRR_5_OPCODE_Y1 = 0, BEQZT_BRANCH_OPCODE_X1 = 16, BEQZ_BRANCH_OPCODE_X1 = 17, BFEXTS_BF_OPCODE_X0 = 4, BFEXTU_BF_OPCODE_X0 = 5, BFINS_BF_OPCODE_X0 = 6, BF_OPCODE_X0 = 3, BGEZT_BRANCH_OPCODE_X1 = 18, BGEZ_BRANCH_OPCODE_X1 = 19, BGTZT_BRANCH_OPCODE_X1 = 20, BGTZ_BRANCH_OPCODE_X1 = 21, BLBCT_BRANCH_OPCODE_X1 = 22, BLBC_BRANCH_OPCODE_X1 = 23, BLBST_BRANCH_OPCODE_X1 = 24, BLBS_BRANCH_OPCODE_X1 = 25, BLEZT_BRANCH_OPCODE_X1 = 26, BLEZ_BRANCH_OPCODE_X1 = 27, BLTZT_BRANCH_OPCODE_X1 = 28, BLTZ_BRANCH_OPCODE_X1 = 29, BNEZT_BRANCH_OPCODE_X1 = 30, BNEZ_BRANCH_OPCODE_X1 = 31, BRANCH_OPCODE_X1 = 2, CMOVEQZ_RRR_0_OPCODE_X0 = 5, CMOVEQZ_RRR_4_OPCODE_Y0 = 0, CMOVNEZ_RRR_0_OPCODE_X0 = 6, CMOVNEZ_RRR_4_OPCODE_Y0 = 1, CMPEQI_IMM8_OPCODE_X0 = 4, CMPEQI_IMM8_OPCODE_X1 = 4, CMPEQI_OPCODE_Y0 = 3, CMPEQI_OPCODE_Y1 = 4, CMPEQ_RRR_0_OPCODE_X0 = 7, CMPEQ_RRR_0_OPCODE_X1 = 5, CMPEQ_RRR_3_OPCODE_Y0 = 0, CMPEQ_RRR_3_OPCODE_Y1 = 2, CMPEXCH4_RRR_0_OPCODE_X1 = 6, CMPEXCH_RRR_0_OPCODE_X1 = 7, CMPLES_RRR_0_OPCODE_X0 = 8, CMPLES_RRR_0_OPCODE_X1 = 8, CMPLES_RRR_2_OPCODE_Y0 = 0, CMPLES_RRR_2_OPCODE_Y1 = 0, CMPLEU_RRR_0_OPCODE_X0 = 9, CMPLEU_RRR_0_OPCODE_X1 = 9, CMPLEU_RRR_2_OPCODE_Y0 = 1, CMPLEU_RRR_2_OPCODE_Y1 = 1, CMPLTSI_IMM8_OPCODE_X0 = 5, CMPLTSI_IMM8_OPCODE_X1 = 5, CMPLTSI_OPCODE_Y0 = 4, CMPLTSI_OPCODE_Y1 = 5, CMPLTS_RRR_0_OPCODE_X0 = 10, CMPLTS_RRR_0_OPCODE_X1 = 10, CMPLTS_RRR_2_OPCODE_Y0 = 2, CMPLTS_RRR_2_OPCODE_Y1 = 2, CMPLTUI_IMM8_OPCODE_X0 = 6, CMPLTUI_IMM8_OPCODE_X1 = 6, CMPLTU_RRR_0_OPCODE_X0 = 11, CMPLTU_RRR_0_OPCODE_X1 = 11, CMPLTU_RRR_2_OPCODE_Y0 = 3, CMPLTU_RRR_2_OPCODE_Y1 = 3, CMPNE_RRR_0_OPCODE_X0 = 12, CMPNE_RRR_0_OPCODE_X1 = 12, CMPNE_RRR_3_OPCODE_Y0 = 1, CMPNE_RRR_3_OPCODE_Y1 = 3, CMULAF_RRR_0_OPCODE_X0 = 13, CMULA_RRR_0_OPCODE_X0 = 14, CMULFR_RRR_0_OPCODE_X0 = 15, CMULF_RRR_0_OPCODE_X0 = 16, CMULHR_RRR_0_OPCODE_X0 = 17, CMULH_RRR_0_OPCODE_X0 = 18, CMUL_RRR_0_OPCODE_X0 = 19, CNTLZ_UNARY_OPCODE_X0 = 1, CNTLZ_UNARY_OPCODE_Y0 = 1, CNTTZ_UNARY_OPCODE_X0 = 2, CNTTZ_UNARY_OPCODE_Y0 = 2, CRC32_32_RRR_0_OPCODE_X0 = 20, CRC32_8_RRR_0_OPCODE_X0 = 21, DBLALIGN2_RRR_0_OPCODE_X0 = 22, DBLALIGN2_RRR_0_OPCODE_X1 = 13, DBLALIGN4_RRR_0_OPCODE_X0 = 23, DBLALIGN4_RRR_0_OPCODE_X1 = 14, DBLALIGN6_RRR_0_OPCODE_X0 = 24, DBLALIGN6_RRR_0_OPCODE_X1 = 15, DBLALIGN_RRR_0_OPCODE_X0 = 25, DRAIN_UNARY_OPCODE_X1 = 1, DTLBPR_UNARY_OPCODE_X1 = 2, EXCH4_RRR_0_OPCODE_X1 = 16, EXCH_RRR_0_OPCODE_X1 = 17, FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26, FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27, FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28, FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29, FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30, FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31, FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32, FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33, FETCHADD4_RRR_0_OPCODE_X1 = 18, FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19, FETCHADDGEZ_RRR_0_OPCODE_X1 = 20, FETCHADD_RRR_0_OPCODE_X1 = 21, FETCHAND4_RRR_0_OPCODE_X1 = 22, FETCHAND_RRR_0_OPCODE_X1 = 23, FETCHOR4_RRR_0_OPCODE_X1 = 24, FETCHOR_RRR_0_OPCODE_X1 = 25, FINV_UNARY_OPCODE_X1 = 3, FLUSHWB_UNARY_OPCODE_X1 = 4, FLUSH_UNARY_OPCODE_X1 = 5, FNOP_UNARY_OPCODE_X0 = 3, FNOP_UNARY_OPCODE_X1 = 6, FNOP_UNARY_OPCODE_Y0 = 3, FNOP_UNARY_OPCODE_Y1 = 8, FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34, FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35, FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36, FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37, FSINGLE_PACK1_UNARY_OPCODE_X0 = 4, FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4, FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38, FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39, ICOH_UNARY_OPCODE_X1 = 7, ILL_UNARY_OPCODE_X1 = 8, ILL_UNARY_OPCODE_Y1 = 9, IMM8_OPCODE_X0 = 4, IMM8_OPCODE_X1 = 3, INV_UNARY_OPCODE_X1 = 9, IRET_UNARY_OPCODE_X1 = 10, JALRP_UNARY_OPCODE_X1 = 11, JALRP_UNARY_OPCODE_Y1 = 10, JALR_UNARY_OPCODE_X1 = 12, JALR_UNARY_OPCODE_Y1 = 11, JAL_JUMP_OPCODE_X1 = 0, JRP_UNARY_OPCODE_X1 = 13, JRP_UNARY_OPCODE_Y1 = 12, JR_UNARY_OPCODE_X1 = 14, JR_UNARY_OPCODE_Y1 = 13, JUMP_OPCODE_X1 = 4, J_JUMP_OPCODE_X1 = 1, LD1S_ADD_IMM8_OPCODE_X1 = 7, LD1S_OPCODE_Y2 = 0, LD1S_UNARY_OPCODE_X1 = 15, LD1U_ADD_IMM8_OPCODE_X1 = 8, LD1U_OPCODE_Y2 = 1, LD1U_UNARY_OPCODE_X1 = 16, LD2S_ADD_IMM8_OPCODE_X1 = 9, LD2S_OPCODE_Y2 = 2, LD2S_UNARY_OPCODE_X1 = 17, LD2U_ADD_IMM8_OPCODE_X1 = 10, LD2U_OPCODE_Y2 = 3, LD2U_UNARY_OPCODE_X1 = 18, LD4S_ADD_IMM8_OPCODE_X1 = 11, LD4S_OPCODE_Y2 = 1, LD4S_UNARY_OPCODE_X1 = 19, LD4U_ADD_IMM8_OPCODE_X1 = 12, LD4U_OPCODE_Y2 = 2, LD4U_UNARY_OPCODE_X1 = 20, LDNA_UNARY_OPCODE_X1 = 21, LDNT1S_ADD_IMM8_OPCODE_X1 = 13, LDNT1S_UNARY_OPCODE_X1 = 22, LDNT1U_ADD_IMM8_OPCODE_X1 = 14, LDNT1U_UNARY_OPCODE_X1 = 23, LDNT2S_ADD_IMM8_OPCODE_X1 = 15, LDNT2S_UNARY_OPCODE_X1 = 24, LDNT2U_ADD_IMM8_OPCODE_X1 = 16, LDNT2U_UNARY_OPCODE_X1 = 25, LDNT4S_ADD_IMM8_OPCODE_X1 = 17, LDNT4S_UNARY_OPCODE_X1 = 26, LDNT4U_ADD_IMM8_OPCODE_X1 = 18, LDNT4U_UNARY_OPCODE_X1 = 27, LDNT_ADD_IMM8_OPCODE_X1 = 19, LDNT_UNARY_OPCODE_X1 = 28, LD_ADD_IMM8_OPCODE_X1 = 20, LD_OPCODE_Y2 = 3, LD_UNARY_OPCODE_X1 = 29, LNK_UNARY_OPCODE_X1 = 30, LNK_UNARY_OPCODE_Y1 = 14, LWNA_ADD_IMM8_OPCODE_X1 = 21, MFSPR_IMM8_OPCODE_X1 = 22, MF_UNARY_OPCODE_X1 = 31, MM_BF_OPCODE_X0 = 7, MNZ_RRR_0_OPCODE_X0 = 40, MNZ_RRR_0_OPCODE_X1 = 26, MNZ_RRR_4_OPCODE_Y0 = 2, MNZ_RRR_4_OPCODE_Y1 = 2, MODE_OPCODE_YA2 = 1, MODE_OPCODE_YB2 = 2, MODE_OPCODE_YC2 = 3, MTSPR_IMM8_OPCODE_X1 = 23, MULAX_RRR_0_OPCODE_X0 = 41, MULAX_RRR_3_OPCODE_Y0 = 2, MULA_HS_HS_RRR_0_OPCODE_X0 = 42, MULA_HS_HS_RRR_9_OPCODE_Y0 = 0, MULA_HS_HU_RRR_0_OPCODE_X0 = 43, MULA_HS_LS_RRR_0_OPCODE_X0 = 44, MULA_HS_LU_RRR_0_OPCODE_X0 = 45, MULA_HU_HU_RRR_0_OPCODE_X0 = 46, MULA_HU_HU_RRR_9_OPCODE_Y0 = 1, MULA_HU_LS_RRR_0_OPCODE_X0 = 47, MULA_HU_LU_RRR_0_OPCODE_X0 = 48, MULA_LS_LS_RRR_0_OPCODE_X0 = 49, MULA_LS_LS_RRR_9_OPCODE_Y0 = 2, MULA_LS_LU_RRR_0_OPCODE_X0 = 50, MULA_LU_LU_RRR_0_OPCODE_X0 = 51, MULA_LU_LU_RRR_9_OPCODE_Y0 = 3, MULX_RRR_0_OPCODE_X0 = 52, MULX_RRR_3_OPCODE_Y0 = 3, MUL_HS_HS_RRR_0_OPCODE_X0 = 53, MUL_HS_HS_RRR_8_OPCODE_Y0 = 0, MUL_HS_HU_RRR_0_OPCODE_X0 = 54, MUL_HS_LS_RRR_0_OPCODE_X0 = 55, MUL_HS_LU_RRR_0_OPCODE_X0 = 56, MUL_HU_HU_RRR_0_OPCODE_X0 = 57, MUL_HU_HU_RRR_8_OPCODE_Y0 = 1, MUL_HU_LS_RRR_0_OPCODE_X0 = 58, MUL_HU_LU_RRR_0_OPCODE_X0 = 59, MUL_LS_LS_RRR_0_OPCODE_X0 = 60, MUL_LS_LS_RRR_8_OPCODE_Y0 = 2, MUL_LS_LU_RRR_0_OPCODE_X0 = 61, MUL_LU_LU_RRR_0_OPCODE_X0 = 62, MUL_LU_LU_RRR_8_OPCODE_Y0 = 3, MZ_RRR_0_OPCODE_X0 = 63, MZ_RRR_0_OPCODE_X1 = 27, MZ_RRR_4_OPCODE_Y0 = 3, MZ_RRR_4_OPCODE_Y1 = 3, NAP_UNARY_OPCODE_X1 = 32, NOP_UNARY_OPCODE_X0 = 5, NOP_UNARY_OPCODE_X1 = 33, NOP_UNARY_OPCODE_Y0 = 5, NOP_UNARY_OPCODE_Y1 = 15, NOR_RRR_0_OPCODE_X0 = 64, NOR_RRR_0_OPCODE_X1 = 28, NOR_RRR_5_OPCODE_Y0 = 1, NOR_RRR_5_OPCODE_Y1 = 1, ORI_IMM8_OPCODE_X0 = 7, ORI_IMM8_OPCODE_X1 = 24, OR_RRR_0_OPCODE_X0 = 65, OR_RRR_0_OPCODE_X1 = 29, OR_RRR_5_OPCODE_Y0 = 2, OR_RRR_5_OPCODE_Y1 = 2, PCNT_UNARY_OPCODE_X0 = 6, PCNT_UNARY_OPCODE_Y0 = 6, REVBITS_UNARY_OPCODE_X0 = 7, REVBITS_UNARY_OPCODE_Y0 = 7, REVBYTES_UNARY_OPCODE_X0 = 8, REVBYTES_UNARY_OPCODE_Y0 = 8, ROTLI_SHIFT_OPCODE_X0 = 1, ROTLI_SHIFT_OPCODE_X1 = 1, ROTLI_SHIFT_OPCODE_Y0 = 0, ROTLI_SHIFT_OPCODE_Y1 = 0, ROTL_RRR_0_OPCODE_X0 = 66, ROTL_RRR_0_OPCODE_X1 = 30, ROTL_RRR_6_OPCODE_Y0 = 0, ROTL_RRR_6_OPCODE_Y1 = 0, RRR_0_OPCODE_X0 = 5, RRR_0_OPCODE_X1 = 5, RRR_0_OPCODE_Y0 = 5, RRR_0_OPCODE_Y1 = 6, RRR_1_OPCODE_Y0 = 6, RRR_1_OPCODE_Y1 = 7, RRR_2_OPCODE_Y0 = 7, RRR_2_OPCODE_Y1 = 8, RRR_3_OPCODE_Y0 = 8, RRR_3_OPCODE_Y1 = 9, RRR_4_OPCODE_Y0 = 9, RRR_4_OPCODE_Y1 = 10, RRR_5_OPCODE_Y0 = 10, RRR_5_OPCODE_Y1 = 11, RRR_6_OPCODE_Y0 = 11, RRR_6_OPCODE_Y1 = 12, RRR_7_OPCODE_Y0 = 12, RRR_7_OPCODE_Y1 = 13, RRR_8_OPCODE_Y0 = 13, RRR_9_OPCODE_Y0 = 14, SHIFT_OPCODE_X0 = 6, SHIFT_OPCODE_X1 = 6, SHIFT_OPCODE_Y0 = 15, SHIFT_OPCODE_Y1 = 14, SHL16INSLI_OPCODE_X0 = 7, SHL16INSLI_OPCODE_X1 = 7, SHL1ADDX_RRR_0_OPCODE_X0 = 67, SHL1ADDX_RRR_0_OPCODE_X1 = 31, SHL1ADDX_RRR_7_OPCODE_Y0 = 1, SHL1ADDX_RRR_7_OPCODE_Y1 = 1, SHL1ADD_RRR_0_OPCODE_X0 = 68, SHL1ADD_RRR_0_OPCODE_X1 = 32, SHL1ADD_RRR_1_OPCODE_Y0 = 0, SHL1ADD_RRR_1_OPCODE_Y1 = 0, SHL2ADDX_RRR_0_OPCODE_X0 = 69, SHL2ADDX_RRR_0_OPCODE_X1 = 33, SHL2ADDX_RRR_7_OPCODE_Y0 = 2, SHL2ADDX_RRR_7_OPCODE_Y1 = 2, SHL2ADD_RRR_0_OPCODE_X0 = 70, SHL2ADD_RRR_0_OPCODE_X1 = 34, SHL2ADD_RRR_1_OPCODE_Y0 = 1, SHL2ADD_RRR_1_OPCODE_Y1 = 1, SHL3ADDX_RRR_0_OPCODE_X0 = 71, SHL3ADDX_RRR_0_OPCODE_X1 = 35, SHL3ADDX_RRR_7_OPCODE_Y0 = 3, SHL3ADDX_RRR_7_OPCODE_Y1 = 3, SHL3ADD_RRR_0_OPCODE_X0 = 72, SHL3ADD_RRR_0_OPCODE_X1 = 36, SHL3ADD_RRR_1_OPCODE_Y0 = 2, SHL3ADD_RRR_1_OPCODE_Y1 = 2, SHLI_SHIFT_OPCODE_X0 = 2, SHLI_SHIFT_OPCODE_X1 = 2, SHLI_SHIFT_OPCODE_Y0 = 1, SHLI_SHIFT_OPCODE_Y1 = 1, SHLXI_SHIFT_OPCODE_X0 = 3, SHLXI_SHIFT_OPCODE_X1 = 3, SHLX_RRR_0_OPCODE_X0 = 73, SHLX_RRR_0_OPCODE_X1 = 37, SHL_RRR_0_OPCODE_X0 = 74, SHL_RRR_0_OPCODE_X1 = 38, SHL_RRR_6_OPCODE_Y0 = 1, SHL_RRR_6_OPCODE_Y1 = 1, SHRSI_SHIFT_OPCODE_X0 = 4, SHRSI_SHIFT_OPCODE_X1 = 4, SHRSI_SHIFT_OPCODE_Y0 = 2, SHRSI_SHIFT_OPCODE_Y1 = 2, SHRS_RRR_0_OPCODE_X0 = 75, SHRS_RRR_0_OPCODE_X1 = 39, SHRS_RRR_6_OPCODE_Y0 = 2, SHRS_RRR_6_OPCODE_Y1 = 2, SHRUI_SHIFT_OPCODE_X0 = 5, SHRUI_SHIFT_OPCODE_X1 = 5, SHRUI_SHIFT_OPCODE_Y0 = 3, SHRUI_SHIFT_OPCODE_Y1 = 3, SHRUXI_SHIFT_OPCODE_X0 = 6, SHRUXI_SHIFT_OPCODE_X1 = 6, SHRUX_RRR_0_OPCODE_X0 = 76, SHRUX_RRR_0_OPCODE_X1 = 40, SHRU_RRR_0_OPCODE_X0 = 77, SHRU_RRR_0_OPCODE_X1 = 41, SHRU_RRR_6_OPCODE_Y0 = 3, SHRU_RRR_6_OPCODE_Y1 = 3, SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78, ST1_ADD_IMM8_OPCODE_X1 = 25, ST1_OPCODE_Y2 = 0, ST1_RRR_0_OPCODE_X1 = 42, ST2_ADD_IMM8_OPCODE_X1 = 26, ST2_OPCODE_Y2 = 1, ST2_RRR_0_OPCODE_X1 = 43, ST4_ADD_IMM8_OPCODE_X1 = 27, ST4_OPCODE_Y2 = 2, ST4_RRR_0_OPCODE_X1 = 44, STNT1_ADD_IMM8_OPCODE_X1 = 28, STNT1_RRR_0_OPCODE_X1 = 45, STNT2_ADD_IMM8_OPCODE_X1 = 29, STNT2_RRR_0_OPCODE_X1 = 46, STNT4_ADD_IMM8_OPCODE_X1 = 30, STNT4_RRR_0_OPCODE_X1 = 47, STNT_ADD_IMM8_OPCODE_X1 = 31, STNT_RRR_0_OPCODE_X1 = 48, ST_ADD_IMM8_OPCODE_X1 = 32, ST_OPCODE_Y2 = 3, ST_RRR_0_OPCODE_X1 = 49, SUBXSC_RRR_0_OPCODE_X0 = 79, SUBXSC_RRR_0_OPCODE_X1 = 50, SUBX_RRR_0_OPCODE_X0 = 80, SUBX_RRR_0_OPCODE_X1 = 51, SUBX_RRR_0_OPCODE_Y0 = 2, SUBX_RRR_0_OPCODE_Y1 = 2, SUB_RRR_0_OPCODE_X0 = 81, SUB_RRR_0_OPCODE_X1 = 52, SUB_RRR_0_OPCODE_Y0 = 3, SUB_RRR_0_OPCODE_Y1 = 3, SWINT0_UNARY_OPCODE_X1 = 34, SWINT1_UNARY_OPCODE_X1 = 35, SWINT2_UNARY_OPCODE_X1 = 36, SWINT3_UNARY_OPCODE_X1 = 37, TBLIDXB0_UNARY_OPCODE_X0 = 9, TBLIDXB0_UNARY_OPCODE_Y0 = 9, TBLIDXB1_UNARY_OPCODE_X0 = 10, TBLIDXB1_UNARY_OPCODE_Y0 = 10, TBLIDXB2_UNARY_OPCODE_X0 = 11, TBLIDXB2_UNARY_OPCODE_Y0 = 11, TBLIDXB3_UNARY_OPCODE_X0 = 12, TBLIDXB3_UNARY_OPCODE_Y0 = 12, UNARY_RRR_0_OPCODE_X0 = 82, UNARY_RRR_0_OPCODE_X1 = 53, UNARY_RRR_1_OPCODE_Y0 = 3, UNARY_RRR_1_OPCODE_Y1 = 3, V1ADDI_IMM8_OPCODE_X0 = 8, V1ADDI_IMM8_OPCODE_X1 = 33, V1ADDUC_RRR_0_OPCODE_X0 = 83, V1ADDUC_RRR_0_OPCODE_X1 = 54, V1ADD_RRR_0_OPCODE_X0 = 84, V1ADD_RRR_0_OPCODE_X1 = 55, V1ADIFFU_RRR_0_OPCODE_X0 = 85, V1AVGU_RRR_0_OPCODE_X0 = 86, V1CMPEQI_IMM8_OPCODE_X0 = 9, V1CMPEQI_IMM8_OPCODE_X1 = 34, V1CMPEQ_RRR_0_OPCODE_X0 = 87, V1CMPEQ_RRR_0_OPCODE_X1 = 56, V1CMPLES_RRR_0_OPCODE_X0 = 88, V1CMPLES_RRR_0_OPCODE_X1 = 57, V1CMPLEU_RRR_0_OPCODE_X0 = 89, V1CMPLEU_RRR_0_OPCODE_X1 = 58, V1CMPLTSI_IMM8_OPCODE_X0 = 10, V1CMPLTSI_IMM8_OPCODE_X1 = 35, V1CMPLTS_RRR_0_OPCODE_X0 = 90, V1CMPLTS_RRR_0_OPCODE_X1 = 59, V1CMPLTUI_IMM8_OPCODE_X0 = 11, V1CMPLTUI_IMM8_OPCODE_X1 = 36, V1CMPLTU_RRR_0_OPCODE_X0 = 91, V1CMPLTU_RRR_0_OPCODE_X1 = 60, V1CMPNE_RRR_0_OPCODE_X0 = 92, V1CMPNE_RRR_0_OPCODE_X1 = 61, V1DDOTPUA_RRR_0_OPCODE_X0 = 161, V1DDOTPUSA_RRR_0_OPCODE_X0 = 93, V1DDOTPUS_RRR_0_OPCODE_X0 = 94, V1DDOTPU_RRR_0_OPCODE_X0 = 162, V1DOTPA_RRR_0_OPCODE_X0 = 95, V1DOTPUA_RRR_0_OPCODE_X0 = 163, V1DOTPUSA_RRR_0_OPCODE_X0 = 96, V1DOTPUS_RRR_0_OPCODE_X0 = 97, V1DOTPU_RRR_0_OPCODE_X0 = 164, V1DOTP_RRR_0_OPCODE_X0 = 98, V1INT_H_RRR_0_OPCODE_X0 = 99, V1INT_H_RRR_0_OPCODE_X1 = 62, V1INT_L_RRR_0_OPCODE_X0 = 100, V1INT_L_RRR_0_OPCODE_X1 = 63, V1MAXUI_IMM8_OPCODE_X0 = 12, V1MAXUI_IMM8_OPCODE_X1 = 37, V1MAXU_RRR_0_OPCODE_X0 = 101, V1MAXU_RRR_0_OPCODE_X1 = 64, V1MINUI_IMM8_OPCODE_X0 = 13, V1MINUI_IMM8_OPCODE_X1 = 38, V1MINU_RRR_0_OPCODE_X0 = 102, V1MINU_RRR_0_OPCODE_X1 = 65, V1MNZ_RRR_0_OPCODE_X0 = 103, V1MNZ_RRR_0_OPCODE_X1 = 66, V1MULTU_RRR_0_OPCODE_X0 = 104, V1MULUS_RRR_0_OPCODE_X0 = 105, V1MULU_RRR_0_OPCODE_X0 = 106, V1MZ_RRR_0_OPCODE_X0 = 107, V1MZ_RRR_0_OPCODE_X1 = 67, V1SADAU_RRR_0_OPCODE_X0 = 108, V1SADU_RRR_0_OPCODE_X0 = 109, V1SHLI_SHIFT_OPCODE_X0 = 7, V1SHLI_SHIFT_OPCODE_X1 = 7, V1SHL_RRR_0_OPCODE_X0 = 110, V1SHL_RRR_0_OPCODE_X1 = 68, V1SHRSI_SHIFT_OPCODE_X0 = 8, V1SHRSI_SHIFT_OPCODE_X1 = 8, V1SHRS_RRR_0_OPCODE_X0 = 111, V1SHRS_RRR_0_OPCODE_X1 = 69, V1SHRUI_SHIFT_OPCODE_X0 = 9, V1SHRUI_SHIFT_OPCODE_X1 = 9, V1SHRU_RRR_0_OPCODE_X0 = 112, V1SHRU_RRR_0_OPCODE_X1 = 70, V1SUBUC_RRR_0_OPCODE_X0 = 113, V1SUBUC_RRR_0_OPCODE_X1 = 71, V1SUB_RRR_0_OPCODE_X0 = 114, V1SUB_RRR_0_OPCODE_X1 = 72, V2ADDI_IMM8_OPCODE_X0 = 14, V2ADDI_IMM8_OPCODE_X1 = 39, V2ADDSC_RRR_0_OPCODE_X0 = 115, V2ADDSC_RRR_0_OPCODE_X1 = 73, V2ADD_RRR_0_OPCODE_X0 = 116, V2ADD_RRR_0_OPCODE_X1 = 74, V2ADIFFS_RRR_0_OPCODE_X0 = 117, V2AVGS_RRR_0_OPCODE_X0 = 118, V2CMPEQI_IMM8_OPCODE_X0 = 15, V2CMPEQI_IMM8_OPCODE_X1 = 40, V2CMPEQ_RRR_0_OPCODE_X0 = 119, V2CMPEQ_RRR_0_OPCODE_X1 = 75, V2CMPLES_RRR_0_OPCODE_X0 = 120, V2CMPLES_RRR_0_OPCODE_X1 = 76, V2CMPLEU_RRR_0_OPCODE_X0 = 121, V2CMPLEU_RRR_0_OPCODE_X1 = 77, V2CMPLTSI_IMM8_OPCODE_X0 = 16, V2CMPLTSI_IMM8_OPCODE_X1 = 41, V2CMPLTS_RRR_0_OPCODE_X0 = 122, V2CMPLTS_RRR_0_OPCODE_X1 = 78, V2CMPLTUI_IMM8_OPCODE_X0 = 17, V2CMPLTUI_IMM8_OPCODE_X1 = 42, V2CMPLTU_RRR_0_OPCODE_X0 = 123, V2CMPLTU_RRR_0_OPCODE_X1 = 79, V2CMPNE_RRR_0_OPCODE_X0 = 124, V2CMPNE_RRR_0_OPCODE_X1 = 80, V2DOTPA_RRR_0_OPCODE_X0 = 125, V2DOTP_RRR_0_OPCODE_X0 = 126, V2INT_H_RRR_0_OPCODE_X0 = 127, V2INT_H_RRR_0_OPCODE_X1 = 81, V2INT_L_RRR_0_OPCODE_X0 = 128, V2INT_L_RRR_0_OPCODE_X1 = 82, V2MAXSI_IMM8_OPCODE_X0 = 18, V2MAXSI_IMM8_OPCODE_X1 = 43, V2MAXS_RRR_0_OPCODE_X0 = 129, V2MAXS_RRR_0_OPCODE_X1 = 83, V2MINSI_IMM8_OPCODE_X0 = 19, V2MINSI_IMM8_OPCODE_X1 = 44, V2MINS_RRR_0_OPCODE_X0 = 130, V2MINS_RRR_0_OPCODE_X1 = 84, V2MNZ_RRR_0_OPCODE_X0 = 131, V2MNZ_RRR_0_OPCODE_X1 = 85, V2MULFSC_RRR_0_OPCODE_X0 = 132, V2MULS_RRR_0_OPCODE_X0 = 133, V2MULTS_RRR_0_OPCODE_X0 = 134, V2MZ_RRR_0_OPCODE_X0 = 135, V2MZ_RRR_0_OPCODE_X1 = 86, V2PACKH_RRR_0_OPCODE_X0 = 136, V2PACKH_RRR_0_OPCODE_X1 = 87, V2PACKL_RRR_0_OPCODE_X0 = 137, V2PACKL_RRR_0_OPCODE_X1 = 88, V2PACKUC_RRR_0_OPCODE_X0 = 138, V2PACKUC_RRR_0_OPCODE_X1 = 89, V2SADAS_RRR_0_OPCODE_X0 = 139, V2SADAU_RRR_0_OPCODE_X0 = 140, V2SADS_RRR_0_OPCODE_X0 = 141, V2SADU_RRR_0_OPCODE_X0 = 142, V2SHLI_SHIFT_OPCODE_X0 = 10, V2SHLI_SHIFT_OPCODE_X1 = 10, V2SHLSC_RRR_0_OPCODE_X0 = 143, V2SHLSC_RRR_0_OPCODE_X1 = 90, V2SHL_RRR_0_OPCODE_X0 = 144, V2SHL_RRR_0_OPCODE_X1 = 91, V2SHRSI_SHIFT_OPCODE_X0 = 11, V2SHRSI_SHIFT_OPCODE_X1 = 11, V2SHRS_RRR_0_OPCODE_X0 = 145, V2SHRS_RRR_0_OPCODE_X1 = 92, V2SHRUI_SHIFT_OPCODE_X0 = 12, V2SHRUI_SHIFT_OPCODE_X1 = 12, V2SHRU_RRR_0_OPCODE_X0 = 146, V2SHRU_RRR_0_OPCODE_X1 = 93, V2SUBSC_RRR_0_OPCODE_X0 = 147, V2SUBSC_RRR_0_OPCODE_X1 = 94, V2SUB_RRR_0_OPCODE_X0 = 148, V2SUB_RRR_0_OPCODE_X1 = 95, V4ADDSC_RRR_0_OPCODE_X0 = 149, V4ADDSC_RRR_0_OPCODE_X1 = 96, V4ADD_RRR_0_OPCODE_X0 = 150, V4ADD_RRR_0_OPCODE_X1 = 97, V4INT_H_RRR_0_OPCODE_X0 = 151, V4INT_H_RRR_0_OPCODE_X1 = 98, V4INT_L_RRR_0_OPCODE_X0 = 152, V4INT_L_RRR_0_OPCODE_X1 = 99, V4PACKSC_RRR_0_OPCODE_X0 = 153, V4PACKSC_RRR_0_OPCODE_X1 = 100, V4SHLSC_RRR_0_OPCODE_X0 = 154, V4SHLSC_RRR_0_OPCODE_X1 = 101, V4SHL_RRR_0_OPCODE_X0 = 155, V4SHL_RRR_0_OPCODE_X1 = 102, V4SHRS_RRR_0_OPCODE_X0 = 156, V4SHRS_RRR_0_OPCODE_X1 = 103, V4SHRU_RRR_0_OPCODE_X0 = 157, V4SHRU_RRR_0_OPCODE_X1 = 104, V4SUBSC_RRR_0_OPCODE_X0 = 158, V4SUBSC_RRR_0_OPCODE_X1 = 105, V4SUB_RRR_0_OPCODE_X0 = 159, V4SUB_RRR_0_OPCODE_X1 = 106, WH64_UNARY_OPCODE_X1 = 38, XORI_IMM8_OPCODE_X0 = 20, XORI_IMM8_OPCODE_X1 = 45, XOR_RRR_0_OPCODE_X0 = 160, XOR_RRR_0_OPCODE_X1 = 107, XOR_RRR_5_OPCODE_Y0 = 3, XOR_RRR_5_OPCODE_Y1 = 3 }; static __inline unsigned int get_BFEnd_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_BFOpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 24)) & 0xf); } static __inline unsigned int get_BFStart_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 18)) & 0x3f); } static __inline unsigned int get_BrOff_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x0000003f) | (((unsigned int)(n >> 37)) & 0x0001ffc0); } static __inline unsigned int get_BrType_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 54)) & 0x1f); } static __inline unsigned int get_Dest_Imm8_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x0000003f) | (((unsigned int)(n >> 43)) & 0x000000c0); } static __inline unsigned int get_Dest_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 0)) & 0x3f); } static __inline unsigned int get_Dest_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x3f); } static __inline unsigned int get_Dest_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 0)) & 0x3f); } static __inline unsigned int get_Dest_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x3f); } static __inline unsigned int get_Imm16_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0xffff); } static __inline unsigned int get_Imm16_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0xffff); } static __inline unsigned int get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 20)) & 0xff); } static __inline unsigned int get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 51)) & 0xff); } static __inline unsigned int get_Imm8_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0xff); } static __inline unsigned int get_Imm8_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0xff); } static __inline unsigned int get_Imm8_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0xff); } static __inline unsigned int get_Imm8_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0xff); } static __inline unsigned int get_JumpOff_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x7ffffff); } static __inline unsigned int get_JumpOpcodeExtension_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 58)) & 0x1); } static __inline unsigned int get_MF_Imm14_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 37)) & 0x3fff); } static __inline unsigned int get_MT_Imm14_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 31)) & 0x0000003f) | (((unsigned int)(n >> 37)) & 0x00003fc0); } static __inline unsigned int get_Mode(tilegx_bundle_bits n) { return (((unsigned int)(n >> 62)) & 0x3); } static __inline unsigned int get_Opcode_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 28)) & 0x7); } static __inline unsigned int get_Opcode_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 59)) & 0x7); } static __inline unsigned int get_Opcode_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 27)) & 0xf); } static __inline unsigned int get_Opcode_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 58)) & 0xf); } static __inline unsigned int get_Opcode_Y2(tilegx_bundle_bits n) { return (((n >> 26)) & 0x00000001) | (((unsigned int)(n >> 56)) & 0x00000002); } static __inline unsigned int get_RRROpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 18)) & 0x3ff); } static __inline unsigned int get_RRROpcodeExtension_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 49)) & 0x3ff); } static __inline unsigned int get_RRROpcodeExtension_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 18)) & 0x3); } static __inline unsigned int get_RRROpcodeExtension_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 49)) & 0x3); } static __inline unsigned int get_ShAmt_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_ShAmt_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int get_ShAmt_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_ShAmt_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 18)) & 0x3ff); } static __inline unsigned int get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 49)) & 0x3ff); } static __inline unsigned int get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 18)) & 0x3); } static __inline unsigned int get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 49)) & 0x3); } static __inline unsigned int get_SrcA_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 6)) & 0x3f); } static __inline unsigned int get_SrcA_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 37)) & 0x3f); } static __inline unsigned int get_SrcA_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 6)) & 0x3f); } static __inline unsigned int get_SrcA_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 37)) & 0x3f); } static __inline unsigned int get_SrcA_Y2(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 20)) & 0x3f); } static __inline unsigned int get_SrcBDest_Y2(tilegx_bundle_bits n) { return (((unsigned int)(n >> 51)) & 0x3f); } static __inline unsigned int get_SrcB_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_SrcB_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int get_SrcB_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_SrcB_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline unsigned int get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num) { const unsigned int n = (unsigned int)num; return (((n >> 12)) & 0x3f); } static __inline unsigned int get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n) { return (((unsigned int)(n >> 43)) & 0x3f); } static __inline int sign_extend(int n, int num_bits) { int shift = (int)(sizeof(int) * 8 - num_bits); return (n << shift) >> shift; } static __inline tilegx_bundle_bits create_BFEnd_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_BFOpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xf) << 24); } static __inline tilegx_bundle_bits create_BFStart_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 18); } static __inline tilegx_bundle_bits create_BrOff_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37); } static __inline tilegx_bundle_bits create_BrType_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x1f)) << 54); } static __inline tilegx_bundle_bits create_Dest_Imm8_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | (((tilegx_bundle_bits)(n & 0x000000c0)) << 43); } static __inline tilegx_bundle_bits create_Dest_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 0); } static __inline tilegx_bundle_bits create_Dest_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 31); } static __inline tilegx_bundle_bits create_Dest_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 0); } static __inline tilegx_bundle_bits create_Dest_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 31); } static __inline tilegx_bundle_bits create_Imm16_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xffff) << 12); } static __inline tilegx_bundle_bits create_Imm16_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0xffff)) << 43); } static __inline tilegx_bundle_bits create_Imm8OpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xff) << 20); } static __inline tilegx_bundle_bits create_Imm8OpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0xff)) << 51); } static __inline tilegx_bundle_bits create_Imm8_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xff) << 12); } static __inline tilegx_bundle_bits create_Imm8_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0xff)) << 43); } static __inline tilegx_bundle_bits create_Imm8_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xff) << 12); } static __inline tilegx_bundle_bits create_Imm8_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0xff)) << 43); } static __inline tilegx_bundle_bits create_JumpOff_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31); } static __inline tilegx_bundle_bits create_JumpOpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x1)) << 58); } static __inline tilegx_bundle_bits create_MF_Imm14_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3fff)) << 37); } static __inline tilegx_bundle_bits create_MT_Imm14_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37); } static __inline tilegx_bundle_bits create_Mode(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3)) << 62); } static __inline tilegx_bundle_bits create_Opcode_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x7) << 28); } static __inline tilegx_bundle_bits create_Opcode_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x7)) << 59); } static __inline tilegx_bundle_bits create_Opcode_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0xf) << 27); } static __inline tilegx_bundle_bits create_Opcode_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0xf)) << 58); } static __inline tilegx_bundle_bits create_Opcode_Y2(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x00000001) << 26) | (((tilegx_bundle_bits)(n & 0x00000002)) << 56); } static __inline tilegx_bundle_bits create_RRROpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3ff) << 18); } static __inline tilegx_bundle_bits create_RRROpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3ff)) << 49); } static __inline tilegx_bundle_bits create_RRROpcodeExtension_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3) << 18); } static __inline tilegx_bundle_bits create_RRROpcodeExtension_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3)) << 49); } static __inline tilegx_bundle_bits create_ShAmt_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_ShAmt_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } static __inline tilegx_bundle_bits create_ShAmt_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_ShAmt_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } static __inline tilegx_bundle_bits create_ShiftOpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3ff) << 18); } static __inline tilegx_bundle_bits create_ShiftOpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3ff)) << 49); } static __inline tilegx_bundle_bits create_ShiftOpcodeExtension_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3) << 18); } static __inline tilegx_bundle_bits create_ShiftOpcodeExtension_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3)) << 49); } static __inline tilegx_bundle_bits create_SrcA_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 6); } static __inline tilegx_bundle_bits create_SrcA_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 37); } static __inline tilegx_bundle_bits create_SrcA_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 6); } static __inline tilegx_bundle_bits create_SrcA_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 37); } static __inline tilegx_bundle_bits create_SrcA_Y2(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 20); } static __inline tilegx_bundle_bits create_SrcBDest_Y2(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 51); } static __inline tilegx_bundle_bits create_SrcB_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_SrcB_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } static __inline tilegx_bundle_bits create_SrcB_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_SrcB_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } static __inline tilegx_bundle_bits create_UnaryOpcodeExtension_X0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_UnaryOpcodeExtension_X1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } static __inline tilegx_bundle_bits create_UnaryOpcodeExtension_Y0(int num) { const unsigned int n = (unsigned int)num; return ((n & 0x3f) << 12); } static __inline tilegx_bundle_bits create_UnaryOpcodeExtension_Y1(int num) { const unsigned int n = (unsigned int)num; return (((tilegx_bundle_bits)(n & 0x3f)) << 43); } const struct tilegx_opcode tilegx_opcodes[336] = { { "bpt", TILEGX_OPC_BPT, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffffffff80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a44ae00000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "info", TILEGX_OPC_INFO, 0xf, 1, TREG_ZERO, 1, { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00fffULL, 0xfff807ff80000000ULL, 0x0000000078000fffULL, 0x3c0007ff80000000ULL, 0ULL }, { 0x0000000040300fffULL, 0x181807ff80000000ULL, 0x0000000010000fffULL, 0x0c0007ff80000000ULL, -1ULL } #endif }, { "infol", TILEGX_OPC_INFOL, 0x3, 1, TREG_ZERO, 1, { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc000000070000fffULL, 0xf80007ff80000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000070000fffULL, 0x380007ff80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld4s_tls", TILEGX_OPC_LD4S_TLS, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1858000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld_tls", TILEGX_OPC_LD_TLS, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18a0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "move", TILEGX_OPC_MOVE, 0xf, 2, TREG_ZERO, 1, { { 8, 9 }, { 6, 7 }, { 10, 11 }, { 12, 13 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0xfffff80000000000ULL, 0x00000000780ff000ULL, 0x3c07f80000000000ULL, 0ULL }, { 0x000000005107f000ULL, 0x283bf80000000000ULL, 0x00000000500bf000ULL, 0x2c05f80000000000ULL, -1ULL } #endif }, { "movei", TILEGX_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1, { { 8, 0 }, { 6, 1 }, { 10, 2 }, { 12, 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00fc0ULL, 0xfff807e000000000ULL, 0x0000000078000fc0ULL, 0x3c0007e000000000ULL, 0ULL }, { 0x0000000040100fc0ULL, 0x180807e000000000ULL, 0x0000000000000fc0ULL, 0x040007e000000000ULL, -1ULL } #endif }, { "moveli", TILEGX_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1, { { 8, 4 }, { 6, 5 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc000000070000fc0ULL, 0xf80007e000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000010000fc0ULL, 0x000007e000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch", TILEGX_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286a801f80000000ULL, -1ULL, -1ULL, 0x41f8000004000000ULL } #endif }, { "prefetch_add_l1", TILEGX_OPC_PREFETCH_ADD_L1, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8001f80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1840001f80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch_add_l1_fault", TILEGX_OPC_PREFETCH_ADD_L1_FAULT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8001f80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1838001f80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch_add_l2", TILEGX_OPC_PREFETCH_ADD_L2, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8001f80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1850001f80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch_add_l2_fault", TILEGX_OPC_PREFETCH_ADD_L2_FAULT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8001f80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1848001f80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch_add_l3", TILEGX_OPC_PREFETCH_ADD_L3, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8001f80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1860001f80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch_add_l3_fault", TILEGX_OPC_PREFETCH_ADD_L3_FAULT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8001f80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1858001f80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "prefetch_l1", TILEGX_OPC_PREFETCH_L1, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286a801f80000000ULL, -1ULL, -1ULL, 0x41f8000004000000ULL } #endif }, { "prefetch_l1_fault", TILEGX_OPC_PREFETCH_L1_FAULT, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286a781f80000000ULL, -1ULL, -1ULL, 0x41f8000000000000ULL } #endif }, { "prefetch_l2", TILEGX_OPC_PREFETCH_L2, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286a901f80000000ULL, -1ULL, -1ULL, 0x43f8000004000000ULL } #endif }, { "prefetch_l2_fault", TILEGX_OPC_PREFETCH_L2_FAULT, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286a881f80000000ULL, -1ULL, -1ULL, 0x43f8000000000000ULL } #endif }, { "prefetch_l3", TILEGX_OPC_PREFETCH_L3, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286aa01f80000000ULL, -1ULL, -1ULL, 0x83f8000000000000ULL } #endif }, { "prefetch_l3_fault", TILEGX_OPC_PREFETCH_L3_FAULT, 0x12, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff81f80000000ULL, 0ULL, 0ULL, 0xc3f8000004000000ULL }, { -1ULL, 0x286a981f80000000ULL, -1ULL, -1ULL, 0x81f8000004000000ULL } #endif }, { "raise", TILEGX_OPC_RAISE, 0x2, 0, TREG_ZERO, 1, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffffffff80000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a44ae80000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "add", TILEGX_OPC_ADD, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x00000000500c0000ULL, 0x2806000000000000ULL, 0x0000000028040000ULL, 0x1802000000000000ULL, -1ULL } #endif }, { "addi", TILEGX_OPC_ADDI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0x0000000078000000ULL, 0x3c00000000000000ULL, 0ULL }, { 0x0000000040100000ULL, 0x1808000000000000ULL, 0ULL, 0x0400000000000000ULL, -1ULL } #endif }, { "addli", TILEGX_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc000000070000000ULL, 0xf800000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000010000000ULL, 0ULL, -1ULL, -1ULL, -1ULL } #endif }, { "addx", TILEGX_OPC_ADDX, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050080000ULL, 0x2804000000000000ULL, 0x0000000028000000ULL, 0x1800000000000000ULL, -1ULL } #endif }, { "addxi", TILEGX_OPC_ADDXI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0x0000000078000000ULL, 0x3c00000000000000ULL, 0ULL }, { 0x0000000040200000ULL, 0x1810000000000000ULL, 0x0000000008000000ULL, 0x0800000000000000ULL, -1ULL } #endif }, { "addxli", TILEGX_OPC_ADDXLI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc000000070000000ULL, 0xf800000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000020000000ULL, 0x0800000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "addxsc", TILEGX_OPC_ADDXSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050040000ULL, 0x2802000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "and", TILEGX_OPC_AND, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050100000ULL, 0x2808000000000000ULL, 0x0000000050000000ULL, 0x2c00000000000000ULL, -1ULL } #endif }, { "andi", TILEGX_OPC_ANDI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0x0000000078000000ULL, 0x3c00000000000000ULL, 0ULL }, { 0x0000000040300000ULL, 0x1818000000000000ULL, 0x0000000010000000ULL, 0x0c00000000000000ULL, -1ULL } #endif }, { "beqz", TILEGX_OPC_BEQZ, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1440000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "beqzt", TILEGX_OPC_BEQZT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1400000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bfexts", TILEGX_OPC_BFEXTS, 0x1, 4, TREG_ZERO, 1, { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007f000000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000034000000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bfextu", TILEGX_OPC_BFEXTU, 0x1, 4, TREG_ZERO, 1, { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007f000000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000035000000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bfins", TILEGX_OPC_BFINS, 0x1, 4, TREG_ZERO, 1, { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007f000000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000036000000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bgez", TILEGX_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x14c0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bgezt", TILEGX_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1480000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bgtz", TILEGX_OPC_BGTZ, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1540000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bgtzt", TILEGX_OPC_BGTZT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1500000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "blbc", TILEGX_OPC_BLBC, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x15c0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "blbct", TILEGX_OPC_BLBCT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1580000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "blbs", TILEGX_OPC_BLBS, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1640000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "blbst", TILEGX_OPC_BLBST, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1600000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "blez", TILEGX_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x16c0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "blezt", TILEGX_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1680000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bltz", TILEGX_OPC_BLTZ, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1740000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bltzt", TILEGX_OPC_BLTZT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1700000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bnez", TILEGX_OPC_BNEZ, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x17c0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "bnezt", TILEGX_OPC_BNEZT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xffc0000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1780000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "clz", TILEGX_OPC_CLZ, 0x5, 2, TREG_ZERO, 1, { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051481000ULL, -1ULL, 0x00000000300c1000ULL, -1ULL, -1ULL } #endif }, { "cmoveqz", TILEGX_OPC_CMOVEQZ, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050140000ULL, -1ULL, 0x0000000048000000ULL, -1ULL, -1ULL } #endif }, { "cmovnez", TILEGX_OPC_CMOVNEZ, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050180000ULL, -1ULL, 0x0000000048040000ULL, -1ULL, -1ULL } #endif }, { "cmpeq", TILEGX_OPC_CMPEQ, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x00000000501c0000ULL, 0x280a000000000000ULL, 0x0000000040000000ULL, 0x2404000000000000ULL, -1ULL } #endif }, { "cmpeqi", TILEGX_OPC_CMPEQI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0x0000000078000000ULL, 0x3c00000000000000ULL, 0ULL }, { 0x0000000040400000ULL, 0x1820000000000000ULL, 0x0000000018000000ULL, 0x1000000000000000ULL, -1ULL } #endif }, { "cmpexch", TILEGX_OPC_CMPEXCH, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x280e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmpexch4", TILEGX_OPC_CMPEXCH4, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x280c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmples", TILEGX_OPC_CMPLES, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050200000ULL, 0x2810000000000000ULL, 0x0000000038000000ULL, 0x2000000000000000ULL, -1ULL } #endif }, { "cmpleu", TILEGX_OPC_CMPLEU, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050240000ULL, 0x2812000000000000ULL, 0x0000000038040000ULL, 0x2002000000000000ULL, -1ULL } #endif }, { "cmplts", TILEGX_OPC_CMPLTS, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050280000ULL, 0x2814000000000000ULL, 0x0000000038080000ULL, 0x2004000000000000ULL, -1ULL } #endif }, { "cmpltsi", TILEGX_OPC_CMPLTSI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0x0000000078000000ULL, 0x3c00000000000000ULL, 0ULL }, { 0x0000000040500000ULL, 0x1828000000000000ULL, 0x0000000020000000ULL, 0x1400000000000000ULL, -1ULL } #endif }, { "cmpltu", TILEGX_OPC_CMPLTU, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x00000000502c0000ULL, 0x2816000000000000ULL, 0x00000000380c0000ULL, 0x2006000000000000ULL, -1ULL } #endif }, { "cmpltui", TILEGX_OPC_CMPLTUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040600000ULL, 0x1830000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmpne", TILEGX_OPC_CMPNE, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050300000ULL, 0x2818000000000000ULL, 0x0000000040040000ULL, 0x2406000000000000ULL, -1ULL } #endif }, { "cmul", TILEGX_OPC_CMUL, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000504c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmula", TILEGX_OPC_CMULA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050380000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmulaf", TILEGX_OPC_CMULAF, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050340000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmulf", TILEGX_OPC_CMULF, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050400000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmulfr", TILEGX_OPC_CMULFR, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000503c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmulh", TILEGX_OPC_CMULH, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050480000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "cmulhr", TILEGX_OPC_CMULHR, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050440000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "crc32_32", TILEGX_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050500000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "crc32_8", TILEGX_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050540000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ctz", TILEGX_OPC_CTZ, 0x5, 2, TREG_ZERO, 1, { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051482000ULL, -1ULL, 0x00000000300c2000ULL, -1ULL, -1ULL } #endif }, { "dblalign", TILEGX_OPC_DBLALIGN, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050640000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "dblalign2", TILEGX_OPC_DBLALIGN2, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050580000ULL, 0x281a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "dblalign4", TILEGX_OPC_DBLALIGN4, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000505c0000ULL, 0x281c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "dblalign6", TILEGX_OPC_DBLALIGN6, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050600000ULL, 0x281e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "drain", TILEGX_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a080000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "dtlbpr", TILEGX_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a100000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "exch", TILEGX_OPC_EXCH, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2822000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "exch4", TILEGX_OPC_EXCH4, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2820000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_add_flags", TILEGX_OPC_FDOUBLE_ADD_FLAGS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000506c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_addsub", TILEGX_OPC_FDOUBLE_ADDSUB, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050680000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_mul_flags", TILEGX_OPC_FDOUBLE_MUL_FLAGS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050700000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_pack1", TILEGX_OPC_FDOUBLE_PACK1, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050740000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_pack2", TILEGX_OPC_FDOUBLE_PACK2, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050780000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_sub_flags", TILEGX_OPC_FDOUBLE_SUB_FLAGS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000507c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_unpack_max", TILEGX_OPC_FDOUBLE_UNPACK_MAX, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050800000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fdouble_unpack_min", TILEGX_OPC_FDOUBLE_UNPACK_MIN, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050840000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchadd", TILEGX_OPC_FETCHADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x282a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchadd4", TILEGX_OPC_FETCHADD4, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2824000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchaddgez", TILEGX_OPC_FETCHADDGEZ, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2828000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchaddgez4", TILEGX_OPC_FETCHADDGEZ4, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2826000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchand", TILEGX_OPC_FETCHAND, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x282e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchand4", TILEGX_OPC_FETCHAND4, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x282c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchor", TILEGX_OPC_FETCHOR, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2832000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fetchor4", TILEGX_OPC_FETCHOR4, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2830000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "finv", TILEGX_OPC_FINV, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a180000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "flush", TILEGX_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a280000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "flushwb", TILEGX_OPC_FLUSHWB, 0x2, 0, TREG_ZERO, 1, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a200000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fnop", TILEGX_OPC_FNOP, 0xf, 0, TREG_ZERO, 1, { { }, { }, { }, { }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0xfffff80000000000ULL, 0x00000000780ff000ULL, 0x3c07f80000000000ULL, 0ULL }, { 0x0000000051483000ULL, 0x286a300000000000ULL, 0x00000000300c3000ULL, 0x1c06400000000000ULL, -1ULL } #endif }, { "fsingle_add1", TILEGX_OPC_FSINGLE_ADD1, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050880000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fsingle_addsub2", TILEGX_OPC_FSINGLE_ADDSUB2, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000508c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fsingle_mul1", TILEGX_OPC_FSINGLE_MUL1, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050900000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fsingle_mul2", TILEGX_OPC_FSINGLE_MUL2, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050940000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fsingle_pack1", TILEGX_OPC_FSINGLE_PACK1, 0x5, 2, TREG_ZERO, 1, { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051484000ULL, -1ULL, 0x00000000300c4000ULL, -1ULL, -1ULL } #endif }, { "fsingle_pack2", TILEGX_OPC_FSINGLE_PACK2, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050980000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "fsingle_sub1", TILEGX_OPC_FSINGLE_SUB1, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000509c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "icoh", TILEGX_OPC_ICOH, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a380000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ill", TILEGX_OPC_ILL, 0xa, 0, TREG_ZERO, 1, { { 0, }, { }, { 0, }, { }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0x3c07f80000000000ULL, 0ULL }, { -1ULL, 0x286a400000000000ULL, -1ULL, 0x1c06480000000000ULL, -1ULL } #endif }, { "inv", TILEGX_OPC_INV, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a480000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "iret", TILEGX_OPC_IRET, 0x2, 0, TREG_ZERO, 1, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286a500000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "j", TILEGX_OPC_J, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfc00000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2400000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "jal", TILEGX_OPC_JAL, 0x2, 1, TREG_LR, 1, { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfc00000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2000000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "jalr", TILEGX_OPC_JALR, 0xa, 1, TREG_LR, 1, { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0x3c07f80000000000ULL, 0ULL }, { -1ULL, 0x286a600000000000ULL, -1ULL, 0x1c06580000000000ULL, -1ULL } #endif }, { "jalrp", TILEGX_OPC_JALRP, 0xa, 1, TREG_LR, 1, { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0x3c07f80000000000ULL, 0ULL }, { -1ULL, 0x286a580000000000ULL, -1ULL, 0x1c06500000000000ULL, -1ULL } #endif }, { "jr", TILEGX_OPC_JR, 0xa, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0x3c07f80000000000ULL, 0ULL }, { -1ULL, 0x286a700000000000ULL, -1ULL, 0x1c06680000000000ULL, -1ULL } #endif }, { "jrp", TILEGX_OPC_JRP, 0xa, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0x3c07f80000000000ULL, 0ULL }, { -1ULL, 0x286a680000000000ULL, -1ULL, 0x1c06600000000000ULL, -1ULL } #endif }, { "ld", TILEGX_OPC_LD, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286ae80000000000ULL, -1ULL, -1ULL, 0x8200000004000000ULL } #endif }, { "ld1s", TILEGX_OPC_LD1S, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286a780000000000ULL, -1ULL, -1ULL, 0x4000000000000000ULL } #endif }, { "ld1s_add", TILEGX_OPC_LD1S_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1838000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld1u", TILEGX_OPC_LD1U, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286a800000000000ULL, -1ULL, -1ULL, 0x4000000004000000ULL } #endif }, { "ld1u_add", TILEGX_OPC_LD1U_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1840000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld2s", TILEGX_OPC_LD2S, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286a880000000000ULL, -1ULL, -1ULL, 0x4200000000000000ULL } #endif }, { "ld2s_add", TILEGX_OPC_LD2S_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1848000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld2u", TILEGX_OPC_LD2U, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286a900000000000ULL, -1ULL, -1ULL, 0x4200000004000000ULL } #endif }, { "ld2u_add", TILEGX_OPC_LD2U_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1850000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld4s", TILEGX_OPC_LD4S, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286a980000000000ULL, -1ULL, -1ULL, 0x8000000004000000ULL } #endif }, { "ld4s_add", TILEGX_OPC_LD4S_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1858000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld4u", TILEGX_OPC_LD4U, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x286aa00000000000ULL, -1ULL, -1ULL, 0x8200000000000000ULL } #endif }, { "ld4u_add", TILEGX_OPC_LD4U_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1860000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ld_add", TILEGX_OPC_LD_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18a0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldna", TILEGX_OPC_LDNA, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286aa80000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldna_add", TILEGX_OPC_LDNA_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18a8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt", TILEGX_OPC_LDNT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ae00000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt1s", TILEGX_OPC_LDNT1S, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ab00000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt1s_add", TILEGX_OPC_LDNT1S_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1868000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt1u", TILEGX_OPC_LDNT1U, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ab80000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt1u_add", TILEGX_OPC_LDNT1U_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1870000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt2s", TILEGX_OPC_LDNT2S, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ac00000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt2s_add", TILEGX_OPC_LDNT2S_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1878000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt2u", TILEGX_OPC_LDNT2U, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ac80000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt2u_add", TILEGX_OPC_LDNT2U_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1880000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt4s", TILEGX_OPC_LDNT4S, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ad00000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt4s_add", TILEGX_OPC_LDNT4S_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1888000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt4u", TILEGX_OPC_LDNT4U, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286ad80000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt4u_add", TILEGX_OPC_LDNT4U_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1890000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "ldnt_add", TILEGX_OPC_LDNT_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1898000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "lnk", TILEGX_OPC_LNK, 0xa, 1, TREG_ZERO, 1, { { 0, }, { 6 }, { 0, }, { 12 }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0x3c07f80000000000ULL, 0ULL }, { -1ULL, 0x286af00000000000ULL, -1ULL, 0x1c06700000000000ULL, -1ULL } #endif }, { "mf", TILEGX_OPC_MF, 0x2, 0, TREG_ZERO, 1, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286af80000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mfspr", TILEGX_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 6, 27 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18b0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mm", TILEGX_OPC_MM, 0x1, 4, TREG_ZERO, 1, { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007f000000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000037000000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mnz", TILEGX_OPC_MNZ, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050a00000ULL, 0x2834000000000000ULL, 0x0000000048080000ULL, 0x2804000000000000ULL, -1ULL } #endif }, { "mtspr", TILEGX_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 28, 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18b8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_hs_hs", TILEGX_OPC_MUL_HS_HS, 0x5, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050d40000ULL, -1ULL, 0x0000000068000000ULL, -1ULL, -1ULL } #endif }, { "mul_hs_hu", TILEGX_OPC_MUL_HS_HU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050d80000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_hs_ls", TILEGX_OPC_MUL_HS_LS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050dc0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_hs_lu", TILEGX_OPC_MUL_HS_LU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050e00000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_hu_hu", TILEGX_OPC_MUL_HU_HU, 0x5, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050e40000ULL, -1ULL, 0x0000000068040000ULL, -1ULL, -1ULL } #endif }, { "mul_hu_ls", TILEGX_OPC_MUL_HU_LS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050e80000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_hu_lu", TILEGX_OPC_MUL_HU_LU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050ec0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_ls_ls", TILEGX_OPC_MUL_LS_LS, 0x5, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050f00000ULL, -1ULL, 0x0000000068080000ULL, -1ULL, -1ULL } #endif }, { "mul_ls_lu", TILEGX_OPC_MUL_LS_LU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050f40000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mul_lu_lu", TILEGX_OPC_MUL_LU_LU, 0x5, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050f80000ULL, -1ULL, 0x00000000680c0000ULL, -1ULL, -1ULL } #endif }, { "mula_hs_hs", TILEGX_OPC_MULA_HS_HS, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050a80000ULL, -1ULL, 0x0000000070000000ULL, -1ULL, -1ULL } #endif }, { "mula_hs_hu", TILEGX_OPC_MULA_HS_HU, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050ac0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mula_hs_ls", TILEGX_OPC_MULA_HS_LS, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050b00000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mula_hs_lu", TILEGX_OPC_MULA_HS_LU, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050b40000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mula_hu_hu", TILEGX_OPC_MULA_HU_HU, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050b80000ULL, -1ULL, 0x0000000070040000ULL, -1ULL, -1ULL } #endif }, { "mula_hu_ls", TILEGX_OPC_MULA_HU_LS, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050bc0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mula_hu_lu", TILEGX_OPC_MULA_HU_LU, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050c00000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mula_ls_ls", TILEGX_OPC_MULA_LS_LS, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050c40000ULL, -1ULL, 0x0000000070080000ULL, -1ULL, -1ULL } #endif }, { "mula_ls_lu", TILEGX_OPC_MULA_LS_LU, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000050c80000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "mula_lu_lu", TILEGX_OPC_MULA_LU_LU, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050cc0000ULL, -1ULL, 0x00000000700c0000ULL, -1ULL, -1ULL } #endif }, { "mulax", TILEGX_OPC_MULAX, 0x5, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050a40000ULL, -1ULL, 0x0000000040080000ULL, -1ULL, -1ULL } #endif }, { "mulx", TILEGX_OPC_MULX, 0x5, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0x00000000780c0000ULL, 0ULL, 0ULL }, { 0x0000000050d00000ULL, -1ULL, 0x00000000400c0000ULL, -1ULL, -1ULL } #endif }, { "mz", TILEGX_OPC_MZ, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000050fc0000ULL, 0x2836000000000000ULL, 0x00000000480c0000ULL, 0x2806000000000000ULL, -1ULL } #endif }, { "nap", TILEGX_OPC_NAP, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286b000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "nop", TILEGX_OPC_NOP, 0xf, 0, TREG_ZERO, 1, { { }, { }, { }, { }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0xfffff80000000000ULL, 0x00000000780ff000ULL, 0x3c07f80000000000ULL, 0ULL }, { 0x0000000051485000ULL, 0x286b080000000000ULL, 0x00000000300c5000ULL, 0x1c06780000000000ULL, -1ULL } #endif }, { "nor", TILEGX_OPC_NOR, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051000000ULL, 0x2838000000000000ULL, 0x0000000050040000ULL, 0x2c02000000000000ULL, -1ULL } #endif }, { "or", TILEGX_OPC_OR, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051040000ULL, 0x283a000000000000ULL, 0x0000000050080000ULL, 0x2c04000000000000ULL, -1ULL } #endif }, { "ori", TILEGX_OPC_ORI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040700000ULL, 0x18c0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "pcnt", TILEGX_OPC_PCNT, 0x5, 2, TREG_ZERO, 1, { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051486000ULL, -1ULL, 0x00000000300c6000ULL, -1ULL, -1ULL } #endif }, { "revbits", TILEGX_OPC_REVBITS, 0x5, 2, TREG_ZERO, 1, { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051487000ULL, -1ULL, 0x00000000300c7000ULL, -1ULL, -1ULL } #endif }, { "revbytes", TILEGX_OPC_REVBYTES, 0x5, 2, TREG_ZERO, 1, { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051488000ULL, -1ULL, 0x00000000300c8000ULL, -1ULL, -1ULL } #endif }, { "rotl", TILEGX_OPC_ROTL, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051080000ULL, 0x283c000000000000ULL, 0x0000000058000000ULL, 0x3000000000000000ULL, -1ULL } #endif }, { "rotli", TILEGX_OPC_ROTLI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000060040000ULL, 0x3002000000000000ULL, 0x0000000078000000ULL, 0x3800000000000000ULL, -1ULL } #endif }, { "shl", TILEGX_OPC_SHL, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051280000ULL, 0x284c000000000000ULL, 0x0000000058040000ULL, 0x3002000000000000ULL, -1ULL } #endif }, { "shl16insli", TILEGX_OPC_SHL16INSLI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc000000070000000ULL, 0xf800000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000070000000ULL, 0x3800000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "shl1add", TILEGX_OPC_SHL1ADD, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051100000ULL, 0x2840000000000000ULL, 0x0000000030000000ULL, 0x1c00000000000000ULL, -1ULL } #endif }, { "shl1addx", TILEGX_OPC_SHL1ADDX, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x00000000510c0000ULL, 0x283e000000000000ULL, 0x0000000060040000ULL, 0x3402000000000000ULL, -1ULL } #endif }, { "shl2add", TILEGX_OPC_SHL2ADD, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051180000ULL, 0x2844000000000000ULL, 0x0000000030040000ULL, 0x1c02000000000000ULL, -1ULL } #endif }, { "shl2addx", TILEGX_OPC_SHL2ADDX, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051140000ULL, 0x2842000000000000ULL, 0x0000000060080000ULL, 0x3404000000000000ULL, -1ULL } #endif }, { "shl3add", TILEGX_OPC_SHL3ADD, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051200000ULL, 0x2848000000000000ULL, 0x0000000030080000ULL, 0x1c04000000000000ULL, -1ULL } #endif }, { "shl3addx", TILEGX_OPC_SHL3ADDX, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x00000000511c0000ULL, 0x2846000000000000ULL, 0x00000000600c0000ULL, 0x3406000000000000ULL, -1ULL } #endif }, { "shli", TILEGX_OPC_SHLI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000060080000ULL, 0x3004000000000000ULL, 0x0000000078040000ULL, 0x3802000000000000ULL, -1ULL } #endif }, { "shlx", TILEGX_OPC_SHLX, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051240000ULL, 0x284a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "shlxi", TILEGX_OPC_SHLXI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000600c0000ULL, 0x3006000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "shrs", TILEGX_OPC_SHRS, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x00000000512c0000ULL, 0x284e000000000000ULL, 0x0000000058080000ULL, 0x3004000000000000ULL, -1ULL } #endif }, { "shrsi", TILEGX_OPC_SHRSI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000060100000ULL, 0x3008000000000000ULL, 0x0000000078080000ULL, 0x3804000000000000ULL, -1ULL } #endif }, { "shru", TILEGX_OPC_SHRU, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051340000ULL, 0x2852000000000000ULL, 0x00000000580c0000ULL, 0x3006000000000000ULL, -1ULL } #endif }, { "shrui", TILEGX_OPC_SHRUI, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000060140000ULL, 0x300a000000000000ULL, 0x00000000780c0000ULL, 0x3806000000000000ULL, -1ULL } #endif }, { "shrux", TILEGX_OPC_SHRUX, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051300000ULL, 0x2850000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "shruxi", TILEGX_OPC_SHRUXI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000060180000ULL, 0x300c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "shufflebytes", TILEGX_OPC_SHUFFLEBYTES, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051380000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "st", TILEGX_OPC_ST, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x2862000000000000ULL, -1ULL, -1ULL, 0xc200000004000000ULL } #endif }, { "st1", TILEGX_OPC_ST1, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x2854000000000000ULL, -1ULL, -1ULL, 0xc000000000000000ULL } #endif }, { "st1_add", TILEGX_OPC_ST1_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18c8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "st2", TILEGX_OPC_ST2, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x2856000000000000ULL, -1ULL, -1ULL, 0xc000000004000000ULL } #endif }, { "st2_add", TILEGX_OPC_ST2_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18d0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "st4", TILEGX_OPC_ST4, 0x12, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0xc200000004000000ULL }, { -1ULL, 0x2858000000000000ULL, -1ULL, -1ULL, 0xc200000000000000ULL } #endif }, { "st4_add", TILEGX_OPC_ST4_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18d8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "st_add", TILEGX_OPC_ST_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x1900000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt", TILEGX_OPC_STNT, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x2860000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt1", TILEGX_OPC_STNT1, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x285a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt1_add", TILEGX_OPC_STNT1_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18e0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt2", TILEGX_OPC_STNT2, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x285c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt2_add", TILEGX_OPC_STNT2_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18e8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt4", TILEGX_OPC_STNT4, 0x2, 2, TREG_ZERO, 1, { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x285e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt4_add", TILEGX_OPC_STNT4_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18f0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "stnt_add", TILEGX_OPC_STNT_ADD, 0x2, 3, TREG_ZERO, 1, { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x18f8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "sub", TILEGX_OPC_SUB, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051440000ULL, 0x2868000000000000ULL, 0x00000000280c0000ULL, 0x1806000000000000ULL, -1ULL } #endif }, { "subx", TILEGX_OPC_SUBX, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000051400000ULL, 0x2866000000000000ULL, 0x0000000028080000ULL, 0x1804000000000000ULL, -1ULL } #endif }, { "subxsc", TILEGX_OPC_SUBXSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000513c0000ULL, 0x2864000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "swint0", TILEGX_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286b100000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "swint1", TILEGX_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286b180000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "swint2", TILEGX_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286b200000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "swint3", TILEGX_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0, { { 0, }, { }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286b280000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "tblidxb0", TILEGX_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1, { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x0000000051489000ULL, -1ULL, 0x00000000300c9000ULL, -1ULL, -1ULL } #endif }, { "tblidxb1", TILEGX_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1, { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x000000005148a000ULL, -1ULL, 0x00000000300ca000ULL, -1ULL, -1ULL } #endif }, { "tblidxb2", TILEGX_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1, { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x000000005148b000ULL, -1ULL, 0x00000000300cb000ULL, -1ULL, -1ULL } #endif }, { "tblidxb3", TILEGX_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1, { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffff000ULL, 0ULL, 0x00000000780ff000ULL, 0ULL, 0ULL }, { 0x000000005148c000ULL, -1ULL, 0x00000000300cc000ULL, -1ULL, -1ULL } #endif }, { "v1add", TILEGX_OPC_V1ADD, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051500000ULL, 0x286e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1addi", TILEGX_OPC_V1ADDI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040800000ULL, 0x1908000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1adduc", TILEGX_OPC_V1ADDUC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000514c0000ULL, 0x286c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1adiffu", TILEGX_OPC_V1ADIFFU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051540000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1avgu", TILEGX_OPC_V1AVGU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051580000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpeq", TILEGX_OPC_V1CMPEQ, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000515c0000ULL, 0x2870000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpeqi", TILEGX_OPC_V1CMPEQI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040900000ULL, 0x1910000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmples", TILEGX_OPC_V1CMPLES, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051600000ULL, 0x2872000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpleu", TILEGX_OPC_V1CMPLEU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051640000ULL, 0x2874000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmplts", TILEGX_OPC_V1CMPLTS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051680000ULL, 0x2876000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpltsi", TILEGX_OPC_V1CMPLTSI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040a00000ULL, 0x1918000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpltu", TILEGX_OPC_V1CMPLTU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000516c0000ULL, 0x2878000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpltui", TILEGX_OPC_V1CMPLTUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040b00000ULL, 0x1920000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1cmpne", TILEGX_OPC_V1CMPNE, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051700000ULL, 0x287a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1ddotpu", TILEGX_OPC_V1DDOTPU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052880000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1ddotpua", TILEGX_OPC_V1DDOTPUA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052840000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1ddotpus", TILEGX_OPC_V1DDOTPUS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051780000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1ddotpusa", TILEGX_OPC_V1DDOTPUSA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051740000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1dotp", TILEGX_OPC_V1DOTP, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051880000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1dotpa", TILEGX_OPC_V1DOTPA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000517c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1dotpu", TILEGX_OPC_V1DOTPU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052900000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1dotpua", TILEGX_OPC_V1DOTPUA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000528c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1dotpus", TILEGX_OPC_V1DOTPUS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051840000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1dotpusa", TILEGX_OPC_V1DOTPUSA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051800000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1int_h", TILEGX_OPC_V1INT_H, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000518c0000ULL, 0x287c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1int_l", TILEGX_OPC_V1INT_L, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051900000ULL, 0x287e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1maxu", TILEGX_OPC_V1MAXU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051940000ULL, 0x2880000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1maxui", TILEGX_OPC_V1MAXUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040c00000ULL, 0x1928000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1minu", TILEGX_OPC_V1MINU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051980000ULL, 0x2882000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1minui", TILEGX_OPC_V1MINUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040d00000ULL, 0x1930000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1mnz", TILEGX_OPC_V1MNZ, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000519c0000ULL, 0x2884000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1multu", TILEGX_OPC_V1MULTU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051a00000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1mulu", TILEGX_OPC_V1MULU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051a80000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1mulus", TILEGX_OPC_V1MULUS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051a40000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1mz", TILEGX_OPC_V1MZ, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051ac0000ULL, 0x2886000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1sadau", TILEGX_OPC_V1SADAU, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051b00000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1sadu", TILEGX_OPC_V1SADU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051b40000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1shl", TILEGX_OPC_V1SHL, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051b80000ULL, 0x2888000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1shli", TILEGX_OPC_V1SHLI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000601c0000ULL, 0x300e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1shrs", TILEGX_OPC_V1SHRS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051bc0000ULL, 0x288a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1shrsi", TILEGX_OPC_V1SHRSI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000060200000ULL, 0x3010000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1shru", TILEGX_OPC_V1SHRU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051c00000ULL, 0x288c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1shrui", TILEGX_OPC_V1SHRUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000060240000ULL, 0x3012000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1sub", TILEGX_OPC_V1SUB, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051c80000ULL, 0x2890000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v1subuc", TILEGX_OPC_V1SUBUC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051c40000ULL, 0x288e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2add", TILEGX_OPC_V2ADD, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051d00000ULL, 0x2894000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2addi", TILEGX_OPC_V2ADDI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040e00000ULL, 0x1938000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2addsc", TILEGX_OPC_V2ADDSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051cc0000ULL, 0x2892000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2adiffs", TILEGX_OPC_V2ADIFFS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051d40000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2avgs", TILEGX_OPC_V2AVGS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051d80000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpeq", TILEGX_OPC_V2CMPEQ, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051dc0000ULL, 0x2896000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpeqi", TILEGX_OPC_V2CMPEQI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000040f00000ULL, 0x1940000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmples", TILEGX_OPC_V2CMPLES, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051e00000ULL, 0x2898000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpleu", TILEGX_OPC_V2CMPLEU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051e40000ULL, 0x289a000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmplts", TILEGX_OPC_V2CMPLTS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051e80000ULL, 0x289c000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpltsi", TILEGX_OPC_V2CMPLTSI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000041000000ULL, 0x1948000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpltu", TILEGX_OPC_V2CMPLTU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051ec0000ULL, 0x289e000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpltui", TILEGX_OPC_V2CMPLTUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000041100000ULL, 0x1950000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2cmpne", TILEGX_OPC_V2CMPNE, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051f00000ULL, 0x28a0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2dotp", TILEGX_OPC_V2DOTP, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051f80000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2dotpa", TILEGX_OPC_V2DOTPA, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051f40000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2int_h", TILEGX_OPC_V2INT_H, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000051fc0000ULL, 0x28a2000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2int_l", TILEGX_OPC_V2INT_L, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052000000ULL, 0x28a4000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2maxs", TILEGX_OPC_V2MAXS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052040000ULL, 0x28a6000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2maxsi", TILEGX_OPC_V2MAXSI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000041200000ULL, 0x1958000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2mins", TILEGX_OPC_V2MINS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052080000ULL, 0x28a8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2minsi", TILEGX_OPC_V2MINSI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000041300000ULL, 0x1960000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2mnz", TILEGX_OPC_V2MNZ, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000520c0000ULL, 0x28aa000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2mulfsc", TILEGX_OPC_V2MULFSC, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052100000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2muls", TILEGX_OPC_V2MULS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052140000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2mults", TILEGX_OPC_V2MULTS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052180000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2mz", TILEGX_OPC_V2MZ, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000521c0000ULL, 0x28ac000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2packh", TILEGX_OPC_V2PACKH, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052200000ULL, 0x28ae000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2packl", TILEGX_OPC_V2PACKL, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052240000ULL, 0x28b0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2packuc", TILEGX_OPC_V2PACKUC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052280000ULL, 0x28b2000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2sadas", TILEGX_OPC_V2SADAS, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000522c0000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2sadau", TILEGX_OPC_V2SADAU, 0x1, 3, TREG_ZERO, 1, { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052300000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2sads", TILEGX_OPC_V2SADS, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052340000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2sadu", TILEGX_OPC_V2SADU, 0x1, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052380000ULL, -1ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shl", TILEGX_OPC_V2SHL, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052400000ULL, 0x28b6000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shli", TILEGX_OPC_V2SHLI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000060280000ULL, 0x3014000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shlsc", TILEGX_OPC_V2SHLSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000523c0000ULL, 0x28b4000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shrs", TILEGX_OPC_V2SHRS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052440000ULL, 0x28b8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shrsi", TILEGX_OPC_V2SHRSI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000602c0000ULL, 0x3016000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shru", TILEGX_OPC_V2SHRU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052480000ULL, 0x28ba000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2shrui", TILEGX_OPC_V2SHRUI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000060300000ULL, 0x3018000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2sub", TILEGX_OPC_V2SUB, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052500000ULL, 0x28be000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v2subsc", TILEGX_OPC_V2SUBSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000524c0000ULL, 0x28bc000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4add", TILEGX_OPC_V4ADD, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052580000ULL, 0x28c2000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4addsc", TILEGX_OPC_V4ADDSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052540000ULL, 0x28c0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4int_h", TILEGX_OPC_V4INT_H, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000525c0000ULL, 0x28c4000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4int_l", TILEGX_OPC_V4INT_L, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052600000ULL, 0x28c6000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4packsc", TILEGX_OPC_V4PACKSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052640000ULL, 0x28c8000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4shl", TILEGX_OPC_V4SHL, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000526c0000ULL, 0x28cc000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4shlsc", TILEGX_OPC_V4SHLSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052680000ULL, 0x28ca000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4shrs", TILEGX_OPC_V4SHRS, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052700000ULL, 0x28ce000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4shru", TILEGX_OPC_V4SHRU, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052740000ULL, 0x28d0000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4sub", TILEGX_OPC_V4SUB, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x00000000527c0000ULL, 0x28d4000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "v4subsc", TILEGX_OPC_V4SUBSC, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000052780000ULL, 0x28d2000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "wh64", TILEGX_OPC_WH64, 0x2, 1, TREG_ZERO, 1, { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0ULL, 0xfffff80000000000ULL, 0ULL, 0ULL, 0ULL }, { -1ULL, 0x286b300000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { "xor", TILEGX_OPC_XOR, 0xf, 3, TREG_ZERO, 1, { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ffc0000ULL, 0xfffe000000000000ULL, 0x00000000780c0000ULL, 0x3c06000000000000ULL, 0ULL }, { 0x0000000052800000ULL, 0x28d6000000000000ULL, 0x00000000500c0000ULL, 0x2c06000000000000ULL, -1ULL } #endif }, { "xori", TILEGX_OPC_XORI, 0x3, 3, TREG_ZERO, 1, { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, #ifndef DISASM_ONLY { 0xc00000007ff00000ULL, 0xfff8000000000000ULL, 0ULL, 0ULL, 0ULL }, { 0x0000000041400000ULL, 0x1968000000000000ULL, -1ULL, -1ULL, -1ULL } #endif }, { NULL, TILEGX_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } }, #ifndef DISASM_ONLY { 0, }, { 0, } #endif } }; #define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6)) #define CHILD(array_index) (TILEGX_OPC_NONE + (array_index)) static const unsigned short decode_X0_fsm[936] = { BITFIELD(22, 9) /* index 0 */, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(528), CHILD(578), CHILD(583), CHILD(588), CHILD(593), CHILD(598), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(603), CHILD(620), CHILD(637), CHILD(654), CHILD(671), CHILD(703), CHILD(797), CHILD(814), CHILD(831), CHILD(848), CHILD(865), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(889), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), BITFIELD(6, 2) /* index 513 */, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), BITFIELD(8, 2) /* index 518 */, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), BITFIELD(10, 2) /* index 523 */, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, BITFIELD(20, 2) /* index 528 */, TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), BITFIELD(6, 2) /* index 533 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), BITFIELD(8, 2) /* index 538 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), BITFIELD(10, 2) /* index 543 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, BITFIELD(0, 2) /* index 548 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), BITFIELD(2, 2) /* index 553 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), BITFIELD(4, 2) /* index 558 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), BITFIELD(6, 2) /* index 563 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), BITFIELD(8, 2) /* index 568 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), BITFIELD(10, 2) /* index 573 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, BITFIELD(20, 2) /* index 578 */, TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, TILEGX_OPC_ORI, BITFIELD(20, 2) /* index 583 */, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI, TILEGX_OPC_V1CMPLTUI, BITFIELD(20, 2) /* index 588 */, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI, TILEGX_OPC_V2CMPEQI, BITFIELD(20, 2) /* index 593 */, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI, TILEGX_OPC_V2MINSI, BITFIELD(20, 2) /* index 598 */, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(18, 4) /* index 603 */, TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_AND, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, TILEGX_OPC_CMPNE, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULA, TILEGX_OPC_CMULFR, BITFIELD(18, 4) /* index 620 */, TILEGX_OPC_CMULF, TILEGX_OPC_CMULHR, TILEGX_OPC_CMULH, TILEGX_OPC_CMUL, TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DBLALIGN, TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_ADD_FLAGS, TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1, TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS, BITFIELD(18, 4) /* index 637 */, TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN, TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2, TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK2, TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_MNZ, TILEGX_OPC_MULAX, TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS, TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS, BITFIELD(18, 4) /* index 654 */, TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU, TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULX, TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU, TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU, TILEGX_OPC_MZ, BITFIELD(18, 4) /* index 671 */, TILEGX_OPC_NOR, CHILD(688), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_SHUFFLEBYTES, TILEGX_OPC_SUBXSC, BITFIELD(12, 2) /* index 688 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(693), BITFIELD(14, 2) /* index 693 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(698), BITFIELD(16, 2) /* index 698 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, BITFIELD(18, 4) /* index 703 */, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, CHILD(720), TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DOTPA, BITFIELD(12, 4) /* index 720 */, TILEGX_OPC_NONE, CHILD(737), CHILD(742), CHILD(747), CHILD(752), CHILD(757), CHILD(762), CHILD(767), CHILD(772), CHILD(777), CHILD(782), CHILD(787), CHILD(792), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 737 */, TILEGX_OPC_CLZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 742 */, TILEGX_OPC_CTZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 747 */, TILEGX_OPC_FNOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 752 */, TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 757 */, TILEGX_OPC_NOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 762 */, TILEGX_OPC_PCNT, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 767 */, TILEGX_OPC_REVBITS, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 772 */, TILEGX_OPC_REVBYTES, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 777 */, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 782 */, TILEGX_OPC_TBLIDXB1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 787 */, TILEGX_OPC_TBLIDXB2, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(16, 2) /* index 792 */, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(18, 4) /* index 797 */, TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTP, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULUS, TILEGX_OPC_V1MULU, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU, TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, BITFIELD(18, 4) /* index 814 */, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS, TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2INT_H, BITFIELD(18, 4) /* index 831 */, TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ, TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS, TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHLSC, BITFIELD(18, 4) /* index 848 */, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, TILEGX_OPC_V4SUB, BITFIELD(18, 3) /* index 865 */, CHILD(874), CHILD(877), CHILD(880), CHILD(883), CHILD(886), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(21, 1) /* index 874 */, TILEGX_OPC_XOR, TILEGX_OPC_NONE, BITFIELD(21, 1) /* index 877 */, TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_NONE, BITFIELD(21, 1) /* index 880 */, TILEGX_OPC_V1DDOTPU, TILEGX_OPC_NONE, BITFIELD(21, 1) /* index 883 */, TILEGX_OPC_V1DOTPUA, TILEGX_OPC_NONE, BITFIELD(21, 1) /* index 886 */, TILEGX_OPC_V1DOTPU, TILEGX_OPC_NONE, BITFIELD(18, 4) /* index 889 */, TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(0, 2) /* index 906 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(911), BITFIELD(2, 2) /* index 911 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(916), BITFIELD(4, 2) /* index 916 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(921), BITFIELD(6, 2) /* index 921 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(926), BITFIELD(8, 2) /* index 926 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(931), BITFIELD(10, 2) /* index 931 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_INFOL, }; static const unsigned short decode_X1_fsm[1266] = { BITFIELD(53, 9) /* index 0 */, CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZ, TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZ, TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZ, TILEGX_OPC_BLBCT, TILEGX_OPC_BLBCT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBC, TILEGX_OPC_BLBST, TILEGX_OPC_BLBST, TILEGX_OPC_BLBS, TILEGX_OPC_BLBS, TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZ, TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZ, TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZ, CHILD(528), CHILD(578), CHILD(598), CHILD(703), CHILD(723), CHILD(728), CHILD(753), CHILD(758), CHILD(763), CHILD(768), CHILD(773), CHILD(778), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, CHILD(783), CHILD(800), CHILD(832), CHILD(849), CHILD(1168), CHILD(1185), CHILD(1202), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1219), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), BITFIELD(37, 2) /* index 513 */, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), BITFIELD(39, 2) /* index 518 */, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), BITFIELD(41, 2) /* index 523 */, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, BITFIELD(51, 2) /* index 528 */, TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), BITFIELD(37, 2) /* index 533 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), BITFIELD(39, 2) /* index 538 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), BITFIELD(41, 2) /* index 543 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, BITFIELD(31, 2) /* index 548 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), BITFIELD(33, 2) /* index 553 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), BITFIELD(35, 2) /* index 558 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), BITFIELD(37, 2) /* index 563 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), BITFIELD(39, 2) /* index 568 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), BITFIELD(41, 2) /* index 573 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, BITFIELD(51, 2) /* index 578 */, TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, CHILD(583), BITFIELD(31, 2) /* index 583 */, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(588), BITFIELD(33, 2) /* index 588 */, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(593), BITFIELD(35, 2) /* index 593 */, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_PREFETCH_ADD_L1_FAULT, BITFIELD(51, 2) /* index 598 */, CHILD(603), CHILD(618), CHILD(633), CHILD(648), BITFIELD(31, 2) /* index 603 */, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(608), BITFIELD(33, 2) /* index 608 */, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(613), BITFIELD(35, 2) /* index 613 */, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_PREFETCH_ADD_L1, BITFIELD(31, 2) /* index 618 */, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(623), BITFIELD(33, 2) /* index 623 */, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(628), BITFIELD(35, 2) /* index 628 */, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_PREFETCH_ADD_L2_FAULT, BITFIELD(31, 2) /* index 633 */, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(638), BITFIELD(33, 2) /* index 638 */, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(643), BITFIELD(35, 2) /* index 643 */, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_PREFETCH_ADD_L2, BITFIELD(31, 2) /* index 648 */, CHILD(653), CHILD(653), CHILD(653), CHILD(673), BITFIELD(43, 2) /* index 653 */, CHILD(658), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, BITFIELD(45, 2) /* index 658 */, CHILD(663), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, BITFIELD(47, 2) /* index 663 */, CHILD(668), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, BITFIELD(49, 2) /* index 668 */, TILEGX_OPC_LD4S_TLS, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, BITFIELD(33, 2) /* index 673 */, CHILD(653), CHILD(653), CHILD(653), CHILD(678), BITFIELD(35, 2) /* index 678 */, CHILD(653), CHILD(653), CHILD(653), CHILD(683), BITFIELD(43, 2) /* index 683 */, CHILD(688), TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, BITFIELD(45, 2) /* index 688 */, CHILD(693), TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, BITFIELD(47, 2) /* index 693 */, CHILD(698), TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, BITFIELD(49, 2) /* index 698 */, TILEGX_OPC_LD4S_TLS, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, BITFIELD(51, 2) /* index 703 */, CHILD(708), TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U_ADD, TILEGX_OPC_LDNT2S_ADD, BITFIELD(31, 2) /* index 708 */, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(713), BITFIELD(33, 2) /* index 713 */, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(718), BITFIELD(35, 2) /* index 718 */, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_PREFETCH_ADD_L3, BITFIELD(51, 2) /* index 723 */, TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U_ADD, TILEGX_OPC_LDNT_ADD, BITFIELD(51, 2) /* index 728 */, CHILD(733), TILEGX_OPC_LDNA_ADD, TILEGX_OPC_MFSPR, TILEGX_OPC_MTSPR, BITFIELD(43, 2) /* index 733 */, CHILD(738), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, BITFIELD(45, 2) /* index 738 */, CHILD(743), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, BITFIELD(47, 2) /* index 743 */, CHILD(748), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, BITFIELD(49, 2) /* index 748 */, TILEGX_OPC_LD_TLS, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, BITFIELD(51, 2) /* index 753 */, TILEGX_OPC_ORI, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4_ADD, BITFIELD(51, 2) /* index 758 */, TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4_ADD, TILEGX_OPC_STNT_ADD, BITFIELD(51, 2) /* index 763 */, TILEGX_OPC_ST_ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI, BITFIELD(51, 2) /* index 768 */, TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI, BITFIELD(51, 2) /* index 773 */, TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI, BITFIELD(51, 2) /* index 778 */, TILEGX_OPC_V2MINSI, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(49, 4) /* index 783 */, TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_AND, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPEXCH, TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, TILEGX_OPC_CMPNE, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, BITFIELD(49, 4) /* index 800 */, TILEGX_OPC_EXCH4, TILEGX_OPC_EXCH, TILEGX_OPC_FETCHADD4, TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADD, TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHOR4, TILEGX_OPC_FETCHOR, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, TILEGX_OPC_NOR, CHILD(817), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, BITFIELD(43, 2) /* index 817 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(822), BITFIELD(45, 2) /* index 822 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(827), BITFIELD(47, 2) /* index 827 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, BITFIELD(49, 4) /* index 832 */, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_ST1, TILEGX_OPC_ST2, TILEGX_OPC_ST4, TILEGX_OPC_STNT1, TILEGX_OPC_STNT2, TILEGX_OPC_STNT4, BITFIELD(46, 7) /* index 849 */, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, CHILD(978), CHILD(987), CHILD(1066), CHILD(1150), CHILD(1159), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, BITFIELD(43, 3) /* index 978 */, TILEGX_OPC_NONE, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_FINV, TILEGX_OPC_FLUSHWB, TILEGX_OPC_FLUSH, TILEGX_OPC_FNOP, TILEGX_OPC_ICOH, BITFIELD(43, 3) /* index 987 */, CHILD(996), TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_JALRP, TILEGX_OPC_JALR, TILEGX_OPC_JRP, TILEGX_OPC_JR, CHILD(1051), BITFIELD(31, 2) /* index 996 */, CHILD(1001), CHILD(1026), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(33, 2) /* index 1001 */, TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1006), BITFIELD(35, 2) /* index 1006 */, TILEGX_OPC_ILL, CHILD(1011), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(37, 2) /* index 1011 */, TILEGX_OPC_ILL, CHILD(1016), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(39, 2) /* index 1016 */, TILEGX_OPC_ILL, CHILD(1021), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(41, 2) /* index 1021 */, TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_BPT, TILEGX_OPC_ILL, BITFIELD(33, 2) /* index 1026 */, TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1031), BITFIELD(35, 2) /* index 1031 */, TILEGX_OPC_ILL, CHILD(1036), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(37, 2) /* index 1036 */, TILEGX_OPC_ILL, CHILD(1041), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(39, 2) /* index 1041 */, TILEGX_OPC_ILL, CHILD(1046), TILEGX_OPC_ILL, TILEGX_OPC_ILL, BITFIELD(41, 2) /* index 1046 */, TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_RAISE, TILEGX_OPC_ILL, BITFIELD(31, 2) /* index 1051 */, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1056), BITFIELD(33, 2) /* index 1056 */, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1061), BITFIELD(35, 2) /* index 1061 */, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_PREFETCH_L1_FAULT, BITFIELD(43, 3) /* index 1066 */, CHILD(1075), CHILD(1090), CHILD(1105), CHILD(1120), CHILD(1135), TILEGX_OPC_LDNA, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1U, BITFIELD(31, 2) /* index 1075 */, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1080), BITFIELD(33, 2) /* index 1080 */, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1085), BITFIELD(35, 2) /* index 1085 */, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, BITFIELD(31, 2) /* index 1090 */, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1095), BITFIELD(33, 2) /* index 1095 */, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1100), BITFIELD(35, 2) /* index 1100 */, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_PREFETCH_L2_FAULT, BITFIELD(31, 2) /* index 1105 */, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1110), BITFIELD(33, 2) /* index 1110 */, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1115), BITFIELD(35, 2) /* index 1115 */, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, BITFIELD(31, 2) /* index 1120 */, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1125), BITFIELD(33, 2) /* index 1125 */, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1130), BITFIELD(35, 2) /* index 1130 */, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT, BITFIELD(31, 2) /* index 1135 */, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1140), BITFIELD(33, 2) /* index 1140 */, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1145), BITFIELD(35, 2) /* index 1145 */, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, BITFIELD(43, 3) /* index 1150 */, TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4U, TILEGX_OPC_LDNT, TILEGX_OPC_LD, TILEGX_OPC_LNK, TILEGX_OPC_MF, BITFIELD(43, 3) /* index 1159 */, TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1, TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_WH64, TILEGX_OPC_NONE, BITFIELD(49, 4) /* index 1168 */, TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, BITFIELD(49, 4) /* index 1185 */, TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MZ, TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB, BITFIELD(49, 4) /* index 1202 */, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, TILEGX_OPC_V4SUB, TILEGX_OPC_XOR, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(49, 4) /* index 1219 */, TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(31, 2) /* index 1236 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(1241), BITFIELD(33, 2) /* index 1241 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(1246), BITFIELD(35, 2) /* index 1246 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(1251), BITFIELD(37, 2) /* index 1251 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(1256), BITFIELD(39, 2) /* index 1256 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, CHILD(1261), BITFIELD(41, 2) /* index 1261 */, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_INFOL, }; static const unsigned short decode_Y0_fsm[178] = { BITFIELD(27, 4) /* index 0 */, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(118), CHILD(123), CHILD(128), CHILD(133), CHILD(153), CHILD(158), CHILD(163), CHILD(168), CHILD(173), BITFIELD(6, 2) /* index 17 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), BITFIELD(8, 2) /* index 22 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), BITFIELD(10, 2) /* index 27 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, BITFIELD(0, 2) /* index 32 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), BITFIELD(2, 2) /* index 37 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), BITFIELD(4, 2) /* index 42 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), BITFIELD(6, 2) /* index 47 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), BITFIELD(8, 2) /* index 52 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), BITFIELD(10, 2) /* index 57 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, BITFIELD(18, 2) /* index 62 */, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, BITFIELD(15, 5) /* index 67 */, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(100), CHILD(109), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(12, 3) /* index 100 */, TILEGX_OPC_NONE, TILEGX_OPC_CLZ, TILEGX_OPC_CTZ, TILEGX_OPC_FNOP, TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NOP, TILEGX_OPC_PCNT, TILEGX_OPC_REVBITS, BITFIELD(12, 3) /* index 109 */, TILEGX_OPC_REVBYTES, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1, TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(18, 2) /* index 118 */, TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, BITFIELD(18, 2) /* index 123 */, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, TILEGX_OPC_MULAX, TILEGX_OPC_MULX, BITFIELD(18, 2) /* index 128 */, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, BITFIELD(18, 2) /* index 133 */, TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(138), TILEGX_OPC_XOR, BITFIELD(12, 2) /* index 138 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(143), BITFIELD(14, 2) /* index 143 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(148), BITFIELD(16, 2) /* index 148 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, BITFIELD(18, 2) /* index 153 */, TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, BITFIELD(18, 2) /* index 158 */, TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL3ADDX, BITFIELD(18, 2) /* index 163 */, TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LU_LU, BITFIELD(18, 2) /* index 168 */, TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LU_LU, BITFIELD(18, 2) /* index 173 */, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, }; static const unsigned short decode_Y1_fsm[167] = { BITFIELD(58, 4) /* index 0 */, TILEGX_OPC_NONE, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(117), CHILD(122), CHILD(127), CHILD(132), CHILD(152), CHILD(157), CHILD(162), TILEGX_OPC_NONE, BITFIELD(37, 2) /* index 17 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), BITFIELD(39, 2) /* index 22 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), BITFIELD(41, 2) /* index 27 */, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, BITFIELD(31, 2) /* index 32 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), BITFIELD(33, 2) /* index 37 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), BITFIELD(35, 2) /* index 42 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), BITFIELD(37, 2) /* index 47 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), BITFIELD(39, 2) /* index 52 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), BITFIELD(41, 2) /* index 57 */, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, BITFIELD(49, 2) /* index 62 */, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, BITFIELD(47, 4) /* index 67 */, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(84), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, BITFIELD(43, 3) /* index 84 */, CHILD(93), CHILD(96), CHILD(99), CHILD(102), CHILD(105), CHILD(108), CHILD(111), CHILD(114), BITFIELD(46, 1) /* index 93 */, TILEGX_OPC_NONE, TILEGX_OPC_FNOP, BITFIELD(46, 1) /* index 96 */, TILEGX_OPC_NONE, TILEGX_OPC_ILL, BITFIELD(46, 1) /* index 99 */, TILEGX_OPC_NONE, TILEGX_OPC_JALRP, BITFIELD(46, 1) /* index 102 */, TILEGX_OPC_NONE, TILEGX_OPC_JALR, BITFIELD(46, 1) /* index 105 */, TILEGX_OPC_NONE, TILEGX_OPC_JRP, BITFIELD(46, 1) /* index 108 */, TILEGX_OPC_NONE, TILEGX_OPC_JR, BITFIELD(46, 1) /* index 111 */, TILEGX_OPC_NONE, TILEGX_OPC_LNK, BITFIELD(46, 1) /* index 114 */, TILEGX_OPC_NONE, TILEGX_OPC_NOP, BITFIELD(49, 2) /* index 117 */, TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, BITFIELD(49, 2) /* index 122 */, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, BITFIELD(49, 2) /* index 127 */, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, BITFIELD(49, 2) /* index 132 */, TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(137), TILEGX_OPC_XOR, BITFIELD(43, 2) /* index 137 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(142), BITFIELD(45, 2) /* index 142 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(147), BITFIELD(47, 2) /* index 147 */, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, BITFIELD(49, 2) /* index 152 */, TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, BITFIELD(49, 2) /* index 157 */, TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL3ADDX, BITFIELD(49, 2) /* index 162 */, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, }; static const unsigned short decode_Y2_fsm[118] = { BITFIELD(62, 2) /* index 0 */, TILEGX_OPC_NONE, CHILD(5), CHILD(66), CHILD(109), BITFIELD(55, 3) /* index 5 */, CHILD(14), CHILD(14), CHILD(14), CHILD(17), CHILD(40), CHILD(40), CHILD(40), CHILD(43), BITFIELD(26, 1) /* index 14 */, TILEGX_OPC_LD1S, TILEGX_OPC_LD1U, BITFIELD(26, 1) /* index 17 */, CHILD(20), CHILD(30), BITFIELD(51, 2) /* index 20 */, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(25), BITFIELD(53, 2) /* index 25 */, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_PREFETCH_L1_FAULT, BITFIELD(51, 2) /* index 30 */, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(35), BITFIELD(53, 2) /* index 35 */, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, BITFIELD(26, 1) /* index 40 */, TILEGX_OPC_LD2S, TILEGX_OPC_LD2U, BITFIELD(26, 1) /* index 43 */, CHILD(46), CHILD(56), BITFIELD(51, 2) /* index 46 */, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(51), BITFIELD(53, 2) /* index 51 */, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_PREFETCH_L2_FAULT, BITFIELD(51, 2) /* index 56 */, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(61), BITFIELD(53, 2) /* index 61 */, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, BITFIELD(56, 2) /* index 66 */, CHILD(71), CHILD(74), CHILD(90), CHILD(93), BITFIELD(26, 1) /* index 71 */, TILEGX_OPC_NONE, TILEGX_OPC_LD4S, BITFIELD(26, 1) /* index 74 */, TILEGX_OPC_NONE, CHILD(77), BITFIELD(51, 2) /* index 77 */, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(82), BITFIELD(53, 2) /* index 82 */, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(87), BITFIELD(55, 1) /* index 87 */, TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT, BITFIELD(26, 1) /* index 90 */, TILEGX_OPC_LD4U, TILEGX_OPC_LD, BITFIELD(26, 1) /* index 93 */, CHILD(96), TILEGX_OPC_LD, BITFIELD(51, 2) /* index 96 */, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(101), BITFIELD(53, 2) /* index 101 */, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(106), BITFIELD(55, 1) /* index 106 */, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, BITFIELD(26, 1) /* index 109 */, CHILD(112), CHILD(115), BITFIELD(57, 1) /* index 112 */, TILEGX_OPC_ST1, TILEGX_OPC_ST4, BITFIELD(57, 1) /* index 115 */, TILEGX_OPC_ST2, TILEGX_OPC_ST, }; #undef BITFIELD #undef CHILD const unsigned short * const tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS] = { decode_X0_fsm, decode_X1_fsm, decode_Y0_fsm, decode_Y1_fsm, decode_Y2_fsm }; const struct tilegx_operand tilegx_operands[35] = { { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X0), 8, 1, 0, 0, 0, 0, create_Imm8_X0, get_Imm8_X0 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X1), 8, 1, 0, 0, 0, 0, create_Imm8_X1, get_Imm8_X1 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y0), 8, 1, 0, 0, 0, 0, create_Imm8_Y0, get_Imm8_Y0 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y1), 8, 1, 0, 0, 0, 0, create_Imm8_Y1, get_Imm8_Y1 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X0_HW0_LAST), 16, 1, 0, 0, 0, 0, create_Imm16_X0, get_Imm16_X0 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X1_HW0_LAST), 16, 1, 0, 0, 0, 0, create_Imm16_X1, get_Imm16_X1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 0, 1, 0, 0, create_Dest_X1, get_Dest_X1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcA_X1, get_SrcA_X1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 0, 1, 0, 0, create_Dest_X0, get_Dest_X0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcA_X0, get_SrcA_X0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 0, 1, 0, 0, create_Dest_Y0, get_Dest_Y0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcA_Y0, get_SrcA_Y0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 0, 1, 0, 0, create_Dest_Y1, get_Dest_Y1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcA_Y1, get_SrcA_Y1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcA_Y2, get_SrcA_Y2 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 1, 0, 0, create_SrcA_X1, get_SrcA_X1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcB_X0, get_SrcB_X0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcB_X1, get_SrcB_X1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcB_Y0, get_SrcB_Y0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcB_Y1, get_SrcB_Y1 }, { TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_BROFF_X1), 17, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, create_BrOff_X1, get_BrOff_X1 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0), 6, 0, 0, 0, 0, 0, create_BFStart_X0, get_BFStart_X0 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0), 6, 0, 0, 0, 0, 0, create_BFEnd_X0, get_BFEnd_X0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 1, 0, 0, create_Dest_X0, get_Dest_X0 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 1, 0, 0, create_Dest_Y0, get_Dest_Y0 }, { TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_JUMPOFF_X1), 27, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, create_JumpOff_X1, get_JumpOff_X1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 0, 1, 0, 0, create_SrcBDest_Y2, get_SrcBDest_Y2 }, { TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MF_IMM14_X1), 14, 0, 0, 0, 0, 0, create_MF_Imm14_X1, get_MF_Imm14_X1 }, { TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MT_IMM14_X1), 14, 0, 0, 0, 0, 0, create_MT_Imm14_X1, get_MT_Imm14_X1 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X0), 6, 0, 0, 0, 0, 0, create_ShAmt_X0, get_ShAmt_X0 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X1), 6, 0, 0, 0, 0, 0, create_ShAmt_X1, get_ShAmt_X1 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y0), 6, 0, 0, 0, 0, 0, create_ShAmt_Y0, get_ShAmt_Y0 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y1), 6, 0, 0, 0, 0, 0, create_ShAmt_Y1, get_ShAmt_Y1 }, { TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), 6, 0, 1, 0, 0, 0, create_SrcBDest_Y2, get_SrcBDest_Y2 }, { TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_DEST_IMM8_X1), 8, 1, 0, 0, 0, 0, create_Dest_Imm8_X1, get_Dest_Imm8_X1 } }; /* Given a set of bundle bits and a specific pipe, returns which * instruction the bundle contains in that pipe. */ const struct tilegx_opcode * find_opcode(tilegx_bundle_bits bits, tilegx_pipeline pipe) { const unsigned short *table = tilegx_bundle_decoder_fsms[pipe]; int index = 0; while (1) { unsigned short bitspec = table[index]; unsigned int bitfield = ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6); unsigned short next = table[index + 1 + bitfield]; if (next <= TILEGX_OPC_NONE) return &tilegx_opcodes[next]; index = next - TILEGX_OPC_NONE; } } int parse_insn_tilegx(tilegx_bundle_bits bits, unsigned long long pc, struct tilegx_decoded_instruction decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]) { int num_instructions = 0; int pipe; int min_pipe, max_pipe; if ((bits & TILEGX_BUNDLE_MODE_MASK) == 0) { min_pipe = TILEGX_PIPELINE_X0; max_pipe = TILEGX_PIPELINE_X1; } else { min_pipe = TILEGX_PIPELINE_Y0; max_pipe = TILEGX_PIPELINE_Y2; } /* For each pipe, find an instruction that fits. */ for (pipe = min_pipe; pipe <= max_pipe; pipe++) { const struct tilegx_opcode *opc; struct tilegx_decoded_instruction *d; int i; d = &decoded[num_instructions++]; opc = find_opcode (bits, (tilegx_pipeline)pipe); d->opcode = opc; /* Decode each operand, sign extending, etc. as appropriate. */ for (i = 0; i < opc->num_operands; i++) { const struct tilegx_operand *op = &tilegx_operands[opc->operands[pipe][i]]; int raw_opval = op->extract (bits); long long opval; if (op->is_signed) { /* Sign-extend the operand. */ int shift = (int)((sizeof(int) * 8) - op->num_bits); raw_opval = (raw_opval << shift) >> shift; } /* Adjust PC-relative scaled branch offsets. */ if (op->type == TILEGX_OP_TYPE_ADDRESS) opval = (raw_opval * TILEGX_BUNDLE_SIZE_IN_BYTES) + pc; else opval = raw_opval; /* Record the final value. */ d->operands[i] = op; d->operand_values[i] = opval; } } return num_instructions; } struct tilegx_spr { /* The number */ int number; /* The name */ const char *name; }; static int tilegx_spr_compare (const void *a_ptr, const void *b_ptr) { const struct tilegx_spr *a = (const struct tilegx_spr *) a_ptr; const struct tilegx_spr *b = (const struct tilegx_spr *) b_ptr; return (a->number - b->number); } const struct tilegx_spr tilegx_sprs[] = { { 0, "MPL_MEM_ERROR_SET_0" }, { 1, "MPL_MEM_ERROR_SET_1" }, { 2, "MPL_MEM_ERROR_SET_2" }, { 3, "MPL_MEM_ERROR_SET_3" }, { 4, "MPL_MEM_ERROR" }, { 5, "MEM_ERROR_CBOX_ADDR" }, { 6, "MEM_ERROR_CBOX_STATUS" }, { 7, "MEM_ERROR_ENABLE" }, { 8, "MEM_ERROR_MBOX_ADDR" }, { 9, "MEM_ERROR_MBOX_STATUS" }, { 10, "SBOX_ERROR" }, { 11, "XDN_DEMUX_ERROR" }, { 256, "MPL_SINGLE_STEP_3_SET_0" }, { 257, "MPL_SINGLE_STEP_3_SET_1" }, { 258, "MPL_SINGLE_STEP_3_SET_2" }, { 259, "MPL_SINGLE_STEP_3_SET_3" }, { 260, "MPL_SINGLE_STEP_3" }, { 261, "SINGLE_STEP_CONTROL_3" }, { 512, "MPL_SINGLE_STEP_2_SET_0" }, { 513, "MPL_SINGLE_STEP_2_SET_1" }, { 514, "MPL_SINGLE_STEP_2_SET_2" }, { 515, "MPL_SINGLE_STEP_2_SET_3" }, { 516, "MPL_SINGLE_STEP_2" }, { 517, "SINGLE_STEP_CONTROL_2" }, { 768, "MPL_SINGLE_STEP_1_SET_0" }, { 769, "MPL_SINGLE_STEP_1_SET_1" }, { 770, "MPL_SINGLE_STEP_1_SET_2" }, { 771, "MPL_SINGLE_STEP_1_SET_3" }, { 772, "MPL_SINGLE_STEP_1" }, { 773, "SINGLE_STEP_CONTROL_1" }, { 1024, "MPL_SINGLE_STEP_0_SET_0" }, { 1025, "MPL_SINGLE_STEP_0_SET_1" }, { 1026, "MPL_SINGLE_STEP_0_SET_2" }, { 1027, "MPL_SINGLE_STEP_0_SET_3" }, { 1028, "MPL_SINGLE_STEP_0" }, { 1029, "SINGLE_STEP_CONTROL_0" }, { 1280, "MPL_IDN_COMPLETE_SET_0" }, { 1281, "MPL_IDN_COMPLETE_SET_1" }, { 1282, "MPL_IDN_COMPLETE_SET_2" }, { 1283, "MPL_IDN_COMPLETE_SET_3" }, { 1284, "MPL_IDN_COMPLETE" }, { 1285, "IDN_COMPLETE_PENDING" }, { 1536, "MPL_UDN_COMPLETE_SET_0" }, { 1537, "MPL_UDN_COMPLETE_SET_1" }, { 1538, "MPL_UDN_COMPLETE_SET_2" }, { 1539, "MPL_UDN_COMPLETE_SET_3" }, { 1540, "MPL_UDN_COMPLETE" }, { 1541, "UDN_COMPLETE_PENDING" }, { 1792, "MPL_ITLB_MISS_SET_0" }, { 1793, "MPL_ITLB_MISS_SET_1" }, { 1794, "MPL_ITLB_MISS_SET_2" }, { 1795, "MPL_ITLB_MISS_SET_3" }, { 1796, "MPL_ITLB_MISS" }, { 1797, "ITLB_TSB_BASE_ADDR_0" }, { 1798, "ITLB_TSB_BASE_ADDR_1" }, { 1920, "ITLB_CURRENT_ATTR" }, { 1921, "ITLB_CURRENT_PA" }, { 1922, "ITLB_CURRENT_VA" }, { 1923, "ITLB_INDEX" }, { 1924, "ITLB_MATCH_0" }, { 1925, "ITLB_PERF" }, { 1926, "ITLB_PR" }, { 1927, "ITLB_TSB_ADDR_0" }, { 1928, "ITLB_TSB_ADDR_1" }, { 1929, "ITLB_TSB_FILL_CURRENT_ATTR" }, { 1930, "ITLB_TSB_FILL_MATCH" }, { 1931, "NUMBER_ITLB" }, { 1932, "REPLACEMENT_ITLB" }, { 1933, "WIRED_ITLB" }, { 2048, "MPL_ILL_SET_0" }, { 2049, "MPL_ILL_SET_1" }, { 2050, "MPL_ILL_SET_2" }, { 2051, "MPL_ILL_SET_3" }, { 2052, "MPL_ILL" }, { 2304, "MPL_GPV_SET_0" }, { 2305, "MPL_GPV_SET_1" }, { 2306, "MPL_GPV_SET_2" }, { 2307, "MPL_GPV_SET_3" }, { 2308, "MPL_GPV" }, { 2309, "GPV_REASON" }, { 2560, "MPL_IDN_ACCESS_SET_0" }, { 2561, "MPL_IDN_ACCESS_SET_1" }, { 2562, "MPL_IDN_ACCESS_SET_2" }, { 2563, "MPL_IDN_ACCESS_SET_3" }, { 2564, "MPL_IDN_ACCESS" }, { 2565, "IDN_DEMUX_COUNT_0" }, { 2566, "IDN_DEMUX_COUNT_1" }, { 2567, "IDN_FLUSH_EGRESS" }, { 2568, "IDN_PENDING" }, { 2569, "IDN_ROUTE_ORDER" }, { 2570, "IDN_SP_FIFO_CNT" }, { 2688, "IDN_DATA_AVAIL" }, { 2816, "MPL_UDN_ACCESS_SET_0" }, { 2817, "MPL_UDN_ACCESS_SET_1" }, { 2818, "MPL_UDN_ACCESS_SET_2" }, { 2819, "MPL_UDN_ACCESS_SET_3" }, { 2820, "MPL_UDN_ACCESS" }, { 2821, "UDN_DEMUX_COUNT_0" }, { 2822, "UDN_DEMUX_COUNT_1" }, { 2823, "UDN_DEMUX_COUNT_2" }, { 2824, "UDN_DEMUX_COUNT_3" }, { 2825, "UDN_FLUSH_EGRESS" }, { 2826, "UDN_PENDING" }, { 2827, "UDN_ROUTE_ORDER" }, { 2828, "UDN_SP_FIFO_CNT" }, { 2944, "UDN_DATA_AVAIL" }, { 3072, "MPL_SWINT_3_SET_0" }, { 3073, "MPL_SWINT_3_SET_1" }, { 3074, "MPL_SWINT_3_SET_2" }, { 3075, "MPL_SWINT_3_SET_3" }, { 3076, "MPL_SWINT_3" }, { 3328, "MPL_SWINT_2_SET_0" }, { 3329, "MPL_SWINT_2_SET_1" }, { 3330, "MPL_SWINT_2_SET_2" }, { 3331, "MPL_SWINT_2_SET_3" }, { 3332, "MPL_SWINT_2" }, { 3584, "MPL_SWINT_1_SET_0" }, { 3585, "MPL_SWINT_1_SET_1" }, { 3586, "MPL_SWINT_1_SET_2" }, { 3587, "MPL_SWINT_1_SET_3" }, { 3588, "MPL_SWINT_1" }, { 3840, "MPL_SWINT_0_SET_0" }, { 3841, "MPL_SWINT_0_SET_1" }, { 3842, "MPL_SWINT_0_SET_2" }, { 3843, "MPL_SWINT_0_SET_3" }, { 3844, "MPL_SWINT_0" }, { 4096, "MPL_ILL_TRANS_SET_0" }, { 4097, "MPL_ILL_TRANS_SET_1" }, { 4098, "MPL_ILL_TRANS_SET_2" }, { 4099, "MPL_ILL_TRANS_SET_3" }, { 4100, "MPL_ILL_TRANS" }, { 4101, "ILL_TRANS_REASON" }, { 4102, "ILL_VA_PC" }, { 4352, "MPL_UNALIGN_DATA_SET_0" }, { 4353, "MPL_UNALIGN_DATA_SET_1" }, { 4354, "MPL_UNALIGN_DATA_SET_2" }, { 4355, "MPL_UNALIGN_DATA_SET_3" }, { 4356, "MPL_UNALIGN_DATA" }, { 4608, "MPL_DTLB_MISS_SET_0" }, { 4609, "MPL_DTLB_MISS_SET_1" }, { 4610, "MPL_DTLB_MISS_SET_2" }, { 4611, "MPL_DTLB_MISS_SET_3" }, { 4612, "MPL_DTLB_MISS" }, { 4613, "DTLB_TSB_BASE_ADDR_0" }, { 4614, "DTLB_TSB_BASE_ADDR_1" }, { 4736, "AAR" }, { 4737, "CACHE_PINNED_WAYS" }, { 4738, "DTLB_BAD_ADDR" }, { 4739, "DTLB_BAD_ADDR_REASON" }, { 4740, "DTLB_CURRENT_ATTR" }, { 4741, "DTLB_CURRENT_PA" }, { 4742, "DTLB_CURRENT_VA" }, { 4743, "DTLB_INDEX" }, { 4744, "DTLB_MATCH_0" }, { 4745, "DTLB_PERF" }, { 4746, "DTLB_TSB_ADDR_0" }, { 4747, "DTLB_TSB_ADDR_1" }, { 4748, "DTLB_TSB_FILL_CURRENT_ATTR" }, { 4749, "DTLB_TSB_FILL_MATCH" }, { 4750, "NUMBER_DTLB" }, { 4751, "REPLACEMENT_DTLB" }, { 4752, "WIRED_DTLB" }, { 4864, "MPL_DTLB_ACCESS_SET_0" }, { 4865, "MPL_DTLB_ACCESS_SET_1" }, { 4866, "MPL_DTLB_ACCESS_SET_2" }, { 4867, "MPL_DTLB_ACCESS_SET_3" }, { 4868, "MPL_DTLB_ACCESS" }, { 5120, "MPL_IDN_FIREWALL_SET_0" }, { 5121, "MPL_IDN_FIREWALL_SET_1" }, { 5122, "MPL_IDN_FIREWALL_SET_2" }, { 5123, "MPL_IDN_FIREWALL_SET_3" }, { 5124, "MPL_IDN_FIREWALL" }, { 5125, "IDN_DIRECTION_PROTECT" }, { 5376, "MPL_UDN_FIREWALL_SET_0" }, { 5377, "MPL_UDN_FIREWALL_SET_1" }, { 5378, "MPL_UDN_FIREWALL_SET_2" }, { 5379, "MPL_UDN_FIREWALL_SET_3" }, { 5380, "MPL_UDN_FIREWALL" }, { 5381, "UDN_DIRECTION_PROTECT" }, { 5632, "MPL_TILE_TIMER_SET_0" }, { 5633, "MPL_TILE_TIMER_SET_1" }, { 5634, "MPL_TILE_TIMER_SET_2" }, { 5635, "MPL_TILE_TIMER_SET_3" }, { 5636, "MPL_TILE_TIMER" }, { 5637, "TILE_TIMER_CONTROL" }, { 5888, "MPL_AUX_TILE_TIMER_SET_0" }, { 5889, "MPL_AUX_TILE_TIMER_SET_1" }, { 5890, "MPL_AUX_TILE_TIMER_SET_2" }, { 5891, "MPL_AUX_TILE_TIMER_SET_3" }, { 5892, "MPL_AUX_TILE_TIMER" }, { 5893, "AUX_TILE_TIMER_CONTROL" }, { 6144, "MPL_IDN_TIMER_SET_0" }, { 6145, "MPL_IDN_TIMER_SET_1" }, { 6146, "MPL_IDN_TIMER_SET_2" }, { 6147, "MPL_IDN_TIMER_SET_3" }, { 6148, "MPL_IDN_TIMER" }, { 6149, "IDN_DEADLOCK_COUNT" }, { 6150, "IDN_DEADLOCK_TIMEOUT" }, { 6400, "MPL_UDN_TIMER_SET_0" }, { 6401, "MPL_UDN_TIMER_SET_1" }, { 6402, "MPL_UDN_TIMER_SET_2" }, { 6403, "MPL_UDN_TIMER_SET_3" }, { 6404, "MPL_UDN_TIMER" }, { 6405, "UDN_DEADLOCK_COUNT" }, { 6406, "UDN_DEADLOCK_TIMEOUT" }, { 6656, "MPL_IDN_AVAIL_SET_0" }, { 6657, "MPL_IDN_AVAIL_SET_1" }, { 6658, "MPL_IDN_AVAIL_SET_2" }, { 6659, "MPL_IDN_AVAIL_SET_3" }, { 6660, "MPL_IDN_AVAIL" }, { 6661, "IDN_AVAIL_EN" }, { 6912, "MPL_UDN_AVAIL_SET_0" }, { 6913, "MPL_UDN_AVAIL_SET_1" }, { 6914, "MPL_UDN_AVAIL_SET_2" }, { 6915, "MPL_UDN_AVAIL_SET_3" }, { 6916, "MPL_UDN_AVAIL" }, { 6917, "UDN_AVAIL_EN" }, { 7168, "MPL_IPI_3_SET_0" }, { 7169, "MPL_IPI_3_SET_1" }, { 7170, "MPL_IPI_3_SET_2" }, { 7171, "MPL_IPI_3_SET_3" }, { 7172, "MPL_IPI_3" }, { 7173, "IPI_EVENT_3" }, { 7174, "IPI_EVENT_RESET_3" }, { 7175, "IPI_EVENT_SET_3" }, { 7176, "IPI_MASK_3" }, { 7177, "IPI_MASK_RESET_3" }, { 7178, "IPI_MASK_SET_3" }, { 7424, "MPL_IPI_2_SET_0" }, { 7425, "MPL_IPI_2_SET_1" }, { 7426, "MPL_IPI_2_SET_2" }, { 7427, "MPL_IPI_2_SET_3" }, { 7428, "MPL_IPI_2" }, { 7429, "IPI_EVENT_2" }, { 7430, "IPI_EVENT_RESET_2" }, { 7431, "IPI_EVENT_SET_2" }, { 7432, "IPI_MASK_2" }, { 7433, "IPI_MASK_RESET_2" }, { 7434, "IPI_MASK_SET_2" }, { 7680, "MPL_IPI_1_SET_0" }, { 7681, "MPL_IPI_1_SET_1" }, { 7682, "MPL_IPI_1_SET_2" }, { 7683, "MPL_IPI_1_SET_3" }, { 7684, "MPL_IPI_1" }, { 7685, "IPI_EVENT_1" }, { 7686, "IPI_EVENT_RESET_1" }, { 7687, "IPI_EVENT_SET_1" }, { 7688, "IPI_MASK_1" }, { 7689, "IPI_MASK_RESET_1" }, { 7690, "IPI_MASK_SET_1" }, { 7936, "MPL_IPI_0_SET_0" }, { 7937, "MPL_IPI_0_SET_1" }, { 7938, "MPL_IPI_0_SET_2" }, { 7939, "MPL_IPI_0_SET_3" }, { 7940, "MPL_IPI_0" }, { 7941, "IPI_EVENT_0" }, { 7942, "IPI_EVENT_RESET_0" }, { 7943, "IPI_EVENT_SET_0" }, { 7944, "IPI_MASK_0" }, { 7945, "IPI_MASK_RESET_0" }, { 7946, "IPI_MASK_SET_0" }, { 8192, "MPL_PERF_COUNT_SET_0" }, { 8193, "MPL_PERF_COUNT_SET_1" }, { 8194, "MPL_PERF_COUNT_SET_2" }, { 8195, "MPL_PERF_COUNT_SET_3" }, { 8196, "MPL_PERF_COUNT" }, { 8197, "PERF_COUNT_0" }, { 8198, "PERF_COUNT_1" }, { 8199, "PERF_COUNT_CTL" }, { 8200, "PERF_COUNT_DN_CTL" }, { 8201, "PERF_COUNT_STS" }, { 8202, "WATCH_MASK" }, { 8203, "WATCH_VAL" }, { 8448, "MPL_AUX_PERF_COUNT_SET_0" }, { 8449, "MPL_AUX_PERF_COUNT_SET_1" }, { 8450, "MPL_AUX_PERF_COUNT_SET_2" }, { 8451, "MPL_AUX_PERF_COUNT_SET_3" }, { 8452, "MPL_AUX_PERF_COUNT" }, { 8453, "AUX_PERF_COUNT_0" }, { 8454, "AUX_PERF_COUNT_1" }, { 8455, "AUX_PERF_COUNT_CTL" }, { 8456, "AUX_PERF_COUNT_STS" }, { 8704, "MPL_INTCTRL_3_SET_0" }, { 8705, "MPL_INTCTRL_3_SET_1" }, { 8706, "MPL_INTCTRL_3_SET_2" }, { 8707, "MPL_INTCTRL_3_SET_3" }, { 8708, "MPL_INTCTRL_3" }, { 8709, "INTCTRL_3_STATUS" }, { 8710, "INTERRUPT_MASK_3" }, { 8711, "INTERRUPT_MASK_RESET_3" }, { 8712, "INTERRUPT_MASK_SET_3" }, { 8713, "INTERRUPT_VECTOR_BASE_3" }, { 8714, "SINGLE_STEP_EN_0_3" }, { 8715, "SINGLE_STEP_EN_1_3" }, { 8716, "SINGLE_STEP_EN_2_3" }, { 8717, "SINGLE_STEP_EN_3_3" }, { 8832, "EX_CONTEXT_3_0" }, { 8833, "EX_CONTEXT_3_1" }, { 8834, "SYSTEM_SAVE_3_0" }, { 8835, "SYSTEM_SAVE_3_1" }, { 8836, "SYSTEM_SAVE_3_2" }, { 8837, "SYSTEM_SAVE_3_3" }, { 8960, "MPL_INTCTRL_2_SET_0" }, { 8961, "MPL_INTCTRL_2_SET_1" }, { 8962, "MPL_INTCTRL_2_SET_2" }, { 8963, "MPL_INTCTRL_2_SET_3" }, { 8964, "MPL_INTCTRL_2" }, { 8965, "INTCTRL_2_STATUS" }, { 8966, "INTERRUPT_MASK_2" }, { 8967, "INTERRUPT_MASK_RESET_2" }, { 8968, "INTERRUPT_MASK_SET_2" }, { 8969, "INTERRUPT_VECTOR_BASE_2" }, { 8970, "SINGLE_STEP_EN_0_2" }, { 8971, "SINGLE_STEP_EN_1_2" }, { 8972, "SINGLE_STEP_EN_2_2" }, { 8973, "SINGLE_STEP_EN_3_2" }, { 9088, "EX_CONTEXT_2_0" }, { 9089, "EX_CONTEXT_2_1" }, { 9090, "SYSTEM_SAVE_2_0" }, { 9091, "SYSTEM_SAVE_2_1" }, { 9092, "SYSTEM_SAVE_2_2" }, { 9093, "SYSTEM_SAVE_2_3" }, { 9216, "MPL_INTCTRL_1_SET_0" }, { 9217, "MPL_INTCTRL_1_SET_1" }, { 9218, "MPL_INTCTRL_1_SET_2" }, { 9219, "MPL_INTCTRL_1_SET_3" }, { 9220, "MPL_INTCTRL_1" }, { 9221, "INTCTRL_1_STATUS" }, { 9222, "INTERRUPT_MASK_1" }, { 9223, "INTERRUPT_MASK_RESET_1" }, { 9224, "INTERRUPT_MASK_SET_1" }, { 9225, "INTERRUPT_VECTOR_BASE_1" }, { 9226, "SINGLE_STEP_EN_0_1" }, { 9227, "SINGLE_STEP_EN_1_1" }, { 9228, "SINGLE_STEP_EN_2_1" }, { 9229, "SINGLE_STEP_EN_3_1" }, { 9344, "EX_CONTEXT_1_0" }, { 9345, "EX_CONTEXT_1_1" }, { 9346, "SYSTEM_SAVE_1_0" }, { 9347, "SYSTEM_SAVE_1_1" }, { 9348, "SYSTEM_SAVE_1_2" }, { 9349, "SYSTEM_SAVE_1_3" }, { 9472, "MPL_INTCTRL_0_SET_0" }, { 9473, "MPL_INTCTRL_0_SET_1" }, { 9474, "MPL_INTCTRL_0_SET_2" }, { 9475, "MPL_INTCTRL_0_SET_3" }, { 9476, "MPL_INTCTRL_0" }, { 9477, "INTCTRL_0_STATUS" }, { 9478, "INTERRUPT_MASK_0" }, { 9479, "INTERRUPT_MASK_RESET_0" }, { 9480, "INTERRUPT_MASK_SET_0" }, { 9481, "INTERRUPT_VECTOR_BASE_0" }, { 9482, "SINGLE_STEP_EN_0_0" }, { 9483, "SINGLE_STEP_EN_1_0" }, { 9484, "SINGLE_STEP_EN_2_0" }, { 9485, "SINGLE_STEP_EN_3_0" }, { 9600, "EX_CONTEXT_0_0" }, { 9601, "EX_CONTEXT_0_1" }, { 9602, "SYSTEM_SAVE_0_0" }, { 9603, "SYSTEM_SAVE_0_1" }, { 9604, "SYSTEM_SAVE_0_2" }, { 9605, "SYSTEM_SAVE_0_3" }, { 9728, "MPL_BOOT_ACCESS_SET_0" }, { 9729, "MPL_BOOT_ACCESS_SET_1" }, { 9730, "MPL_BOOT_ACCESS_SET_2" }, { 9731, "MPL_BOOT_ACCESS_SET_3" }, { 9732, "MPL_BOOT_ACCESS" }, { 9733, "BIG_ENDIAN_CONFIG" }, { 9734, "CACHE_INVALIDATION_COMPRESSION_MODE" }, { 9735, "CACHE_INVALIDATION_MASK_0" }, { 9736, "CACHE_INVALIDATION_MASK_1" }, { 9737, "CACHE_INVALIDATION_MASK_2" }, { 9738, "CBOX_CACHEASRAM_CONFIG" }, { 9739, "CBOX_CACHE_CONFIG" }, { 9740, "CBOX_HOME_MAP_ADDR" }, { 9741, "CBOX_HOME_MAP_DATA" }, { 9742, "CBOX_MMAP_0" }, { 9743, "CBOX_MMAP_1" }, { 9744, "CBOX_MMAP_2" }, { 9745, "CBOX_MMAP_3" }, { 9746, "CBOX_MSR" }, { 9747, "DIAG_BCST_CTL" }, { 9748, "DIAG_BCST_MASK" }, { 9749, "DIAG_BCST_TRIGGER" }, { 9750, "DIAG_MUX_CTL" }, { 9751, "DIAG_TRACE_CTL" }, { 9752, "DIAG_TRACE_DATA" }, { 9753, "DIAG_TRACE_STS" }, { 9754, "IDN_DEMUX_BUF_THRESH" }, { 9755, "L1_I_PIN_WAY_0" }, { 9756, "MEM_ROUTE_ORDER" }, { 9757, "MEM_STRIPE_CONFIG" }, { 9758, "PERF_COUNT_PLS" }, { 9759, "PSEUDO_RANDOM_NUMBER_MODIFY" }, { 9760, "QUIESCE_CTL" }, { 9761, "RSHIM_COORD" }, { 9762, "SBOX_CONFIG" }, { 9763, "UDN_DEMUX_BUF_THRESH" }, { 9764, "XDN_CORE_STARVATION_COUNT" }, { 9765, "XDN_ROUND_ROBIN_ARB_CTL" }, { 9856, "CYCLE_MODIFY" }, { 9857, "I_AAR" }, { 9984, "MPL_WORLD_ACCESS_SET_0" }, { 9985, "MPL_WORLD_ACCESS_SET_1" }, { 9986, "MPL_WORLD_ACCESS_SET_2" }, { 9987, "MPL_WORLD_ACCESS_SET_3" }, { 9988, "MPL_WORLD_ACCESS" }, { 9989, "DONE" }, { 9990, "DSTREAM_PF" }, { 9991, "FAIL" }, { 9992, "INTERRUPT_CRITICAL_SECTION" }, { 9993, "PASS" }, { 9994, "PSEUDO_RANDOM_NUMBER" }, { 9995, "TILE_COORD" }, { 9996, "TILE_RTF_HWM" }, { 10112, "CMPEXCH_VALUE" }, { 10113, "CYCLE" }, { 10114, "EVENT_BEGIN" }, { 10115, "EVENT_END" }, { 10116, "PROC_STATUS" }, { 10117, "SIM_CONTROL" }, { 10118, "SIM_SOCKET" }, { 10119, "STATUS_SATURATE" }, { 10240, "MPL_I_ASID_SET_0" }, { 10241, "MPL_I_ASID_SET_1" }, { 10242, "MPL_I_ASID_SET_2" }, { 10243, "MPL_I_ASID_SET_3" }, { 10244, "MPL_I_ASID" }, { 10245, "I_ASID" }, { 10496, "MPL_D_ASID_SET_0" }, { 10497, "MPL_D_ASID_SET_1" }, { 10498, "MPL_D_ASID_SET_2" }, { 10499, "MPL_D_ASID_SET_3" }, { 10500, "MPL_D_ASID" }, { 10501, "D_ASID" }, { 10752, "MPL_DOUBLE_FAULT_SET_0" }, { 10753, "MPL_DOUBLE_FAULT_SET_1" }, { 10754, "MPL_DOUBLE_FAULT_SET_2" }, { 10755, "MPL_DOUBLE_FAULT_SET_3" }, { 10756, "MPL_DOUBLE_FAULT" }, { 10757, "LAST_INTERRUPT_REASON" }, }; const int tilegx_num_sprs = 441; const char * get_tilegx_spr_name (int num) { void *result; struct tilegx_spr key; key.number = num; result = bsearch((const void *) &key, (const void *) tilegx_sprs, tilegx_num_sprs, sizeof (struct tilegx_spr), tilegx_spr_compare); if (result == NULL) { return (NULL); } else { struct tilegx_spr *result_ptr = (struct tilegx_spr *) result; return (result_ptr->name); } } int print_insn_tilegx (unsigned char * memaddr) { struct tilegx_decoded_instruction decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; unsigned char opbuf[TILEGX_BUNDLE_SIZE_IN_BYTES]; int i, num_instructions, num_printed; tilegx_mnemonic padding_mnemonic; memcpy((void *)opbuf, (void *)memaddr, TILEGX_BUNDLE_SIZE_IN_BYTES); /* Parse the instructions in the bundle. */ num_instructions = parse_insn_tilegx (*(unsigned long long *)opbuf, (unsigned long long)memaddr, decoded); /* Print the instructions in the bundle. */ printf("{ "); num_printed = 0; /* Determine which nop opcode is used for padding and should be skipped. */ padding_mnemonic = TILEGX_OPC_FNOP; for (i = 0; i < num_instructions; i++) { if (!decoded[i].opcode->can_bundle) { /* Instructions that cannot be bundled are padded out with nops, rather than fnops. Displaying them is always clutter. */ padding_mnemonic = TILEGX_OPC_NOP; break; } } for (i = 0; i < num_instructions; i++) { const struct tilegx_opcode *opcode = decoded[i].opcode; const char *name; int j; /* Do not print out fnops, unless everything is an fnop, in which case we will print out just the last one. */ if (opcode->mnemonic == padding_mnemonic && (num_printed > 0 || i + 1 < num_instructions)) continue; if (num_printed > 0) printf(" ; "); ++num_printed; name = opcode->name; if (name == NULL) name = ""; printf("%s", name); for (j = 0; j < opcode->num_operands; j++) { unsigned long long num; const struct tilegx_operand *op; const char *spr_name; if (j > 0) printf (","); printf (" "); num = decoded[i].operand_values[j]; op = decoded[i].operands[j]; switch (op->type) { case TILEGX_OP_TYPE_REGISTER: printf ("%s", tilegx_register_names[(int)num]); break; case TILEGX_OP_TYPE_SPR: spr_name = get_tilegx_spr_name(num); if (spr_name != NULL) printf ("%s", spr_name); else printf ("%d", (int)num); break; case TILEGX_OP_TYPE_IMMEDIATE: printf ("%d", (int)num); break; case TILEGX_OP_TYPE_ADDRESS: printf ("0x%016llx", num); break; default: abort (); } } } printf (" }\n"); return TILEGX_BUNDLE_SIZE_IN_BYTES; } ================================================ FILE: src/pcre/sljit/sljitNativeTILEGX_64.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved. * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* TileGX architecture. */ /* Contributed by Tilera Corporation. */ #include "sljitNativeTILEGX-encoder.c" #define SIMM_8BIT_MAX (0x7f) #define SIMM_8BIT_MIN (-0x80) #define SIMM_16BIT_MAX (0x7fff) #define SIMM_16BIT_MIN (-0x8000) #define SIMM_17BIT_MAX (0xffff) #define SIMM_17BIT_MIN (-0x10000) #define SIMM_32BIT_MAX (0x7fffffff) #define SIMM_32BIT_MIN (-0x7fffffff - 1) #define SIMM_48BIT_MAX (0x7fffffff0000L) #define SIMM_48BIT_MIN (-0x800000000000L) #define IMM16(imm) ((imm) & 0xffff) #define UIMM_16BIT_MAX (0xffff) #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) #define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5) #define PIC_ADDR_REG TMP_REG2 static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7 }; #define SLJIT_LOCALS_REG_mapped 54 #define TMP_REG1_mapped 5 #define TMP_REG2_mapped 16 #define TMP_REG3_mapped 6 #define ADDR_TMP_mapped 7 /* Flags are keept in volatile registers. */ #define EQUAL_FLAG 8 /* And carry flag as well. */ #define ULESS_FLAG 9 #define UGREATER_FLAG 10 #define LESS_FLAG 11 #define GREATER_FLAG 12 #define OVERFLOW_FLAG 13 #define ZERO 63 #define RA 55 #define TMP_EREG1 14 #define TMP_EREG2 15 #define LOAD_DATA 0x01 #define WORD_DATA 0x00 #define BYTE_DATA 0x02 #define HALF_DATA 0x04 #define INT_DATA 0x06 #define SIGNED_DATA 0x08 #define DOUBLE_DATA 0x10 /* Separates integer and floating point registers */ #define GPR_REG 0xf #define MEM_MASK 0x1f #define WRITE_BACK 0x00020 #define ARG_TEST 0x00040 #define ALT_KEEP_CACHE 0x00080 #define CUMULATIVE_OP 0x00100 #define LOGICAL_OP 0x00200 #define IMM_OP 0x00400 #define SRC2_IMM 0x00800 #define UNUSED_DEST 0x01000 #define REG_DEST 0x02000 #define REG1_SOURCE 0x04000 #define REG2_SOURCE 0x08000 #define SLOW_SRC1 0x10000 #define SLOW_SRC2 0x20000 #define SLOW_DEST 0x40000 /* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */ #define CHECK_FLAGS(list) (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list)))) SLJIT_API_FUNC_ATTRIBUTE const char *sljit_get_platform_name(void) { return "TileGX" SLJIT_CPUINFO; } /* Length of an instruction word */ typedef sljit_uw sljit_ins; struct jit_instr { const struct tilegx_opcode* opcode; tilegx_pipeline pipe; unsigned long input_registers; unsigned long output_registers; int operand_value[4]; int line; }; /* Opcode Helper Macros */ #define TILEGX_X_MODE 0 #define X_MODE create_Mode(TILEGX_X_MODE) #define FNOP_X0 \ create_Opcode_X0(RRR_0_OPCODE_X0) | \ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \ create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0) #define FNOP_X1 \ create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ create_UnaryOpcodeExtension_X1(FNOP_UNARY_OPCODE_X1) #define NOP \ create_Mode(TILEGX_X_MODE) | FNOP_X0 | FNOP_X1 #define ANOP_X0 \ create_Opcode_X0(RRR_0_OPCODE_X0) | \ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \ create_UnaryOpcodeExtension_X0(NOP_UNARY_OPCODE_X0) #define BPT create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ create_UnaryOpcodeExtension_X1(ILL_UNARY_OPCODE_X1) | \ create_Dest_X1(0x1C) | create_SrcA_X1(0x25) | ANOP_X0 #define ADD_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(ADD_RRR_0_OPCODE_X1) | FNOP_X0 #define ADDI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ create_Imm8OpcodeExtension_X1(ADDI_IMM8_OPCODE_X1) | FNOP_X0 #define SUB_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(SUB_RRR_0_OPCODE_X1) | FNOP_X0 #define NOR_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(NOR_RRR_0_OPCODE_X1) | FNOP_X0 #define OR_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(OR_RRR_0_OPCODE_X1) | FNOP_X0 #define AND_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(AND_RRR_0_OPCODE_X1) | FNOP_X0 #define XOR_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(XOR_RRR_0_OPCODE_X1) | FNOP_X0 #define CMOVNEZ_X0 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \ create_RRROpcodeExtension_X0(CMOVNEZ_RRR_0_OPCODE_X0) | FNOP_X1 #define CMOVEQZ_X0 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \ create_RRROpcodeExtension_X0(CMOVEQZ_RRR_0_OPCODE_X0) | FNOP_X1 #define ADDLI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(ADDLI_OPCODE_X1) | FNOP_X0 #define V4INT_L_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(V4INT_L_RRR_0_OPCODE_X1) | FNOP_X0 #define BFEXTU_X0 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \ create_BFOpcodeExtension_X0(BFEXTU_BF_OPCODE_X0) | FNOP_X1 #define BFEXTS_X0 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \ create_BFOpcodeExtension_X0(BFEXTS_BF_OPCODE_X0) | FNOP_X1 #define SHL16INSLI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHL16INSLI_OPCODE_X1) | FNOP_X0 #define ST_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(ST_RRR_0_OPCODE_X1) | create_Dest_X1(0x0) | FNOP_X0 #define LD_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ create_UnaryOpcodeExtension_X1(LD_UNARY_OPCODE_X1) | FNOP_X0 #define JR_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ create_UnaryOpcodeExtension_X1(JR_UNARY_OPCODE_X1) | FNOP_X0 #define JALR_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ create_UnaryOpcodeExtension_X1(JALR_UNARY_OPCODE_X1) | FNOP_X0 #define CLZ_X0 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \ create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \ create_UnaryOpcodeExtension_X0(CNTLZ_UNARY_OPCODE_X0) | FNOP_X1 #define CMPLTUI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ create_Imm8OpcodeExtension_X1(CMPLTUI_IMM8_OPCODE_X1) | FNOP_X0 #define CMPLTU_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(CMPLTU_RRR_0_OPCODE_X1) | FNOP_X0 #define CMPLTS_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(CMPLTS_RRR_0_OPCODE_X1) | FNOP_X0 #define XORI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ create_Imm8OpcodeExtension_X1(XORI_IMM8_OPCODE_X1) | FNOP_X0 #define ORI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ create_Imm8OpcodeExtension_X1(ORI_IMM8_OPCODE_X1) | FNOP_X0 #define ANDI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ create_Imm8OpcodeExtension_X1(ANDI_IMM8_OPCODE_X1) | FNOP_X0 #define SHLI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \ create_ShiftOpcodeExtension_X1(SHLI_SHIFT_OPCODE_X1) | FNOP_X0 #define SHL_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(SHL_RRR_0_OPCODE_X1) | FNOP_X0 #define SHRSI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \ create_ShiftOpcodeExtension_X1(SHRSI_SHIFT_OPCODE_X1) | FNOP_X0 #define SHRS_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(SHRS_RRR_0_OPCODE_X1) | FNOP_X0 #define SHRUI_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \ create_ShiftOpcodeExtension_X1(SHRUI_SHIFT_OPCODE_X1) | FNOP_X0 #define SHRU_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ create_RRROpcodeExtension_X1(SHRU_RRR_0_OPCODE_X1) | FNOP_X0 #define BEQZ_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \ create_BrType_X1(BEQZ_BRANCH_OPCODE_X1) | FNOP_X0 #define BNEZ_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \ create_BrType_X1(BNEZ_BRANCH_OPCODE_X1) | FNOP_X0 #define J_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \ create_JumpOpcodeExtension_X1(J_JUMP_OPCODE_X1) | FNOP_X0 #define JAL_X1 \ create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \ create_JumpOpcodeExtension_X1(JAL_JUMP_OPCODE_X1) | FNOP_X0 #define DEST_X0(x) create_Dest_X0(x) #define SRCA_X0(x) create_SrcA_X0(x) #define SRCB_X0(x) create_SrcB_X0(x) #define DEST_X1(x) create_Dest_X1(x) #define SRCA_X1(x) create_SrcA_X1(x) #define SRCB_X1(x) create_SrcB_X1(x) #define IMM16_X1(x) create_Imm16_X1(x) #define IMM8_X1(x) create_Imm8_X1(x) #define BFSTART_X0(x) create_BFStart_X0(x) #define BFEND_X0(x) create_BFEnd_X0(x) #define SHIFTIMM_X1(x) create_ShAmt_X1(x) #define JOFF_X1(x) create_JumpOff_X1(x) #define BOFF_X1(x) create_BrOff_X1(x) static const tilegx_mnemonic data_transfer_insts[16] = { /* u w s */ TILEGX_OPC_ST /* st */, /* u w l */ TILEGX_OPC_LD /* ld */, /* u b s */ TILEGX_OPC_ST1 /* st1 */, /* u b l */ TILEGX_OPC_LD1U /* ld1u */, /* u h s */ TILEGX_OPC_ST2 /* st2 */, /* u h l */ TILEGX_OPC_LD2U /* ld2u */, /* u i s */ TILEGX_OPC_ST4 /* st4 */, /* u i l */ TILEGX_OPC_LD4U /* ld4u */, /* s w s */ TILEGX_OPC_ST /* st */, /* s w l */ TILEGX_OPC_LD /* ld */, /* s b s */ TILEGX_OPC_ST1 /* st1 */, /* s b l */ TILEGX_OPC_LD1S /* ld1s */, /* s h s */ TILEGX_OPC_ST2 /* st2 */, /* s h l */ TILEGX_OPC_LD2S /* ld2s */, /* s i s */ TILEGX_OPC_ST4 /* st4 */, /* s i l */ TILEGX_OPC_LD4S /* ld4s */, }; #ifdef TILEGX_JIT_DEBUG static sljit_s32 push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line) { sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; printf("|%04d|S0|:\t\t", line); print_insn_tilegx(ptr); return SLJIT_SUCCESS; } static sljit_s32 push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins) { sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; return SLJIT_SUCCESS; } #define push_inst(a, b) push_inst_debug(a, b, __LINE__) #else static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) { sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; return SLJIT_SUCCESS; } #endif #define BUNDLE_FORMAT_MASK(p0, p1, p2) \ ((p0) | ((p1) << 8) | ((p2) << 16)) #define BUNDLE_FORMAT(p0, p1, p2) \ { \ { \ (tilegx_pipeline)(p0), \ (tilegx_pipeline)(p1), \ (tilegx_pipeline)(p2) \ }, \ BUNDLE_FORMAT_MASK(1 << (p0), 1 << (p1), (1 << (p2))) \ } #define NO_PIPELINE TILEGX_NUM_PIPELINE_ENCODINGS #define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1) #define PI(encoding) \ push_inst(compiler, encoding) #define PB3(opcode, dst, srca, srcb) \ push_3_buffer(compiler, opcode, dst, srca, srcb, __LINE__) #define PB2(opcode, dst, src) \ push_2_buffer(compiler, opcode, dst, src, __LINE__) #define JR(reg) \ push_jr_buffer(compiler, TILEGX_OPC_JR, reg, __LINE__) #define ADD(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_ADD, dst, srca, srcb, __LINE__) #define SUB(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__) #define MUL(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__) #define NOR(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__) #define OR(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_OR, dst, srca, srcb, __LINE__) #define XOR(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_XOR, dst, srca, srcb, __LINE__) #define AND(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_AND, dst, srca, srcb, __LINE__) #define CLZ(dst, src) \ push_2_buffer(compiler, TILEGX_OPC_CLZ, dst, src, __LINE__) #define SHLI(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_SHLI, dst, srca, srcb, __LINE__) #define SHRUI(dst, srca, imm) \ push_3_buffer(compiler, TILEGX_OPC_SHRUI, dst, srca, imm, __LINE__) #define XORI(dst, srca, imm) \ push_3_buffer(compiler, TILEGX_OPC_XORI, dst, srca, imm, __LINE__) #define ORI(dst, srca, imm) \ push_3_buffer(compiler, TILEGX_OPC_ORI, dst, srca, imm, __LINE__) #define CMPLTU(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_CMPLTU, dst, srca, srcb, __LINE__) #define CMPLTS(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_CMPLTS, dst, srca, srcb, __LINE__) #define CMPLTUI(dst, srca, imm) \ push_3_buffer(compiler, TILEGX_OPC_CMPLTUI, dst, srca, imm, __LINE__) #define CMOVNEZ(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_CMOVNEZ, dst, srca, srcb, __LINE__) #define CMOVEQZ(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_CMOVEQZ, dst, srca, srcb, __LINE__) #define ADDLI(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_ADDLI, dst, srca, srcb, __LINE__) #define SHL16INSLI(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_SHL16INSLI, dst, srca, srcb, __LINE__) #define LD_ADD(dst, addr, adjust) \ push_3_buffer(compiler, TILEGX_OPC_LD_ADD, dst, addr, adjust, __LINE__) #define ST_ADD(src, addr, adjust) \ push_3_buffer(compiler, TILEGX_OPC_ST_ADD, src, addr, adjust, __LINE__) #define LD(dst, addr) \ push_2_buffer(compiler, TILEGX_OPC_LD, dst, addr, __LINE__) #define BFEXTU(dst, src, start, end) \ push_4_buffer(compiler, TILEGX_OPC_BFEXTU, dst, src, start, end, __LINE__) #define BFEXTS(dst, src, start, end) \ push_4_buffer(compiler, TILEGX_OPC_BFEXTS, dst, src, start, end, __LINE__) #define ADD_SOLO(dest, srca, srcb) \ push_inst(compiler, ADD_X1 | DEST_X1(dest) | SRCA_X1(srca) | SRCB_X1(srcb)) #define ADDI_SOLO(dest, srca, imm) \ push_inst(compiler, ADDI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM8_X1(imm)) #define ADDLI_SOLO(dest, srca, imm) \ push_inst(compiler, ADDLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm)) #define SHL16INSLI_SOLO(dest, srca, imm) \ push_inst(compiler, SHL16INSLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm)) #define JALR_SOLO(reg) \ push_inst(compiler, JALR_X1 | SRCA_X1(reg)) #define JR_SOLO(reg) \ push_inst(compiler, JR_X1 | SRCA_X1(reg)) struct Format { /* Mapping of bundle issue slot to assigned pipe. */ tilegx_pipeline pipe[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; /* Mask of pipes used by this bundle. */ unsigned int pipe_mask; }; const struct Format formats[] = { /* In Y format we must always have something in Y2, since it has * no fnop, so this conveys that Y2 must always be used. */ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, NO_PIPELINE), BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, NO_PIPELINE), BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, NO_PIPELINE), BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, NO_PIPELINE), /* Y format has three instructions. */ BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2), BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1), BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2), BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0), BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1), BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0), /* X format has only two instructions. */ BUNDLE_FORMAT(TILEGX_PIPELINE_X0, TILEGX_PIPELINE_X1, NO_PIPELINE), BUNDLE_FORMAT(TILEGX_PIPELINE_X1, TILEGX_PIPELINE_X0, NO_PIPELINE) }; struct jit_instr inst_buf[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; unsigned long inst_buf_index; tilegx_pipeline get_any_valid_pipe(const struct tilegx_opcode* opcode) { /* FIXME: tile: we could pregenerate this. */ int pipe; for (pipe = 0; ((opcode->pipes & (1 << pipe)) == 0 && pipe < TILEGX_NUM_PIPELINE_ENCODINGS); pipe++) ; return (tilegx_pipeline)(pipe); } void insert_nop(tilegx_mnemonic opc, int line) { const struct tilegx_opcode* opcode = NULL; memmove(&inst_buf[1], &inst_buf[0], inst_buf_index * sizeof inst_buf[0]); opcode = &tilegx_opcodes[opc]; inst_buf[0].opcode = opcode; inst_buf[0].pipe = get_any_valid_pipe(opcode); inst_buf[0].input_registers = 0; inst_buf[0].output_registers = 0; inst_buf[0].line = line; ++inst_buf_index; } const struct Format* compute_format() { unsigned int compatible_pipes = BUNDLE_FORMAT_MASK( inst_buf[0].opcode->pipes, inst_buf[1].opcode->pipes, (inst_buf_index == 3 ? inst_buf[2].opcode->pipes : (1 << NO_PIPELINE))); const struct Format* match = NULL; const struct Format *b = NULL; unsigned int i; for (i = 0; i < sizeof formats / sizeof formats[0]; i++) { b = &formats[i]; if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) { match = b; break; } } return match; } sljit_s32 assign_pipes() { unsigned long output_registers = 0; unsigned int i = 0; if (inst_buf_index == 1) { tilegx_mnemonic opc = inst_buf[0].opcode->can_bundle ? TILEGX_OPC_FNOP : TILEGX_OPC_NOP; insert_nop(opc, __LINE__); } const struct Format* match = compute_format(); if (match == NULL) return -1; for (i = 0; i < inst_buf_index; i++) { if ((i > 0) && ((inst_buf[i].input_registers & output_registers) != 0)) return -1; if ((i > 0) && ((inst_buf[i].output_registers & output_registers) != 0)) return -1; /* Don't include Rzero in the match set, to avoid triggering needlessly on 'prefetch' instrs. */ output_registers |= inst_buf[i].output_registers & 0xFFFFFFFFFFFFFFL; inst_buf[i].pipe = match->pipe[i]; } /* If only 2 instrs, and in Y-mode, insert a nop. */ if (inst_buf_index == 2 && !tilegx_is_x_pipeline(match->pipe[0])) { insert_nop(TILEGX_OPC_FNOP, __LINE__); /* Select the yet unassigned pipe. */ tilegx_pipeline pipe = (tilegx_pipeline)(((TILEGX_PIPELINE_Y0 + TILEGX_PIPELINE_Y1 + TILEGX_PIPELINE_Y2) - (inst_buf[1].pipe + inst_buf[2].pipe))); inst_buf[0].pipe = pipe; } return 0; } tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst) { int i, val; const struct tilegx_opcode* opcode = inst->opcode; tilegx_bundle_bits bits = opcode->fixed_bit_values[inst->pipe]; const struct tilegx_operand* operand = NULL; for (i = 0; i < opcode->num_operands; i++) { operand = &tilegx_operands[opcode->operands[inst->pipe][i]]; val = inst->operand_value[i]; bits |= operand->insert(val); } return bits; } static sljit_s32 update_buffer(struct sljit_compiler *compiler) { int i; int orig_index = inst_buf_index; struct jit_instr inst0 = inst_buf[0]; struct jit_instr inst1 = inst_buf[1]; struct jit_instr inst2 = inst_buf[2]; tilegx_bundle_bits bits = 0; /* If the bundle is valid as is, perform the encoding and return 1. */ if (assign_pipes() == 0) { for (i = 0; i < inst_buf_index; i++) { bits |= get_bundle_bit(inst_buf + i); #ifdef TILEGX_JIT_DEBUG printf("|%04d", inst_buf[i].line); #endif } #ifdef TILEGX_JIT_DEBUG if (inst_buf_index == 3) printf("|M0|:\t"); else printf("|M0|:\t\t"); print_insn_tilegx(&bits); #endif inst_buf_index = 0; #ifdef TILEGX_JIT_DEBUG return push_inst_nodebug(compiler, bits); #else return push_inst(compiler, bits); #endif } /* If the bundle is invalid, split it in two. First encode the first two (or possibly 1) instructions, and then the last, separately. Note that assign_pipes may have re-ordered the instrs (by inserting no-ops in lower slots) so we need to reset them. */ inst_buf_index = orig_index - 1; inst_buf[0] = inst0; inst_buf[1] = inst1; inst_buf[2] = inst2; if (assign_pipes() == 0) { for (i = 0; i < inst_buf_index; i++) { bits |= get_bundle_bit(inst_buf + i); #ifdef TILEGX_JIT_DEBUG printf("|%04d", inst_buf[i].line); #endif } #ifdef TILEGX_JIT_DEBUG if (inst_buf_index == 3) printf("|M1|:\t"); else printf("|M1|:\t\t"); print_insn_tilegx(&bits); #endif if ((orig_index - 1) == 2) { inst_buf[0] = inst2; inst_buf_index = 1; } else if ((orig_index - 1) == 1) { inst_buf[0] = inst1; inst_buf_index = 1; } else SLJIT_UNREACHABLE(); #ifdef TILEGX_JIT_DEBUG return push_inst_nodebug(compiler, bits); #else return push_inst(compiler, bits); #endif } else { /* We had 3 instrs of which the first 2 can't live in the same bundle. Split those two. Note that we don't try to then combine the second and third instr into a single bundle. First instruction: */ inst_buf_index = 1; inst_buf[0] = inst0; inst_buf[1] = inst1; inst_buf[2] = inst2; if (assign_pipes() == 0) { for (i = 0; i < inst_buf_index; i++) { bits |= get_bundle_bit(inst_buf + i); #ifdef TILEGX_JIT_DEBUG printf("|%04d", inst_buf[i].line); #endif } #ifdef TILEGX_JIT_DEBUG if (inst_buf_index == 3) printf("|M2|:\t"); else printf("|M2|:\t\t"); print_insn_tilegx(&bits); #endif inst_buf[0] = inst1; inst_buf[1] = inst2; inst_buf_index = orig_index - 1; #ifdef TILEGX_JIT_DEBUG return push_inst_nodebug(compiler, bits); #else return push_inst(compiler, bits); #endif } else SLJIT_UNREACHABLE(); } SLJIT_UNREACHABLE(); } static sljit_s32 flush_buffer(struct sljit_compiler *compiler) { while (inst_buf_index != 0) { FAIL_IF(update_buffer(compiler)); } return SLJIT_SUCCESS; } static sljit_s32 push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line) { if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) FAIL_IF(update_buffer(compiler)); const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; inst_buf[inst_buf_index].opcode = opcode; inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); inst_buf[inst_buf_index].operand_value[0] = op0; inst_buf[inst_buf_index].operand_value[1] = op1; inst_buf[inst_buf_index].operand_value[2] = op2; inst_buf[inst_buf_index].operand_value[3] = op3; inst_buf[inst_buf_index].input_registers = 1L << op1; inst_buf[inst_buf_index].output_registers = 1L << op0; inst_buf[inst_buf_index].line = line; inst_buf_index++; return SLJIT_SUCCESS; } static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line) { if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) FAIL_IF(update_buffer(compiler)); const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; inst_buf[inst_buf_index].opcode = opcode; inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); inst_buf[inst_buf_index].operand_value[0] = op0; inst_buf[inst_buf_index].operand_value[1] = op1; inst_buf[inst_buf_index].operand_value[2] = op2; inst_buf[inst_buf_index].line = line; switch (opc) { case TILEGX_OPC_ST_ADD: inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1); inst_buf[inst_buf_index].output_registers = 1L << op0; break; case TILEGX_OPC_LD_ADD: inst_buf[inst_buf_index].input_registers = 1L << op1; inst_buf[inst_buf_index].output_registers = (1L << op0) | (1L << op1); break; case TILEGX_OPC_ADD: case TILEGX_OPC_AND: case TILEGX_OPC_SUB: case TILEGX_OPC_MULX: case TILEGX_OPC_OR: case TILEGX_OPC_XOR: case TILEGX_OPC_NOR: case TILEGX_OPC_SHL: case TILEGX_OPC_SHRU: case TILEGX_OPC_SHRS: case TILEGX_OPC_CMPLTU: case TILEGX_OPC_CMPLTS: case TILEGX_OPC_CMOVEQZ: case TILEGX_OPC_CMOVNEZ: inst_buf[inst_buf_index].input_registers = (1L << op1) | (1L << op2); inst_buf[inst_buf_index].output_registers = 1L << op0; break; case TILEGX_OPC_ADDLI: case TILEGX_OPC_XORI: case TILEGX_OPC_ORI: case TILEGX_OPC_SHLI: case TILEGX_OPC_SHRUI: case TILEGX_OPC_SHRSI: case TILEGX_OPC_SHL16INSLI: case TILEGX_OPC_CMPLTUI: case TILEGX_OPC_CMPLTSI: inst_buf[inst_buf_index].input_registers = 1L << op1; inst_buf[inst_buf_index].output_registers = 1L << op0; break; default: printf("unrecoginzed opc: %s\n", opcode->name); SLJIT_UNREACHABLE(); } inst_buf_index++; return SLJIT_SUCCESS; } static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line) { if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) FAIL_IF(update_buffer(compiler)); const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; inst_buf[inst_buf_index].opcode = opcode; inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); inst_buf[inst_buf_index].operand_value[0] = op0; inst_buf[inst_buf_index].operand_value[1] = op1; inst_buf[inst_buf_index].line = line; switch (opc) { case TILEGX_OPC_BEQZ: case TILEGX_OPC_BNEZ: inst_buf[inst_buf_index].input_registers = 1L << op0; break; case TILEGX_OPC_ST: case TILEGX_OPC_ST1: case TILEGX_OPC_ST2: case TILEGX_OPC_ST4: inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1); inst_buf[inst_buf_index].output_registers = 0; break; case TILEGX_OPC_CLZ: case TILEGX_OPC_LD: case TILEGX_OPC_LD1U: case TILEGX_OPC_LD1S: case TILEGX_OPC_LD2U: case TILEGX_OPC_LD2S: case TILEGX_OPC_LD4U: case TILEGX_OPC_LD4S: inst_buf[inst_buf_index].input_registers = 1L << op1; inst_buf[inst_buf_index].output_registers = 1L << op0; break; default: printf("unrecoginzed opc: %s\n", opcode->name); SLJIT_UNREACHABLE(); } inst_buf_index++; return SLJIT_SUCCESS; } static sljit_s32 push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line) { if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) FAIL_IF(update_buffer(compiler)); const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; inst_buf[inst_buf_index].opcode = opcode; inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); inst_buf[inst_buf_index].input_registers = 0; inst_buf[inst_buf_index].output_registers = 0; inst_buf[inst_buf_index].line = line; inst_buf_index++; return SLJIT_SUCCESS; } static sljit_s32 push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line) { if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) FAIL_IF(update_buffer(compiler)); const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; inst_buf[inst_buf_index].opcode = opcode; inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); inst_buf[inst_buf_index].operand_value[0] = op0; inst_buf[inst_buf_index].input_registers = 1L << op0; inst_buf[inst_buf_index].output_registers = 0; inst_buf[inst_buf_index].line = line; inst_buf_index++; return flush_buffer(compiler); } static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code) { sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; if (jump->flags & SLJIT_REWRITABLE_JUMP) return code_ptr; if (jump->flags & JUMP_ADDR) target_addr = jump->u.target; else { SLJIT_ASSERT(jump->flags & JUMP_LABEL); target_addr = (sljit_uw)(code + jump->u.label->size); } inst = (sljit_ins *)jump->addr; if (jump->flags & IS_COND) inst--; diff = ((sljit_sw) target_addr - (sljit_sw) inst) >> 3; if (diff <= SIMM_17BIT_MAX && diff >= SIMM_17BIT_MIN) { jump->flags |= PATCH_B; if (!(jump->flags & IS_COND)) { if (jump->flags & IS_JAL) { jump->flags &= ~(PATCH_B); jump->flags |= PATCH_J; inst[0] = JAL_X1; #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(inst); #endif } else { inst[0] = BEQZ_X1 | SRCA_X1(ZERO); #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(inst); #endif } return inst; } inst[0] = inst[0] ^ (0x7L << 55); #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(inst); #endif jump->addr -= sizeof(sljit_ins); return inst; } if (jump->flags & IS_COND) { if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) { jump->flags |= PATCH_J; inst[0] = (inst[0] & ~(BOFF_X1(-1))) | BOFF_X1(2); inst[1] = J_X1; return inst + 1; } return code_ptr; } if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) { jump->flags |= PATCH_J; if (jump->flags & IS_JAL) { inst[0] = JAL_X1; #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(inst); #endif } else { inst[0] = J_X1; #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(inst); #endif } return inst; } return code_ptr; } SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_ins *code; sljit_ins *code_ptr; sljit_ins *buf_ptr; sljit_ins *buf_end; sljit_uw word_count; sljit_uw addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; word_count = 0; label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; do { buf_ptr = (sljit_ins *)buf->memory; buf_end = buf_ptr + (buf->used_size >> 3); do { *code_ptr = *buf_ptr++; SLJIT_ASSERT(!label || label->size >= word_count); SLJIT_ASSERT(!jump || jump->addr >= word_count); SLJIT_ASSERT(!const_ || const_->addr >= word_count); /* These structures are ordered by their address. */ if (label && label->size == word_count) { /* Just recording the address. */ label->addr = (sljit_uw) code_ptr; label->size = code_ptr - code; label = label->next; } if (jump && jump->addr == word_count) { if (jump->flags & IS_JAL) jump->addr = (sljit_uw)(code_ptr - 4); else jump->addr = (sljit_uw)(code_ptr - 3); code_ptr = detect_jump_type(jump, code_ptr, code); jump = jump->next; } if (const_ && const_->addr == word_count) { /* Just recording the address. */ const_->addr = (sljit_uw) code_ptr; const_ = const_->next; } code_ptr++; word_count++; } while (buf_ptr < buf_end); buf = buf->next; } while (buf); if (label && label->size == word_count) { label->addr = (sljit_uw) code_ptr; label->size = code_ptr - code; label = label->next; } SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); jump = compiler->jumps; while (jump) { do { addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; buf_ptr = (sljit_ins *)jump->addr; if (jump->flags & PATCH_B) { addr = (sljit_sw)(addr - (jump->addr)) >> 3; SLJIT_ASSERT((sljit_sw) addr <= SIMM_17BIT_MAX && (sljit_sw) addr >= SIMM_17BIT_MIN); buf_ptr[0] = (buf_ptr[0] & ~(BOFF_X1(-1))) | BOFF_X1(addr); #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(buf_ptr); #endif break; } if (jump->flags & PATCH_J) { SLJIT_ASSERT((addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)); addr = (sljit_sw)(addr - (jump->addr)) >> 3; buf_ptr[0] = (buf_ptr[0] & ~(JOFF_X1(-1))) | JOFF_X1(addr); #ifdef TILEGX_JIT_DEBUG printf("[runtime relocate]%04d:\t", __LINE__); print_insn_tilegx(buf_ptr); #endif break; } SLJIT_ASSERT(!(jump->flags & IS_JAL)); /* Set the fields of immediate loads. */ buf_ptr[0] = (buf_ptr[0] & ~(0xFFFFL << 43)) | (((addr >> 32) & 0xFFFFL) << 43); buf_ptr[1] = (buf_ptr[1] & ~(0xFFFFL << 43)) | (((addr >> 16) & 0xFFFFL) << 43); buf_ptr[2] = (buf_ptr[2] & ~(0xFFFFL << 43)) | ((addr & 0xFFFFL) << 43); } while (0); jump = jump->next; } compiler->error = SLJIT_ERR_COMPILED; compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); SLJIT_CACHE_FLUSH(code, code_ptr); return code; } static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) { if (imm <= SIMM_16BIT_MAX && imm >= SIMM_16BIT_MIN) return ADDLI(dst_ar, ZERO, imm); if (imm <= SIMM_32BIT_MAX && imm >= SIMM_32BIT_MIN) { FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 16)); return SHL16INSLI(dst_ar, dst_ar, imm); } if (imm <= SIMM_48BIT_MAX && imm >= SIMM_48BIT_MIN) { FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32)); FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16)); return SHL16INSLI(dst_ar, dst_ar, imm); } FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 48)); FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 32)); FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16)); return SHL16INSLI(dst_ar, dst_ar, imm); } static sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush) { /* Should *not* be optimized as load_immediate, as pcre relocation mechanism will match this fixed 4-instruction pattern. */ if (flush) { FAIL_IF(ADDLI_SOLO(dst_ar, ZERO, imm >> 32)); FAIL_IF(SHL16INSLI_SOLO(dst_ar, dst_ar, imm >> 16)); return SHL16INSLI_SOLO(dst_ar, dst_ar, imm); } FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32)); FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16)); return SHL16INSLI(dst_ar, dst_ar, imm); } static sljit_s32 emit_const_64(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush) { /* Should *not* be optimized as load_immediate, as pcre relocation mechanism will match this fixed 4-instruction pattern. */ if (flush) { FAIL_IF(ADDLI_SOLO(reg_map[dst_ar], ZERO, imm >> 48)); FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 32)); FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 16)); return SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm); } FAIL_IF(ADDLI(reg_map[dst_ar], ZERO, imm >> 48)); FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 32)); FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 16)); return SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_ins base; sljit_s32 i, tmp; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = (local_size + 7) & ~7; compiler->local_size = local_size; if (local_size <= SIMM_16BIT_MAX) { /* Frequent case. */ FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, -local_size)); base = SLJIT_LOCALS_REG_mapped; } else { FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size)); FAIL_IF(ADD(TMP_REG2_mapped, SLJIT_LOCALS_REG_mapped, ZERO)); FAIL_IF(SUB(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped)); base = TMP_REG2_mapped; local_size = 0; } /* Save the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8)); /* Save the S registers. */ tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) { FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); } /* Save the R registers that need to be reserved. */ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); } /* Move the arguments to S registers. */ for (i = 0; i < args; i++) { FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO)); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = (local_size + 7) & ~7; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 local_size; sljit_ins base; sljit_s32 i, tmp; sljit_s32 saveds; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); local_size = compiler->local_size; if (local_size <= SIMM_16BIT_MAX) base = SLJIT_LOCALS_REG_mapped; else { FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size)); FAIL_IF(ADD(TMP_REG1_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped)); base = TMP_REG1_mapped; local_size = 0; } /* Restore the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8)); /* Restore the S registers. */ saveds = compiler->saveds; tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) { FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } /* Restore the R registers that need to be reserved. */ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } if (compiler->local_size <= SIMM_16BIT_MAX) FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, compiler->local_size)); else FAIL_IF(ADD(SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped, ZERO)); return JR(RA); } /* reg_ar is an absoulute register! */ /* Can perform an operation using at most 1 instruction. */ static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) { SLJIT_ASSERT(arg & SLJIT_MEM); if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) && !(arg & OFFS_REG_MASK) && argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) { /* Works for both absoulte and relative addresses. */ if (SLJIT_UNLIKELY(flags & ARG_TEST)) return 1; FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[arg & REG_MASK], argw)); if (flags & LOAD_DATA) FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped)); else FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar)); return -1; } return 0; } /* See getput_arg below. Note: can_cache is called only for binary operators. Those operators always uses word arguments without write back. */ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); /* Simple operation except for updates. */ if (arg & OFFS_REG_MASK) { argw &= 0x3; next_argw &= 0x3; if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK))) return 1; return 0; } if (arg == next_arg) { if (((next_argw - argw) <= SIMM_16BIT_MAX && (next_argw - argw) >= SIMM_16BIT_MIN)) return 1; return 0; } return 0; } /* Emit the necessary instructions. See can_cache above. */ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) { sljit_s32 tmp_ar, base; SLJIT_ASSERT(arg & SLJIT_MEM); if (!(next_arg & SLJIT_MEM)) { next_arg = 0; next_argw = 0; } if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) tmp_ar = reg_ar; else tmp_ar = TMP_REG1_mapped; base = arg & REG_MASK; if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { argw &= 0x3; if ((flags & WRITE_BACK) && reg_ar == reg_map[base]) { SLJIT_ASSERT(!(flags & LOAD_DATA) && reg_map[TMP_REG1] != reg_ar); FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO)); reg_ar = TMP_REG1_mapped; } /* Using the cache. */ if (argw == compiler->cache_argw) { if (!(flags & WRITE_BACK)) { if (arg == compiler->cache_arg) { if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); else return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); } if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { if (arg == next_arg && argw == (next_argw & 0x3)) { compiler->cache_arg = arg; compiler->cache_argw = argw; FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], TMP_REG3_mapped)); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); else return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); } FAIL_IF(ADD(tmp_ar, reg_map[base], TMP_REG3_mapped)); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar); else return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar); } } else { if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped)); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]); else return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar); } } } if (SLJIT_UNLIKELY(argw)) { compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK); compiler->cache_argw = argw; FAIL_IF(SHLI(TMP_REG3_mapped, reg_map[OFFS_REG(arg)], argw)); } if (!(flags & WRITE_BACK)) { if (arg == next_arg && argw == (next_argw & 0x3)) { compiler->cache_arg = arg; compiler->cache_argw = argw; FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3])); tmp_ar = TMP_REG3_mapped; } else FAIL_IF(ADD(tmp_ar, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3])); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar); else return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar); } FAIL_IF(ADD(reg_map[base], reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3])); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]); else return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar); } if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) { /* Update only applies if a base register exists. */ if (reg_ar == reg_map[base]) { SLJIT_ASSERT(!(flags & LOAD_DATA) && TMP_REG1_mapped != reg_ar); if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) { FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[base], argw)); if (flags & LOAD_DATA) FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped)); else FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar)); if (argw) return ADDLI(reg_map[base], reg_map[base], argw); return SLJIT_SUCCESS; } FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO)); reg_ar = TMP_REG1_mapped; } if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) { if (argw) FAIL_IF(ADDLI(reg_map[base], reg_map[base], argw)); } else { if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_16BIT_MAX && argw - compiler->cache_argw >= SIMM_16BIT_MIN) { if (argw != compiler->cache_argw) { FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw)); compiler->cache_argw = argw; } FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped)); } else { compiler->cache_arg = SLJIT_MEM; compiler->cache_argw = argw; FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw)); FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped)); } } if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]); else return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar); } if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_16BIT_MAX && argw - compiler->cache_argw >= SIMM_16BIT_MIN) { if (argw != compiler->cache_argw) { FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw)); compiler->cache_argw = argw; } if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); else return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); } if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_16BIT_MAX && argw - compiler->cache_argw >= SIMM_16BIT_MIN) { if (argw != compiler->cache_argw) FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw)); } else { compiler->cache_arg = SLJIT_MEM; FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw)); } compiler->cache_argw = argw; if (!base) { if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); else return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); } if (arg == next_arg && next_argw - argw <= SIMM_16BIT_MAX && next_argw - argw >= SIMM_16BIT_MIN) { compiler->cache_arg = arg; FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, reg_map[base])); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); else return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); } FAIL_IF(ADD(tmp_ar, TMP_REG3_mapped, reg_map[base])); if (flags & LOAD_DATA) return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar); else return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar); } static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) { if (getput_arg_fast(compiler, flags, reg_ar, arg, argw)) return compiler->error; compiler->cache_arg = 0; compiler->cache_argw = 0; return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0); } static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w) { if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) return compiler->error; return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); /* For UNUSED dst. Uncommon, but possible. */ if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; if (FAST_IS_REG(dst)) return ADD(reg_map[dst], RA, ZERO); /* Memory. */ return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) FAIL_IF(ADD(RA, reg_map[src], ZERO)); else if (src & SLJIT_MEM) FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw)); else if (src & SLJIT_IMM) FAIL_IF(load_immediate(compiler, RA, srcw)); return JR(RA); } static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) { sljit_s32 overflow_ra = 0; switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_P: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (dst != src2) return ADD(reg_map[dst], reg_map[src2], ZERO); return SLJIT_SUCCESS; case SLJIT_MOV_U32: case SLJIT_MOV_S32: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S32) return BFEXTS(reg_map[dst], reg_map[src2], 0, 31); return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); } else if (dst != src2) { SLJIT_ASSERT(src2 == 0); return ADD(reg_map[dst], reg_map[src2], ZERO); } return SLJIT_SUCCESS; case SLJIT_MOV_U8: case SLJIT_MOV_S8: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) return BFEXTS(reg_map[dst], reg_map[src2], 0, 7); return BFEXTU(reg_map[dst], reg_map[src2], 0, 7); } else if (dst != src2) { SLJIT_ASSERT(src2 == 0); return ADD(reg_map[dst], reg_map[src2], ZERO); } return SLJIT_SUCCESS; case SLJIT_MOV_U16: case SLJIT_MOV_S16: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) return BFEXTS(reg_map[dst], reg_map[src2], 0, 15); return BFEXTU(reg_map[dst], reg_map[src2], 0, 15); } else if (dst != src2) { SLJIT_ASSERT(src2 == 0); return ADD(reg_map[dst], reg_map[src2], ZERO); } return SLJIT_SUCCESS; case SLJIT_NOT: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (op & SLJIT_SET_E) FAIL_IF(NOR(EQUAL_FLAG, reg_map[src2], reg_map[src2])); if (CHECK_FLAGS(SLJIT_SET_E)) FAIL_IF(NOR(reg_map[dst], reg_map[src2], reg_map[src2])); return SLJIT_SUCCESS; case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if (op & SLJIT_SET_E) FAIL_IF(CLZ(EQUAL_FLAG, reg_map[src2])); if (CHECK_FLAGS(SLJIT_SET_E)) FAIL_IF(CLZ(reg_map[dst], reg_map[src2])); return SLJIT_SUCCESS; case SLJIT_ADD: if (flags & SRC2_IMM) { if (op & SLJIT_SET_O) { FAIL_IF(SHRUI(TMP_EREG1, reg_map[src1], 63)); if (src2 < 0) FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1)); } if (op & SLJIT_SET_E) FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], src2)); if (op & SLJIT_SET_C) { if (src2 >= 0) FAIL_IF(ORI(ULESS_FLAG ,reg_map[src1], src2)); else { FAIL_IF(ADDLI(ULESS_FLAG ,ZERO, src2)); FAIL_IF(OR(ULESS_FLAG,reg_map[src1],ULESS_FLAG)); } } /* dst may be the same as src1 or src2. */ if (CHECK_FLAGS(SLJIT_SET_E)) FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2)); if (op & SLJIT_SET_O) { FAIL_IF(SHRUI(OVERFLOW_FLAG, reg_map[dst], 63)); if (src2 < 0) FAIL_IF(XORI(OVERFLOW_FLAG, OVERFLOW_FLAG, 1)); } } else { if (op & SLJIT_SET_O) { FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2])); FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63)); if (src1 != dst) overflow_ra = reg_map[src1]; else if (src2 != dst) overflow_ra = reg_map[src2]; else { /* Rare ocasion. */ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); overflow_ra = TMP_EREG2; } } if (op & SLJIT_SET_E) FAIL_IF(ADD(EQUAL_FLAG ,reg_map[src1], reg_map[src2])); if (op & SLJIT_SET_C) FAIL_IF(OR(ULESS_FLAG,reg_map[src1], reg_map[src2])); /* dst may be the same as src1 or src2. */ if (CHECK_FLAGS(SLJIT_SET_E)) FAIL_IF(ADD(reg_map[dst],reg_map[src1], reg_map[src2])); if (op & SLJIT_SET_O) { FAIL_IF(XOR(OVERFLOW_FLAG,reg_map[dst], overflow_ra)); FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63)); } } /* a + b >= a | b (otherwise, the carry should be set to 1). */ if (op & SLJIT_SET_C) FAIL_IF(CMPLTU(ULESS_FLAG ,reg_map[dst] ,ULESS_FLAG)); if (op & SLJIT_SET_O) return CMOVNEZ(OVERFLOW_FLAG, TMP_EREG1, ZERO); return SLJIT_SUCCESS; case SLJIT_ADDC: if (flags & SRC2_IMM) { if (op & SLJIT_SET_C) { if (src2 >= 0) FAIL_IF(ORI(TMP_EREG1, reg_map[src1], src2)); else { FAIL_IF(ADDLI(TMP_EREG1, ZERO, src2)); FAIL_IF(OR(TMP_EREG1, reg_map[src1], TMP_EREG1)); } } FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2)); } else { if (op & SLJIT_SET_C) FAIL_IF(OR(TMP_EREG1, reg_map[src1], reg_map[src2])); /* dst may be the same as src1 or src2. */ FAIL_IF(ADD(reg_map[dst], reg_map[src1], reg_map[src2])); } if (op & SLJIT_SET_C) FAIL_IF(CMPLTU(TMP_EREG1, reg_map[dst], TMP_EREG1)); FAIL_IF(ADD(reg_map[dst], reg_map[dst], ULESS_FLAG)); if (!(op & SLJIT_SET_C)) return SLJIT_SUCCESS; /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */ FAIL_IF(CMPLTUI(TMP_EREG2, reg_map[dst], 1)); FAIL_IF(AND(TMP_EREG2, TMP_EREG2, ULESS_FLAG)); /* Set carry flag. */ return OR(ULESS_FLAG, TMP_EREG2, TMP_EREG1); case SLJIT_SUB: if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_16BIT_MIN)) { FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2)); src2 = TMP_REG2; flags &= ~SRC2_IMM; } if (flags & SRC2_IMM) { if (op & SLJIT_SET_O) { FAIL_IF(SHRUI(TMP_EREG1,reg_map[src1], 63)); if (src2 < 0) FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1)); if (src1 != dst) overflow_ra = reg_map[src1]; else { /* Rare ocasion. */ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); overflow_ra = TMP_EREG2; } } if (op & SLJIT_SET_E) FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], -src2)); if (op & SLJIT_SET_C) { FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], ADDR_TMP_mapped)); } /* dst may be the same as src1 or src2. */ if (CHECK_FLAGS(SLJIT_SET_E)) FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2)); } else { if (op & SLJIT_SET_O) { FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2])); FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63)); if (src1 != dst) overflow_ra = reg_map[src1]; else { /* Rare ocasion. */ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); overflow_ra = TMP_EREG2; } } if (op & SLJIT_SET_E) FAIL_IF(SUB(EQUAL_FLAG, reg_map[src1], reg_map[src2])); if (op & (SLJIT_SET_U | SLJIT_SET_C)) FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], reg_map[src2])); if (op & SLJIT_SET_U) FAIL_IF(CMPLTU(UGREATER_FLAG, reg_map[src2], reg_map[src1])); if (op & SLJIT_SET_S) { FAIL_IF(CMPLTS(LESS_FLAG ,reg_map[src1] ,reg_map[src2])); FAIL_IF(CMPLTS(GREATER_FLAG ,reg_map[src2] ,reg_map[src1])); } /* dst may be the same as src1 or src2. */ if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C)) FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2])); } if (op & SLJIT_SET_O) { FAIL_IF(XOR(OVERFLOW_FLAG, reg_map[dst], overflow_ra)); FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63)); return CMOVEQZ(OVERFLOW_FLAG, TMP_EREG1, ZERO); } return SLJIT_SUCCESS; case SLJIT_SUBC: if ((flags & SRC2_IMM) && src2 == SIMM_16BIT_MIN) { FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2)); src2 = TMP_REG2; flags &= ~SRC2_IMM; } if (flags & SRC2_IMM) { if (op & SLJIT_SET_C) { FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, -src2)); FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], ADDR_TMP_mapped)); } /* dst may be the same as src1 or src2. */ FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2)); } else { if (op & SLJIT_SET_C) FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], reg_map[src2])); /* dst may be the same as src1 or src2. */ FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2])); } if (op & SLJIT_SET_C) FAIL_IF(CMOVEQZ(TMP_EREG1, reg_map[dst], ULESS_FLAG)); FAIL_IF(SUB(reg_map[dst], reg_map[dst], ULESS_FLAG)); if (op & SLJIT_SET_C) FAIL_IF(ADD(ULESS_FLAG, TMP_EREG1, ZERO)); return SLJIT_SUCCESS; case SLJIT_MUL: if (flags & SRC2_IMM) { FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2)); src2 = TMP_REG2; flags &= ~SRC2_IMM; } FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2])); return SLJIT_SUCCESS; #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ ADDR_TMP_mapped, __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, reg_map[dst], reg_map[src1], \ ADDR_TMP_mapped, __LINE__)); \ } else { \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ reg_map[src2], __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, reg_map[dst], reg_map[src1], \ reg_map[src2], __LINE__)); \ } case SLJIT_AND: EMIT_LOGICAL(TILEGX_OPC_ANDI, TILEGX_OPC_AND); return SLJIT_SUCCESS; case SLJIT_OR: EMIT_LOGICAL(TILEGX_OPC_ORI, TILEGX_OPC_OR); return SLJIT_SUCCESS; case SLJIT_XOR: EMIT_LOGICAL(TILEGX_OPC_XORI, TILEGX_OPC_XOR); return SLJIT_SUCCESS; #define EMIT_SHIFT(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ compiler, op_imm, EQUAL_FLAG, reg_map[src1], \ src2 & 0x3F, __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_imm, reg_map[dst], reg_map[src1], \ src2 & 0x3F, __LINE__)); \ } else { \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ reg_map[src2], __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, reg_map[dst], reg_map[src1], \ reg_map[src2], __LINE__)); \ } case SLJIT_SHL: EMIT_SHIFT(TILEGX_OPC_SHLI, TILEGX_OPC_SHL); return SLJIT_SUCCESS; case SLJIT_LSHR: EMIT_SHIFT(TILEGX_OPC_SHRUI, TILEGX_OPC_SHRU); return SLJIT_SUCCESS; case SLJIT_ASHR: EMIT_SHIFT(TILEGX_OPC_SHRSI, TILEGX_OPC_SHRS); return SLJIT_SUCCESS; } SLJIT_UNREACHABLE(); return SLJIT_SUCCESS; } static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* arg1 goes to TMP_REG1 or src reg. arg2 goes to TMP_REG2, imm or src reg. TMP_REG3 can be used for caching. result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ sljit_s32 dst_r = TMP_REG2; sljit_s32 src1_r; sljit_sw src2_r = 0; sljit_s32 sugg_src2_r = TMP_REG2; if (!(flags & ALT_KEEP_CACHE)) { compiler->cache_arg = 0; compiler->cache_argw = 0; } if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM)) return SLJIT_SUCCESS; if (GET_FLAGS(op)) flags |= UNUSED_DEST; } else if (FAST_IS_REG(dst)) { dst_r = dst; flags |= REG_DEST; if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) sugg_src2_r = dst_r; } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1_mapped, dst, dstw)) flags |= SLOW_DEST; if (flags & IMM_OP) { if ((src2 & SLJIT_IMM) && src2w) { if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_16BIT_MAX && src2w >= SIMM_16BIT_MIN)) || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_16BIT_MAX))) { flags |= SRC2_IMM; src2_r = src2w; } } if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) { if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_16BIT_MAX && src1w >= SIMM_16BIT_MIN)) || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_16BIT_MAX))) { flags |= SRC2_IMM; src2_r = src1w; /* And swap arguments. */ src1 = src2; src1w = src2w; src2 = SLJIT_IMM; /* src2w = src2_r unneeded. */ } } } /* Source 1. */ if (FAST_IS_REG(src1)) { src1_r = src1; flags |= REG1_SOURCE; } else if (src1 & SLJIT_IMM) { if (src1w) { FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, src1w)); src1_r = TMP_REG1; } else src1_r = 0; } else { if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w)) FAIL_IF(compiler->error); else flags |= SLOW_SRC1; src1_r = TMP_REG1; } /* Source 2. */ if (FAST_IS_REG(src2)) { src2_r = src2; flags |= REG2_SOURCE; if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) dst_r = src2_r; } else if (src2 & SLJIT_IMM) { if (!(flags & SRC2_IMM)) { if (src2w) { FAIL_IF(load_immediate(compiler, reg_map[sugg_src2_r], src2w)); src2_r = sugg_src2_r; } else { src2_r = 0; if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM)) dst_r = 0; } } } else { if (getput_arg_fast(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w)) FAIL_IF(compiler->error); else flags |= SLOW_SRC2; src2_r = sugg_src2_r; } if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { SLJIT_ASSERT(src2_r == TMP_REG2); if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, src1, src1w)); FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw)); } else { FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, src2, src2w)); FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, dst, dstw)); } } else if (flags & SLOW_SRC1) FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw)); else if (flags & SLOW_SRC2) FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w, dst, dstw)); FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); if (dst & SLJIT_MEM) { if (!(flags & SLOW_DEST)) { getput_arg_fast(compiler, flags, reg_map[dst_r], dst, dstw); return compiler->error; } return getput_arg(compiler, flags, reg_map[dst_r], dst, dstw, 0, 0); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw, sljit_s32 type) { sljit_s32 sugg_dst_ar, dst_ar; sljit_s32 flags = GET_ALL_FLAGS(op); sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); op = GET_OPCODE(op); if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32) mem_type = INT_DATA | SIGNED_DATA; sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2]; compiler->cache_arg = 0; compiler->cache_argw = 0; if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { ADJUST_LOCAL_OFFSET(src, srcw); FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); src = TMP_REG1; srcw = 0; } switch (type & 0xff) { case SLJIT_EQUAL: case SLJIT_NOT_EQUAL: FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1)); dst_ar = sugg_dst_ar; break; case SLJIT_LESS: case SLJIT_GREATER_EQUAL: dst_ar = ULESS_FLAG; break; case SLJIT_GREATER: case SLJIT_LESS_EQUAL: dst_ar = UGREATER_FLAG; break; case SLJIT_SIG_LESS: case SLJIT_SIG_GREATER_EQUAL: dst_ar = LESS_FLAG; break; case SLJIT_SIG_GREATER: case SLJIT_SIG_LESS_EQUAL: dst_ar = GREATER_FLAG; break; case SLJIT_OVERFLOW: case SLJIT_NOT_OVERFLOW: dst_ar = OVERFLOW_FLAG; break; case SLJIT_MUL_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1)); dst_ar = sugg_dst_ar; type ^= 0x1; /* Flip type bit for the XORI below. */ break; default: SLJIT_UNREACHABLE(); dst_ar = sugg_dst_ar; break; } if (type & 0x1) { FAIL_IF(XORI(sugg_dst_ar, dst_ar, 1)); dst_ar = sugg_dst_ar; } if (op >= SLJIT_ADD) { if (TMP_REG2_mapped != dst_ar) FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO)); return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); } if (dst & SLJIT_MEM) return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw); if (sugg_dst_ar != dst_ar) return ADD(sugg_dst_ar, dst_ar, ZERO); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { case SLJIT_NOP: return push_0_buffer(compiler, TILEGX_OPC_FNOP, __LINE__); case SLJIT_BREAKPOINT: return PI(BPT); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_UNREACHABLE(); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_P: return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U32: return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_S32: return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOV_U8: return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw); case SLJIT_MOV_S8: return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw); case SLJIT_MOV_U16: return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw); case SLJIT_MOV_S16: return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw); case SLJIT_MOVU: case SLJIT_MOVU_P: return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOVU_U32: return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOVU_S32: return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_MOVU_U8: return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw); case SLJIT_MOVU_S8: return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw); case SLJIT_MOVU_U16: return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw); case SLJIT_MOVU_S16: return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw); case SLJIT_NOT: return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); case SLJIT_NEG: return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); case SLJIT_CLZ: return emit_op(compiler, op, (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); switch (GET_OPCODE(op)) { case SLJIT_ADD: case SLJIT_ADDC: return emit_op(compiler, op, CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: case SLJIT_SUBC: return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: return emit_op(compiler, op, CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: case SLJIT_OR: case SLJIT_XOR: return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: case SLJIT_LSHR: case SLJIT_ASHR: if (src2 & SLJIT_IMM) src2w &= 0x3f; if (op & SLJIT_I32_OP) src2w &= 0x1f; return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler) { struct sljit_label *label; flush_buffer(compiler); CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label *)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); return label; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { sljit_s32 src_r = TMP_REG2; struct sljit_jump *jump = NULL; flush_buffer(compiler); CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { if (reg_map[src] != 0) src_r = src; else FAIL_IF(ADD_SOLO(TMP_REG2_mapped, reg_map[src], ZERO)); } if (type >= SLJIT_CALL0) { SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2); if (src & (SLJIT_IMM | SLJIT_MEM)) { if (src & SLJIT_IMM) FAIL_IF(emit_const(compiler, reg_map[PIC_ADDR_REG], srcw, 1)); else { SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM)); FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); } FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO)); FAIL_IF(ADDI_SOLO(54, 54, -16)); FAIL_IF(JALR_SOLO(reg_map[PIC_ADDR_REG])); return ADDI_SOLO(54, 54, 16); } /* Register input. */ if (type >= SLJIT_CALL1) FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO)); FAIL_IF(ADD_SOLO(reg_map[PIC_ADDR_REG], reg_map[src_r], ZERO)); FAIL_IF(ADDI_SOLO(54, 54, -16)); FAIL_IF(JALR_SOLO(reg_map[src_r])); return ADDI_SOLO(54, 54, 16); } if (src & SLJIT_IMM) { jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF(!jump); set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0)); jump->u.target = srcw; FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1)); if (type >= SLJIT_FAST_CALL) { FAIL_IF(ADD_SOLO(ZERO, ZERO, ZERO)); jump->addr = compiler->size; FAIL_IF(JR_SOLO(reg_map[src_r])); } else { jump->addr = compiler->size; FAIL_IF(JR_SOLO(reg_map[src_r])); } return SLJIT_SUCCESS; } else if (src & SLJIT_MEM) { FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); flush_buffer(compiler); } FAIL_IF(JR_SOLO(reg_map[src_r])); if (jump) jump->addr = compiler->size; return SLJIT_SUCCESS; } #define BR_Z(src) \ inst = BEQZ_X1 | SRCA_X1(src); \ flags = IS_COND; #define BR_NZ(src) \ inst = BNEZ_X1 | SRCA_X1(src); \ flags = IS_COND; SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { struct sljit_jump *jump; sljit_ins inst; sljit_s32 flags = 0; flush_buffer(compiler); CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; switch (type) { case SLJIT_EQUAL: BR_NZ(EQUAL_FLAG); break; case SLJIT_NOT_EQUAL: BR_Z(EQUAL_FLAG); break; case SLJIT_LESS: BR_Z(ULESS_FLAG); break; case SLJIT_GREATER_EQUAL: BR_NZ(ULESS_FLAG); break; case SLJIT_GREATER: BR_Z(UGREATER_FLAG); break; case SLJIT_LESS_EQUAL: BR_NZ(UGREATER_FLAG); break; case SLJIT_SIG_LESS: BR_Z(LESS_FLAG); break; case SLJIT_SIG_GREATER_EQUAL: BR_NZ(LESS_FLAG); break; case SLJIT_SIG_GREATER: BR_Z(GREATER_FLAG); break; case SLJIT_SIG_LESS_EQUAL: BR_NZ(GREATER_FLAG); break; case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: BR_Z(OVERFLOW_FLAG); break; case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: BR_NZ(OVERFLOW_FLAG); break; default: /* Not conditional branch. */ inst = 0; break; } jump->flags |= flags; if (inst) { inst = inst | ((type <= SLJIT_JUMP) ? BOFF_X1(5) : BOFF_X1(6)); PTR_FAIL_IF(PI(inst)); } PTR_FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1)); if (type <= SLJIT_JUMP) { jump->addr = compiler->size; PTR_FAIL_IF(JR_SOLO(TMP_REG2_mapped)); } else { SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2); /* Cannot be optimized out if type is >= CALL0. */ jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0); PTR_FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO)); jump->addr = compiler->size; PTR_FAIL_IF(JALR_SOLO(TMP_REG2_mapped)); } return jump; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { SLJIT_UNREACHABLE(); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { struct sljit_const *const_; sljit_s32 reg; flush_buffer(compiler); CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); reg = FAST_IS_REG(dst) ? dst : TMP_REG2; PTR_FAIL_IF(emit_const_64(compiler, reg, init_value, 1)); if (dst & SLJIT_MEM) PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); return const_; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_target >> 32) & 0xffff) << 43); inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_target >> 16) & 0xffff) << 43); inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_target & 0xffff) << 43); SLJIT_CACHE_FLUSH(inst, inst + 3); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant) { sljit_ins *inst = (sljit_ins *)addr; inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_constant >> 48) & 0xFFFFL) << 43); inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_constant >> 32) & 0xFFFFL) << 43); inst[2] = (inst[2] & ~(0xFFFFL << 43)) | (((new_constant >> 16) & 0xFFFFL) << 43); inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43); SLJIT_CACHE_FLUSH(inst, inst + 4); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); return SLJIT_ERR_UNSUPPORTED; } ================================================ FILE: src/pcre/sljit/sljitNativeX86_32.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* x86 32-bit arch dependent functions. */ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm) { sljit_u8 *inst; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw)); FAIL_IF(!inst); INC_SIZE(1 + sizeof(sljit_sw)); *inst++ = opcode; sljit_unaligned_store_sw(inst, imm); return SLJIT_SUCCESS; } static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset) { if (type == SLJIT_JUMP) { *code_ptr++ = JMP_i32; jump->addr++; } else if (type >= SLJIT_FAST_CALL) { *code_ptr++ = CALL_i32; jump->addr++; } else { *code_ptr++ = GROUP_0F; *code_ptr++ = get_jump_code(type); jump->addr += 2; } if (jump->flags & JUMP_LABEL) jump->flags |= PATCH_MW; else sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset); code_ptr += 4; return code_ptr; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args, size; sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); args = get_arg_count(arg_types); compiler->args = args; /* [esp+0] for saving temporaries and function calls. */ compiler->stack_tmp_size = 2 * sizeof(sljit_sw); #if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (scratches > 3) compiler->stack_tmp_size = 3 * sizeof(sljit_sw); #endif compiler->saveds_offset = compiler->stack_tmp_size; if (scratches > 3) compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw); compiler->locals_offset = compiler->saveds_offset; if (saveds > 3) compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw); if (options & SLJIT_F64_ALIGNMENT) compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1); size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0); #else size += (args > 0 ? (2 + args * 3) : 0); #endif inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); PUSH_REG(reg_map[TMP_REG1]); #if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (args > 0) { *inst++ = MOV_r_rm; *inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */; } #endif if (saveds > 2 || scratches > 9) PUSH_REG(reg_map[SLJIT_S2]); if (saveds > 1 || scratches > 10) PUSH_REG(reg_map[SLJIT_S1]); if (saveds > 0 || scratches > 11) PUSH_REG(reg_map[SLJIT_S0]); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (args > 0) { inst[0] = MOV_r_rm; inst[1] = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2]; inst += 2; } if (args > 1) { inst[0] = MOV_r_rm; inst[1] = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1]; inst += 2; } if (args > 2) { inst[0] = MOV_r_rm; inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */; inst[2] = 0x24; inst[3] = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */ } #else if (args > 0) { inst[0] = MOV_r_rm; inst[1] = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1]; inst[2] = sizeof(sljit_sw) * 2; inst += 3; } if (args > 1) { inst[0] = MOV_r_rm; inst[1] = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1]; inst[2] = sizeof(sljit_sw) * 3; inst += 3; } if (args > 2) { inst[0] = MOV_r_rm; inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1]; inst[2] = sizeof(sljit_sw) * 4; } #endif SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0); #if defined(__APPLE__) /* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */ saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw); local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds; #else if (options & SLJIT_F64_ALIGNMENT) local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1)); else local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1)); #endif compiler->local_size = local_size; #ifdef _WIN32 if (local_size > 0) { if (local_size <= 4 * 4096) { if (local_size > 4096) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096); if (local_size > 2 * 4096) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2); if (local_size > 3 * 4096) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3); } else { EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0); EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_IMM, (local_size - 1) >> 12); SLJIT_ASSERT (reg_map[SLJIT_R0] == 0); EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_R0), -4096); FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096)); FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1)); inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); inst[0] = JNE_i8; inst[1] = (sljit_s8) -16; } EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size); } #endif SLJIT_ASSERT(local_size > 0); #if !defined(__APPLE__) if (options & SLJIT_F64_ALIGNMENT) { EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0); /* Some space might allocated during sljit_grow_stack() above on WIN32. */ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw))); #if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (compiler->local_size > 1024) FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw))); #endif inst = (sljit_u8*)ensure_buf(compiler, 1 + 6); FAIL_IF(!inst); INC_SIZE(6); inst[0] = GROUP_BINARY_81; inst[1] = MOD_REG | AND | reg_map[SLJIT_SP]; sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1)); /* The real local size must be used. */ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0); } #endif return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); compiler->args = get_arg_count(arg_types); /* [esp+0] for saving temporaries and function calls. */ compiler->stack_tmp_size = 2 * sizeof(sljit_sw); #if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (scratches > 3) compiler->stack_tmp_size = 3 * sizeof(sljit_sw); #endif compiler->saveds_offset = compiler->stack_tmp_size; if (scratches > 3) compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw); compiler->locals_offset = compiler->saveds_offset; if (saveds > 3) compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw); if (options & SLJIT_F64_ALIGNMENT) compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1); #if defined(__APPLE__) saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw); compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds; #else if (options & SLJIT_F64_ALIGNMENT) compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1)); else compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1)); #endif return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 size; sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); SLJIT_ASSERT(compiler->args >= 0); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); SLJIT_ASSERT(compiler->local_size > 0); #if !defined(__APPLE__) if (compiler->options & SLJIT_F64_ALIGNMENT) EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size) else FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); #else FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); #endif size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (compiler->args > 2) size += 2; #else if (compiler->args > 0) size += 2; #endif inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); if (compiler->saveds > 0 || compiler->scratches > 11) POP_REG(reg_map[SLJIT_S0]); if (compiler->saveds > 1 || compiler->scratches > 10) POP_REG(reg_map[SLJIT_S1]); if (compiler->saveds > 2 || compiler->scratches > 9) POP_REG(reg_map[SLJIT_S2]); POP_REG(reg_map[TMP_REG1]); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (compiler->args > 2) RET_I16(sizeof(sljit_sw)); else RET(); #else RET(); #endif return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ /* Size contains the flags as well. */ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size, /* The register or immediate operand. */ sljit_s32 a, sljit_sw imma, /* The general operand (not immediate). */ sljit_s32 b, sljit_sw immb) { sljit_u8 *inst; sljit_u8 *buf_ptr; sljit_s32 flags = size & ~0xf; sljit_s32 inst_size; /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); size &= 0xf; inst_size = size; if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) inst_size++; if (flags & EX86_PREF_66) inst_size++; /* Calculate size of b. */ inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if ((b & REG_MASK) == SLJIT_UNUSED) inst_size += sizeof(sljit_sw); else if (immb != 0 && !(b & OFFS_REG_MASK)) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_sw); } if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK)) b |= TO_OFFS_REG(SLJIT_SP); if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) inst_size += 1; /* SIB byte. */ } /* Calculate size of a. */ if (a & SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; } else if (flags & EX86_SHIFT_INS) { imma &= 0x1f; if (imma != 1) { inst_size ++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) inst_size++; else if (flags & EX86_HALF_ARG) inst_size += sizeof(short); else inst_size += sizeof(sljit_sw); } else SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); /* Encoding the byte. */ INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2; if (flags & EX86_PREF_F3) *inst++ = 0xf3; if (flags & EX86_PREF_66) *inst++ = 0x66; buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; if (a & SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = reg_map[a] << 3; else *buf_ptr = a << 3; } else { if (a & SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else *inst = GROUP_SHIFT_N; } else *inst = GROUP_SHIFT_CL; *buf_ptr = 0; } if (!(b & SLJIT_MEM)) *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_map[b] : b); else if ((b & REG_MASK) != SLJIT_UNUSED) { if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40; else *buf_ptr |= 0x80; } if ((b & OFFS_REG_MASK) == SLJIT_UNUSED) *buf_ptr++ |= reg_map[b & REG_MASK]; else { *buf_ptr++ |= 0x04; *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3); } if (immb != 0) { if (immb <= 127 && immb >= -128) *buf_ptr++ = immb; /* 8 bit displacement. */ else { sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_sw); } } } else { *buf_ptr++ |= 0x04; *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6); } } else { *buf_ptr++ |= 0x05; sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_sw); } if (a & SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = imma; else if (flags & EX86_HALF_ARG) sljit_unaligned_store_s16(buf_ptr, imma); else if (!(flags & EX86_SHIFT_INS)) sljit_unaligned_store_sw(buf_ptr, imma); } return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); } /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */ #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) static sljit_s32 c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) { sljit_s32 stack_size = 0; sljit_s32 word_arg_count = 0; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: stack_size += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: stack_size += sizeof(sljit_f64); break; default: word_arg_count++; if (word_arg_count > 2) stack_size += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } if (word_arg_count_ptr) *word_arg_count_ptr = word_arg_count; return stack_size; } static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args) { sljit_u8 *inst; sljit_s32 float_arg_count; if (stack_size == sizeof(sljit_sw) && word_arg_count == 3) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); PUSH_REG(reg_map[SLJIT_R2]); } else if (stack_size > 0) { if (word_arg_count >= 4) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw)); FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size)); stack_size = 0; arg_types >>= SLJIT_DEF_SHIFT; word_arg_count = 0; float_arg_count = 0; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: float_arg_count++; FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); stack_size += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: float_arg_count++; FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); stack_size += sizeof(sljit_f64); break; default: word_arg_count++; if (word_arg_count == 3) { EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0); stack_size += sizeof(sljit_sw); } else if (word_arg_count == 4) { EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0); stack_size += sizeof(sljit_sw); } break; } arg_types >>= SLJIT_DEF_SHIFT; } } if (word_arg_count > 0) { if (swap_args) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst++ = XCHG_EAX_r | reg_map[SLJIT_R2]; } else { inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); *inst++ = MOV_r_rm; *inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0]; } } return SLJIT_SUCCESS; } #endif static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr) { sljit_s32 stack_size = 0; sljit_s32 word_arg_count = 0; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: stack_size += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: stack_size += sizeof(sljit_f64); break; default: word_arg_count++; stack_size += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } if (word_arg_count_ptr) *word_arg_count_ptr = word_arg_count; if (stack_size <= compiler->stack_tmp_size) return 0; #if defined(__APPLE__) return ((stack_size - compiler->stack_tmp_size + 15) & ~15); #else return stack_size - compiler->stack_tmp_size; #endif } static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count) { sljit_s32 float_arg_count = 0; if (word_arg_count >= 4) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw)); if (stack_size > 0) FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size)); stack_size = 0; word_arg_count = 0; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: float_arg_count++; FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); stack_size += sizeof(sljit_f32); break; case SLJIT_ARG_TYPE_F64: float_arg_count++; FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count)); stack_size += sizeof(sljit_f64); break; default: word_arg_count++; EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0); stack_size += sizeof(sljit_sw); break; } arg_types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 stack_size) { sljit_u8 *inst; sljit_s32 single; if (stack_size > 0) FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size)); if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32) return SLJIT_SUCCESS; single = ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32); inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); FAIL_IF(!inst); INC_SIZE(3); inst[0] = single ? FSTPS : FSTPD; inst[1] = (0x03 << 3) | 0x04; inst[2] = (0x04 << 3) | reg_map[SLJIT_SP]; return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { struct sljit_jump *jump; sljit_s32 stack_size = 0; sljit_s32 word_arg_count; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if ((type & 0xff) == SLJIT_CALL) { stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count); PTR_FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, 0)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif jump = sljit_emit_jump(compiler, type); PTR_FAIL_IF(jump == NULL); PTR_FAIL_IF(post_call_with_args(compiler, arg_types, 0)); return jump; } #endif stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count); PTR_FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif jump = sljit_emit_jump(compiler, type); PTR_FAIL_IF(jump == NULL); PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size)); return jump; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { sljit_s32 stack_size = 0; sljit_s32 word_arg_count; #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) sljit_s32 swap_args; #endif CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3); if ((type & 0xff) == SLJIT_CALL) { stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count); swap_args = 0; if (word_arg_count > 0) { if ((src & REG_MASK) == SLJIT_R2 || OFFS_REG(src) == SLJIT_R2) { swap_args = 1; if (((src & REG_MASK) | 0x2) == SLJIT_R2) src ^= 0x2; if ((OFFS_REG(src) | 0x2) == SLJIT_R2) src ^= TO_OFFS_REG(0x2); } } FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args)); compiler->saveds_offset += stack_size; compiler->locals_offset += stack_size; #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); compiler->saveds_offset -= stack_size; compiler->locals_offset -= stack_size; return post_call_with_args(compiler, arg_types, 0); } #endif stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count); FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count)); compiler->saveds_offset += stack_size; compiler->locals_offset += stack_size; #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw)); compiler->saveds_offset -= stack_size; compiler->locals_offset -= stack_size; return post_call_with_args(compiler, arg_types, stack_size); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); /* For UNUSED dst. Uncommon, but possible. */ if (dst == SLJIT_UNUSED) dst = TMP_REG1; if (FAST_IS_REG(dst)) { /* Unused dest is possible here. */ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); POP_REG(reg_map[dst]); return SLJIT_SUCCESS; } /* Memory. */ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst); *inst++ = POP_rm; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(src, srcw, (void)0); if (FAST_IS_REG(src)) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1); FAIL_IF(!inst); INC_SIZE(1 + 1); PUSH_REG(reg_map[src]); } else { inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_FF; *inst |= PUSH_rm; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); } RET(); return SLJIT_SUCCESS; } ================================================ FILE: src/pcre/sljit/sljitNativeX86_64.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* x86 64-bit arch dependent functions. */ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) { sljit_u8 *inst; inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw)); FAIL_IF(!inst); INC_SIZE(2 + sizeof(sljit_sw)); *inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B); *inst++ = MOV_r_i32 + (reg_map[reg] & 0x7); sljit_unaligned_store_sw(inst, imm); return SLJIT_SUCCESS; } static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type) { int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff); /* The relative jump below specialized for this case. */ SLJIT_ASSERT(reg_map[TMP_REG2] >= 8); if (type < SLJIT_JUMP) { /* Invert type. */ *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10; *code_ptr++ = short_addr ? (6 + 3) : (10 + 3); } *code_ptr++ = short_addr ? REX_B : (REX_W | REX_B); *code_ptr++ = MOV_r_i32 | reg_lmap[TMP_REG2]; jump->addr = (sljit_uw)code_ptr; if (jump->flags & JUMP_LABEL) jump->flags |= PATCH_MD; else if (short_addr) sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target); else sljit_unaligned_store_sw(code_ptr, jump->u.target); code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw); *code_ptr++ = REX_B; *code_ptr++ = GROUP_FF; *code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]; return code_ptr; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 args, i, tmp, size, saved_register_size; sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); compiler->mode32 = 0; #ifdef _WIN64 /* Two/four register slots for parameters plus space for xmm6 register if needed. */ if (fscratches >= 6 || fsaveds >= 1) compiler->locals_offset = 6 * sizeof(sljit_sw); else compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw); #endif /* Including the return address saved by the call instruction. */ saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; for (i = SLJIT_S0; i >= tmp; i--) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); if (reg_map[i] >= 8) *inst++ = REX_B; PUSH_REG(reg_lmap[i]); } for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); if (reg_map[i] >= 8) *inst++ = REX_B; PUSH_REG(reg_lmap[i]); } args = get_arg_count(arg_types); if (args > 0) { size = args * 3; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); #ifndef _WIN64 if (args > 0) { inst[0] = REX_W; inst[1] = MOV_r_rm; inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */; inst += 3; } if (args > 1) { inst[0] = REX_W | REX_R; inst[1] = MOV_r_rm; inst[2] = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */; inst += 3; } if (args > 2) { inst[0] = REX_W | REX_R; inst[1] = MOV_r_rm; inst[2] = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */; } #else if (args > 0) { inst[0] = REX_W; inst[1] = MOV_r_rm; inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */; inst += 3; } if (args > 1) { inst[0] = REX_W; inst[1] = MOV_r_rm; inst[2] = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */; inst += 3; } if (args > 2) { inst[0] = REX_W | REX_B; inst[1] = MOV_r_rm; inst[2] = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */; } #endif } local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size; compiler->local_size = local_size; #ifdef _WIN64 if (local_size > 0) { if (local_size <= 4 * 4096) { if (local_size > 4096) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096); if (local_size > 2 * 4096) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2); if (local_size > 3 * 4096) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3); } else { EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0); EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, (local_size - 1) >> 12); SLJIT_ASSERT (reg_map[SLJIT_R0] == 0); EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_R0), -4096); FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096)); FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, 1)); inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); inst[0] = JNE_i8; inst[1] = (sljit_s8) -19; } EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size); } #endif if (local_size > 0) { FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size)); } #ifdef _WIN64 /* Save xmm6 register: movaps [rsp + 0x20], xmm6 */ if (fscratches >= 6 || fsaveds >= 1) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); FAIL_IF(!inst); INC_SIZE(5); *inst++ = GROUP_0F; sljit_unaligned_store_s32(inst, 0x20247429); } #endif return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) { sljit_s32 saved_register_size; CHECK_ERROR(); CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); #ifdef _WIN64 /* Two/four register slots for parameters plus space for xmm6 register if needed. */ if (fscratches >= 6 || fsaveds >= 1) compiler->locals_offset = 6 * sizeof(sljit_sw); else compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw); #endif /* Including the return address saved by the call instruction. */ saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_s32 i, tmp, size; sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); #ifdef _WIN64 /* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */ if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 5); FAIL_IF(!inst); INC_SIZE(5); *inst++ = GROUP_0F; sljit_unaligned_store_s32(inst, 0x20247428); } #endif if (compiler->local_size > 0) { if (compiler->local_size <= 127) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); *inst++ = REX_W; *inst++ = GROUP_BINARY_83; *inst++ = MOD_REG | ADD | 4; *inst = compiler->local_size; } else { inst = (sljit_u8*)ensure_buf(compiler, 1 + 7); FAIL_IF(!inst); INC_SIZE(7); *inst++ = REX_W; *inst++ = GROUP_BINARY_81; *inst++ = MOD_REG | ADD | 4; sljit_unaligned_store_s32(inst, compiler->local_size); } } tmp = compiler->scratches; for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); if (reg_map[i] >= 8) *inst++ = REX_B; POP_REG(reg_lmap[i]); } tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; for (i = tmp; i <= SLJIT_S0; i++) { size = reg_map[i] >= 8 ? 2 : 1; inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); if (reg_map[i] >= 8) *inst++ = REX_B; POP_REG(reg_lmap[i]); } inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); RET(); return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm) { sljit_u8 *inst; sljit_s32 length = 1 + (rex ? 1 : 0) + sizeof(sljit_s32); inst = (sljit_u8*)ensure_buf(compiler, 1 + length); FAIL_IF(!inst); INC_SIZE(length); if (rex) *inst++ = rex; *inst++ = opcode; sljit_unaligned_store_s32(inst, imm); return SLJIT_SUCCESS; } static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size, /* The register or immediate operand. */ sljit_s32 a, sljit_sw imma, /* The general operand (not immediate). */ sljit_s32 b, sljit_sw immb) { sljit_u8 *inst; sljit_u8 *buf_ptr; sljit_u8 rex = 0; sljit_s32 flags = size & ~0xf; sljit_s32 inst_size; /* The immediate operand must be 32 bit. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma)); /* Both cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); /* Size flags not allowed for typed instructions. */ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); /* Both size flags cannot be switched on. */ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); /* SSE2 and immediate is not possible. */ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); size &= 0xf; inst_size = size; if (!compiler->mode32 && !(flags & EX86_NO_REXW)) rex |= REX_W; else if (flags & EX86_REX) rex |= REX; if (flags & (EX86_PREF_F2 | EX86_PREF_F3)) inst_size++; if (flags & EX86_PREF_66) inst_size++; /* Calculate size of b. */ inst_size += 1; /* mod r/m byte. */ if (b & SLJIT_MEM) { if (!(b & OFFS_REG_MASK)) { if (NOT_HALFWORD(immb)) { PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb)); immb = 0; if (b & REG_MASK) b |= TO_OFFS_REG(TMP_REG2); else b |= TMP_REG2; } else if (reg_lmap[b & REG_MASK] == 4) b |= TO_OFFS_REG(SLJIT_SP); } if ((b & REG_MASK) == SLJIT_UNUSED) inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */ else { if (reg_map[b & REG_MASK] >= 8) rex |= REX_B; if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) { /* Immediate operand. */ if (immb <= 127 && immb >= -128) inst_size += sizeof(sljit_s8); else inst_size += sizeof(sljit_s32); } else if (reg_lmap[b & REG_MASK] == 5) inst_size += sizeof(sljit_s8); if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) { inst_size += 1; /* SIB byte. */ if (reg_map[OFFS_REG(b)] >= 8) rex |= REX_X; } } } else if (!(flags & EX86_SSE2_OP2)) { if (reg_map[b] >= 8) rex |= REX_B; } else if (freg_map[b] >= 8) rex |= REX_B; if (a & SLJIT_IMM) { if (flags & EX86_BIN_INS) { if (imma <= 127 && imma >= -128) { inst_size += 1; flags |= EX86_BYTE_ARG; } else inst_size += 4; } else if (flags & EX86_SHIFT_INS) { imma &= compiler->mode32 ? 0x1f : 0x3f; if (imma != 1) { inst_size ++; flags |= EX86_BYTE_ARG; } } else if (flags & EX86_BYTE_ARG) inst_size++; else if (flags & EX86_HALF_ARG) inst_size += sizeof(short); else inst_size += sizeof(sljit_s32); } else { SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ if (!(flags & EX86_SSE2_OP1)) { if (reg_map[a] >= 8) rex |= REX_R; } else if (freg_map[a] >= 8) rex |= REX_R; } if (rex) inst_size++; inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size); PTR_FAIL_IF(!inst); /* Encoding the byte. */ INC_SIZE(inst_size); if (flags & EX86_PREF_F2) *inst++ = 0xf2; if (flags & EX86_PREF_F3) *inst++ = 0xf3; if (flags & EX86_PREF_66) *inst++ = 0x66; if (rex) *inst++ = rex; buf_ptr = inst + size; /* Encode mod/rm byte. */ if (!(flags & EX86_SHIFT_INS)) { if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81; if (a & SLJIT_IMM) *buf_ptr = 0; else if (!(flags & EX86_SSE2_OP1)) *buf_ptr = reg_lmap[a] << 3; else *buf_ptr = freg_lmap[a] << 3; } else { if (a & SLJIT_IMM) { if (imma == 1) *inst = GROUP_SHIFT_1; else *inst = GROUP_SHIFT_N; } else *inst = GROUP_SHIFT_CL; *buf_ptr = 0; } if (!(b & SLJIT_MEM)) *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : freg_lmap[b]); else if ((b & REG_MASK) != SLJIT_UNUSED) { if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) { if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { if (immb <= 127 && immb >= -128) *buf_ptr |= 0x40; else *buf_ptr |= 0x80; } if ((b & OFFS_REG_MASK) == SLJIT_UNUSED) *buf_ptr++ |= reg_lmap[b & REG_MASK]; else { *buf_ptr++ |= 0x04; *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3); } if (immb != 0 || reg_lmap[b & REG_MASK] == 5) { if (immb <= 127 && immb >= -128) *buf_ptr++ = immb; /* 8 bit displacement. */ else { sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_s32); } } } else { if (reg_lmap[b & REG_MASK] == 5) *buf_ptr |= 0x40; *buf_ptr++ |= 0x04; *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6); if (reg_lmap[b & REG_MASK] == 5) *buf_ptr++ = 0; } } else { *buf_ptr++ |= 0x04; *buf_ptr++ = 0x25; sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */ buf_ptr += sizeof(sljit_s32); } if (a & SLJIT_IMM) { if (flags & EX86_BYTE_ARG) *buf_ptr = imma; else if (flags & EX86_HALF_ARG) sljit_unaligned_store_s16(buf_ptr, imma); else if (!(flags & EX86_SHIFT_INS)) sljit_unaligned_store_s32(buf_ptr, imma); } return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1); } /* --------------------------------------------------------------------- */ /* Call / return instructions */ /* --------------------------------------------------------------------- */ #ifndef _WIN64 static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw) { sljit_s32 src = src_ptr ? (*src_ptr) : 0; sljit_s32 word_arg_count = 0; SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2); compiler->mode32 = 0; /* Remove return value. */ arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32) word_arg_count++; arg_types >>= SLJIT_DEF_SHIFT; } if (word_arg_count == 0) return SLJIT_SUCCESS; if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); *src_ptr = TMP_REG2; } else if (src == SLJIT_R2 && word_arg_count >= SLJIT_R2) *src_ptr = TMP_REG1; if (word_arg_count >= 3) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0); return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0); } #else static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw) { sljit_s32 src = src_ptr ? (*src_ptr) : 0; sljit_s32 arg_count = 0; sljit_s32 word_arg_count = 0; sljit_s32 float_arg_count = 0; sljit_s32 types = 0; sljit_s32 data_trandfer = 0; static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 }; SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9); compiler->mode32 = 0; arg_types >>= SLJIT_DEF_SHIFT; while (arg_types) { types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK); switch (arg_types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: case SLJIT_ARG_TYPE_F64: arg_count++; float_arg_count++; if (arg_count != float_arg_count) data_trandfer = 1; break; default: arg_count++; word_arg_count++; if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) { data_trandfer = 1; if (src == word_arg_regs[arg_count]) { EMIT_MOV(compiler, TMP_REG2, 0, src, 0); *src_ptr = TMP_REG2; } } break; } arg_types >>= SLJIT_DEF_SHIFT; } if (!data_trandfer) return SLJIT_SUCCESS; if (src & SLJIT_MEM) { ADJUST_LOCAL_OFFSET(src, srcw); EMIT_MOV(compiler, TMP_REG2, 0, src, srcw); *src_ptr = TMP_REG2; } while (types) { switch (types & SLJIT_DEF_MASK) { case SLJIT_ARG_TYPE_F32: if (arg_count != float_arg_count) FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0)); arg_count--; float_arg_count--; break; case SLJIT_ARG_TYPE_F64: if (arg_count != float_arg_count) FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0)); arg_count--; float_arg_count--; break; default: if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0); arg_count--; word_arg_count--; break; } types >>= SLJIT_DEF_SHIFT; } return SLJIT_SUCCESS; } #endif SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types) { CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL, 0)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_jump(compiler, type); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw) { CHECK_ERROR(); CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); FAIL_IF(call_with_args(compiler, arg_types, &src, srcw)); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_ijump(compiler, type, src, srcw); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) { sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); /* For UNUSED dst. Uncommon, but possible. */ if (dst == SLJIT_UNUSED) dst = TMP_REG1; if (FAST_IS_REG(dst)) { if (reg_map[dst] < 8) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); POP_REG(reg_lmap[dst]); return SLJIT_SUCCESS; } inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); *inst++ = REX_B; POP_REG(reg_lmap[dst]); return SLJIT_SUCCESS; } /* REX_W is not necessary (src is not immediate). */ compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst); *inst++ = POP_rm; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { if (reg_map[src] < 8) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1); FAIL_IF(!inst); INC_SIZE(1 + 1); PUSH_REG(reg_lmap[src]); } else { inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1); FAIL_IF(!inst); INC_SIZE(2 + 1); *inst++ = REX_B; PUSH_REG(reg_lmap[src]); } } else { /* REX_W is not necessary (src is not immediate). */ compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_FF; *inst |= PUSH_rm; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); } RET(); return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Extend input */ /* --------------------------------------------------------------------- */ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; compiler->mode32 = 0; if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) return SLJIT_SUCCESS; /* Empty instruction. */ if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { if (sign || ((sljit_uw)srcw <= 0x7fffffff)) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_i32; return SLJIT_SUCCESS; } return emit_load_imm64(compiler, dst, srcw); } compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_i32; compiler->mode32 = 0; return SLJIT_SUCCESS; } dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) dst_r = src; else { if (sign) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = MOVSXD_r_rm; } else { compiler->mode32 = 1; FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); compiler->mode32 = 0; } } if (dst & SLJIT_MEM) { compiler->mode32 = 1; inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; compiler->mode32 = 0; } return SLJIT_SUCCESS; } ================================================ FILE: src/pcre/sljit/sljitNativeX86_common.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) return "x86" SLJIT_CPUINFO " ABI:fastcall"; #else return "x86" SLJIT_CPUINFO; #endif } /* 32b register indexes: 0 - EAX 1 - ECX 2 - EDX 3 - EBX 4 - ESP 5 - EBP 6 - ESI 7 - EDI */ /* 64b register indexes: 0 - RAX 1 - RCX 2 - RDX 3 - RBX 4 - RSP 5 - RBP 6 - RSI 7 - RDI 8 - R8 - From now on REX prefix is required 9 - R9 10 - R10 11 - R11 12 - R12 13 - R13 14 - R14 15 - R15 */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = { 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 7, 6, 3, 4, 5 }; #define CHECK_EXTRA_REGS(p, w, do) \ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \ if (p <= compiler->scratches) \ w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \ else \ w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \ p = SLJIT_MEM1(SLJIT_SP); \ do; \ } #else /* SLJIT_CONFIG_X86_32 */ /* Last register + 1. */ #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) /* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present Note: avoid to use r12 and r13 for memory addessing therefore r12 is better to be a higher saved register. */ #ifndef _WIN64 /* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { 0, 0, 6, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9 }; /* low-map. reg_map & 0x7. */ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = { 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1 }; #else /* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { 0, 0, 2, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10 }; /* low-map. reg_map & 0x7. */ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = { 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2 }; #endif /* Args: xmm0-xmm3 */ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { 4, 0, 1, 2, 3, 5, 6 }; /* low-map. freg_map & 0x7. */ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = { 4, 0, 1, 2, 3, 5, 6 }; #define REX_W 0x48 #define REX_R 0x44 #define REX_X 0x42 #define REX_B 0x41 #define REX 0x40 #ifndef _WIN64 #define HALFWORD_MAX 0x7fffffffl #define HALFWORD_MIN -0x80000000l #else #define HALFWORD_MAX 0x7fffffffll #define HALFWORD_MIN -0x80000000ll #endif #define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN) #define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN) #define CHECK_EXTRA_REGS(p, w, do) #endif /* SLJIT_CONFIG_X86_32 */ #define TMP_FREG (0) /* Size flags for emit_x86_instruction: */ #define EX86_BIN_INS 0x0010 #define EX86_SHIFT_INS 0x0020 #define EX86_REX 0x0040 #define EX86_NO_REXW 0x0080 #define EX86_BYTE_ARG 0x0100 #define EX86_HALF_ARG 0x0200 #define EX86_PREF_66 0x0400 #define EX86_PREF_F2 0x0800 #define EX86_PREF_F3 0x1000 #define EX86_SSE2_OP1 0x2000 #define EX86_SSE2_OP2 0x4000 #define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2) /* --------------------------------------------------------------------- */ /* Instrucion forms */ /* --------------------------------------------------------------------- */ #define ADD (/* BINARY */ 0 << 3) #define ADD_EAX_i32 0x05 #define ADD_r_rm 0x03 #define ADD_rm_r 0x01 #define ADDSD_x_xm 0x58 #define ADC (/* BINARY */ 2 << 3) #define ADC_EAX_i32 0x15 #define ADC_r_rm 0x13 #define ADC_rm_r 0x11 #define AND (/* BINARY */ 4 << 3) #define AND_EAX_i32 0x25 #define AND_r_rm 0x23 #define AND_rm_r 0x21 #define ANDPD_x_xm 0x54 #define BSR_r_rm (/* GROUP_0F */ 0xbd) #define CALL_i32 0xe8 #define CALL_rm (/* GROUP_FF */ 2 << 3) #define CDQ 0x99 #define CMOVE_r_rm (/* GROUP_0F */ 0x44) #define CMP (/* BINARY */ 7 << 3) #define CMP_EAX_i32 0x3d #define CMP_r_rm 0x3b #define CMP_rm_r 0x39 #define CVTPD2PS_x_xm 0x5a #define CVTSI2SD_x_rm 0x2a #define CVTTSD2SI_r_xm 0x2c #define DIV (/* GROUP_F7 */ 6 << 3) #define DIVSD_x_xm 0x5e #define FSTPS 0xd9 #define FSTPD 0xdd #define INT3 0xcc #define IDIV (/* GROUP_F7 */ 7 << 3) #define IMUL (/* GROUP_F7 */ 5 << 3) #define IMUL_r_rm (/* GROUP_0F */ 0xaf) #define IMUL_r_rm_i8 0x6b #define IMUL_r_rm_i32 0x69 #define JE_i8 0x74 #define JNE_i8 0x75 #define JMP_i8 0xeb #define JMP_i32 0xe9 #define JMP_rm (/* GROUP_FF */ 4 << 3) #define LEA_r_m 0x8d #define MOV_r_rm 0x8b #define MOV_r_i32 0xb8 #define MOV_rm_r 0x89 #define MOV_rm_i32 0xc7 #define MOV_rm8_i8 0xc6 #define MOV_rm8_r8 0x88 #define MOVSD_x_xm 0x10 #define MOVSD_xm_x 0x11 #define MOVSXD_r_rm 0x63 #define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe) #define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf) #define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6) #define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7) #define MUL (/* GROUP_F7 */ 4 << 3) #define MULSD_x_xm 0x59 #define NEG_rm (/* GROUP_F7 */ 3 << 3) #define NOP 0x90 #define NOT_rm (/* GROUP_F7 */ 2 << 3) #define OR (/* BINARY */ 1 << 3) #define OR_r_rm 0x0b #define OR_EAX_i32 0x0d #define OR_rm_r 0x09 #define OR_rm8_r8 0x08 #define POP_r 0x58 #define POP_rm 0x8f #define POPF 0x9d #define PREFETCH 0x18 #define PUSH_i32 0x68 #define PUSH_r 0x50 #define PUSH_rm (/* GROUP_FF */ 6 << 3) #define PUSHF 0x9c #define RET_near 0xc3 #define RET_i16 0xc2 #define SBB (/* BINARY */ 3 << 3) #define SBB_EAX_i32 0x1d #define SBB_r_rm 0x1b #define SBB_rm_r 0x19 #define SAR (/* SHIFT */ 7 << 3) #define SHL (/* SHIFT */ 4 << 3) #define SHR (/* SHIFT */ 5 << 3) #define SUB (/* BINARY */ 5 << 3) #define SUB_EAX_i32 0x2d #define SUB_r_rm 0x2b #define SUB_rm_r 0x29 #define SUBSD_x_xm 0x5c #define TEST_EAX_i32 0xa9 #define TEST_rm_r 0x85 #define UCOMISD_x_xm 0x2e #define UNPCKLPD_x_xm 0x14 #define XCHG_EAX_r 0x90 #define XCHG_r_rm 0x87 #define XOR (/* BINARY */ 6 << 3) #define XOR_EAX_i32 0x35 #define XOR_r_rm 0x33 #define XOR_rm_r 0x31 #define XORPD_x_xm 0x57 #define GROUP_0F 0x0f #define GROUP_F7 0xf7 #define GROUP_FF 0xff #define GROUP_BINARY_81 0x81 #define GROUP_BINARY_83 0x83 #define GROUP_SHIFT_1 0xd1 #define GROUP_SHIFT_N 0xc1 #define GROUP_SHIFT_CL 0xd3 #define MOD_REG 0xc0 #define MOD_DISP8 0x40 #define INC_SIZE(s) (*inst++ = (s), compiler->size += (s)) #define PUSH_REG(r) (*inst++ = (PUSH_r + (r))) #define POP_REG(r) (*inst++ = (POP_r + (r))) #define RET() (*inst++ = (RET_near)) #define RET_I16(n) (*inst++ = (RET_i16), *inst++ = n, *inst++ = 0) /* r32, r/m32 */ #define MOV_RM(mod, reg, rm) (*inst++ = (MOV_r_rm), *inst++ = (mod) << 6 | (reg) << 3 | (rm)) /* Multithreading does not affect these static variables, since they store built-in CPU features. Therefore they can be overwritten by different threads if they detect the CPU features in the same time. */ #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) static sljit_s32 cpu_has_sse2 = -1; #endif static sljit_s32 cpu_has_cmov = -1; #ifdef _WIN32_WCE #include #elif defined(_MSC_VER) && _MSC_VER >= 1400 #include #endif /******************************************************/ /* Unaligned-store functions */ /******************************************************/ static SLJIT_INLINE void sljit_unaligned_store_s16(void *addr, sljit_s16 value) { SLJIT_MEMCPY(addr, &value, sizeof(value)); } static SLJIT_INLINE void sljit_unaligned_store_s32(void *addr, sljit_s32 value) { SLJIT_MEMCPY(addr, &value, sizeof(value)); } static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value) { SLJIT_MEMCPY(addr, &value, sizeof(value)); } /******************************************************/ /* Utility functions */ /******************************************************/ static void get_cpu_features(void) { sljit_u32 features; #if defined(_MSC_VER) && _MSC_VER >= 1400 int CPUInfo[4]; __cpuid(CPUInfo, 1); features = (sljit_u32)CPUInfo[3]; #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) /* AT&T syntax. */ __asm__ ( "movl $0x1, %%eax\n" #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) /* On x86-32, there is no red zone, so this should work (no need for a local variable). */ "push %%ebx\n" #endif "cpuid\n" #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) "pop %%ebx\n" #endif "movl %%edx, %0\n" : "=g" (features) : #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) : "%eax", "%ecx", "%edx" #else : "%rax", "%rbx", "%rcx", "%rdx" #endif ); #else /* _MSC_VER && _MSC_VER >= 1400 */ /* Intel syntax. */ __asm { mov eax, 1 cpuid mov features, edx } #endif /* _MSC_VER && _MSC_VER >= 1400 */ #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) cpu_has_sse2 = (features >> 26) & 0x1; #endif cpu_has_cmov = (features >> 15) & 0x1; } static sljit_u8 get_jump_code(sljit_s32 type) { switch (type) { case SLJIT_EQUAL: case SLJIT_EQUAL_F64: return 0x84 /* je */; case SLJIT_NOT_EQUAL: case SLJIT_NOT_EQUAL_F64: return 0x85 /* jne */; case SLJIT_LESS: case SLJIT_LESS_F64: return 0x82 /* jc */; case SLJIT_GREATER_EQUAL: case SLJIT_GREATER_EQUAL_F64: return 0x83 /* jae */; case SLJIT_GREATER: case SLJIT_GREATER_F64: return 0x87 /* jnbe */; case SLJIT_LESS_EQUAL: case SLJIT_LESS_EQUAL_F64: return 0x86 /* jbe */; case SLJIT_SIG_LESS: return 0x8c /* jl */; case SLJIT_SIG_GREATER_EQUAL: return 0x8d /* jnl */; case SLJIT_SIG_GREATER: return 0x8f /* jnle */; case SLJIT_SIG_LESS_EQUAL: return 0x8e /* jle */; case SLJIT_OVERFLOW: case SLJIT_MUL_OVERFLOW: return 0x80 /* jo */; case SLJIT_NOT_OVERFLOW: case SLJIT_MUL_NOT_OVERFLOW: return 0x81 /* jno */; case SLJIT_UNORDERED_F64: return 0x8a /* jp */; case SLJIT_ORDERED_F64: return 0x8b /* jpo */; } return 0; } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type, sljit_sw executable_offset); #else static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_s32 type); #endif static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_s32 type, sljit_sw executable_offset) { sljit_s32 short_jump; sljit_uw label_addr; if (jump->flags & JUMP_LABEL) label_addr = (sljit_uw)(code + jump->u.label->size); else label_addr = jump->u.target - executable_offset; short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((sljit_sw)(label_addr - (jump->addr + 1)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump->addr + 1)) < HALFWORD_MIN) return generate_far_jump_code(jump, code_ptr, type); #endif if (type == SLJIT_JUMP) { if (short_jump) *code_ptr++ = JMP_i8; else *code_ptr++ = JMP_i32; jump->addr++; } else if (type >= SLJIT_FAST_CALL) { short_jump = 0; *code_ptr++ = CALL_i32; jump->addr++; } else if (short_jump) { *code_ptr++ = get_jump_code(type) - 0x10; jump->addr++; } else { *code_ptr++ = GROUP_0F; *code_ptr++ = get_jump_code(type); jump->addr += 2; } if (short_jump) { jump->flags |= PATCH_MB; code_ptr += sizeof(sljit_s8); } else { jump->flags |= PATCH_MW; code_ptr += sizeof(sljit_s32); } return code_ptr; } SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) { struct sljit_memory_fragment *buf; sljit_u8 *code; sljit_u8 *code_ptr; sljit_u8 *buf_ptr; sljit_u8 *buf_end; sljit_u8 len; sljit_sw executable_offset; sljit_sw jump_addr; struct sljit_label *label; struct sljit_jump *jump; struct sljit_const *const_; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); /* Second code generation pass. */ code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; code_ptr = code; label = compiler->labels; jump = compiler->jumps; const_ = compiler->consts; executable_offset = SLJIT_EXEC_OFFSET(code); do { buf_ptr = buf->memory; buf_end = buf_ptr + buf->used_size; do { len = *buf_ptr++; if (len > 0) { /* The code is already generated. */ SLJIT_MEMCPY(code_ptr, buf_ptr, len); code_ptr += len; buf_ptr += len; } else { if (*buf_ptr >= 2) { jump->addr = (sljit_uw)code_ptr; if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 2, executable_offset); else { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2, executable_offset); #else code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 2); #endif } jump = jump->next; } else if (*buf_ptr == 0) { label->addr = ((sljit_uw)code_ptr) + executable_offset; label->size = code_ptr - code; label = label->next; } else { /* *buf_ptr is 1 */ const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw); const_ = const_->next; } buf_ptr++; } } while (buf_ptr < buf_end); SLJIT_ASSERT(buf_ptr == buf_end); buf = buf->next; } while (buf); SLJIT_ASSERT(!label); SLJIT_ASSERT(!jump); SLJIT_ASSERT(!const_); jump = compiler->jumps; while (jump) { jump_addr = jump->addr + executable_offset; if (jump->flags & PATCH_MB) { SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127); *(sljit_u8*)jump->addr = (sljit_u8)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))); } else if (jump->flags & PATCH_MW) { if (jump->flags & JUMP_LABEL) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_sw)))); #else SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX); sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump_addr + sizeof(sljit_s32)))); #endif } else { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_sw)))); #else SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump_addr + sizeof(sljit_s32))) <= HALFWORD_MAX); sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump_addr + sizeof(sljit_s32)))); #endif } } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) else if (jump->flags & PATCH_MD) sljit_unaligned_store_sw((void*)jump->addr, jump->u.label->addr); #endif jump = jump->next; } /* Some space may be wasted because of short jumps. */ SLJIT_ASSERT(code_ptr <= code + compiler->size); compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = code_ptr - code; return (void*)(code + executable_offset); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) { switch (feature_type) { case SLJIT_HAS_FPU: #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) if (cpu_has_sse2 == -1) get_cpu_features(); return cpu_has_sse2; #else /* SLJIT_DETECT_SSE2 */ return 1; #endif /* SLJIT_DETECT_SSE2 */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) case SLJIT_HAS_VIRTUAL_REGISTERS: return 1; #endif case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: if (cpu_has_cmov == -1) get_cpu_features(); return cpu_has_cmov; case SLJIT_HAS_SSE2: #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) if (cpu_has_sse2 == -1) get_cpu_features(); return cpu_has_sse2; #else return 1; #endif default: return 0; } } /* --------------------------------------------------------------------- */ /* Operators */ /* --------------------------------------------------------------------- */ #define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode)) static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); static sljit_s32 emit_mov(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw); #define EMIT_MOV(compiler, dst, dstw, src, srcw) \ FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src); static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #include "sljitNativeX86_32.c" #else #include "sljitNativeX86_64.c" #endif static sljit_s32 emit_mov(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; SLJIT_ASSERT(dst != SLJIT_UNUSED); if (FAST_IS_REG(src)) { inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; return SLJIT_SUCCESS; } if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw); #else if (!compiler->mode32) { if (NOT_HALFWORD(srcw)) return emit_load_imm64(compiler, dst, srcw); } else return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, MOV_r_i32 + reg_lmap[dst], srcw); #endif } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (!compiler->mode32 && NOT_HALFWORD(srcw)) { /* Immediate to memory move. Only SLJIT_MOV operation copies an immediate directly into memory so TMP_REG1 can be used. */ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw)); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; return SLJIT_SUCCESS; } #endif inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_i32; return SLJIT_SUCCESS; } if (FAST_IS_REG(dst)) { inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw); FAIL_IF(!inst); *inst = MOV_r_rm; return SLJIT_SUCCESS; } /* Memory to memory move. Only SLJIT_MOV operation copies data from memory to memory so TMP_REG1 can be used. */ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw); FAIL_IF(!inst); *inst = MOV_r_rm; inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { sljit_u8 *inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 size; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); switch (GET_OPCODE(op)) { case SLJIT_BREAKPOINT: inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst = INT3; break; case SLJIT_NOP: inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst = NOP; break; case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #ifdef _WIN64 SLJIT_ASSERT( reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R1] == 2 && reg_map[TMP_REG1] > 7); #else SLJIT_ASSERT( reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R1] < 7 && reg_map[TMP_REG1] == 2); #endif compiler->mode32 = op & SLJIT_I32_OP; #endif SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); op = GET_OPCODE(op); if ((op | 0x2) == SLJIT_DIV_UW) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0); #else inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0); #endif FAIL_IF(!inst); *inst = XOR_r_rm; } if ((op | 0x2) == SLJIT_DIV_SW) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); #endif #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst = CDQ; #else if (compiler->mode32) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst = CDQ; } else { inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); *inst++ = REX_W; *inst = CDQ; } #endif } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); FAIL_IF(!inst); INC_SIZE(2); *inst++ = GROUP_F7; *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); #else #ifdef _WIN64 size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2; #else size = (!compiler->mode32) ? 3 : 2; #endif inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); #ifdef _WIN64 if (!compiler->mode32) *inst++ = REX_W | ((op >= SLJIT_DIVMOD_UW) ? REX_B : 0); else if (op >= SLJIT_DIVMOD_UW) *inst++ = REX_B; *inst++ = GROUP_F7; *inst = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); #else if (!compiler->mode32) *inst++ = REX_W; *inst++ = GROUP_F7; *inst = MOD_REG | reg_map[SLJIT_R1]; #endif #endif switch (op) { case SLJIT_LMUL_UW: *inst |= MUL; break; case SLJIT_LMUL_SW: *inst |= IMUL; break; case SLJIT_DIVMOD_UW: case SLJIT_DIV_UW: *inst |= DIV; break; case SLJIT_DIVMOD_SW: case SLJIT_DIV_SW: *inst |= IDIV; break; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) if (op <= SLJIT_DIVMOD_SW) EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #else if (op >= SLJIT_DIV_UW) EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #endif break; } return SLJIT_SUCCESS; } #define ENCODE_PREFIX(prefix) \ do { \ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \ FAIL_IF(!inst); \ INC_SIZE(1); \ *inst = (prefix); \ } while (0) static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 work_r; #endif #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw); #else inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0); FAIL_IF(!inst); *inst = MOV_rm_i32; return SLJIT_SUCCESS; #endif } inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm8_i8; return SLJIT_SUCCESS; } dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (reg_map[src] >= 4) { SLJIT_ASSERT(dst_r == TMP_REG1); EMIT_MOV(compiler, TMP_REG1, 0, src, 0); } else dst_r = src; #else dst_r = src; #endif } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) else if (FAST_IS_REG(src) && reg_map[src] >= 4) { /* src, dst are registers. */ SLJIT_ASSERT(SLOW_IS_REG(dst)); if (reg_map[dst] < 4) { if (dst != src) EMIT_MOV(compiler, dst, 0, src, 0); inst = emit_x86_instruction(compiler, 2, dst, 0, dst, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; } else { if (dst != src) EMIT_MOV(compiler, dst, 0, src, 0); if (sign) { /* shl reg, 24 */ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0); FAIL_IF(!inst); *inst |= SHL; /* sar reg, 24 */ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0); FAIL_IF(!inst); *inst |= SAR; } else { inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0); FAIL_IF(!inst); *(inst + 1) |= AND; } } return SLJIT_SUCCESS; } #endif else { /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */ inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = sign ? MOVSX_r_rm8 : MOVZX_r_rm8; } if (dst & SLJIT_MEM) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (dst_r == TMP_REG1) { /* Find a non-used register, whose reg_map[src] < 4. */ if ((dst & REG_MASK) == SLJIT_R0) { if ((dst & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_R1)) work_r = SLJIT_R2; else work_r = SLJIT_R1; } else { if ((dst & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_R0)) work_r = SLJIT_R0; else if ((dst & REG_MASK) == SLJIT_R1) work_r = SLJIT_R2; else work_r = SLJIT_R1; } if (work_r == SLJIT_R0) { ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]); } else { inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0); FAIL_IF(!inst); *inst = XCHG_r_rm; } inst = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm8_r8; if (work_r == SLJIT_R0) { ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]); } else { inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0); FAIL_IF(!inst); *inst = XCHG_r_rm; } } else { inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm8_r8; } #else inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm8_r8; #endif } return SLJIT_SUCCESS; } static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; #endif inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst++ = PREFETCH; if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) *inst |= (3 << 3); else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) *inst |= (2 << 3); else *inst |= (1 << 3); return SLJIT_SUCCESS; } static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif if (src & SLJIT_IMM) { if (FAST_IS_REG(dst)) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw); #else inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0); FAIL_IF(!inst); *inst = MOV_rm_i32; return SLJIT_SUCCESS; #endif } inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_i32; return SLJIT_SUCCESS; } dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) dst_r = src; else { inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = sign ? MOVSX_r_rm16 : MOVZX_r_rm16; } if (dst & SLJIT_MEM) { inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw); FAIL_IF(!inst); *inst = MOV_rm_r; } return SLJIT_SUCCESS; } static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; if (dst == src && dstw == srcw) { /* Same input and output */ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= opcode; return SLJIT_SUCCESS; } if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) dst = TMP_REG1; if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= opcode; return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= opcode; EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; if (dst == SLJIT_UNUSED) dst = TMP_REG1; if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= NOT_rm; inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0); FAIL_IF(!inst); *inst = OR_r_rm; return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst++ = GROUP_F7; *inst |= NOT_rm; inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst = OR_r_rm; EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) static const sljit_sw emit_clz_arg = 32 + 31; #endif static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; sljit_s32 dst_r; SLJIT_UNUSED_ARG(op_flags); if (cpu_has_cmov == -1) get_cpu_features(); dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; inst = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = BSR_r_rm; #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (cpu_has_cmov) { if (dst_r != TMP_REG1) { EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 32 + 31); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0); } else inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), (sljit_sw)&emit_clz_arg); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = CMOVE_r_rm; } else FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, 32 + 31)); inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); #else if (cpu_has_cmov) { EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = CMOVE_r_rm; } else FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31))); inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, dst_r, 0); #endif FAIL_IF(!inst); *(inst + 1) |= XOR; if (dst & SLJIT_MEM) EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 op_flags = GET_ALL_FLAGS(op); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_s32 dst_is_ereg = 0; #endif CHECK_ERROR(); CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1); CHECK_EXTRA_REGS(src, srcw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = op_flags & SLJIT_I32_OP; #endif if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) return emit_prefetch(compiler, op, src, srcw); return SLJIT_SUCCESS; } op = GET_OPCODE(op); if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif if (FAST_IS_REG(src) && src == dst) { if (!TYPE_CAST_NEEDED(op)) return SLJIT_SUCCESS; } if (op_flags & SLJIT_I32_OP) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (src & SLJIT_MEM) { if (op == SLJIT_MOV_S32) op = SLJIT_MOV_U32; } else if (src & SLJIT_IMM) { if (op == SLJIT_MOV_U32) op = SLJIT_MOV_S32; } #endif } if (src & SLJIT_IMM) { switch (op) { case SLJIT_MOV_U8: srcw = (sljit_u8)srcw; break; case SLJIT_MOV_S8: srcw = (sljit_s8)srcw; break; case SLJIT_MOV_U16: srcw = (sljit_u16)srcw; break; case SLJIT_MOV_S16: srcw = (sljit_s16)srcw; break; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) case SLJIT_MOV_U32: srcw = (sljit_u32)srcw; break; case SLJIT_MOV_S32: srcw = (sljit_s32)srcw; break; #endif } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (SLJIT_UNLIKELY(dst_is_ereg)) return emit_mov(compiler, dst, dstw, src, srcw); #endif } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) { SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP)); dst = TMP_REG1; } #endif switch (op) { case SLJIT_MOV: case SLJIT_MOV_P: #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) case SLJIT_MOV_U32: case SLJIT_MOV_S32: #endif FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); break; case SLJIT_MOV_U8: FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw)); break; case SLJIT_MOV_S8: FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw)); break; case SLJIT_MOV_U16: FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw)); break; case SLJIT_MOV_S16: FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, srcw)); break; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) case SLJIT_MOV_U32: FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw)); break; case SLJIT_MOV_S32: FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw)); break; #endif } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1) return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0); #endif return SLJIT_SUCCESS; } switch (op) { case SLJIT_NOT: if (SLJIT_UNLIKELY(op_flags & SLJIT_SET_Z)) return emit_not_with_flags(compiler, dst, dstw, src, srcw); return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw); case SLJIT_NEG: return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw); case SLJIT_CLZ: return emit_clz(compiler, op_flags, dst, dstw, src, srcw); } return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \ if (IS_HALFWORD(immw) || compiler->mode32) { \ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \ FAIL_IF(!inst); \ *(inst + 1) |= (op_imm); \ } \ else { \ FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \ inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \ FAIL_IF(!inst); \ *inst = (op_mr); \ } #define BINARY_EAX_IMM(op_eax_imm, immw) \ FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw)) #else #define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \ FAIL_IF(!inst); \ *(inst + 1) |= (op_imm); #define BINARY_EAX_IMM(op_eax_imm, immw) \ FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw)) #endif static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler, sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; sljit_u8 op_eax_imm = (op_types >> 24); sljit_u8 op_rm = (op_types >> 16) & 0xff; sljit_u8 op_mr = (op_types >> 8) & 0xff; sljit_u8 op_imm = op_types & 0xff; if (dst == SLJIT_UNUSED) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); if (src2 & SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0); } else { inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } return SLJIT_SUCCESS; } if (dst == src1 && dstw == src1w) { if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) { #endif BINARY_EAX_IMM(op_eax_imm, src2w); } else { BINARY_IMM(op_imm, op_mr, src2w, dst, dstw); } } else if (FAST_IS_REG(dst)) { inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } else if (FAST_IS_REG(src2)) { /* Special exception for sljit_emit_op_flags. */ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw); FAIL_IF(!inst); *inst = op_mr; } else { EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw); FAIL_IF(!inst); *inst = op_mr; } return SLJIT_SUCCESS; } /* Only for cumulative operations. */ if (dst == src2 && dstw == src2w) { if (src1 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { #else if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128)) { #endif BINARY_EAX_IMM(op_eax_imm, src1w); } else { BINARY_IMM(op_imm, op_mr, src1w, dst, dstw); } } else if (FAST_IS_REG(dst)) { inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w); FAIL_IF(!inst); *inst = op_rm; } else if (FAST_IS_REG(src1)) { inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw); FAIL_IF(!inst); *inst = op_mr; } else { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw); FAIL_IF(!inst); *inst = op_mr; } return SLJIT_SUCCESS; } /* General version. */ if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src1, src1w); if (src2 & SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, dst, 0); } else { inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } } else { /* This version requires less memory writing. */ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); if (src2 & SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0); } else { inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); } return SLJIT_SUCCESS; } static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler, sljit_u32 op_types, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; sljit_u8 op_eax_imm = (op_types >> 24); sljit_u8 op_rm = (op_types >> 16) & 0xff; sljit_u8 op_mr = (op_types >> 8) & 0xff; sljit_u8 op_imm = op_types & 0xff; if (dst == SLJIT_UNUSED) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); if (src2 & SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0); } else { inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } return SLJIT_SUCCESS; } if (dst == src1 && dstw == src1w) { if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) { #endif BINARY_EAX_IMM(op_eax_imm, src2w); } else { BINARY_IMM(op_imm, op_mr, src2w, dst, dstw); } } else if (FAST_IS_REG(dst)) { inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } else if (FAST_IS_REG(src2)) { inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw); FAIL_IF(!inst); *inst = op_mr; } else { EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw); FAIL_IF(!inst); *inst = op_mr; } return SLJIT_SUCCESS; } /* General version. */ if (FAST_IS_REG(dst) && dst != src2) { EMIT_MOV(compiler, dst, 0, src1, src1w); if (src2 & SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, dst, 0); } else { inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } } else { /* This version requires less memory writing. */ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); if (src2 & SLJIT_IMM) { BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0); } else { inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = op_rm; } EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); } return SLJIT_SUCCESS; } static sljit_s32 emit_mul(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; sljit_s32 dst_r; dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; /* Register destination. */ if (dst_r == src1 && !(src2 & SLJIT_IMM)) { inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = IMUL_r_rm; } else if (dst_r == src2 && !(src1 & SLJIT_IMM)) { inst = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = IMUL_r_rm; } else if (src1 & SLJIT_IMM) { if (src2 & SLJIT_IMM) { EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w); src2 = dst_r; src2w = 0; } if (src1w <= 127 && src1w >= -128) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); FAIL_IF(!inst); *inst = IMUL_r_rm_i8; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst = (sljit_s8)src1w; } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) else { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); FAIL_IF(!inst); *inst = IMUL_r_rm_i32; inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); sljit_unaligned_store_sw(inst, src1w); } #else else if (IS_HALFWORD(src1w)) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); FAIL_IF(!inst); *inst = IMUL_r_rm_i32; inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); sljit_unaligned_store_s32(inst, (sljit_s32)src1w); } else { if (dst_r != src2) EMIT_MOV(compiler, dst_r, 0, src2, src2w); FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = IMUL_r_rm; } #endif } else if (src2 & SLJIT_IMM) { /* Note: src1 is NOT immediate. */ if (src2w <= 127 && src2w >= -128) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst = IMUL_r_rm_i8; inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); FAIL_IF(!inst); INC_SIZE(1); *inst = (sljit_s8)src2w; } #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) else { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst = IMUL_r_rm_i32; inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); sljit_unaligned_store_sw(inst, src2w); } #else else if (IS_HALFWORD(src2w)) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); FAIL_IF(!inst); *inst = IMUL_r_rm_i32; inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); FAIL_IF(!inst); INC_SIZE(4); sljit_unaligned_store_s32(inst, (sljit_s32)src2w); } else { if (dst_r != src1) EMIT_MOV(compiler, dst_r, 0, src1, src1w); FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = IMUL_r_rm; } #endif } else { /* Neither argument is immediate. */ if (ADDRESSING_DEPENDS_ON(src2, dst_r)) dst_r = TMP_REG1; EMIT_MOV(compiler, dst_r, 0, src1, src1w); inst = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = IMUL_r_rm; } if (dst & SLJIT_MEM) EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; sljit_s32 dst_r, done = 0; /* These cases better be left to handled by normal way. */ if (dst == src1 && dstw == src1w) return SLJIT_ERR_UNSUPPORTED; if (dst == src2 && dstw == src2w) return SLJIT_ERR_UNSUPPORTED; dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; if (FAST_IS_REG(src1)) { if (FAST_IS_REG(src2)) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0); FAIL_IF(!inst); *inst = LEA_r_m; done = 1; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_s32)src2w); #else if (src2 & SLJIT_IMM) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w); #endif FAIL_IF(!inst); *inst = LEA_r_m; done = 1; } } else if (FAST_IS_REG(src2)) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_s32)src1w); #else if (src1 & SLJIT_IMM) { inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w); #endif FAIL_IF(!inst); *inst = LEA_r_m; done = 1; } } if (done) { if (dst_r == TMP_REG1) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } return SLJIT_ERR_UNSUPPORTED; } static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) { #endif BINARY_EAX_IMM(CMP_EAX_i32, src2w); return SLJIT_SUCCESS; } if (FAST_IS_REG(src1)) { if (src2 & SLJIT_IMM) { BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0); } else { inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); FAIL_IF(!inst); *inst = CMP_r_rm; } return SLJIT_SUCCESS; } if (FAST_IS_REG(src2) && !(src1 & SLJIT_IMM)) { inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); FAIL_IF(!inst); *inst = CMP_rm_r; return SLJIT_SUCCESS; } if (src2 & SLJIT_IMM) { if (src1 & SLJIT_IMM) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); src1 = TMP_REG1; src1w = 0; } BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w); } else { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = CMP_r_rm; } return SLJIT_SUCCESS; } static sljit_s32 emit_test_binary(struct sljit_compiler *compiler, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { #else if (src1 == SLJIT_R0 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) { #endif BINARY_EAX_IMM(TEST_EAX_i32, src2w); return SLJIT_SUCCESS; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { #else if (src2 == SLJIT_R0 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) { #endif BINARY_EAX_IMM(TEST_EAX_i32, src1w); return SLJIT_SUCCESS; } if (!(src1 & SLJIT_IMM)) { if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src2w)); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; #endif return SLJIT_SUCCESS; } else if (FAST_IS_REG(src1)) { inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; return SLJIT_SUCCESS; } } if (!(src2 & SLJIT_IMM)) { if (src1 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src1w) || compiler->mode32) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src1w)); inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; #endif return SLJIT_SUCCESS; } else if (FAST_IS_REG(src2)) { inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; return SLJIT_SUCCESS; } } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst = TEST_rm_r; } #else inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0); FAIL_IF(!inst); *inst = GROUP_F7; #endif } else { inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; } return SLJIT_SUCCESS; } static sljit_s32 emit_shift(struct sljit_compiler *compiler, sljit_u8 mode, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_u8* inst; if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) { if (dst == src1 && dstw == src1w) { inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw); FAIL_IF(!inst); *inst |= mode; return SLJIT_SUCCESS; } if (dst == SLJIT_UNUSED) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; return SLJIT_SUCCESS; } if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); return SLJIT_SUCCESS; } if (FAST_IS_REG(dst)) { EMIT_MOV(compiler, dst, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0); FAIL_IF(!inst); *inst |= mode; return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } if (dst == SLJIT_PREF_SHIFT_REG) { EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } else if (SLOW_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) { if (src1 != dst) EMIT_MOV(compiler, dst, 0, src1, src1w); EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0); EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0); FAIL_IF(!inst); *inst |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); } else { /* This case is complex since ecx itself may be used for addressing, and this case must be supported as well. */ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0); EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0); #else EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0); FAIL_IF(!inst); *inst |= mode; EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); #endif if (dst != SLJIT_UNUSED) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); } return SLJIT_SUCCESS; } static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler, sljit_u8 mode, sljit_s32 set_flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { /* The CPU does not set flags if the shift count is 0. */ if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0)) return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); #else if ((src2w & 0x1f) != 0) return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); #endif if (!set_flags) return emit_mov(compiler, dst, dstw, src1, src1w); /* OR dst, src, 0 */ return emit_cum_binary(compiler, BINARY_OPCODE(OR), dst, dstw, src1, src1w, SLJIT_IMM, 0); } if (!set_flags) return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); if (!FAST_IS_REG(dst)) FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0)); FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w)); if (FAST_IS_REG(dst)) return emit_cmp_binary(compiler, (dst == SLJIT_UNUSED) ? TMP_REG1 : dst, dstw, SLJIT_IMM, 0); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { CHECK_ERROR(); CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); CHECK_EXTRA_REGS(dst, dstw, (void)0); CHECK_EXTRA_REGS(src1, src1w, (void)0); CHECK_EXTRA_REGS(src2, src2w, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = op & SLJIT_I32_OP; #endif if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) return SLJIT_SUCCESS; switch (GET_OPCODE(op)) { case SLJIT_ADD: if (!HAS_FLAGS(op)) { if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; } return emit_cum_binary(compiler, BINARY_OPCODE(ADD), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ADDC: return emit_cum_binary(compiler, BINARY_OPCODE(ADC), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUB: if (!HAS_FLAGS(op)) { if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; } if (dst == SLJIT_UNUSED) return emit_cmp_binary(compiler, src1, src1w, src2, src2w); return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SUBC: return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB), dst, dstw, src1, src1w, src2, src2w); case SLJIT_MUL: return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w); case SLJIT_AND: if (dst == SLJIT_UNUSED) return emit_test_binary(compiler, src1, src1w, src2, src2w); return emit_cum_binary(compiler, BINARY_OPCODE(AND), dst, dstw, src1, src1w, src2, src2w); case SLJIT_OR: return emit_cum_binary(compiler, BINARY_OPCODE(OR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_XOR: return emit_cum_binary(compiler, BINARY_OPCODE(XOR), dst, dstw, src1, src1w, src2, src2w); case SLJIT_SHL: return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_LSHR: return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); case SLJIT_ASHR: return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op), dst, dstw, src1, src1w, src2, src2w); } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) if (reg >= SLJIT_R3 && reg <= SLJIT_R8) return -1; #endif return reg_map[reg]; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) return reg; #else return freg_map[reg]; #endif } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, void *instruction, sljit_s32 size) { sljit_u8 *inst; CHECK_ERROR(); CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); INC_SIZE(size); SLJIT_MEMCPY(inst, instruction, size); return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Floating point operators */ /* --------------------------------------------------------------------- */ /* Alignment(3) + 4 * 16 bytes. */ static sljit_s32 sse2_data[3 + (4 * 4)]; static sljit_s32 *sse2_buffer; static void init_compiler(void) { /* Align to 16 bytes. */ sse2_buffer = (sljit_s32*)(((sljit_uw)sse2_data + 15) & ~0xf); /* Single precision constants (each constant is 16 byte long). */ sse2_buffer[0] = 0x80000000; sse2_buffer[4] = 0x7fffffff; /* Double precision constants (each constant is 16 byte long). */ sse2_buffer[8] = 0; sse2_buffer[9] = 0x80000000; sse2_buffer[12] = 0xffffffff; sse2_buffer[13] = 0x7fffffff; } static sljit_s32 emit_sse2(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_s32 single, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w) { sljit_u8 *inst; inst = emit_x86_instruction(compiler, 2 | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, xmm1, 0, xmm2, xmm2w); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = opcode; return SLJIT_SUCCESS; } static sljit_s32 emit_sse2_logic(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_s32 pref66, sljit_s32 xmm1, sljit_s32 xmm2, sljit_sw xmm2w) { sljit_u8 *inst; inst = emit_x86_instruction(compiler, 2 | (pref66 ? EX86_PREF_66 : 0) | EX86_SSE2, xmm1, 0, xmm2, xmm2w); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = opcode; return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw) { return emit_sse2(compiler, MOVSD_x_xm, single, dst, src, srcw); } static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src) { return emit_sse2(compiler, MOVSD_xm_x, single, src, dst, dstw); } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1; sljit_u8 *inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) compiler->mode32 = 0; #endif inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = CVTTSD2SI_r_xm; if (dst & SLJIT_MEM) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG; sljit_u8 *inst; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) compiler->mode32 = 0; #endif if (src & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) srcw = (sljit_s32)srcw; #endif EMIT_MOV(compiler, TMP_REG1, 0, src, srcw); src = TMP_REG1; srcw = 0; } inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = CVTSI2SD_x_rm; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; #endif if (dst_r == TMP_FREG) return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG); return SLJIT_SUCCESS; } static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { if (!FAST_IS_REG(src1)) { FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w)); src1 = TMP_FREG; } return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_F32_OP), src1, src2, src2w); } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) { sljit_s32 dst_r; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; #endif CHECK_ERROR(); SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw); if (GET_OPCODE(op) == SLJIT_MOV_F64) { if (FAST_IS_REG(dst)) return emit_sse2_load(compiler, op & SLJIT_F32_OP, dst, src, srcw); if (FAST_IS_REG(src)) return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, src); FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src, srcw)); return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG); } if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) { dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG; if (FAST_IS_REG(src)) { /* We overwrite the high bits of source. From SLJIT point of view, this is not an issue. Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */ FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_F32_OP, src, src, 0)); } else { FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_F32_OP), TMP_FREG, src, srcw)); src = TMP_FREG; } FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_F32_OP, dst_r, src, 0)); if (dst_r == TMP_FREG) return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG); return SLJIT_SUCCESS; } if (FAST_IS_REG(dst)) { dst_r = dst; if (dst != src) FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw)); } else { dst_r = TMP_FREG; FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw)); } switch (GET_OPCODE(op)) { case SLJIT_NEG_F64: FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer : sse2_buffer + 8))); break; case SLJIT_ABS_F64: FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer + 4 : sse2_buffer + 12))); break; } if (dst_r == TMP_FREG) return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG); return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) { sljit_s32 dst_r; CHECK_ERROR(); CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 1; #endif if (FAST_IS_REG(dst)) { dst_r = dst; if (dst == src1) ; /* Do nothing here. */ else if (dst == src2 && (op == SLJIT_ADD_F64 || op == SLJIT_MUL_F64)) { /* Swap arguments. */ src2 = src1; src2w = src1w; } else if (dst != src2) FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src1, src1w)); else { dst_r = TMP_FREG; FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w)); } } else { dst_r = TMP_FREG; FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w)); } switch (GET_OPCODE(op)) { case SLJIT_ADD_F64: FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w)); break; case SLJIT_SUB_F64: FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w)); break; case SLJIT_MUL_F64: FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w)); break; case SLJIT_DIV_F64: FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w)); break; } if (dst_r == TMP_FREG) return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG); return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) { sljit_u8 *inst; struct sljit_label *label; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); PTR_FAIL_IF(!label); set_label(label, compiler); inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF(!inst); *inst++ = 0; *inst++ = 0; return label; } SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { sljit_u8 *inst; struct sljit_jump *jump; CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF_NULL(jump); set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); type &= 0xff; /* Worst case size. */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) compiler->size += (type >= SLJIT_JUMP) ? 5 : 6; #else compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3); #endif inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF_NULL(inst); *inst++ = 0; *inst++ = type + 2; return jump; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { sljit_u8 *inst; struct sljit_jump *jump; CHECK_ERROR(); CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); CHECK_EXTRA_REGS(src, srcw, (void)0); if (src == SLJIT_IMM) { jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); FAIL_IF_NULL(jump); set_jump(jump, compiler, JUMP_ADDR); jump->u.target = srcw; /* Worst case size. */ #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) compiler->size += 5; #else compiler->size += 10 + 3; #endif inst = (sljit_u8*)ensure_buf(compiler, 2); FAIL_IF_NULL(inst); *inst++ = 0; *inst++ = type + 2; } else { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) /* REX_W is not necessary (src is not immediate). */ compiler->mode32 = 1; #endif inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_FF; *inst |= (type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm; } return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 type) { sljit_u8 *inst; sljit_u8 cond_set = 0; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 reg; #endif /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */ sljit_s32 dst_save = dst; sljit_sw dstw_save = dstw; CHECK_ERROR(); CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); type &= 0xff; /* setcc = jcc + 0x10. */ cond_set = get_jump_code(type) + 0x10; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 3); FAIL_IF(!inst); INC_SIZE(4 + 3); /* Set low register to conditional flag. */ *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B; *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | reg_lmap[TMP_REG1]; *inst++ = REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B); *inst++ = OR_rm8_r8; *inst++ = MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]; return SLJIT_SUCCESS; } reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1; inst = (sljit_u8*)ensure_buf(compiler, 1 + 4 + 4); FAIL_IF(!inst); INC_SIZE(4 + 4); /* Set low register to conditional flag. */ *inst++ = (reg_map[reg] <= 7) ? REX : REX_B; *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | reg_lmap[reg]; *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); /* The movzx instruction does not affect flags. */ *inst++ = GROUP_0F; *inst++ = MOVZX_r_rm8; *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]; if (reg != TMP_REG1) return SLJIT_SUCCESS; if (GET_OPCODE(op) < SLJIT_ADD) { compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV; return emit_mov(compiler, dst, dstw, TMP_REG1, 0); } #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0); #else /* The SLJIT_CONFIG_X86_32 code path starts here. */ if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) { if (reg_map[dst] <= 4) { /* Low byte is accessible. */ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3); FAIL_IF(!inst); INC_SIZE(3 + 3); /* Set low byte to conditional flag. */ *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | reg_map[dst]; *inst++ = GROUP_0F; *inst++ = MOVZX_r_rm8; *inst = MOD_REG | (reg_map[dst] << 3) | reg_map[dst]; return SLJIT_SUCCESS; } /* Low byte is not accessible. */ if (cpu_has_cmov == -1) get_cpu_features(); if (cpu_has_cmov) { EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1); /* a xor reg, reg operation would overwrite the flags. */ EMIT_MOV(compiler, dst, 0, SLJIT_IMM, 0); inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); FAIL_IF(!inst); INC_SIZE(3); *inst++ = GROUP_0F; /* cmovcc = setcc - 0x50. */ *inst++ = cond_set - 0x50; *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1]; return SLJIT_SUCCESS; } inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1); FAIL_IF(!inst); INC_SIZE(1 + 3 + 3 + 1); *inst++ = XCHG_EAX_r + reg_map[TMP_REG1]; /* Set al to conditional flag. */ *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | 0 /* eax */; *inst++ = GROUP_0F; *inst++ = MOVZX_r_rm8; *inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */; *inst++ = XCHG_EAX_r + reg_map[TMP_REG1]; return SLJIT_SUCCESS; } if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) { SLJIT_ASSERT(reg_map[SLJIT_R0] == 0); if (dst != SLJIT_R0) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 2 + 1); FAIL_IF(!inst); INC_SIZE(1 + 3 + 2 + 1); /* Set low register to conditional flag. */ *inst++ = XCHG_EAX_r + reg_map[TMP_REG1]; *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | 0 /* eax */; *inst++ = OR_rm8_r8; *inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst]; *inst++ = XCHG_EAX_r + reg_map[TMP_REG1]; } else { inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2); FAIL_IF(!inst); INC_SIZE(2 + 3 + 2 + 2); /* Set low register to conditional flag. */ *inst++ = XCHG_r_rm; *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]; *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | 1 /* ecx */; *inst++ = OR_rm8_r8; *inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */; *inst++ = XCHG_r_rm; *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]; } return SLJIT_SUCCESS; } /* Set TMP_REG1 to the bit. */ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1); FAIL_IF(!inst); INC_SIZE(1 + 3 + 3 + 1); *inst++ = XCHG_EAX_r + reg_map[TMP_REG1]; /* Set al to conditional flag. */ *inst++ = GROUP_0F; *inst++ = cond_set; *inst++ = MOD_REG | 0 /* eax */; *inst++ = GROUP_0F; *inst++ = MOVZX_r_rm8; *inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */; *inst++ = XCHG_EAX_r + reg_map[TMP_REG1]; if (GET_OPCODE(op) < SLJIT_ADD) return emit_mov(compiler, dst, dstw, TMP_REG1, 0); #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) compiler->skip_checks = 1; #endif return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0); #endif /* SLJIT_CONFIG_X86_64 */ } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { sljit_u8* inst; CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) dst_reg &= ~SLJIT_I32_OP; if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3)) return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); #else if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV)) return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); #endif /* ADJUST_LOCAL_OFFSET is not needed. */ CHECK_EXTRA_REGS(src, srcw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = dst_reg & SLJIT_I32_OP; dst_reg &= ~SLJIT_I32_OP; #endif if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); src = TMP_REG1; srcw = 0; } inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); FAIL_IF(!inst); *inst++ = GROUP_0F; *inst = get_jump_code(type & 0xff) - 0x40; return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset) { CHECK_ERROR(); CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset)); ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; #endif ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (NOT_HALFWORD(offset)) { FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset)); #if (defined SLJIT_DEBUG && SLJIT_DEBUG) SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED); return compiler->error; #else return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0); #endif } #endif if (offset != 0) return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset); return emit_mov(compiler, dst, dstw, SLJIT_SP, 0); } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) { sljit_u8 *inst; struct sljit_const *const_; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) sljit_s32 reg; #endif CHECK_ERROR_PTR(); CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); CHECK_EXTRA_REGS(dst, dstw, (void)0); const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); PTR_FAIL_IF(!const_); set_const(const_, compiler); #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) compiler->mode32 = 0; reg = FAST_IS_REG(dst) ? dst : TMP_REG1; if (emit_load_imm64(compiler, reg, init_value)) return NULL; #else if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value)) return NULL; #endif inst = (sljit_u8*)ensure_buf(compiler, 2); PTR_FAIL_IF(!inst); *inst++ = 0; *inst++ = 1; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (dst & SLJIT_MEM) if (emit_mov(compiler, dst, dstw, TMP_REG1, 0)) return NULL; #endif return const_; } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { SLJIT_UNUSED_ARG(executable_offset); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_unaligned_store_sw((void*)addr, new_target - (addr + 4) - (sljit_uw)executable_offset); #else sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_target); #endif } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { SLJIT_UNUSED_ARG(executable_offset); sljit_unaligned_store_sw((void*)addr, new_constant); } ================================================ FILE: src/pcre/sljit/sljitUtils.c ================================================ /* * Stack-less Just-In-Time compiler * * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. * * 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 COPYRIGHT HOLDER(S) 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 HOLDER(S) 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. */ /* ------------------------------------------------------------------------ */ /* Locks */ /* ------------------------------------------------------------------------ */ #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) static SLJIT_INLINE void allocator_grab_lock(void) { /* Always successful. */ } static SLJIT_INLINE void allocator_release_lock(void) { /* Always successful. */ } #endif /* SLJIT_EXECUTABLE_ALLOCATOR */ #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) { /* Always successful. */ } SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) { /* Always successful. */ } #endif /* SLJIT_UTIL_GLOBAL_LOCK */ #elif defined(_WIN32) /* SLJIT_SINGLE_THREADED */ #include "windows.h" #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) static HANDLE allocator_mutex = 0; static SLJIT_INLINE void allocator_grab_lock(void) { /* No idea what to do if an error occures. Static mutexes should never fail... */ if (!allocator_mutex) allocator_mutex = CreateMutex(NULL, TRUE, NULL); else WaitForSingleObject(allocator_mutex, INFINITE); } static SLJIT_INLINE void allocator_release_lock(void) { ReleaseMutex(allocator_mutex); } #endif /* SLJIT_EXECUTABLE_ALLOCATOR */ #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) static HANDLE global_mutex = 0; SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) { /* No idea what to do if an error occures. Static mutexes should never fail... */ if (!global_mutex) global_mutex = CreateMutex(NULL, TRUE, NULL); else WaitForSingleObject(global_mutex, INFINITE); } SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) { ReleaseMutex(global_mutex); } #endif /* SLJIT_UTIL_GLOBAL_LOCK */ #else /* _WIN32 */ #if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) #include static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER; static SLJIT_INLINE void allocator_grab_lock(void) { pthread_mutex_lock(&allocator_mutex); } static SLJIT_INLINE void allocator_release_lock(void) { pthread_mutex_unlock(&allocator_mutex); } #endif /* SLJIT_EXECUTABLE_ALLOCATOR */ #if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) #include static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) { pthread_mutex_lock(&global_mutex); } SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) { pthread_mutex_unlock(&global_mutex); } #endif /* SLJIT_UTIL_GLOBAL_LOCK */ #endif /* _WIN32 */ /* ------------------------------------------------------------------------ */ /* Stack */ /* ------------------------------------------------------------------------ */ #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) #ifdef _WIN32 #include "windows.h" #else /* Provides mmap function. */ #include /* For detecting the page size. */ #include #ifndef MAP_ANON #include /* Some old systems does not have MAP_ANON. */ static sljit_s32 dev_zero = -1; #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) static SLJIT_INLINE sljit_s32 open_dev_zero(void) { dev_zero = open("/dev/zero", O_RDWR); return dev_zero < 0; } #else /* SLJIT_SINGLE_THREADED */ #include static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER; static SLJIT_INLINE sljit_s32 open_dev_zero(void) { pthread_mutex_lock(&dev_zero_mutex); /* The dev_zero might be initialized by another thread during the waiting. */ if (dev_zero < 0) { dev_zero = open("/dev/zero", O_RDWR); } pthread_mutex_unlock(&dev_zero_mutex); return dev_zero < 0; } #endif /* SLJIT_SINGLE_THREADED */ #endif #endif #endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */ #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) /* Planning to make it even more clever in the future. */ static sljit_sw sljit_page_align = 0; SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data) { struct sljit_stack *stack; void *ptr; #ifdef _WIN32 SYSTEM_INFO si; #endif SLJIT_UNUSED_ARG(allocator_data); if (start_size > max_size || start_size < 1) return NULL; #ifdef _WIN32 if (!sljit_page_align) { GetSystemInfo(&si); sljit_page_align = si.dwPageSize - 1; } #else if (!sljit_page_align) { sljit_page_align = sysconf(_SC_PAGESIZE); /* Should never happen. */ if (sljit_page_align < 0) sljit_page_align = 4096; sljit_page_align--; } #endif stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); if (!stack) return NULL; /* Align max_size. */ max_size = (max_size + sljit_page_align) & ~sljit_page_align; #ifdef _WIN32 ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE); if (!ptr) { SLJIT_FREE(stack, allocator_data); return NULL; } stack->min_start = (sljit_u8 *)ptr; stack->end = stack->min_start + max_size; stack->start = stack->end; if (sljit_stack_resize(stack, stack->end - start_size) == NULL) { sljit_free_stack(stack, allocator_data); return NULL; } #else #ifdef MAP_ANON ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #else if (dev_zero < 0) { if (open_dev_zero()) { SLJIT_FREE(stack, allocator_data); return NULL; } } ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); #endif if (ptr == MAP_FAILED) { SLJIT_FREE(stack, allocator_data); return NULL; } stack->min_start = (sljit_u8 *)ptr; stack->end = stack->min_start + max_size; stack->start = stack->end - start_size; #endif stack->top = stack->end; return stack; } #undef PAGE_ALIGN SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) { SLJIT_UNUSED_ARG(allocator_data); #ifdef _WIN32 VirtualFree((void*)stack->min_start, 0, MEM_RELEASE); #else munmap((void*)stack->min_start, stack->end - stack->min_start); #endif SLJIT_FREE(stack, allocator_data); } SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start) { sljit_uw aligned_old_start; sljit_uw aligned_new_start; if ((new_start < stack->min_start) || (new_start >= stack->end)) return NULL; #ifdef _WIN32 aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; if (aligned_new_start != aligned_old_start) { if (aligned_new_start < aligned_old_start) { if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE)) return NULL; } else { if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT)) return NULL; } } #else if (stack->start < new_start) { aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; /* If madvise is available, we release the unnecessary space. */ #if defined(MADV_DONTNEED) if (aligned_new_start > aligned_old_start) madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) if (aligned_new_start > aligned_old_start) posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED); #endif } #endif stack->start = new_start; return new_start; } #endif /* SLJIT_UTIL_STACK */ #endif ================================================ FILE: src/pcre/test-driver ================================================ #! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2018-03-07.03; # UTC # Copyright (C) 2011-2018 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>$log_file # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/pcre/testdata/grepfilelist ================================================ testdata/grepinputv testdata/grepinputx ================================================ FILE: src/pcre/testdata/grepinput ================================================ This is a file of miscellaneous text that is used as test data for checking that the pcregrep command is working correctly. The file must be more than 24K long so that it needs more than a single read() call to process it. New features should be added at the end, because some of the tests involve the output of line numbers, and we don't want these to change. PATTERN at the start of a line. In the middle of a line, PATTERN appears. This pattern is in lower case. Here follows a whole lot of stuff that makes the file over 24K long. ------------------------------------------------------------------------------- The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. ------------------------------------------------------------------------------- aaaaa0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbb cccccccccccccccccccccccccccccccccccccccccc aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa eeeee aaaaa2 ffffffffff This is a line before the binary zero. This line contains a binary zero here >< for testing. This is a line after the binary zero. ABOVE the elephant ABOVE ABOVE theatre AB.VE AB.VE the turtle 010203040506 PUT NEW DATA ABOVE THIS LINE. ============================= Check up on PATTERN near the end. This is the last line of this file. ================================================ FILE: src/pcre/testdata/grepinput3 ================================================ triple: t1_txt s1_tag s_txt p_tag p_txt o_tag o_txt triple: t2_txt s1_tag s_txt p_tag p_txt o_tag Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. triple: t3_txt s2_tag s_txt p_tag p_txt o_tag o_txt triple: t4_txt s1_tag s_txt p_tag p_txt o_tag o_txt triple: t5_txt s1_tag s_txt p_tag p_txt o_tag o_txt triple: t6_txt s2_tag s_txt p_tag p_txt o_tag o_txt triple: t7_txt s1_tag s_txt p_tag p_txt o_tag o_txt ================================================ FILE: src/pcre/testdata/grepinput8 ================================================ X one X two X three X four X five X six X seven…X eight
X nine
X ten Before 111 Before 222
Before 333…Match After 111 After 222
After 333 And so on and so on And so on and so on ================================================ FILE: src/pcre/testdata/grepinputv ================================================ The quick brown fox jumps over the lazy dog. This time it jumps and jumps and jumps. ================================================ FILE: src/pcre/testdata/grepinputx ================================================ This is a second file of input for the pcregrep tests. Here is the pattern again. Pattern That time it was on a line by itself. To pat or not to pat, that is the question. complete pair of lines That was a complete pair of lines all by themselves. complete pair of lines And there they were again, to check line numbers. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty This line contains pattern not on a line by itself. This is the last line of this file. ================================================ FILE: src/pcre/testdata/greplist ================================================ This is a file of patterns for testing the -f option. Don't include any blank lines because they will match everything! This is no longer true, so have one. pattern line by itself End of the list of patterns. ================================================ FILE: src/pcre/testdata/grepoutput ================================================ ---------------------------- Test 1 ------------------------------ PATTERN at the start of a line. In the middle of a line, PATTERN appears. Check up on PATTERN near the end. RC=0 ---------------------------- Test 2 ------------------------------ PATTERN at the start of a line. RC=0 ---------------------------- Test 3 ------------------------------ 7:PATTERN at the start of a line. 8:In the middle of a line, PATTERN appears. 10:This pattern is in lower case. 610:Check up on PATTERN near the end. RC=0 ---------------------------- Test 4 ------------------------------ 4 RC=0 ---------------------------- Test 5 ------------------------------ ./testdata/grepinput:7:PATTERN at the start of a line. ./testdata/grepinput:8:In the middle of a line, PATTERN appears. ./testdata/grepinput:10:This pattern is in lower case. ./testdata/grepinput:610:Check up on PATTERN near the end. ./testdata/grepinputx:3:Here is the pattern again. ./testdata/grepinputx:5:Pattern ./testdata/grepinputx:42:This line contains pattern not on a line by itself. RC=0 ---------------------------- Test 6 ------------------------------ 7:PATTERN at the start of a line. 8:In the middle of a line, PATTERN appears. 10:This pattern is in lower case. 610:Check up on PATTERN near the end. 3:Here is the pattern again. 5:Pattern 42:This line contains pattern not on a line by itself. RC=0 ---------------------------- Test 7 ------------------------------ ./testdata/grepinput ./testdata/grepinputx RC=0 ---------------------------- Test 8 ------------------------------ ./testdata/grepinput RC=0 ---------------------------- Test 9 ------------------------------ RC=0 ---------------------------- Test 10 ----------------------------- RC=1 ---------------------------- Test 11 ----------------------------- 1:This is a second file of input for the pcregrep tests. 2: 4: 5:Pattern 6:That time it was on a line by itself. 7: 8:To pat or not to pat, that is the question. 9: 10:complete pair 11:of lines 12: 13:That was a complete pair 14:of lines all by themselves. 15: 16:complete pair 17:of lines 18: 19:And there they were again, to check line numbers. 20: 21:one 22:two 23:three 24:four 25:five 26:six 27:seven 28:eight 29:nine 30:ten 31:eleven 32:twelve 33:thirteen 34:fourteen 35:fifteen 36:sixteen 37:seventeen 38:eighteen 39:nineteen 40:twenty 41: 43:This is the last line of this file. RC=0 ---------------------------- Test 12 ----------------------------- Pattern RC=0 ---------------------------- Test 13 ----------------------------- Here is the pattern again. That time it was on a line by itself. seventeen This line contains pattern not on a line by itself. RC=0 ---------------------------- Test 14 ----------------------------- ./testdata/grepinputx:To pat or not to pat, that is the question. RC=0 ---------------------------- Test 15 ----------------------------- pcregrep: Error in command-line regex at offset 4: nothing to repeat RC=2 ---------------------------- Test 16 ----------------------------- pcregrep: Failed to open ./testdata/nonexistfile: No such file or directory RC=2 ---------------------------- Test 17 ----------------------------- features should be added at the end, because some of the tests involve the output of line numbers, and we don't want these to change. RC=0 ---------------------------- Test 18 ----------------------------- 4:features should be added at the end, because some of the tests involve the output of line numbers, and we don't want these to change. 583:brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. ------------------------------------------------------------------------------- RC=0 ---------------------------- Test 19 ----------------------------- Pattern RC=0 ---------------------------- Test 20 ----------------------------- 10:complete pair of lines 16:complete pair of lines RC=0 ---------------------------- Test 21 ----------------------------- 24:four 25-five 26-six 27-seven -- 34:fourteen 35-fifteen 36-sixteen 37-seventeen RC=0 ---------------------------- Test 22 ----------------------------- 21-one 22-two 23-three 24:four -- 31-eleven 32-twelve 33-thirteen 34:fourteen RC=0 ---------------------------- Test 23 ----------------------------- one two three four five six seven -- eleven twelve thirteen fourteen fifteen sixteen seventeen RC=0 ---------------------------- Test 24 ----------------------------- four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty This line contains pattern not on a line by itself. This is the last line of this file. RC=0 ---------------------------- Test 25 ----------------------------- 15- 16-complete pair 17-of lines 18- 19-And there they were again, to check line numbers. 20- 21-one 22-two 23-three 24:four 25-five 26-six 27-seven 28-eight 29-nine 30-ten 31-eleven 32-twelve 33-thirteen 34:fourteen RC=0 ---------------------------- Test 26 ----------------------------- complete pair of lines And there they were again, to check line numbers. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty This line contains pattern not on a line by itself. This is the last line of this file. RC=0 ---------------------------- Test 27 ----------------------------- four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty This line contains pattern not on a line by itself. This is the last line of this file. RC=0 ---------------------------- Test 28 ----------------------------- 14-of lines all by themselves. 15- 16-complete pair 17-of lines 18- 19-And there they were again, to check line numbers. 20- 21-one 22-two 23-three 24:four 25-five 26-six 27-seven 28-eight 29-nine 30-ten 31-eleven 32-twelve 33-thirteen 34:fourteen RC=0 ---------------------------- Test 29 ----------------------------- of lines all by themselves. complete pair of lines And there they were again, to check line numbers. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty This line contains pattern not on a line by itself. This is the last line of this file. RC=0 ---------------------------- Test 30 ----------------------------- ./testdata/grepinput-4-features should be added at the end, because some of the tests involve the ./testdata/grepinput-5-output of line numbers, and we don't want these to change. ./testdata/grepinput-6- ./testdata/grepinput:7:PATTERN at the start of a line. ./testdata/grepinput:8:In the middle of a line, PATTERN appears. ./testdata/grepinput-9- ./testdata/grepinput:10:This pattern is in lower case. -- ./testdata/grepinput-607-PUT NEW DATA ABOVE THIS LINE. ./testdata/grepinput-608-============================= ./testdata/grepinput-609- ./testdata/grepinput:610:Check up on PATTERN near the end. -- ./testdata/grepinputx-1-This is a second file of input for the pcregrep tests. ./testdata/grepinputx-2- ./testdata/grepinputx:3:Here is the pattern again. ./testdata/grepinputx-4- ./testdata/grepinputx:5:Pattern -- ./testdata/grepinputx-39-nineteen ./testdata/grepinputx-40-twenty ./testdata/grepinputx-41- ./testdata/grepinputx:42:This line contains pattern not on a line by itself. RC=0 ---------------------------- Test 31 ----------------------------- ./testdata/grepinput:7:PATTERN at the start of a line. ./testdata/grepinput:8:In the middle of a line, PATTERN appears. ./testdata/grepinput-9- ./testdata/grepinput:10:This pattern is in lower case. ./testdata/grepinput-11- ./testdata/grepinput-12-Here follows a whole lot of stuff that makes the file over 24K long. ./testdata/grepinput-13- -- ./testdata/grepinput:610:Check up on PATTERN near the end. ./testdata/grepinput-611-This is the last line of this file. -- ./testdata/grepinputx:3:Here is the pattern again. ./testdata/grepinputx-4- ./testdata/grepinputx:5:Pattern ./testdata/grepinputx-6-That time it was on a line by itself. ./testdata/grepinputx-7- ./testdata/grepinputx-8-To pat or not to pat, that is the question. -- ./testdata/grepinputx:42:This line contains pattern not on a line by itself. ./testdata/grepinputx-43-This is the last line of this file. RC=0 ---------------------------- Test 32 ----------------------------- ./testdata/grepinputx RC=0 ---------------------------- Test 33 ----------------------------- pcregrep: Failed to open ./testdata/grepnonexist: No such file or directory RC=2 ---------------------------- Test 34 ----------------------------- RC=2 ---------------------------- Test 35 ----------------------------- ./testdata/grepinput8 ./testdata/grepinputx RC=0 ---------------------------- Test 36 ----------------------------- ./testdata/grepinput3 ./testdata/grepinputx RC=0 ---------------------------- Test 37 ----------------------------- aaaaa0 aaaaa2 010203040506 RC=0 ======== STDERR ======== pcregrep: pcre_exec() gave error -8 while matching this text: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa pcregrep: pcre_exec() gave error -8 while matching this text: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa pcregrep: Error -8, -21 or -27 means that a resource limit was exceeded. pcregrep: Check your regex for nested unlimited loops. ---------------------------- Test 38 ------------------------------ This line contains a binary zero here >< for testing. RC=0 ---------------------------- Test 39 ------------------------------ This is a line before the binary zero. This line contains a binary zero here >< for testing. RC=0 ---------------------------- Test 40 ------------------------------ This line contains a binary zero here >< for testing. This is a line after the binary zero. RC=0 ---------------------------- Test 41 ------------------------------ before the binary zero after the binary zero RC=0 ---------------------------- Test 42 ------------------------------ ./testdata/grepinput:595:before the binary zero ./testdata/grepinput:597:after the binary zero RC=0 ---------------------------- Test 43 ------------------------------ 595:before 595:zero 596:zero 597:after 597:zero RC=0 ---------------------------- Test 44 ------------------------------ 595:before 595:zero 596:zero 597:zero RC=0 ---------------------------- Test 45 ------------------------------ 10:pattern 595:binary 596:binary 597:binary RC=0 ---------------------------- Test 46 ------------------------------ pcregrep: Error in 2nd command-line regex at offset 9: missing ) RC=2 ---------------------------- Test 47 ------------------------------ AB.VE RC=0 ---------------------------- Test 48 ------------------------------ ABOVE the elephant AB.VE AB.VE the turtle RC=0 ---------------------------- Test 49 ------------------------------ ABOVE the elephant AB.VE AB.VE the turtle PUT NEW DATA ABOVE THIS LINE. RC=0 ---------------------------- Test 50 ------------------------------ RC=1 ---------------------------- Test 51 ------------------------------ over the lazy dog. This time it jumps and jumps and jumps. RC=0 ---------------------------- Test 52 ------------------------------ fox jumps This time it jumps and jumps and jumps. RC=0 ---------------------------- Test 53 ------------------------------ 36972,6 36990,4 37024,4 37066,5 37083,4 RC=0 ---------------------------- Test 54 ------------------------------ 595:15,6 595:33,4 596:28,4 597:15,5 597:32,4 RC=0 ---------------------------- Test 55 ----------------------------- Here is the pattern again. That time it was on a line by itself. This line contains pattern not on a line by itself. RC=0 ---------------------------- Test 56 ----------------------------- ./testdata/grepinput:456 ./testdata/grepinput3:0 ./testdata/grepinput8:0 ./testdata/grepinputv:1 ./testdata/grepinputx:0 RC=0 ---------------------------- Test 57 ----------------------------- ./testdata/grepinput:456 ./testdata/grepinputv:1 RC=0 ---------------------------- Test 58 ----------------------------- PATTERN at the start of a line. In the middle of a line, PATTERN appears. Check up on PATTERN near the end. RC=0 ---------------------------- Test 59 ----------------------------- PATTERN at the start of a line. In the middle of a line, PATTERN appears. Check up on PATTERN near the end. RC=0 ---------------------------- Test 60 ----------------------------- PATTERN at the start of a line. In the middle of a line, PATTERN appears. Check up on PATTERN near the end. RC=0 ---------------------------- Test 61 ----------------------------- PATTERN at the start of a line. In the middle of a line, PATTERN appears. Check up on PATTERN near the end. RC=0 ---------------------------- Test 62 ----------------------------- pcregrep: pcre_exec() gave error -8 while matching text that starts: This is a file of miscellaneous text that is used as test data for checking that the pcregrep command is working correctly. The file must be more than 24K long so that it needs more than a single read pcregrep: Error -8, -21 or -27 means that a resource limit was exceeded. pcregrep: Check your regex for nested unlimited loops. RC=1 ---------------------------- Test 63 ----------------------------- pcregrep: pcre_exec() gave error -21 while matching text that starts: This is a file of miscellaneous text that is used as test data for checking that the pcregrep command is working correctly. The file must be more than 24K long so that it needs more than a single read pcregrep: Error -8, -21 or -27 means that a resource limit was exceeded. pcregrep: Check your regex for nested unlimited loops. RC=1 ---------------------------- Test 64 ------------------------------ appears RC=0 ---------------------------- Test 65 ------------------------------ pear RC=0 ---------------------------- Test 66 ------------------------------ RC=0 ---------------------------- Test 67 ------------------------------ RC=0 ---------------------------- Test 68 ------------------------------ pear RC=0 ---------------------------- Test 69 ----------------------------- 1:This is a second file of input for the pcregrep tests. 2: 4: 5:Pattern 6:That time it was on a line by itself. 7: 8:To pat or not to pat, that is the question. 9: 10:complete pair 11:of lines 12: 13:That was a complete pair 14:of lines all by themselves. 15: 16:complete pair 17:of lines 18: 19:And there they were again, to check line numbers. 20: 21:one 22:two 23:three 24:four 25:five 26:six 27:seven 28:eight 29:nine 30:ten 31:eleven 32:twelve 33:thirteen 34:fourteen 35:fifteen 36:sixteen 37:seventeen 38:eighteen 39:nineteen 40:twenty 41: 43:This is the last line of this file. RC=0 ---------------------------- Test 70 ----------------------------- triple: t1_txt s1_tag s_txt p_tag p_txt o_tag o_txt triple: t3_txt s2_tag s_txt p_tag p_txt o_tag o_txt triple: t4_txt s1_tag s_txt p_tag p_txt o_tag o_txt triple: t6_txt s2_tag s_txt p_tag p_txt o_tag o_txt RC=0 ---------------------------- Test 71 ----------------------------- 01 RC=0 ---------------------------- Test 72 ----------------------------- 010203040506 RC=0 ---------------------------- Test 73 ----------------------------- 01 RC=0 ---------------------------- Test 74 ----------------------------- 01 02 RC=0 ---------------------------- Test 75 ----------------------------- 010203040506 RC=0 ---------------------------- Test 76 ----------------------------- 01 02 RC=0 ---------------------------- Test 77 ----------------------------- 01 03 RC=0 ---------------------------- Test 78 ----------------------------- 010203040506 RC=0 ---------------------------- Test 79 ----------------------------- 01 03 RC=0 ---------------------------- Test 80 ----------------------------- 01 RC=0 ---------------------------- Test 81 ----------------------------- 010203040506 RC=0 ---------------------------- Test 82 ----------------------------- 01 RC=0 ---------------------------- Test 83 ----------------------------- pcregrep: line 4 of file ./testdata/grepinput3 is too long for the internal buffer pcregrep: check the --buffer-size option RC=2 ---------------------------- Test 84 ----------------------------- testdata/grepinputv:fox jumps testdata/grepinputx:complete pair testdata/grepinputx:That was a complete pair testdata/grepinputx:complete pair testdata/grepinput3:triple: t7_txt s1_tag s_txt p_tag p_txt o_tag o_txt RC=0 ---------------------------- Test 85 ----------------------------- ./testdata/grepinput3:Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. RC=0 ---------------------------- Test 86 ----------------------------- Binary file ./testdata/grepbinary matches RC=0 ---------------------------- Test 87 ----------------------------- RC=1 ---------------------------- Test 88 ----------------------------- Binary file ./testdata/grepbinary matches RC=0 ---------------------------- Test 89 ----------------------------- RC=1 ---------------------------- Test 90 ----------------------------- RC=1 ---------------------------- Test 91 ----------------------------- The quick brown fx jumps over the lazy dog. RC=0 ---------------------------- Test 92 ----------------------------- The quick brown fx jumps over the lazy dog. RC=0 ---------------------------- Test 93 ----------------------------- The quick brown fx jumps over the lazy dog. RC=0 ---------------------------- Test 94 ----------------------------- ./testdata/grepinput8 ./testdata/grepinputx RC=0 ---------------------------- Test 95 ----------------------------- testdata/grepinputx:complete pair testdata/grepinputx:That was a complete pair testdata/grepinputx:complete pair RC=0 ---------------------------- Test 96 ----------------------------- ./testdata/grepinput3 ./testdata/grepinput8 ./testdata/grepinputx RC=0 ---------------------------- Test 97 ----------------------------- ./testdata/grepinput3 ./testdata/grepinputx RC=0 ---------------------------- Test 98 ----------------------------- ./testdata/grepinputx RC=0 ---------------------------- Test 99 ----------------------------- ./testdata/grepinput3 ./testdata/grepinputx RC=0 ---------------------------- Test 100 ------------------------------ ./testdata/grepinput:zerothe. ./testdata/grepinput:zeroa ./testdata/grepinput:zerothe. RC=0 ---------------------------- Test 101 ------------------------------ ./testdata/grepinput:.|zero|the|. ./testdata/grepinput:zero|a ./testdata/grepinput:.|zero|the|. RC=0 ---------------------------- Test 102 ----------------------------- 2: 5: 7: 9: 12: 14: RC=0 ---------------------------- Test 103 ----------------------------- RC=0 ---------------------------- Test 104 ----------------------------- 2: 5: 7: 9: 12: 14: RC=0 ---------------------------- Test 105 ----------------------------- triple: t1_txt s1_tag s_txt p_tag p_txt o_tag o_txt  triple: t2_txt s1_tag s_txt p_tag p_txt o_tag Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.  triple: t3_txt s2_tag s_txt p_tag p_txt o_tag o_txt  triple: t4_txt s1_tag s_txt p_tag p_txt o_tag o_txt  triple: t5_txt s1_tag s_txt p_tag p_txt o_tag o_txt  triple: t6_txt s2_tag s_txt p_tag p_txt o_tag o_txt  triple: t7_txt s1_tag s_txt p_tag p_txt o_tag o_txt RC=0 ---------------------------- Test 106 ----------------------------- a RC=0 ---------------------------- Test 107 ----------------------------- 1:0,1 2:0,1 2:1,1 2:2,1 2:3,1 2:4,1 RC=0 ---------------------------- Test 108 ------------------------------ RC=0 ---------------------------- Test 109 ----------------------------- RC=0 ================================================ FILE: src/pcre/testdata/grepoutput8 ================================================ ---------------------------- Test U1 ------------------------------ 1:X one 2:X two 3:X three 4:X four 5:X five 6:X six 7:X seven…8:X eight
9:X nine
10:X ten RC=0 ---------------------------- Test U2 ------------------------------ 12-Before 111 13-Before 222
14-Before 333…15:Match 16-After 111 17-After 222
18-After 333 RC=0 ================================================ FILE: src/pcre/testdata/grepoutputN ================================================ ---------------------------- Test N1 ------------------------------ 1:abc 2:def ---------------------------- Test N2 ------------------------------ 1:abc def 2:ghi jkl---------------------------- Test N3 ------------------------------ 2:def 3: ghi jkl---------------------------- Test N4 ------------------------------ 2:ghi jkl---------------------------- Test N5 ------------------------------ 1:abc 2:def 3:ghi 4:jkl---------------------------- Test N6 ------------------------------ 1:abc 2:def 3:ghi 4:jkl ================================================ FILE: src/pcre/testdata/greppatN4 ================================================ xxx jkl ================================================ FILE: src/pcre/testdata/testinput1 ================================================ /-- This set of tests is for features that are compatible with all versions of Perl >= 5.10, in non-UTF-8 mode. It should run clean for the 8-bit, 16-bit, and 32-bit PCRE libraries. --/ < forbid 89?=ABCDEFfGILMNPTUWXZ< /the quick brown fox/ the quick brown fox The quick brown FOX What do you know about the quick brown fox? What do you know about THE QUICK BROWN FOX? /The quick brown fox/i the quick brown fox The quick brown FOX What do you know about the quick brown fox? What do you know about THE QUICK BROWN FOX? /abcd\t\n\r\f\a\e\071\x3b\$\\\?caxyz/ abcd\t\n\r\f\a\e9;\$\\?caxyz /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/ abxyzpqrrrabbxyyyypqAzz abxyzpqrrrabbxyyyypqAzz aabxyzpqrrrabbxyyyypqAzz aaabxyzpqrrrabbxyyyypqAzz aaaabxyzpqrrrabbxyyyypqAzz abcxyzpqrrrabbxyyyypqAzz aabcxyzpqrrrabbxyyyypqAzz aaabcxyzpqrrrabbxyyyypAzz aaabcxyzpqrrrabbxyyyypqAzz aaabcxyzpqrrrabbxyyyypqqAzz aaabcxyzpqrrrabbxyyyypqqqAzz aaabcxyzpqrrrabbxyyyypqqqqAzz aaabcxyzpqrrrabbxyyyypqqqqqAzz aaabcxyzpqrrrabbxyyyypqqqqqqAzz aaaabcxyzpqrrrabbxyyyypqAzz abxyzzpqrrrabbxyyyypqAzz aabxyzzzpqrrrabbxyyyypqAzz aaabxyzzzzpqrrrabbxyyyypqAzz aaaabxyzzzzpqrrrabbxyyyypqAzz abcxyzzpqrrrabbxyyyypqAzz aabcxyzzzpqrrrabbxyyyypqAzz aaabcxyzzzzpqrrrabbxyyyypqAzz aaaabcxyzzzzpqrrrabbxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyyypqAzz aaabcxyzpqrrrabbxyyyypABzz aaabcxyzpqrrrabbxyyyypABBzz >>>aaabxyzpqrrrabbxyyyypqAzz >aaaabxyzpqrrrabbxyyyypqAzz >>>>abcxyzpqrrrabbxyyyypqAzz *** Failers abxyzpqrrabbxyyyypqAzz abxyzpqrrrrabbxyyyypqAzz abxyzpqrrrabxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyypqAzz aaabcxyzpqrrrabbxyyyypqqqqqqqAzz /^(abc){1,2}zz/ abczz abcabczz *** Failers zz abcabcabczz >>abczz /^(b+?|a){1,2}?c/ bc bbc bbbc bac bbac aac abbbbbbbbbbbc bbbbbbbbbbbac *** Failers aaac abbbbbbbbbbbac /^(b+|a){1,2}c/ bc bbc bbbc bac bbac aac abbbbbbbbbbbc bbbbbbbbbbbac *** Failers aaac abbbbbbbbbbbac /^(b+|a){1,2}?bc/ bbc /^(b*|ba){1,2}?bc/ babc bbabc bababc *** Failers bababbc babababc /^(ba|b*){1,2}?bc/ babc bbabc bababc *** Failers bababbc babababc /^\ca\cA\c[;\c:/ \x01\x01\e;z /^[ab\]cde]/ athing bthing ]thing cthing dthing ething *** Failers fthing [thing \\thing /^[]cde]/ ]thing cthing dthing ething *** Failers athing fthing /^[^ab\]cde]/ fthing [thing \\thing *** Failers athing bthing ]thing cthing dthing ething /^[^]cde]/ athing fthing *** Failers ]thing cthing dthing ething /^\/ /^/ /^[0-9]+$/ 0 1 2 3 4 5 6 7 8 9 10 100 *** Failers abc /^.*nter/ enter inter uponter /^xxx[0-9]+$/ xxx0 xxx1234 *** Failers xxx /^.+[0-9][0-9][0-9]$/ x123 xx123 123456 *** Failers 123 x1234 /^.+?[0-9][0-9][0-9]$/ x123 xx123 123456 *** Failers 123 x1234 /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ abc!pqr=apquxz.ixr.zzz.ac.uk *** Failers !pqr=apquxz.ixr.zzz.ac.uk abc!=apquxz.ixr.zzz.ac.uk abc!pqr=apquxz:ixr.zzz.ac.uk abc!pqr=apquxz.ixr.zzz.ac.ukk /:/ Well, we need a colon: somewhere *** Fail if we don't /([\da-f:]+)$/i 0abc abc fed E :: 5f03:12C0::932e fed def Any old stuff *** Failers 0zzz gzzz fed\x20 Any old rubbish /^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ .1.2.3 A.12.123.0 *** Failers .1.2.3333 1.2.3 1234.2.3 /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( 1 IN SOA non-sp1 non-sp2 ( *** Failers 1IN SOA non-sp1 non-sp2( /^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ a. Z. 2. ab-c.pq-r. sxk.zzz.ac.uk. x-.y-. *** Failers -abc.peq. /^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ *.a *.b0-a *.c3-b.c *.c-a.b-c *** Failers *.0 *.a- *.a-b.c- *.c-a.0-c /^(?=ab(de))(abd)(e)/ abde /^(?!(ab)de|x)(abd)(f)/ abdf /^(?=(ab(cd)))(ab)/ abcd /^[\da-f](\.[\da-f])*$/i a.b.c.d A.B.C.D a.b.c.1.2.3.C /^\".*\"\s*(;.*)?$/ \"1234\" \"abcd\" ; \"\" ; rhubarb *** Failers \"1234\" : things /^$/ \ *** Failers / ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x ab c *** Failers abc ab cde /(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ ab c *** Failers abc ab cde /^ a\ b[c ]d $/x a bcd a b d *** Failers abcd ab d /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ abcdefhijklm /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ abcdefhijklm /^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ a+ Z0+\x08\n\x1d\x12 /^[.^$|()*+?{,}]+/ .^\$(*+)|{?,?} /^a*\w/ z az aaaz a aa aaaa a+ aa+ /^a*?\w/ z az aaaz a aa aaaa a+ aa+ /^a+\w/ az aaaz aa aaaa aa+ /^a+?\w/ az aaaz aa aaaa aa+ /^\d{8}\w{2,}/ 1234567890 12345678ab 12345678__ *** Failers 1234567 /^[aeiou\d]{4,5}$/ uoie 1234 12345 aaaaa *** Failers 123456 /^[aeiou\d]{4,5}?/ uoie 1234 12345 aaaaa 123456 /\A(abc|def)=(\1){2,3}\Z/ abc=abcabc def=defdefdef *** Failers abc=defdef /^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\11*(\3\4)\1(?#)2$/ abcdefghijkcda2 abcdefghijkkkkcda2 /(cat(a(ract|tonic)|erpillar)) \1()2(3)/ cataract cataract23 catatonic catatonic23 caterpillar caterpillar23 /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ From abcd Mon Sep 01 12:33:02 1997 /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ From abcd Mon Sep 01 12:33:02 1997 From abcd Mon Sep 1 12:33:02 1997 *** Failers From abcd Sep 01 12:33:02 1997 /^12.34/s 12\n34 12\r34 /\w+(?=\t)/ the quick brown\t fox /foo(?!bar)(.*)/ foobar is foolish see? /(?:(?!foo)...|^.{0,2})bar(.*)/ foobar crowbar etc barrel 2barrel A barrel /^(\D*)(?=\d)(?!123)/ abc456 *** Failers abc123 /^1234(?# test newlines inside)/ 1234 /^1234 #comment in extended re /x 1234 /#rhubarb abcd/x abcd /^abcd#rhubarb/x abcd /^(a)\1{2,3}(.)/ aaab aaaab aaaaab aaaaaab /(?!^)abc/ the abc *** Failers abc /(?=^)abc/ abc *** Failers the abc /^[ab]{1,3}(ab*|b)/ aabbbbb /^[ab]{1,3}?(ab*|b)/ aabbbbb /^[ab]{1,3}?(ab*?|b)/ aabbbbb /^[ab]{1,3}(ab*?|b)/ aabbbbb / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /x Alan Other user\@dom.ain \"A. Other\" (a comment) A. Other (a comment) \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) # leading word [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces (?: (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) | " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " ) # "special" comment or quoted string [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" )* < [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # < (?: @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* (?: , [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* )* # additional domains : [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address spec > # > # name and address ) /x Alan Other user\@dom.ain \"A. Other\" (a comment) A. Other (a comment) \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay A missing angle ]{0,})>]{0,})>([\d]{0,}\.)(.*)((
    ([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is 43.
    Word Processor
    (N-1286)
    Lega lstaff.comCA - Statewide /a[^a]b/ acb a\nb /a.b/ acb *** Failers a\nb /a[^a]b/s acb a\nb /a.b/s acb a\nb /^(b+?|a){1,2}?c/ bac bbac bbbac bbbbac bbbbbac /^(b+|a){1,2}?c/ bac bbac bbbac bbbbac bbbbbac /(?!\A)x/m x\nb\n a\bx\n /\x0{ab}/ \0{ab} /(A|B)*?CD/ CD /(A|B)*CD/ CD /(AB)*?\1/ ABABAB /(AB)*\1/ ABABAB /(?.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ "(?>.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo /(?>(\.\d\d[1-9]?))\d+/ 1.230003938 1.875000282 *** Failers 1.235 /^((?>\w+)|(?>\s+))*$/ now is the time for all good men to come to the aid of the party *** Failers this is not a line with only words and spaces! /(\d+)(\w)/ 12345a 12345+ /((?>\d+))(\w)/ 12345a *** Failers 12345+ /(?>a+)b/ aaab /((?>a+)b)/ aaab /(?>(a+))b/ aaab /(?>b)+/ aaabbbccc /(?>a+|b+|c+)*c/ aaabbbbccccd /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x /\(((?>[^()]+)|\([^()]+\))+\)/ (abc) (abc(def)xyz) *** Failers ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /a(?-i)b/i ab Ab *** Failers aB AB /(a (?x)b c)d e/ a bcd e *** Failers a b cd e abcd e a bcde /(a b(?x)c d (?-x)e f)/ a bcde f *** Failers abcdef /(a(?i)b)c/ abc aBc *** Failers abC aBC Abc ABc ABC AbC /a(?i:b)c/ abc aBc *** Failers ABC abC aBC /a(?i:b)*c/ aBc aBBc *** Failers aBC aBBC /a(?=b(?i)c)\w\wd/ abcd abCd *** Failers aBCd abcD /(?s-i:more.*than).*million/i more than million more than MILLION more \n than Million *** Failers MORE THAN MILLION more \n than \n million /(?:(?s-i)more.*than).*million/i more than million more than MILLION more \n than Million *** Failers MORE THAN MILLION more \n than \n million /(?>a(?i)b+)+c/ abc aBbc aBBc *** Failers Abc abAb abbC /(?=a(?i)b)\w\wc/ abc aBc *** Failers Ab abC aBC /(?<=a(?i)b)(\w\w)c/ abxxc aBxxc *** Failers Abxxc ABxxc abxxC /(?:(a)|b)(?(1)A|B)/ aA bB *** Failers aB bA /^(a)?(?(1)a|b)+$/ aa b bb *** Failers ab /^(?(?=abc)\w{3}:|\d\d)$/ abc: 12 *** Failers 123 xyz /^(?(?!abc)\d\d|\w{3}:)$/ abc: 12 *** Failers 123 xyz /(?(?<=foo)bar|cat)/ foobar cat fcat focat *** Failers foocat /(?(?a*)*/ a aa aaaa /(abc|)+/ abc abcabc abcabcabc xyz /([a]*)*/ a aaaaa /([ab]*)*/ a b ababab aaaabcde bbbb /([^a]*)*/ b bbbb aaa /([^ab]*)*/ cccc abab /([a]*?)*/ a aaaa /([ab]*?)*/ a b abab baba /([^a]*?)*/ b bbbb aaa /([^ab]*?)*/ c cccc baba /(?>a*)*/ a aaabcde /((?>a*))*/ aaaaa aabbaa /((?>a*?))*/ aaaaa aabbaa /(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x 12-sep-98 12-09-98 *** Failers sep-12-98 /(?<=(foo))bar\1/ foobarfoo foobarfootling *** Failers foobar barfoo /(?i:saturday|sunday)/ saturday sunday Saturday Sunday SATURDAY SUNDAY SunDay /(a(?i)bc|BB)x/ abcx aBCx bbx BBx *** Failers abcX aBCX bbX BBX /^([ab](?i)[cd]|[ef])/ ac aC bD elephant Europe frog France *** Failers Africa /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ ab aBd xy xY zebra Zambesi *** Failers aCD XY /(?<=foo\n)^bar/m foo\nbar *** Failers bar baz\nbar /(?<=(?]&/ <&OUT /^(a\1?){4}$/ aaaaaaaaaa *** Failers AB aaaaaaaaa aaaaaaaaaaa /^(a(?(1)\1)){4}$/ aaaaaaaaaa *** Failers aaaaaaaaa aaaaaaaaaaa /(?:(f)(o)(o)|(b)(a)(r))*/ foobar /(?<=a)b/ ab *** Failers cb b /(?a+)ab/ /(?>a+)b/ aaab /([[:]+)/ a:[b]: /([[=]+)/ a=[b]= /([[.]+)/ a.[b]. /((?>a+)b)/ aaab /(?>(a+))b/ aaab /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x /a\Z/ *** Failers aaab a\nb\n /b\Z/ a\nb\n /b\z/ /b\Z/ a\nb /b\z/ a\nb *** Failers /^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$/ a abc a-b 0-9 a.b 5.6.7 the.quick.brown.fox a100.b200.300c 12-ab.1245 *** Failers \ .a -a a- a. a_b a.- a.. ab..bc the.quick.brown.fox- the.quick.brown.fox. the.quick.brown.fox_ the.quick.brown.fox+ /(?>.*)(?<=(abcd|wxyz))/ alphabetabcd endingwxyz *** Failers a rather long string that doesn't end with one of them /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark /word (?>[a-zA-Z0-9]+ ){0,30}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope /(?<=\d{3}(?!999))foo/ 999foo 123999foo *** Failers 123abcfoo /(?<=(?!...999)\d{3})foo/ 999foo 123999foo *** Failers 123abcfoo /(?<=\d{3}(?!999)...)foo/ 123abcfoo 123456foo *** Failers 123999foo /(?<=\d{3}...)(?\s*)=(?>\s*) # find Z)+|A)*/ ZABCDEFG /((?>)+|A)*/ ZABCDEFG /a*/g abbab /^[\d-a]/ abcde -things 0digit *** Failers bcdef /[[:space:]]+/ > \x09\x0a\x0c\x0d\x0b< /[[:blank:]]+/ > \x09\x0a\x0c\x0d\x0b< /[\s]+/ > \x09\x0a\x0c\x0d\x0b< /\s+/ > \x09\x0a\x0c\x0d\x0b< /a b/x ab /(?!\A)x/m a\nxb\n /(?!^)x/m a\nxb\n /abc\Qabc\Eabc/ abcabcabc /abc\Q(*+|\Eabc/ abc(*+|abc / abc\Q abc\Eabc/x abc abcabc *** Failers abcabcabc /abc#comment \Q#not comment literal\E/x abc#not comment\n literal /abc#comment \Q#not comment literal/x abc#not comment\n literal /abc#comment \Q#not comment literal\E #more comment /x abc#not comment\n literal /abc#comment \Q#not comment literal\E #more comment/x abc#not comment\n literal /\Qabc\$xyz\E/ abc\\\$xyz /\Qabc\E\$\Qxyz\E/ abc\$xyz /\Gabc/ abc *** Failers xyzabc /\Gabc./g abc1abc2xyzabc3 /abc./g abc1abc2xyzabc3 /a(?x: b c )d/ XabcdY *** Failers Xa b c d Y /((?x)x y z | a b c)/ XabcY AxyzB /(?i)AB(?-i)C/ XabCY *** Failers XabcY /((?i)AB(?-i)C|D)E/ abCE DE *** Failers abcE abCe dE De /(.*)\d+\1/ abc123abc abc123bc /(.*)\d+\1/s abc123abc abc123bc /((.*))\d+\1/ abc123abc abc123bc /-- This tests for an IPv6 address in the form where it can have up to eight components, one and only one of which is empty. This must be an internal component. --/ /^(?!:) # colon disallowed at start (?: # start of item (?: [0-9a-f]{1,4} | # 1-4 hex digits or (?(1)0 | () ) ) # if null previously matched, fail; else null : # followed by colon ){1,7} # end item; 1-7 of them required [0-9a-f]{1,4} $ # final hex number at end of string (?(1)|.) # check that there was an empty component /xi a123::a123 a123:b342::abcd a123:b342::324e:abcd a123:ddde:b342::324e:abcd a123:ddde:b342::324e:dcba:abcd a123:ddde:9999:b342::324e:dcba:abcd *** Failers 1:2:3:4:5:6:7:8 a123:bce:ddde:9999:b342::324e:dcba:abcd a123::9999:b342::324e:dcba:abcd abcde:2:3:4:5:6:7:8 ::1 abcd:fee0:123:: :1 1: /[z\Qa-d]\E]/ z a - d ] *** Failers b /[\z\C]/ z C /\M/ M /(a+)*b/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /(?i)reg(?:ul(?:[a]|ae)r|ex)/ REGular regulaer Regex regulr /[--]+/ /(?<=Z)X./ \x84XAZXB /ab cd (?x) de fg/ ab cd defg /ab cd(?x) de fg/ ab cddefg ** Failers abcddefg /(?a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /(?:a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /\Z/g abc\n /^(?s)(?>.*)(?(a))b|(a)c/ ac /(?=(a))ab|(a)c/ ac /((?>(a))b|(a)c)/ ac /((?>(a))b|(a)c)++/ ac /(?:(?>(a))b|(a)c)++/ ac /(?=(?>(a))b|(a)c)(..)/ ac /(?>(?>(a))b|(a)c)/ ac /(?:(?>([ab])))+a=/+ =ba= /(?>([ab]))+a=/+ =ba= /((?>(a+)b)+(aabab))/ aaaabaaabaabab /(?>a+|ab)+?c/ aabc /(?>a+|ab)+c/ aabc /(?:a+|ab)+c/ aabc /(?(?=(a))a)/ a /(?(?=(a))a)(b)/ ab /^(?:a|ab)++c/ aaaabc /^(?>a|ab)++c/ aaaabc /^(?:a|ab)+c/ aaaabc /(?=abc){3}abc/+ abcabcabc ** Failers xyz /(?=abc)+abc/+ abcabcabc ** Failers xyz /(?=abc)++abc/+ abcabcabc ** Failers xyz /(?=abc){0}xyz/ xyz /(?=abc){1}xyz/ ** Failers xyz /(?=(a))?./ ab bc /(?=(a))??./ ab bc /^(?=(?1))?[az]([abc])d/ abd zcdxx /^(?!a){0}\w+/ aaaaa /(?<=(abc))?xyz/ abcxyz pqrxyz /^[\g]+/ ggg<<>> ** Failers \\ga /^[\ga]+/ gggagagaxyz /^[:a[:digit:]]+/ aaaa444:::Z /^[:a[:digit:]:b]+/ aaaa444:::bbbZ /[:a]xxx[b:]/ :xxx: /(?<=a{2})b/i xaabc ** Failers xabc /(?XNNNYZ > X NYQZ ** Failers >XYZ > X NY Z /\v*X\v?Y\v+Z\V*\x0a\V+\x0b\V{2,3}\x0c/ >XY\x0aZ\x0aA\x0bNN\x0c >\x0a\x0dX\x0aY\x0a\x0bZZZ\x0aAAA\x0bNNN\x0c /(foo)\Kbar/ foobar /(foo)(\Kbar|baz)/ foobar foobaz /(foo\Kbar)baz/ foobarbaz /abc\K|def\K/g+ Xabcdefghi /ab\Kc|de\Kf/g+ Xabcdefghi /(?=C)/g+ ABCDECBA /^abc\K/+ abcdef ** Failers defabcxyz /^(a(b))\1\g1\g{1}\g-1\g{-1}\g{-02}Z/ ababababbbabZXXXX /(?tom|bon)-\g{A}/ tom-tom bon-bon /(^(a|b\g{-1}))/ bacxxx /(?|(abc)|(xyz))\1/ abcabc xyzxyz ** Failers abcxyz xyzabc /(?|(abc)|(xyz))(?1)/ abcabc xyzabc ** Failers xyzxyz /^X(?5)(a)(?|(b)|(q))(c)(d)(Y)/ XYabcdY /^X(?7)(a)(?|(b|(r)(s))|(q))(c)(d)(Y)/ XYabcdY /^X(?7)(a)(?|(b|(?|(r)|(t))(s))|(q))(c)(d)(Y)/ XYabcdY /(?'abc'\w+):\k{2}/ a:aaxyz ab:ababxyz ** Failers a:axyz ab:abxyz /(?'abc'\w+):\g{abc}{2}/ a:aaxyz ab:ababxyz ** Failers a:axyz ab:abxyz /^(?a)? (?()b|c) (?('ab')d|e)/x abd ce /^(a.)\g-1Z/ aXaXZ /^(a.)\g{-1}Z/ aXaXZ /^(?(DEFINE) (? a) (? b) ) (?&A) (?&B) /x abcd /(?(?&NAME_PAT))\s+(?(?&ADDRESS_PAT)) (?(DEFINE) (?[a-z]+) (?\d+) )/x metcalfe 33 /(?(DEFINE)(?2[0-4]\d|25[0-5]|1\d\d|[1-9]?\d))\b(?&byte)(\.(?&byte)){3}/ 1.2.3.4 131.111.10.206 10.0.0.0 ** Failers 10.6 455.3.4.5 /\b(?&byte)(\.(?&byte)){3}(?(DEFINE)(?2[0-4]\d|25[0-5]|1\d\d|[1-9]?\d))/ 1.2.3.4 131.111.10.206 10.0.0.0 ** Failers 10.6 455.3.4.5 /^(\w++|\s++)*$/ now is the time for all good men to come to the aid of the party *** Failers this is not a line with only words and spaces! /(\d++)(\w)/ 12345a *** Failers 12345+ /a++b/ aaab /(a++b)/ aaab /(a++)b/ aaab /([^()]++|\([^()]*\))+/ ((abc(ade)ufh()()x /\(([^()]++|\([^()]+\))+\)/ (abc) (abc(def)xyz) *** Failers ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /^([^()]|\((?1)*\))*$/ abc a(b)c a(b(c))d *** Failers) a(b(c)d /^>abc>([^()]|\((?1)*\))*abc>123abc>1(2)3abc>(1(2)3)]*+) | (?2)) * >))/x <> hij> hij> def> *** Failers a)(?<=b(?&X))/ baz /^(?|(abc)|(def))\1/ abcabc defdef ** Failers abcdef defabc /^(?|(abc)|(def))(?1)/ abcabc defabc ** Failers defdef abcdef /(?:a(? (?')|(?")) |b(? (?')|(?")) ) (?('quote')[a-z]+|[0-9]+)/xJ a\"aaaaa b\"aaaaa ** Failers b\"11111 /(?:(?1)|B)(A(*F)|C)/ ABCD CCD ** Failers CAD /^(?:(?1)|B)(A(*F)|C)/ CCD BCD ** Failers ABCD CAD BAD /(?:(?1)|B)(A(*ACCEPT)XX|C)D/ AAD ACD BAD BCD BAX ** Failers ACX ABC /(?(DEFINE)(A))B(?1)C/ BAC /(?(DEFINE)((A)\2))B(?1)C/ BAAC /(? \( ( [^()]++ | (?&pn) )* \) )/x (ab(cd)ef) /^(?=a(*SKIP)b|ac)/ ** Failers ac /^(?=a(*PRUNE)b)/ ab ** Failers ac /^(?=a(*ACCEPT)b)/ ac /(?>a\Kb)/ ab /((?>a\Kb))/ ab /(a\Kb)/ ab /^a\Kcz|ac/ ac /(?>a\Kbz|ab)/ ab /^(?&t)(?(DEFINE)(?a\Kb))$/ ab /^([^()]|\((?1)*\))*$/ a(b)c a(b(c)d)e /(?P(?P0)(?P>L1)|(?P>L2))/ 0 00 0000 /(?P(?P0)|(?P>L2)(?P>L1))/ 0 00 0000 /--- This one does fail, as expected, in Perl. It needs the complex item at the end of the pattern. A single letter instead of (B|D) makes it not fail, which I think is a Perl bug. --- / /A(*COMMIT)(B|D)/ ACABX /--- Check the use of names for failure ---/ /^(A(*PRUNE:A)B|C(*PRUNE:B)D)/K ** Failers AC CB /--- Force no study, otherwise mark is not seen. The studied version is in test 2 because it isn't Perl-compatible. ---/ /(*MARK:A)(*SKIP:B)(C|X)/KSS C D /^(A(*THEN:A)B|C(*THEN:B)D)/K ** Failers CB /^(?:A(*THEN:A)B|C(*THEN:B)D)/K CB /^(?>A(*THEN:A)B|C(*THEN:B)D)/K CB /--- This should succeed, as the skip causes bump to offset 1 (the mark). Note that we have to have something complicated such as (B|Z) at the end because, for Perl, a simple character somehow causes an unwanted optimization to mess with the handling of backtracking verbs. ---/ /A(*MARK:A)A+(*SKIP:A)(B|Z) | AC/xK AAAC /--- Test skipping over a non-matching mark. ---/ /A(*MARK:A)A+(*MARK:B)(*SKIP:A)(B|Z) | AC/xK AAAC /--- Check shorthand for MARK ---/ /A(*:A)A+(*SKIP:A)(B|Z) | AC/xK AAAC /--- Don't loop! Force no study, otherwise mark is not seen. ---/ /(*:A)A+(*SKIP:A)(B|Z)/KSS AAAC /--- This should succeed, as a non-existent skip name disables the skip ---/ /A(*MARK:A)A+(*SKIP:B)(B|Z) | AC/xK AAAC /A(*MARK:A)A+(*SKIP:B)(B|Z) | AC(*:B)/xK AAAC /--- COMMIT at the start of a pattern should act like an anchor. Again, however, we need the complication for Perl. ---/ /(*COMMIT)(A|P)(B|P)(C|P)/ ABCDEFG ** Failers DEFGABC /--- COMMIT inside an atomic group can't stop backtracking over the group. ---/ /(\w+)(?>b(*COMMIT))\w{2}/ abbb /(\w+)b(*COMMIT)\w{2}/ abbb /--- Check opening parens in comment when seeking forward reference. ---/ /(?&t)(?#()(?(DEFINE)(?a))/ bac /--- COMMIT should override THEN ---/ /(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?/ yes /(?>(*COMMIT)(yes|no)(*THEN)(*F))?/ yes /b?(*SKIP)c/ bc abc /(*SKIP)bc/ a /(*SKIP)b/ a /(?P(?P=abn)xxx|)+/ xxx /(?i:([^b]))(?1)/ aa aA ** Failers ab aB Ba ba /^(?&t)*+(?(DEFINE)(?a))\w$/ aaaaaaX ** Failers aaaaaa /^(?&t)*(?(DEFINE)(?a))\w$/ aaaaaaX aaaaaa /^(a)*+(\w)/ aaaaX YZ ** Failers aaaa /^(?:a)*+(\w)/ aaaaX YZ ** Failers aaaa /^(a)++(\w)/ aaaaX ** Failers aaaa YZ /^(?:a)++(\w)/ aaaaX ** Failers aaaa YZ /^(a)?+(\w)/ aaaaX YZ /^(?:a)?+(\w)/ aaaaX YZ /^(a){2,}+(\w)/ aaaaX ** Failers aaa YZ /^(?:a){2,}+(\w)/ aaaaX ** Failers aaa YZ /(a|)*(?1)b/ b ab aab /(a)++(?1)b/ ** Failers ab aab /(a)*+(?1)b/ ** Failers ab aab /(?1)(?:(b)){0}/ b /(foo ( \( ((?:(?> [^()]+ )|(?2))*) \) ) )/x foo(bar(baz)+baz(bop)) /(A (A|B(*ACCEPT)|C) D)(E)/x AB /\A.*?(a|bc)/ ba /\A.*?(?:a|bc)++/ ba /\A.*?(a|bc)++/ ba /\A.*?(?:a|bc|d)/ ba /(?:(b))++/ beetle /(?(?=(a(*ACCEPT)z))a)/ a /^(a)(?1)+ab/ aaaab /^(a)(?1)++ab/ aaaab /^(?=a(*:M))aZ/K aZbc /^(?!(*:M)b)aZ/K aZbc /(?(DEFINE)(a))?b(?1)/ backgammon /^\N+/ abc\ndef /^\N{1,}/ abc\ndef /(?(R)a+|(?R)b)/ aaaabcde /(?(R)a+|((?R))b)/ aaaabcde /((?(R)a+|(?1)b))/ aaaabcde /((?(R1)a+|(?1)b))/ aaaabcde /((?(R)a|(?1)))*/ aaa /((?(R)a|(?1)))+/ aaa /a(*:any name)/K abc /(?>(?&t)c|(?&t))(?(DEFINE)(?a|b(*PRUNE)c))/ a ba bba /--- Checking revised (*THEN) handling ---/ /--- Capture ---/ /^.*? (a(*THEN)b) c/x aabc /^.*? (a(*THEN)b|(*F)) c/x aabc /^.*? ( (a(*THEN)b) | (*F) ) c/x aabc /^.*? ( (a(*THEN)b) ) c/x aabc /--- Non-capture ---/ /^.*? (?:a(*THEN)b) c/x aabc /^.*? (?:a(*THEN)b|(*F)) c/x aabc /^.*? (?: (?:a(*THEN)b) | (*F) ) c/x aabc /^.*? (?: (?:a(*THEN)b) ) c/x aabc /--- Atomic ---/ /^.*? (?>a(*THEN)b) c/x aabc /^.*? (?>a(*THEN)b|(*F)) c/x aabc /^.*? (?> (?>a(*THEN)b) | (*F) ) c/x aabc /^.*? (?> (?>a(*THEN)b) ) c/x aabc /--- Possessive capture ---/ /^.*? (a(*THEN)b)++ c/x aabc /^.*? (a(*THEN)b|(*F))++ c/x aabc /^.*? ( (a(*THEN)b)++ | (*F) )++ c/x aabc /^.*? ( (a(*THEN)b)++ )++ c/x aabc /--- Possessive non-capture ---/ /^.*? (?:a(*THEN)b)++ c/x aabc /^.*? (?:a(*THEN)b|(*F))++ c/x aabc /^.*? (?: (?:a(*THEN)b)++ | (*F) )++ c/x aabc /^.*? (?: (?:a(*THEN)b)++ )++ c/x aabc /--- Condition assertion ---/ /^(?(?=a(*THEN)b)ab|ac)/ ac /--- Condition ---/ /^.*?(?(?=a)a|b(*THEN)c)/ ba /^.*?(?:(?(?=a)a|b(*THEN)c)|d)/ ba /^.*?(?(?=a)a(*THEN)b|c)/ ac /--- Assertion ---/ /^.*(?=a(*THEN)b)/ aabc /------------------------------/ /(?>a(*:m))/imsxSK a /(?>(a)(*:m))/imsxSK a /(?<=a(*ACCEPT)b)c/ xacd /(?<=(a(*ACCEPT)b))c/ xacd /(?<=(a(*COMMIT)b))c/ xabcd ** Failers xacd /(?a?)*)*c/ aac /(?>.*?a)(?<=ba)/ aba /(?:.*?a)(?<=ba)/ aba /.*?a(*PRUNE)b/ aab /.*?a(*PRUNE)b/s aab /^a(*PRUNE)b/s aab /.*?a(*SKIP)b/ aab /(?>.*?a)b/s aab /(?>.*?a)b/ aab /(?>^a)b/s aab /(?>.*?)(?<=(abcd)|(wxyz))/ alphabetabcd endingwxyz /(?>.*)(?<=(abcd)|(wxyz))/ alphabetabcd endingwxyz "(?>.*)foo" abcdfooxyz "(?>.*?)foo" abcdfooxyz /(?:(a(*PRUNE)b)){0}(?:(?1)|ac)/ ac /(?:(a(*SKIP)b)){0}(?:(?1)|ac)/ ac /(?<=(*SKIP)ac)a/ aa /A(*MARK:A)A+(*SKIP:B)(B|Z) | AC/xK AAAC /a(*SKIP:m)x|ac(*:n)(*SKIP:n)d|ac/K acacd /A(*SKIP:m)x|A(*SKIP:n)x|AB/K AB /((*SKIP:r)d){0}a(*SKIP:m)x|ac(*:n)|ac/K acacd /-- Tests that try to figure out how Perl works. My hypothesis is that the first verb that is backtracked onto is the one that acts. This seems to be the case almost all the time, but there is one exception that is perhaps a bug. --/ /-- This matches "aaaac"; each PRUNE advances one character until the subject no longer starts with 5 'a's. --/ /aaaaa(*PRUNE)b|a+c/ aaaaaac /-- Putting SKIP in front of PRUNE makes no difference, as it is never backtracked onto, whether or not it has a label. --/ /aaaaa(*SKIP)(*PRUNE)b|a+c/ aaaaaac /aaaaa(*SKIP:N)(*PRUNE)b|a+c/ aaaaaac /aaaa(*:N)a(*SKIP:N)(*PRUNE)b|a+c/ aaaaaac /-- Putting THEN in front makes no difference. */ /aaaaa(*THEN)(*PRUNE)b|a+c/ aaaaaac /-- However, putting COMMIT in front of the prune changes it to "no match". I think this is inconsistent and possibly a bug. For the moment, running this test is moved out of the Perl-compatible file. --/ /aaaaa(*COMMIT)(*PRUNE)b|a+c/ /---- OK, lets play the same game again using SKIP instead of PRUNE. ----/ /-- This matches "ac" because SKIP forces the next match to start on the sixth "a". --/ /aaaaa(*SKIP)b|a+c/ aaaaaac /-- Putting PRUNE in front makes no difference. --/ /aaaaa(*PRUNE)(*SKIP)b|a+c/ aaaaaac /-- Putting THEN in front makes no difference. --/ /aaaaa(*THEN)(*SKIP)b|a+c/ aaaaaac /-- In this case, neither does COMMIT. This still matches "ac". --/ /aaaaa(*COMMIT)(*SKIP)b|a+c/ aaaaaac /-- This gives "no match", as expected. --/ /aaaaa(*COMMIT)b|a+c/ aaaaaac /------ Tests using THEN ------/ /-- This matches "aaaaaac", as expected. --/ /aaaaa(*THEN)b|a+c/ aaaaaac /-- Putting SKIP in front makes no difference. --/ /aaaaa(*SKIP)(*THEN)b|a+c/ aaaaaac /-- Putting PRUNE in front makes no difference. --/ /aaaaa(*PRUNE)(*THEN)b|a+c/ aaaaaac /-- Putting COMMIT in front makes no difference. --/ /aaaaa(*COMMIT)(*THEN)b|a+c/ aaaaaac /-- End of "priority" tests --/ /aaaaa(*:m)(*PRUNE:m)(*SKIP:m)m|a+/ aaaaaa /aaaaa(*:m)(*MARK:m)(*PRUNE)(*SKIP:m)m|a+/ aaaaaa /aaaaa(*:n)(*PRUNE:m)(*SKIP:m)m|a+/ aaaaaa /aaaaa(*:n)(*MARK:m)(*PRUNE)(*SKIP:m)m|a+/ aaaaaa /a(*MARK:A)aa(*PRUNE:A)a(*SKIP:A)b|a+c/ aaaac /a(*MARK:A)aa(*MARK:A)a(*SKIP:A)b|a+c/ aaaac /aaa(*PRUNE:A)a(*SKIP:A)b|a+c/ aaaac /aaa(*MARK:A)a(*SKIP:A)b|a+c/ aaaac /a(*:m)a(*COMMIT)(*SKIP:m)b|a+c/K aaaaaac /.?(a|b(*THEN)c)/ ba /(a(*COMMIT)b)c|abd/ abc abd /(?=a(*COMMIT)b)abc|abd/ abc abd /(?>a(*COMMIT)b)c|abd/ abc abd /a(?=b(*COMMIT)c)[^d]|abd/ abd abc /a(?=bc).|abd/ abd abc /a(?>b(*COMMIT)c)d|abd/ abceabd /a(?>bc)d|abd/ abceabd /(?>a(*COMMIT)b)c|abd/ abd /(?>a(*COMMIT)c)d|abd/ abd /((?=a(*COMMIT)b)ab|ac){0}(?:(?1)|a(c))/ ac /-- These tests were formerly in test 2, but changes in PCRE and Perl have made them compatible. --/ /^(a)?(?(1)a|b)+$/ *** Failers a /(?=a\Kb)ab/ ab /(?!a\Kb)ac/ ac /^abc(?<=b\Kc)d/ abcd /^abc(?b))/K abc /(*PRUNE:m(m)(?&y)(?(DEFINE)(?b))/K abc /(*SKIP:m(m)(?&y)(?(DEFINE)(?b))/K abc /(*THEN:m(m)(?&y)(?(DEFINE)(?b))/K abc /^\d*\w{4}/ 1234 123 /^[^b]*\w{4}/ aaaa aaa /^[^b]*\w{4}/i aaaa aaa /^a*\w{4}/ aaaa aaa /^a*\w{4}/i aaaa aaa /(?(?=ab)ab)/+ ca cd /(?:(?foo)|(?bar))\k/J foofoo barbar /(?A)(?:(?foo)|(?bar))\k/J AfooA AbarA ** Failers Afoofoo Abarbar /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( /^ (?:(?A)|(?'B'B)(?A)) (?('A')x) (?()y)$/xJ Ax BAxy /^A\xZ/ A\0Z /^A\o{123}B/ A\123B / ^ a + + b $ /x aaaab / ^ a + #comment + b $ /x aaaab / ^ a + #comment #comment + b $ /x aaaab / ^ (?> a + ) b $ /x aaaab / ^ ( a + ) + + \w $ /x aaaab /(?:a\Kb)*+/+ ababc /(?>a\Kb)*/+ ababc /(?:a\Kb)*/+ ababc /(a\Kb)*+/+ ababc /(a\Kb)*/+ ababc /(?:x|(?:(xx|yy)+|x|x|x|x|x)|a|a|a)bc/ acb '\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED '\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED '\A(?:[^\"]++|\"(?:[^\"]++|\"\")++\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED '\A([^\"1]++|[\"2]([^\"3]*+|[\"4][\"5])*+[\"6])++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED /^\w+(?>\s*)(?<=\w)/ test test /(?Pa)(?Pb)/gJ abbaba /(?Pa)(?Pb)(?P=same)/gJ abbaba /(?P=same)?(?Pa)(?Pb)/gJ abbaba /(?:(?P=same)?(?:(?Pa)|(?Pb))(?P=same))+/gJ bbbaaabaabb /(?:(?P=same)?(?:(?P=same)(?Pa)(?P=same)|(?P=same)?(?Pb)(?P=same)){2}(?P=same)(?Pc)(?P=same)){2}(?Pz)?/gJ bbbaaaccccaaabbbcc /(?Pa)?(?Pb)?(?()c|d)*l/ acl bdl adl bcl /\sabc/ \x{0b}abc /[\Qa]\E]+/ aa]] /[\Q]a\E]+/ aa]] /(?:((abcd))|(((?:(?:(?:(?:abc|(?:abcdef))))b)abcdefghi)abc)|((*ACCEPT)))/ 1234abcd /(\2)(\1)/ "Z*(|d*){216}" "(?1)(?#?'){8}(a)" baaaaaaaaac "(?|(\k'Pm')|(?'Pm'))" abcd /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/ \ Fred:099 /(?=.*X)X$/ \ X /X+(?#comment)?/ >XXX< / (? \w+ )* \. /xi pokus. /(?(DEFINE) (? \w+ ) ) (?&word)* \./xi pokus. /(?(DEFINE) (? \w+ ) ) ( (?&word)* ) \./xi pokus. /(?&word)* (?(DEFINE) (? \w+ ) ) \./xi pokus. /(?&word)* \. (? \w+ )/xi pokus.hokus /-- End of testinput1 --/ ================================================ FILE: src/pcre/testdata/testinput10 ================================================ /-- This set of tests check Unicode property support with the DFA matching functionality of pcre_dfa_exec(). The -dfa flag must be used with pcretest when running it. --/ /\pL\P{Nd}/8 AB *** Failers A0 00 /\X./8 AB A\x{300}BC A\x{300}\x{301}\x{302}BC *** Failers \x{300} /\X\X/8 ABC A\x{300}B\x{300}\x{301}C A\x{300}\x{301}\x{302}BC *** Failers \x{300} /^\pL+/8 abcd a *** Failers /^\PL+/8 1234 = *** Failers abcd /^\X+/8 abcdA\x{300}\x{301}\x{302} A\x{300}\x{301}\x{302} A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302} a *** Failers \x{300}\x{301}\x{302} /\X?abc/8 abc A\x{300}abc A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz \x{300}abc *** Failers /^\X?abc/8 abc A\x{300}abc *** Failers A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz \x{300}abc /\X*abc/8 abc A\x{300}abc A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz \x{300}abc *** Failers /^\X*abc/8 abc A\x{300}abc A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz *** Failers \x{300}abc /^\pL?=./8 A=b =c *** Failers 1=2 AAAA=b /^\pL*=./8 AAAA=b =c *** Failers 1=2 /^\X{2,3}X/8 A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X *** Failers X A\x{300}\x{301}\x{302}X A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X /^\pC\pL\pM\pN\pP\pS\pZ\p{Xsp}/8 >\x{1680}\x{2028}\x{0b} ** Failers \x{0b} /^>\p{Xsp}+/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}*/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}{2,9}/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>[\p{Xsp}]/8O >\x{2028}\x{0b} /^>[\p{Xsp}]+/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}/8 >\x{1680}\x{2028}\x{0b} >\x{a0} ** Failers \x{0b} /^>\p{Xps}+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}+?/8 >\x{1680}\x{2028}\x{0b} /^>\p{Xps}*/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}?/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>[\p{Xps}]/8 >\x{2028}\x{0b} /^>[\p{Xps}]+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^\p{Xwd}/8 ABCD 1234 \x{6ca} \x{a6c} \x{10a7} _ABC ** Failers [] /^\p{Xwd}+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}*/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}{2,9}/8 A_12\x{6ca}\x{a6c}\x{10a7} /^[\p{Xwd}]/8 ABCD1234_ 1234abcd_ \x{6ca} \x{a6c} \x{10a7} _ABC ** Failers [] /^[\p{Xwd}]+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /-- Unicode properties for \b abd \B --/ /\b...\B/8W abc_ \x{37e}abc\x{376} \x{37e}\x{376}\x{371}\x{393}\x{394} !\x{c0}++\x{c1}\x{c2} !\x{c0}+++++ /-- Without PCRE_UCP, non-ASCII always fail, even if < 256 --/ /\b...\B/8 abc_ ** Failers \x{37e}abc\x{376} \x{37e}\x{376}\x{371}\x{393}\x{394} !\x{c0}++\x{c1}\x{c2} !\x{c0}+++++ /-- With PCRE_UCP, non-UTF8 chars that are < 256 still check properties --/ /\b...\B/W abc_ !\x{c0}++\x{c1}\x{c2} !\x{c0}+++++ /-- Caseless single negated characters > 127 need UCP support --/ /[^\x{100}]/8i \x{100}\x{101}X /[^\x{100}]+/8i \x{100}\x{101}XX /^\X/8 A\P A\P\P A\x{300}\x{301}\P A\x{300}\x{301}\P\P A\x{301}\P A\x{301}\P\P /^\X{2,3}/8 A\P A\P\P AA\P AA\P\P A\x{300}\x{301}\P A\x{300}\x{301}\P\P A\x{300}\x{301}A\x{300}\x{301}\P A\x{300}\x{301}A\x{300}\x{301}\P\P /^\X{2}/8 AA\P AA\P\P A\x{300}\x{301}A\x{300}\x{301}\P A\x{300}\x{301}A\x{300}\x{301}\P\P /^\X+/8 AA\P AA\P\P /^\X+?Z/8 AA\P AA\P\P /-- These are tests for extended grapheme clusters --/ /^\X/8+ G\x{34e}\x{34e}X \x{34e}\x{34e}X \x04X \x{1100}X \x{1100}\x{34e}X \x{1b04}\x{1b04}X *These match up to the roman letters \x{1111}\x{1111}L,L \x{1111}\x{1111}\x{1169}L,L,V \x{1111}\x{ae4c}L, LV \x{1111}\x{ad89}L, LVT \x{1111}\x{ae4c}\x{1169}L, LV, V \x{1111}\x{ae4c}\x{1169}\x{1169}L, LV, V, V \x{1111}\x{ae4c}\x{1169}\x{11fe}L, LV, V, T \x{1111}\x{ad89}\x{11fe}L, LVT, T \x{1111}\x{ad89}\x{11fe}\x{11fe}L, LVT, T, T \x{ad89}\x{11fe}\x{11fe}LVT, T, T *These match just the first codepoint (invalid sequence) \x{1111}\x{11fe}L, T \x{ae4c}\x{1111}LV, L \x{ae4c}\x{ae4c}LV, LV \x{ae4c}\x{ad89}LV, LVT \x{1169}\x{1111}V, L \x{1169}\x{ae4c}V, LV \x{1169}\x{ad89}V, LVT \x{ad89}\x{1111}LVT, L \x{ad89}\x{1169}LVT, V \x{ad89}\x{ae4c}LVT, LV \x{ad89}\x{ad89}LVT, LVT \x{11fe}\x{1111}T, L \x{11fe}\x{1169}T, V \x{11fe}\x{ae4c}T, LV \x{11fe}\x{ad89}T, LVT *Test extend and spacing mark \x{1111}\x{ae4c}\x{0711}L, LV, extend \x{1111}\x{ae4c}\x{1b04}L, LV, spacing mark \x{1111}\x{ae4c}\x{1b04}\x{0711}\x{1b04}L, LV, spacing mark, extend, spacing mark *Test CR, LF, and control \x0d\x{0711}CR, extend \x0d\x{1b04}CR, spacingmark \x0a\x{0711}LF, extend \x0a\x{1b04}LF, spacingmark \x0b\x{0711}Control, extend \x09\x{1b04}Control, spacingmark *There are no Prepend characters, so we can't test Prepend, CR /^(?>\X{2})X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X /^\X{2,4}X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X /^\X{2,4}?X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X /-- --/ /\x{1e9e}+/8i \x{1e9e}\x{00df} /[z\x{1e9e}]+/8i \x{1e9e}\x{00df} /\x{00df}+/8i \x{1e9e}\x{00df} /[z\x{00df}]+/8i \x{1e9e}\x{00df} /\x{1f88}+/8i \x{1f88}\x{1f80} /[z\x{1f88}]+/8i \x{1f88}\x{1f80} /-- Perl matches these --/ /\x{00b5}+/8i \x{00b5}\x{039c}\x{03bc} /\x{039c}+/8i \x{00b5}\x{039c}\x{03bc} /\x{03bc}+/8i \x{00b5}\x{039c}\x{03bc} /\x{00c5}+/8i \x{00c5}\x{00e5}\x{212b} /\x{00e5}+/8i \x{00c5}\x{00e5}\x{212b} /\x{212b}+/8i \x{00c5}\x{00e5}\x{212b} /\x{01c4}+/8i \x{01c4}\x{01c5}\x{01c6} /\x{01c5}+/8i \x{01c4}\x{01c5}\x{01c6} /\x{01c6}+/8i \x{01c4}\x{01c5}\x{01c6} /\x{01c7}+/8i \x{01c7}\x{01c8}\x{01c9} /\x{01c8}+/8i \x{01c7}\x{01c8}\x{01c9} /\x{01c9}+/8i \x{01c7}\x{01c8}\x{01c9} /\x{01ca}+/8i \x{01ca}\x{01cb}\x{01cc} /\x{01cb}+/8i \x{01ca}\x{01cb}\x{01cc} /\x{01cc}+/8i \x{01ca}\x{01cb}\x{01cc} /\x{01f1}+/8i \x{01f1}\x{01f2}\x{01f3} /\x{01f2}+/8i \x{01f1}\x{01f2}\x{01f3} /\x{01f3}+/8i \x{01f1}\x{01f2}\x{01f3} /\x{0345}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{0399}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{03b9}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{1fbe}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{0392}+/8i \x{0392}\x{03b2}\x{03d0} /\x{03b2}+/8i \x{0392}\x{03b2}\x{03d0} /\x{03d0}+/8i \x{0392}\x{03b2}\x{03d0} /\x{0395}+/8i \x{0395}\x{03b5}\x{03f5} /\x{03b5}+/8i \x{0395}\x{03b5}\x{03f5} /\x{03f5}+/8i \x{0395}\x{03b5}\x{03f5} /\x{0398}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{03b8}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{03d1}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{03f4}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{039a}+/8i \x{039a}\x{03ba}\x{03f0} /\x{03ba}+/8i \x{039a}\x{03ba}\x{03f0} /\x{03f0}+/8i \x{039a}\x{03ba}\x{03f0} /\x{03a0}+/8i \x{03a0}\x{03c0}\x{03d6} /\x{03c0}+/8i \x{03a0}\x{03c0}\x{03d6} /\x{03d6}+/8i \x{03a0}\x{03c0}\x{03d6} /\x{03a1}+/8i \x{03a1}\x{03c1}\x{03f1} /\x{03c1}+/8i \x{03a1}\x{03c1}\x{03f1} /\x{03f1}+/8i \x{03a1}\x{03c1}\x{03f1} /\x{03a3}+/8i \x{03A3}\x{03C2}\x{03C3} /\x{03c2}+/8i \x{03A3}\x{03C2}\x{03C3} /\x{03c3}+/8i \x{03A3}\x{03C2}\x{03C3} /\x{03a6}+/8i \x{03a6}\x{03c6}\x{03d5} /\x{03c6}+/8i \x{03a6}\x{03c6}\x{03d5} /\x{03d5}+/8i \x{03a6}\x{03c6}\x{03d5} /\x{03c9}+/8i \x{03c9}\x{03a9}\x{2126} /\x{03a9}+/8i \x{03c9}\x{03a9}\x{2126} /\x{2126}+/8i \x{03c9}\x{03a9}\x{2126} /\x{1e60}+/8i \x{1e60}\x{1e61}\x{1e9b} /\x{1e61}+/8i \x{1e60}\x{1e61}\x{1e9b} /\x{1e9b}+/8i \x{1e60}\x{1e61}\x{1e9b} /\x{1e9e}+/8i \x{1e9e}\x{00df} /\x{00df}+/8i \x{1e9e}\x{00df} /\x{1f88}+/8i \x{1f88}\x{1f80} /\x{1f80}+/8i \x{1f88}\x{1f80} /\x{004b}+/8i \x{004b}\x{006b}\x{212a} /\x{006b}+/8i \x{004b}\x{006b}\x{212a} /\x{212a}+/8i \x{004b}\x{006b}\x{212a} /\x{0053}+/8i \x{0053}\x{0073}\x{017f} /\x{0073}+/8i \x{0053}\x{0073}\x{017f} /\x{017f}+/8i \x{0053}\x{0073}\x{017f} /ist/8i ikt /is+t/8i iSs\x{17f}t ikt /is+?t/8i ikt /is?t/8i ikt /is{2}t/8i iskt /^\p{Xuc}/8 $abc @abc `abc \x{1234}abc ** Failers abc /^\p{Xuc}+/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}+?/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}+?\*/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}++/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}{3,5}/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}{3,5}?/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^[\p{Xuc}]/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^[\p{Xuc}]+/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\P{Xuc}/8 abc ** Failers $abc @abc `abc \x{1234}abc /^[\P{Xuc}]/8 abc ** Failers $abc @abc `abc \x{1234}abc /^A\s+Z/8W A\x{2005}Z A\x{85}\x{180e}\x{2005}Z /^A[\s]+Z/8W A\x{2005}Z A\x{85}\x{180e}\x{2005}Z /-- End of testinput10 --/ ================================================ FILE: src/pcre/testdata/testinput11 ================================================ /-- These are a few representative patterns whose lengths and offsets are to be shown when the link size is 2. This is just a doublecheck test to ensure the sizes don't go horribly wrong when something is changed. The pattern contents are all themselves checked in other tests. Unicode, including property support, is required for these tests. --/ /((?i)b)/BM /(?s)(.*X|^B)/BM /(?s:.*X|^B)/BM /^[[:alnum:]]/BM /#/IxMD /a#/IxMD /x?+/BM /x++/BM /x{1,3}+/BM /(x)*+/BM /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/BM |8J\$WE\<\.rX\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM /(a(?1)b)/BM /(a(?1)+b)/BM /a(?Pb|c)d(?Pe)/BM /(?:a(?Pc(?Pd)))(?Pa)/BM /(?Pa)...(?P=a)bbb(?P>a)d/BM /abc(?C255)de(?C)f/BM /abcde/CBM /\x{100}/8BM /\x{1000}/8BM /\x{10000}/8BM /\x{100000}/8BM /\x{10ffff}/8BM /\x{110000}/8BM /[\x{ff}]/8BM /[\x{100}]/8BM /\x80/8BM /\xff/8BM /\x{0041}\x{2262}\x{0391}\x{002e}/D8M /\x{D55c}\x{ad6d}\x{C5B4}/D8M /\x{65e5}\x{672c}\x{8a9e}/D8M /[\x{100}]/8BM /[Z\x{100}]/8BM /^[\x{100}\E-\Q\E\x{150}]/B8M /^[\QĀ\E-\QŐ\E]/B8M /^[\QĀ\E-\QŐ\E/B8M /[\p{L}]/BM /[\p{^L}]/BM /[\P{L}]/BM /[\P{^L}]/BM /[abc\p{L}\x{0660}]/8BM /[\p{Nd}]/8BM /[\p{Nd}+-]+/8BM /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iBM /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8BM /[\x{105}-\x{109}]/8iBM /( ( (?(1)0|) )* )/xBM /( (?(1)0|)* )/xBM /[a]/BM /[a]/8BM /[\xaa]/BM /[\xaa]/8BM /[^a]/BM /[^a]/8BM /[^\xaa]/BM /[^\xaa]/8BM /[^\d]/8WB /[[:^alpha:][:^cntrl:]]+/8WB /[[:^cntrl:][:^alpha:]]+/8WB /[[:alpha:]]+/8WB /[[:^alpha:]\S]+/8WB /abc(d|e)(*THEN)x(123(*THEN)4|567(b|q)(*THEN)xx)/B /(((a\2)|(a*)\g<-1>))*a?/B /((?+1)(\1))/B /.((?2)(?R)\1)()/B /([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/ /-- End of testinput11 --/ ================================================ FILE: src/pcre/testdata/testinput12 ================================================ /-- This test is run only when JIT support is available. It checks for a successful and an unsuccessful JIT compile and save and restore behaviour, and a couple of things that are different with JIT. --/ /abc/S+I /(?(?C1)(?=a)a)/S+I /(?(?C1)(?=a)a)/S!+I /b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*/S+I /abc/S+I>testsavedregex b)c/PN abc /a?|b?/P abc ** Failers ddd\N /\w+A/P CDAAAAB /\w+A/PU CDAAAAB /\Biss\B/I+P Mississippi /abc/\P /-- End of POSIX tests --/ /a\Cb/ aXb a\nb ** Failers (too big char) A\x{123}B A\o{443}B /\x{100}/I /\o{400}/I / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /xSI /-- Although this saved pattern was compiled with link-size=2, it does no harm to run this test with other link sizes because it is going to generated a "compiled in wrong mode" error as soon as it is loaded, so the link size does not matter. --/ \x09< /[\h]+/BZ >\x09\x20\xa0< /[\v]/BZ /[\H]/BZ /[^\h]/BZ /[\V]/BZ /[\x0a\V]/BZ /\777/I /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF)XX/K XX /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE)XX/K XX /\u0100/ /[\u0100-\u0200]/ /[^\x00-a]{12,}[^b-\xff]*/BZ /[^\s]*\s* [^\W]+\W+ [^\d]*?\d0 [^\d\w]{4,6}?\w*A/BZ /(?'ABC'[bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar](*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/ /-- End of testinput14 --/ ================================================ FILE: src/pcre/testdata/testinput15 ================================================ /-- This set of tests is for UTF-8 support but not Unicode property support, and is relevant only to the 8-bit library. --/ < forbid W /X(\C{3})/8 X\x{1234} /X(\C{4})/8 X\x{1234}YZ /X\C*/8 XYZabcdce /X\C*?/8 XYZabcde /X\C{3,5}/8 Xabcdefg X\x{1234} X\x{1234}YZ X\x{1234}\x{512} X\x{1234}\x{512}YZ /X\C{3,5}?/8 Xabcdefg X\x{1234} X\x{1234}YZ X\x{1234}\x{512} /a\Cb/8 aXb a\nb /a\C\Cb/8 a\x{100}b /ab\Cde/8 abXde /a\C\Cb/8 a\x{100}b ** Failers a\x{12257}b /[]/8 //8 /xxx/8 /xxx/8?DZSSO /badutf/8 \xdf \xef \xef\x80 \xf7 \xf7\x80 \xf7\x80\x80 \xfb \xfb\x80 \xfb\x80\x80 \xfb\x80\x80\x80 \xfd \xfd\x80 \xfd\x80\x80 \xfd\x80\x80\x80 \xfd\x80\x80\x80\x80 \xdf\x7f \xef\x7f\x80 \xef\x80\x7f \xf7\x7f\x80\x80 \xf7\x80\x7f\x80 \xf7\x80\x80\x7f \xfb\x7f\x80\x80\x80 \xfb\x80\x7f\x80\x80 \xfb\x80\x80\x7f\x80 \xfb\x80\x80\x80\x7f \xfd\x7f\x80\x80\x80\x80 \xfd\x80\x7f\x80\x80\x80 \xfd\x80\x80\x7f\x80\x80 \xfd\x80\x80\x80\x7f\x80 \xfd\x80\x80\x80\x80\x7f \xed\xa0\x80 \xc0\x8f \xe0\x80\x8f \xf0\x80\x80\x8f \xf8\x80\x80\x80\x8f \xfc\x80\x80\x80\x80\x8f \x80 \xfe \xff /badutf/8 \xfb\x80\x80\x80\x80 \xfd\x80\x80\x80\x80\x80 \xf7\xbf\xbf\xbf /shortutf/8 \P\P\xdf \P\P\xef \P\P\xef\x80 \P\P\xf7 \P\P\xf7\x80 \P\P\xf7\x80\x80 \P\P\xfb \P\P\xfb\x80 \P\P\xfb\x80\x80 \P\P\xfb\x80\x80\x80 \P\P\xfd \P\P\xfd\x80 \P\P\xfd\x80\x80 \P\P\xfd\x80\x80\x80 \P\P\xfd\x80\x80\x80\x80 /anything/8 \xc0\x80 \xc1\x8f \xe0\x9f\x80 \xf0\x8f\x80\x80 \xf8\x87\x80\x80\x80 \xfc\x83\x80\x80\x80\x80 \xfe\x80\x80\x80\x80\x80 \xff\x80\x80\x80\x80\x80 \xc3\x8f \xe0\xaf\x80 \xe1\x80\x80 \xf0\x9f\x80\x80 \xf1\x8f\x80\x80 \xf8\x88\x80\x80\x80 \xf9\x87\x80\x80\x80 \xfc\x84\x80\x80\x80\x80 \xfd\x83\x80\x80\x80\x80 \?\xf8\x88\x80\x80\x80 \?\xf9\x87\x80\x80\x80 \?\xfc\x84\x80\x80\x80\x80 \?\xfd\x83\x80\x80\x80\x80 /\x{100}/8DZ /\x{1000}/8DZ /\x{10000}/8DZ /\x{100000}/8DZ /\x{10ffff}/8DZ /[\x{ff}]/8DZ /[\x{100}]/8DZ /\x80/8DZ /\xff/8DZ /\x{D55c}\x{ad6d}\x{C5B4}/DZ8 \x{D55c}\x{ad6d}\x{C5B4} /\x{65e5}\x{672c}\x{8a9e}/DZ8 \x{65e5}\x{672c}\x{8a9e} /\x{80}/DZ8 /\x{084}/DZ8 /\x{104}/DZ8 /\x{861}/DZ8 /\x{212ab}/DZ8 /-- This one is here not because it's different to Perl, but because the way the captured single-byte is displayed. (In Perl it becomes a character, and you can't tell the difference.) --/ /X(\C)(.*)/8 X\x{1234} X\nabc /-- This one is here because Perl gives out a grumbly error message (quite correctly, but that messes up comparisons). --/ /a\Cb/8 *** Failers a\x{100}b /[^ab\xC0-\xF0]/8SDZ \x{f1} \x{bf} \x{100} \x{1000} *** Failers \x{c0} \x{f0} /Ā{3,4}/8SDZ \x{100}\x{100}\x{100}\x{100\x{100} /(\x{100}+|x)/8SDZ /(\x{100}*a|x)/8SDZ /(\x{100}{0,2}a|x)/8SDZ /(\x{100}{1,2}a|x)/8SDZ /\x{100}/8DZ /a\x{100}\x{101}*/8DZ /a\x{100}\x{101}+/8DZ /[^\x{c4}]/DZ /[\x{100}]/8DZ \x{100} Z\x{100} \x{100}Z *** Failers /[\xff]/DZ8 >\x{ff}< /[^\xff]/8DZ /\x{100}abc(xyz(?1))/8DZ /a\x{1234}b/P8 a\x{1234}b /\777/8I \x{1ff} \777 /\x{100}+\x{200}/8DZ /\x{100}+X/8DZ /^[\QĀ\E-\QŐ\E/BZ8 /-- This tests the stricter UTF-8 check according to RFC 3629. --/ /X/8 \x{d800} \x{d800}\? \x{da00} \x{da00}\? \x{dfff} \x{dfff}\? \x{110000} \x{110000}\? \x{2000000} \x{2000000}\? \x{7fffffff} \x{7fffffff}\? /(*UTF8)\x{1234}/ abcd\x{1234}pqr /(*CRLF)(*UTF)(*BSR_UNICODE)a\Rb/I /\h/SI8 ABC\x{09} ABC\x{20} ABC\x{a0} ABC\x{1680} ABC\x{180e} ABC\x{2000} ABC\x{202f} ABC\x{205f} ABC\x{3000} /\v/SI8 ABC\x{0a} ABC\x{0b} ABC\x{0c} ABC\x{0d} ABC\x{85} ABC\x{2028} /\h*A/SI8 CDBABC /\v+A/SI8 /\s?xxx\s/8SI /\sxxx\s/I8ST1 AB\x{85}xxx\x{a0}XYZ AB\x{a0}xxx\x{85}XYZ /\S \S/I8ST1 \x{a2} \x{84} A Z /a+/8 a\x{123}aa\>1 a\x{123}aa\>2 a\x{123}aa\>3 a\x{123}aa\>4 a\x{123}aa\>5 a\x{123}aa\>6 /\x{1234}+/iS8I /\x{1234}+?/iS8I /\x{1234}++/iS8I /\x{1234}{2}/iS8I /[^\x{c4}]/8DZ /X+\x{200}/8DZ /\R/SI8 /\777/8DZ /\w+\x{C4}/8BZ a\x{C4}\x{C4} /\w+\x{C4}/8BZT1 a\x{C4}\x{C4} /\W+\x{C4}/8BZ !\x{C4} /\W+\x{C4}/8BZT1 !\x{C4} /\W+\x{A1}/8BZ !\x{A1} /\W+\x{A1}/8BZT1 !\x{A1} /X\s+\x{A0}/8BZ X\x20\x{A0}\x{A0} /X\s+\x{A0}/8BZT1 X\x20\x{A0}\x{A0} /\S+\x{A0}/8BZ X\x{A0}\x{A0} /\S+\x{A0}/8BZT1 X\x{A0}\x{A0} /\x{a0}+\s!/8BZ \x{a0}\x20! /\x{a0}+\s!/8BZT1 \x{a0}\x20! /A/8 \x{ff000041} \x{7f000041} /(*UTF8)abc/9 /abc/89 //8+L \xf1\xad\xae\xae /-- End of testinput15 --/ ================================================ FILE: src/pcre/testdata/testinput16 ================================================ /-- This set of tests is run only with the 8-bit library when Unicode property support is available. It starts with tests of the POSIX interface, because that is supported only with the 8-bit library. --/ /\w/P +++\x{c2} /\w/WP +++\x{c2} /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iDZ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8DZ /AB\x{1fb0}/8DZ /AB\x{1fb0}/8DZi /\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/8iSI \x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f} \x{451}\x{440}\x{441}\x{442}\x{443}\x{444}\x{445}\x{446}\x{447}\x{448}\x{449}\x{44a}\x{44b}\x{44c}\x{44d}\x{44e}\x{44f} /[ⱥ]/8iBZ /[^ⱥ]/8iBZ /\h/SI /\v/SI /\R/SI /[[:blank:]]/WBZ /\x{212a}+/i8SI KKkk\x{212a} /s+/i8SI SSss\x{17f} /[\W\p{Any}]/BZ abc 123 /[\W\pL]/BZ abc ** Failers 123 /[\D]/8 \x{1d7cf} /[\D\P{Nd}]/8 \x{1d7cf} /[^\D]/8 a9b ** Failers \x{1d7cf} /[^\D\P{Nd}]/8 a9b \x{1d7cf} ** Failers \x{10000} /-- End of testinput16 --/ ================================================ FILE: src/pcre/testdata/testinput17 ================================================ /-- This set of tests is for the 16- and 32-bit library's basic (non-UTF-16 or -32) features that are not compatible with the 8-bit library, or which give different output in 16- or 32-bit mode. --/ < forbid 8W /a\Cb/ aXb a\nb /[^\x{c4}]/DZ /\x{100}/I / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /xSI /[\h]/BZ >\x09< /[\h]+/BZ >\x09\x20\xa0< /[\v]/BZ /[^\h]/BZ /\h+/SI \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\xa0\x{2000} /[\h\x{dc00}]+/BZSI \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\xa0\x{2000} /\H+/SI \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} \xa0\x{3000}\x9f\xa1\x{2fff}\x{3001} /[\H\x{d800}]+/ \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} \xa0\x{3000}\x9f\xa1\x{2fff}\x{3001} /\v+/SI \x{2027}\x{2030}\x{2028}\x{2029} \x09\x0e\x84\x86\x85\x0a\x0b\x0c\x0d /[\v\x{dc00}]+/BZSI \x{2027}\x{2030}\x{2028}\x{2029} \x09\x0e\x84\x86\x85\x0a\x0b\x0c\x0d /\V+/SI \x{2028}\x{2029}\x{2027}\x{2030} \x85\x0a\x0b\x0c\x0d\x09\x0e\x84\x86 /[\V\x{d800}]+/ \x{2028}\x{2029}\x{2027}\x{2030} \x85\x0a\x0b\x0c\x0d\x09\x0e\x84\x86 /\R+/SI \x{2027}\x{2030}\x{2028}\x{2029} \x09\x0e\x84\x86\x85\x0a\x0b\x0c\x0d /\x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00}/I \x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00} /[^\x{80}][^\x{ff}][^\x{100}][^\x{1000}][^\x{ffff}]/BZ /[^\x{80}][^\x{ff}][^\x{100}][^\x{1000}][^\x{ffff}]/BZi /[^\x{100}]*[^\x{1000}]+[^\x{ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{100}]{5,6}+/BZ /[^\x{100}]*[^\x{1000}]+[^\x{ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{100}]{5,6}+/BZi /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF)XX/K XX /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE)XX/K XX /\u0100/BZ /[\u0100-\u0200]/BZ /\ud800/BZ /^\x{ffff}+/i \x{ffff} /^\x{ffff}?/i \x{ffff} /^\x{ffff}*/i \x{ffff} /^\x{ffff}{3}/i \x{ffff}\x{ffff}\x{ffff} /^\x{ffff}{0,3}/i \x{ffff} /[^\x00-a]{12,}[^b-\xff]*/BZ /[^\s]*\s* [^\W]+\W+ [^\d]*?\d0 [^\d\w]{4,6}?\w*A/BZ /a*[b-\x{200}]?a#a*[b-\x{200}]?b#[a-f]*[g-\x{200}]*#[g-\x{200}]*[a-c]*#[g-\x{200}]*[a-h]*/BZ /^[\x{1234}\x{4321}]{2,4}?/ \x{1234}\x{1234}\x{1234} /(*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)/ /-- End of testinput17 --/ ================================================ FILE: src/pcre/testdata/testinput18 ================================================ /-- This set of tests is for UTF-16 and UTF-32 support, and is relevant only to the 16- and 32-bit libraries. --/ < forbid W /xxx/8?DZSS /abc/8 ] /X(\C{3})/8 X\x{11234}Y X\x{11234}YZ /X(\C{4})/8 X\x{11234}YZ X\x{11234}YZW /X\C*/8 XYZabcdce /X\C*?/8 XYZabcde /X\C{3,5}/8 Xabcdefg X\x{11234}Y X\x{11234}YZ X\x{11234}\x{512} X\x{11234}\x{512}YZ X\x{11234}\x{512}\x{11234}Z /X\C{3,5}?/8 Xabcdefg X\x{11234}Y X\x{11234}YZ X\x{11234}\x{512}YZ *** Failers X\x{11234} /a\Cb/8 aXb a\nb /a\C\Cb/8 a\x{12257}b a\x{12257}\x{11234}b ** Failers a\x{100}b /ab\Cde/8 abXde /-- Check maximum character size --/ /\x{ffff}/8DZ /\x{10000}/8DZ /\x{100}/8DZ /\x{1000}/8DZ /\x{10000}/8DZ /\x{100000}/8DZ /\x{10ffff}/8DZ /[\x{ff}]/8DZ /[\x{100}]/8DZ /\x80/8DZ /\xff/8DZ /\x{D55c}\x{ad6d}\x{C5B4}/DZ8 \x{D55c}\x{ad6d}\x{C5B4} /\x{65e5}\x{672c}\x{8a9e}/DZ8 \x{65e5}\x{672c}\x{8a9e} /\x{80}/DZ8 /\x{084}/DZ8 /\x{104}/DZ8 /\x{861}/DZ8 /\x{212ab}/DZ8 /-- This one is here not because it's different to Perl, but because the way the captured single-byte is displayed. (In Perl it becomes a character, and you can't tell the difference.) --/ /X(\C)(.*)/8 X\x{1234} X\nabc /-- This one is here because Perl gives out a grumbly error message (quite correctly, but that messes up comparisons). --/ /a\Cb/8 *** Failers a\x{100}b /[^ab\xC0-\xF0]/8SDZ \x{f1} \x{bf} \x{100} \x{1000} *** Failers \x{c0} \x{f0} /Ā{3,4}/8SDZ \x{100}\x{100}\x{100}\x{100\x{100} /(\x{100}+|x)/8SDZ /(\x{100}*a|x)/8SDZ /(\x{100}{0,2}a|x)/8SDZ /(\x{100}{1,2}a|x)/8SDZ /\x{100}/8DZ /a\x{100}\x{101}*/8DZ /a\x{100}\x{101}+/8DZ /[^\x{c4}]/DZ /[\x{100}]/8DZ \x{100} Z\x{100} \x{100}Z *** Failers /[\xff]/DZ8 >\x{ff}< /[^\xff]/8DZ /\x{100}abc(xyz(?1))/8DZ /\777/8I \x{1ff} \777 /\x{100}+\x{200}/8DZ /\x{100}+X/8DZ /^[\QĀ\E-\QŐ\E/BZ8 /X/8 \x{d800} \x{d800}\? \x{da00} \x{da00}\? \x{dc00} \x{dc00}\? \x{de00} \x{de00}\? \x{dfff} \x{dfff}\? \x{110000} \x{d800}\x{1234} /(*UTF16)\x{11234}/ abcd\x{11234}pqr /(*UTF)\x{11234}/I abcd\x{11234}pqr /(*UTF-32)\x{11234}/ abcd\x{11234}pqr /(*CRLF)(*UTF16)(*BSR_UNICODE)a\Rb/I /(*CRLF)(*UTF32)(*BSR_UNICODE)a\Rb/I /\h/SI8 ABC\x{09} ABC\x{20} ABC\x{a0} ABC\x{1680} ABC\x{180e} ABC\x{2000} ABC\x{202f} ABC\x{205f} ABC\x{3000} /\v/SI8 ABC\x{0a} ABC\x{0b} ABC\x{0c} ABC\x{0d} ABC\x{85} ABC\x{2028} /\h*A/SI8 CDBABC \x{2000}ABC /\R*A/SI8 CDBABC \x{2028}A /\v+A/SI8 /\s?xxx\s/8SI /\sxxx\s/I8ST1 AB\x{85}xxx\x{a0}XYZ AB\x{a0}xxx\x{85}XYZ /\S \S/I8ST1 \x{a2} \x{84} A Z /a+/8 a\x{123}aa\>1 a\x{123}aa\>2 a\x{123}aa\>3 a\x{123}aa\>4 a\x{123}aa\>5 a\x{123}aa\>6 /\x{1234}+/iS8I /\x{1234}+?/iS8I /\x{1234}++/iS8I /\x{1234}{2}/iS8I /[^\x{c4}]/8DZ /X+\x{200}/8DZ /\R/SI8 /-- Check bad offset --/ /a/8 \x{10000}\>1 \x{10000}ab\>1 \x{10000}ab\>2 \x{10000}ab\>3 \x{10000}ab\>4 \x{10000}ab\>5 //8 /\w+\x{C4}/8BZ a\x{C4}\x{C4} /\w+\x{C4}/8BZT1 a\x{C4}\x{C4} /\W+\x{C4}/8BZ !\x{C4} /\W+\x{C4}/8BZT1 !\x{C4} /\W+\x{A1}/8BZ !\x{A1} /\W+\x{A1}/8BZT1 !\x{A1} /X\s+\x{A0}/8BZ X\x20\x{A0}\x{A0} /X\s+\x{A0}/8BZT1 X\x20\x{A0}\x{A0} /\S+\x{A0}/8BZ X\x{A0}\x{A0} /\S+\x{A0}/8BZT1 X\x{A0}\x{A0} /\x{a0}+\s!/8BZ \x{a0}\x20! /\x{a0}+\s!/8BZT1 \x{a0}\x20! /(*UTF)abc/9 /abc/89 /-- End of testinput18 --/ ================================================ FILE: src/pcre/testdata/testinput19 ================================================ /-- This set of tests is for Unicode property support, relevant only to the 16- and 32-bit library. --/ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iDZ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8DZ /AB\x{1fb0}/8DZ /AB\x{1fb0}/8DZi /\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/8iSI \x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f} \x{451}\x{440}\x{441}\x{442}\x{443}\x{444}\x{445}\x{446}\x{447}\x{448}\x{449}\x{44a}\x{44b}\x{44c}\x{44d}\x{44e}\x{44f} /[ⱥ]/8iBZ /[^ⱥ]/8iBZ /[[:blank:]]/WBZ /\x{212a}+/i8SI KKkk\x{212a} /s+/i8SI SSss\x{17f} /[\D]/8 \x{1d7cf} /[\D\P{Nd}]/8 \x{1d7cf} /[^\D]/8 a9b ** Failers \x{1d7cf} /[^\D\P{Nd}]/8 a9b \x{1d7cf} ** Failers \x{10000} /-- End of testinput19 --/ ================================================ FILE: src/pcre/testdata/testinput2 ================================================ /-- This set of tests is not Perl-compatible. It checks on special features of PCRE's API, error diagnostics, and the compiled code of some patterns. It also checks the non-Perl syntax the PCRE supports (Python, .NET, Oniguruma). Finally, there are some tests where PCRE and Perl differ, either because PCRE can't be compatible, or there is a possible Perl bug. NOTE: This is a non-UTF set of tests. When UTF support is needed, use test 5, and if Unicode Property Support is needed, use test 7. --/ < forbid 8W /(a)b|/I /abc/I abc defabc \Aabc *** Failers \Adefabc ABC /^abc/I abc \Aabc *** Failers defabc \Adefabc /a+bc/I /a*bc/I /a{3}bc/I /(abc|a+z)/I /^abc$/I abc *** Failers def\nabc /ab\idef/X /(?X)ab\idef/X /x{5,4}/ /z{65536}/ /[abcd/ /(?X)[\B]/ /(?X)[\R]/ /(?X)[\X]/ /[\B]/BZ /[\R]/BZ /[\X]/BZ /[z-a]/ /^*/ /(abc/ /(?# abc/ /(?z)abc/ /.*b/I /.*?b/I /cat|dog|elephant/I this sentence eventually mentions a cat this sentences rambles on and on for a while and then reaches elephant /cat|dog|elephant/IS this sentence eventually mentions a cat this sentences rambles on and on for a while and then reaches elephant /cat|dog|elephant/IiS this sentence eventually mentions a CAT cat this sentences rambles on and on for a while to elephant ElePhant /a|[bcd]/IS /(a|[^\dZ])/IS /(a|b)*[\s]/IS /(ab\2)/ /{4,5}abc/ /(a)(b)(c)\2/I abcb \O0abcb \O3abcb \O6abcb \O9abcb \O12abcb /(a)bc|(a)(b)\2/I abc \O0abc \O3abc \O6abc aba \O0aba \O3aba \O6aba \O9aba \O12aba /abc$/IE abc *** Failers abc\n abc\ndef /(a)(b)(c)(d)(e)\6/ /the quick brown fox/I the quick brown fox this is a line with the quick brown fox /the quick brown fox/IA the quick brown fox *** Failers this is a line with the quick brown fox /ab(?z)cd/ /^abc|def/I abcdef abcdef\B /.*((abc)$|(def))/I defabc \Zdefabc /)/ /a[]b/ /[^aeiou ]{3,}/I co-processors, and for /<.*>/I abcghinop /<.*?>/I abcghinop /<.*>/IU abcghinop /(?U)<.*>/I abcghinop /<.*?>/IU abcghinop /={3,}/IU abc========def /(?U)={3,}?/I abc========def /(?^abc)/Im abc def\nabc *** Failers defabc /(?<=ab(c+)d)ef/ /(?<=ab(?<=c+)d)ef/ /(?<=ab(c|de)f)g/ /The next three are in testinput2 because they have variable length branches/ /(?<=bullock|donkey)-cart/I the bullock-cart a donkey-cart race *** Failers cart horse-and-cart /(?<=ab(?i)x|y|z)/I /(?>.*)(?<=(abcd)|(xyz))/I alphabetabcd endingxyz /(?<=ab(?i)x(?-i)y|(?i)z|b)ZZ/I abxyZZ abXyZZ ZZZ zZZ bZZ BZZ *** Failers ZZ abXYZZ zzz bzz /(?[^()]+) # Either a sequence of non-brackets (no backtracking) | # Or (?R) # Recurse - i.e. nested bracketed string )* # Zero or more contents \) # Closing ) /Ix (abcd) (abcd)xyz xyz(abcd) (ab(xy)cd)pqr (ab(xycd)pqr () abc () 12(abcde(fsh)xyz(foo(bar))lmno)89 *** Failers abcd abcd) (abcd /\( ( (?>[^()]+) | (?R) )* \) /Ixg (ab(xy)cd)pqr 1(abcd)(x(y)z)pqr /\( (?: (?>[^()]+) | (?R) ) \) /Ix (abcd) (ab(xy)cd) (a(b(c)d)e) ((ab)) *** Failers () /\( (?: (?>[^()]+) | (?R) )? \) /Ix () 12(abcde(fsh)xyz(foo(bar))lmno)89 /\( ( (?>[^()]+) | (?R) )* \) /Ix (ab(xy)cd) /\( ( ( (?>[^()]+) | (?R) )* ) \) /Ix (ab(xy)cd) /\( (123)? ( ( (?>[^()]+) | (?R) )* ) \) /Ix (ab(xy)cd) (123ab(xy)cd) /\( ( (123)? ( (?>[^()]+) | (?R) )* ) \) /Ix (ab(xy)cd) (123ab(xy)cd) /\( (((((((((( ( (?>[^()]+) | (?R) )* )))))))))) \) /Ix (ab(xy)cd) /\( ( ( (?>[^()<>]+) | ((?>[^()]+)) | (?R) )* ) \) /Ix (abcd(xyz

    qrs)123) /\( ( ( (?>[^()]+) | ((?R)) )* ) \) /Ix (ab(cd)ef) (ab(cd(ef)gh)ij) /^[[:alnum:]]/DZ /^[[:^alnum:]]/DZ /^[[:alpha:]]/DZ /^[[:^alpha:]]/DZ /[_[:alpha:]]/IS /^[[:ascii:]]/DZ /^[[:^ascii:]]/DZ /^[[:blank:]]/DZ /^[[:^blank:]]/DZ /[\n\x0b\x0c\x0d[:blank:]]/IS /^[[:cntrl:]]/DZ /^[[:digit:]]/DZ /^[[:graph:]]/DZ /^[[:lower:]]/DZ /^[[:print:]]/DZ /^[[:punct:]]/DZ /^[[:space:]]/DZ /^[[:upper:]]/DZ /^[[:xdigit:]]/DZ /^[[:word:]]/DZ /^[[:^cntrl:]]/DZ /^[12[:^digit:]]/DZ /^[[:^blank:]]/DZ /[01[:alpha:]%]/DZ /[[.ch.]]/I /[[=ch=]]/I /[[:rhubarb:]]/I /[[:upper:]]/Ii A a /[[:lower:]]/Ii A a /((?-i)[[:lower:]])[[:lower:]]/Ii ab aB *** Failers Ab AB /[\200-\110]/I /^(?(0)f|b)oo/I /This one's here because of the large output vector needed/I /(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\w+)\s+(\270)/I \O900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC /This one's here because Perl does this differently and PCRE can't at present/I /(main(O)?)+/I mainmain mainOmain /These are all cases where Perl does it differently (nested captures)/I /^(a(b)?)+$/I aba /^(aa(bb)?)+$/I aabbaa /^(aa|aa(bb))+$/I aabbaa /^(aa(bb)??)+$/I aabbaa /^(?:aa(bb)?)+$/I aabbaa /^(aa(b(b))?)+$/I aabbaa /^(?:aa(b(b))?)+$/I aabbaa /^(?:aa(b(?:b))?)+$/I aabbaa /^(?:aa(bb(?:b))?)+$/I aabbbaa /^(?:aa(b(?:bb))?)+$/I aabbbaa /^(?:aa(?:b(b))?)+$/I aabbaa /^(?:aa(?:b(bb))?)+$/I aabbbaa /^(aa(b(bb))?)+$/I aabbbaa /^(aa(bb(bb))?)+$/I aabbbbaa /--------------------------------------------------------------------/I /#/IxDZ /a#/IxDZ /[\s]/DZ /[\S]/DZ /a(?i)b/DZ ab aB *** Failers AB /(a(?i)b)/DZ ab aB *** Failers AB / (?i)abc/IxDZ /#this is a comment (?i)abc/IxDZ /123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/DZ /\Q123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/DZ /\Q\E/DZ \ /\Q\Ex/DZ / \Q\E/DZ /a\Q\E/DZ abc bca bac /a\Q\Eb/DZ abc /\Q\Eabc/DZ /x*+\w/DZ *** Failers xxxxx /x?+/DZ /x++/DZ /x{1,3}+/BZO /x{1,3}+/BZOi /[^x]{1,3}+/BZO /[^x]{1,3}+/BZOi /(x)*+/DZ /^(\w++|\s++)*$/I now is the time for all good men to come to the aid of the party *** Failers this is not a line with only words and spaces! /(\d++)(\w)/I 12345a *** Failers 12345+ /a++b/I aaab /(a++b)/I aaab /(a++)b/I aaab /([^()]++|\([^()]*\))+/I ((abc(ade)ufh()()x /\(([^()]++|\([^()]+\))+\)/I (abc) (abc(def)xyz) *** Failers ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /(abc){1,3}+/DZ /a+?+/I /a{2,3}?+b/I /(?U)a+?+/I /a{2,3}?+b/IU /x(?U)a++b/DZ xaaaab /(?U)xa++b/DZ xaaaab /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/DZ /^x(?U)a+b/DZ /^x(?U)(a+)b/DZ /[.x.]/I /[=x=]/I /[:x:]/I /\l/I /\L/I /\N{name}/I /\u/I /\U/I /a{1,3}b/U ab /[/I /[a-/I /[[:space:]/I /[\s]/IDZ /[[:space:]]/IDZ /[[:space:]abcde]/IDZ /< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/Ix <> hij> hij> def> *** Failers iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|IDZ |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|IDZ /(.*)\d+\1/I /(.*)\d+/I /(.*)\d+\1/Is /(.*)\d+/Is /(.*(xyz))\d+\2/I /((.*))\d+\1/I abc123bc /a[b]/I /(?=a).*/I /(?=abc).xyz/IiI /(?=abc)(?i).xyz/I /(?=a)(?=b)/I /(?=.)a/I /((?=abcda)a)/I /((?=abcda)ab)/I /()a/I /(?(1)ab|ac)(.)/I /(?(1)abz|acz)(.)/I /(?(1)abz)(.)/I /(?(1)abz)(1)23/I /(a)+/I /(a){2,3}/I /(a)*/I /[a]/I /[ab]/I /[ab]/IS /[^a]/I /\d456/I /\d456/IS /a^b/I /^a/Im abcde xy\nabc *** Failers xyabc /c|abc/I /(?i)[ab]/IS /[ab](?i)cd/IS /abc(?C)def/I abcdef 1234abcdef *** Failers abcxyz abcxyzf /abc(?C)de(?C1)f/I 123abcdef /(?C1)\dabc(?C2)def/IS 1234abcdef *** Failers abcdef /(?C1)\dabc(?C2)def/ISS 1234abcdef *** Failers abcdef /(?C255)ab/I /(?C256)ab/I /(?Cab)xx/I /(?C12vr)x/I /abc(?C)def/I *** Failers \x83\x0\x61bcdef /(abc)(?C)de(?C1)f/I 123abcdef 123abcdef\C+ 123abcdef\C- *** Failers 123abcdef\C!1 /(?C0)(abc(?C1))*/I abcabcabc abcabc\C!1!3 *** Failers abcabcabc\C!1!3 /(\d{3}(?C))*/I 123\C+ 123456\C+ 123456789\C+ /((xyz)(?C)p|(?C1)xyzabc)/I xyzabc\C+ /(X)((xyz)(?C)p|(?C1)xyzabc)/I Xxyzabc\C+ /(?=(abc))(?C)abcdef/I abcdef\C+ /(?!(abc)(?C1)d)(?C2)abcxyz/I abcxyz\C+ /(?<=(abc)(?C))xyz/I abcxyz\C+ /a(b+)(c*)(?C1)/I abbbbbccc\C*1 /a(b+?)(c*?)(?C1)/I abbbbbccc\C*1 /(?C)abc/I /(?C)^abc/I /(?C)a|b/IS /(?R)/I /(a|(?R))/I /(ab|(bc|(de|(?R))))/I /x(ab|(bc|(de|(?R))))/I xab xbc xde xxab xxxab *** Failers xyab /(ab|(bc|(de|(?1))))/I /x(ab|(bc|(de|(?1)x)x)x)/I /^([^()]|\((?1)*\))*$/I abc a(b)c a(b(c))d *** Failers) a(b(c)d /^>abc>([^()]|\((?1)*\))*abc>123abc>1(2)3abc>(1(2)3)]*+) | (?2)) * >))/Ix <> hij> hij> def> *** Failers b|c)d(?Pe)/DZ abde acde /(?:a(?Pc(?Pd)))(?Pa)/DZ /(?Pa)...(?P=a)bbb(?P>a)d/DZ /^\W*(?:(?P(?P.)\W*(?P>one)\W*(?P=two)|)|(?P(?P.)\W*(?P>three)\W*(?P=four)|\W*.\W*))\W*$/Ii 1221 Satan, oscillate my metallic sonatas! A man, a plan, a canal: Panama! Able was I ere I saw Elba. *** Failers The quick brown fox /((?(R)a|b))\1(?1)?/I bb bbaa /(.*)a/Is /(.*)a\1/Is /(.*)a(b)\2/Is /((.*)a|(.*)b)z/Is /((.*)a|(.*)b)z\1/Is /((.*)a|(.*)b)z\2/Is /((.*)a|(.*)b)z\3/Is /((.*)a|^(.*)b)z\3/Is /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a/Is /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\31/Is /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\32/Is /(a)(bc)/INDZ abc /(?Pa)(bc)/INDZ abc /(a)(?Pbc)/INDZ /(a+)*zz/I aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazzbbbbbb\M aaaaaaaaaaaaaz\M /(aaa(?C1)bbb|ab)/I aaabbb aaabbb\C*0 aaabbb\C*1 aaabbb\C*-1 /ab(?Pcd)ef(?Pgh)/I abcdefgh abcdefgh\C1\Gtwo abcdefgh\Cone\Ctwo abcdefgh\Cthree /(?P)(?P)/DZ /(?P)(?P)/DZ /(?Pzz)(?Paa)/I zzaa\CZ zzaa\CA /(?Peks)(?Peccs)/I /(?Pabc(?Pdef)(?Pxyz))/I "\[((?P\d+)(,(?P>elem))*)\]"I [10,20,30,5,5,4,4,2,43,23,4234] *** Failers [] "\[((?P\d+)(,(?P>elem))*)?\]"I [10,20,30,5,5,4,4,2,43,23,4234] [] /(a(b(?2)c))?/DZ /(a(b(?2)c))*/DZ /(a(b(?2)c)){0,2}/DZ /[ab]{1}+/DZ /((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/Ii Baby Bjorn Active Carrier - With free SHIPPING!! /((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/IiS Baby Bjorn Active Carrier - With free SHIPPING!! /a*.*b/ISDZ /(a|b)*.?c/ISDZ /abc(?C255)de(?C)f/DZ /abcde/ICDZ abcde abcdfe /a*b/ICDZS ab aaaab aaaacb /a*b/ICDZSS ab aaaab aaaacb /a+b/ICDZ ab aaaab aaaacb /(abc|def)x/ICDZS abcx defx ** Failers abcdefzx /(abc|def)x/ICDZSS abcx defx ** Failers abcdefzx /(ab|cd){3,4}/IC ababab abcdabcd abcdcdcdcdcd /([ab]{,4}c|xy)/ICDZS Note: that { does NOT introduce a quantifier /([ab]{,4}c|xy)/ICDZSS Note: that { does NOT introduce a quantifier /([ab]{1,4}c|xy){4,5}?123/ICDZ aacaacaacaacaac123 /\b.*/I ab cd\>1 /\b.*/Is ab cd\>1 /(?!.bcd).*/I Xbcd12345 /abcde/I ab\P abc\P abcd\P abcde\P the quick brown abc\P ** Failers\P the quick brown abxyz fox\P "^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/(20)?\d\d$"I 13/05/04\P 13/5/2004\P 02/05/09\P 1\P 1/2\P 1/2/0\P 1/2/04\P 0\P 02/\P 02/0\P 02/1\P ** Failers\P \P 123\P 33/4/04\P 3/13/04\P 0/1/2003\P 0/\P 02/0/\P 02/13\P /0{0,2}ABC/I /\d{3,}ABC/I /\d*ABC/I /[abc]+DE/I /[abc]?123/I 123\P a\P b\P c\P c12\P c123\P /^(?:\d){3,5}X/I 1\P 123\P 123X 1234\P 1234X 12345\P 12345X *** Failers 1X 123456\P //KF>testsavedregex /abc/IS>testsavedregex testsavedregex testsavedregex testsavedregex testsavedregex testsavedregex testsavedregex testsavedregex (.)*~smgI \J1024\n\n\nPartner der LCO\nde\nPartner der LINEAS Consulting\nGmbH\nLINEAS Consulting GmbH Hamburg\nPartnerfirmen\n30 days\nindex,follow\n\nja\n3\nPartner\n\n\nLCO\nLINEAS Consulting\n15.10.2003\n\n\n\n\nDie Partnerfirmen der LINEAS Consulting\nGmbH\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n /^a/IF /line\nbreak/I this is a line\nbreak line one\nthis is a line\nbreak in the second line /line\nbreak/If this is a line\nbreak ** Failers line one\nthis is a line\nbreak in the second line /line\nbreak/Imf this is a line\nbreak ** Failers line one\nthis is a line\nbreak in the second line /(?i)(?-i)AbCd/I AbCd ** Failers abcd /a{11111111111111111111}/I /(){64294967295}/I /(){2,4294967295}/I "(?i:a)(?i:b)(?i:c)(?i:d)(?i:e)(?i:f)(?i:g)(?i:h)(?i:i)(?i:j)(k)(?i:l)A\1B"I abcdefghijklAkB "(?Pa)(?Pb)(?Pc)(?Pd)(?Pe)(?Pf)(?Pg)(?Ph)(?Pi)(?Pj)(?Pk)(?Pl)A\11B"I abcdefghijklAkB "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)A\11B"I abcdefghijklAkB "(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)"I aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)"I aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /[^()]*(?:\((?R)\)[^()]*)*/I (this(and)that (this(and)that) (this(and)that)stuff /[^()]*(?:\((?>(?R))\)[^()]*)*/I (this(and)that (this(and)that) /[^()]*(?:\((?R)\))*[^()]*/I (this(and)that (this(and)that) /(?:\((?R)\))*[^()]*/I (this(and)that (this(and)that) ((this)) /(?:\((?R)\))|[^()]*/I (this(and)that (this(and)that) (this) ((this)) /\x{0000ff}/I /^((?Pa1)|(?Pa2)b)/I /^((?Pa1)|(?Pa2)b)/IJ a1b\CA a2b\CA ** Failers a1b\CZ\CA /(?|(?)(?)(?)|(?)(?)(?))/IJ /^(?Pa)(?Pb)/IJ ab\CA /^(?Pa)(?Pb)|cd/IJ ab\CA cd\CA /^(?Pa)(?Pb)|cd(?Pef)(?Pgh)/IJ cdefgh\CA /^((?Pa1)|(?Pa2)b)/IJ a1b\GA a2b\GA ** Failers a1b\GZ\GA /^(?Pa)(?Pb)/IJ ab\GA /^(?Pa)(?Pb)|cd/IJ ab\GA cd\GA /^(?Pa)(?Pb)|cd(?Pef)(?Pgh)/IJ cdefgh\GA /(?J)^((?Pa1)|(?Pa2)b)/I a1b\CA a2b\CA /^(?Pa) (?J:(?Pb)(?Pc)) (?Pd)/I / In this next test, J is not set at the outer level; consequently it isn't set in the pattern's options; consequently pcre_get_named_substring() produces a random value. /Ix /^(?Pa) (?J:(?Pb)(?Pc)) (?Pd)/I a bc d\CA\CB\CC /^(?Pa)?(?(A)a|b)/I aabc bc ** Failers abc /(?:(?(ZZ)a|b)(?PX))+/I bXaX /(?:(?(2y)a|b)(X))+/I /(?:(?(ZA)a|b)(?PX))+/I /(?:(?(ZZ)a|b)(?(ZZ)a|b)(?PX))+/I bbXaaX /(?:(?(ZZ)a|\(b\))\\(?PX))+/I (b)\\Xa\\X /(?PX|Y))+/I bXXaYYaY bXYaXXaX /()()()()()()()()()(?:(?(A)(?P=A)a|b)(?PX|Y))+/I bXXaYYaY /\s*,\s*/IS \x0b,\x0b \x0c,\x0d /^abc/Im xyz\nabc xyz\nabc\ xyz\r\nabc\ xyz\rabc\ xyz\r\nabc\ ** Failers xyz\nabc\ xyz\r\nabc\ xyz\nabc\ xyz\rabc\ xyz\rabc\ /abc$/Im xyzabc xyzabc\n xyzabc\npqr xyzabc\r\ xyzabc\rpqr\ xyzabc\r\n\ xyzabc\r\npqr\ ** Failers xyzabc\r xyzabc\rpqr xyzabc\r\n xyzabc\r\npqr /^abc/Im xyz\rabcdef xyz\nabcdef\ ** Failers xyz\nabcdef /^abc/Im xyz\nabcdef xyz\rabcdef\ ** Failers xyz\rabcdef /^abc/Im xyz\r\nabcdef xyz\rabcdef\ ** Failers xyz\rabcdef /^abc/Im /abc/I xyz\rabc\ abc /.*/I abc\ndef abc\rdef abc\r\ndef \abc\ndef \abc\rdef \abc\r\ndef \abc\ndef \abc\rdef \abc\r\ndef /\w+(.)(.)?def/Is abc\ndef abc\rdef abc\r\ndef +((?:\s|//.*\\n|/[*](?:\\n|.)*?[*]/)*)+I /* this is a C style comment */\M /(?P25[0-5]|2[0-4]\d|[01]?\d?\d)(?:\.(?P>B)){3}/I /()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() (.(.))/Ix XY\O400 /(a*b|(?i:c*(?-i)d))/IS /()[ab]xyz/IS /(|)[ab]xyz/IS /(|c)[ab]xyz/IS /(|c?)[ab]xyz/IS /(d?|c?)[ab]xyz/IS /(d?|c)[ab]xyz/IS /^a*b\d/DZ /^a*+b\d/DZ /^a*?b\d/DZ /^a+A\d/DZ aaaA5 ** Failers aaaa5 /^a*A\d/IiDZ aaaA5 aaaa5 /(a*|b*)[cd]/IS /(a+|b*)[cd]/IS /(a*|b+)[cd]/IS /(a+|b+)[cd]/IS /(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((( a )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ))) /Ix large nest /a*\d/BZ /a*\D/BZ /0*\d/BZ /0*\D/BZ /a*\s/BZ /a*\S/BZ / *\s/BZ / *\S/BZ /a*\w/BZ /a*\W/BZ /=*\w/BZ /=*\W/BZ /\d*a/BZ /\d*2/BZ /\d*\d/BZ /\d*\D/BZ /\d*\s/BZ /\d*\S/BZ /\d*\w/BZ /\d*\W/BZ /\D*a/BZ /\D*2/BZ /\D*\d/BZ /\D*\D/BZ /\D*\s/BZ /\D*\S/BZ /\D*\w/BZ /\D*\W/BZ /\s*a/BZ /\s*2/BZ /\s*\d/BZ /\s*\D/BZ /\s*\s/BZ /\s*\S/BZ /\s*\w/BZ /\s*\W/BZ /\S*a/BZ /\S*2/BZ /\S*\d/BZ /\S*\D/BZ /\S*\s/BZ /\S*\S/BZ /\S*\w/BZ /\S*\W/BZ /\w*a/BZ /\w*2/BZ /\w*\d/BZ /\w*\D/BZ /\w*\s/BZ /\w*\S/BZ /\w*\w/BZ /\w*\W/BZ /\W*a/BZ /\W*2/BZ /\W*\d/BZ /\W*\D/BZ /\W*\s/BZ /\W*\S/BZ /\W*\w/BZ /\W*\W/BZ /[^a]+a/BZ /[^a]+a/BZi /[^a]+A/BZi /[^a]+b/BZ /[^a]+\d/BZ /a*[^a]/BZ /(?Px)(?Py)/I xy\Cabc\Cxyz /(?x)(?'xyz'y)/I xy\Cabc\Cxyz /(?x)(?'xyz>y)/I /(?P'abc'x)(?Py)/I /^(?:(?(ZZ)a|b)(?X))+/ bXaX bXbX ** Failers aXaX aXbX /^(?P>abc)(?xxx)/ /^(?P>abc)(?x|y)/ xx xy yy yx /^(?P>abc)(?Px|y)/ xx xy yy yx /^((?(abc)a|b)(?x|y))+/ bxay bxby ** Failers axby /^(((?P=abc)|X)(?x|y))+/ XxXxxx XxXyyx XxXyxx ** Failers x /^(?1)(abc)/ abcabc /^(?:(?:\1|X)(a|b))+/ Xaaa Xaba /^[\E\Qa\E-\Qz\E]+/BZ /^[a\Q]bc\E]/BZ /^[a-\Q\E]/BZ /^(?P>abc)[()](?)/BZ /^((?(abc)y)[()](?Px))+/BZ (xy)x /^(?P>abc)\Q()\E(?)/BZ /^(?P>abc)[a\Q(]\E(](?)/BZ /^(?P>abc) # this is (a comment) (?)/BZx /^\W*(?:(?(?.)\W*(?&one)\W*\k|)|(?(?.)\W*(?&three)\W*\k'four'|\W*.\W*))\W*$/Ii 1221 Satan, oscillate my metallic sonatas! A man, a plan, a canal: Panama! Able was I ere I saw Elba. *** Failers The quick brown fox /(?=(\w+))\1:/I abcd: /(?=(?'abc'\w+))\k:/I abcd: /(?'abc'a|b)(?d|e)\k{2}/J adaa ** Failers addd adbb /(?'abc'a|b)(?d|e)(?&abc){2}/J bdaa bdab ** Failers bddd /(?( (?'B' abc (?(R) (?(R&A)1) (?(R&B)2) X | (?1) (?2) (?R) ))) /x abcabc1Xabc2XabcXabcabc /(? (?'B' abc (?(R) (?(R&C)1) (?(R&B)2) X | (?1) (?2) (?R) ))) /x /^(?(DEFINE) abc | xyz ) /x /(?(DEFINE) abc) xyz/xI /(a|)*\d/ \O0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \O0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /^a.b/ a\rb a\nb\ a\x85b\ ** Failers a\nb a\nb\ a\rb\ a\rb\ a\x85b\ a\rb\ /^abc./mgx abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x85abc7 JUNK /abc.$/mgx abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x85 abc7 abc9 /a/ /a/ /^a\Rb/ a\nb a\rb a\r\nb a\x0bb a\x0cb a\x85b ** Failers a\n\rb /^a\R*b/ ab a\nb a\rb a\r\nb a\x0bb a\x0cb a\x85b a\n\rb a\n\r\x85\x0cb /^a\R+b/ a\nb a\rb a\r\nb a\x0bb a\x0cb a\x85b a\n\rb a\n\r\x85\x0cb ** Failers ab /^a\R{1,3}b/ a\nb a\n\rb a\n\r\x85b a\r\n\r\nb a\r\n\r\n\r\nb a\n\r\n\rb a\n\n\r\nb ** Failers a\n\n\n\rb a\r /^a[\R]b/ aRb ** Failers a\nb /(?&abc)X(?P)/I abcPXP123 /(?1)X(?P)/I abcPXP123 /(?:a(?&abc)b)*(?x)/ 123axbaxbaxbx456 123axbaxbaxb456 /(?:a(?&abc)b){1,5}(?x)/ 123axbaxbaxbx456 /(?:a(?&abc)b){2,5}(?x)/ 123axbaxbaxbx456 /(?:a(?&abc)b){2,}(?x)/ 123axbaxbaxbx456 /(abc)(?i:(?1))/ defabcabcxyz DEFabcABCXYZ /(abc)(?:(?i)(?1))/ defabcabcxyz DEFabcABCXYZ /^(a)\g-2/ /^(a)\g/ /^(a)\g{0}/ /^(a)\g{3/ /^(a)\g{aa}/ /^a.b/ a\rb *** Failers a\nb /.+foo/ afoo ** Failers \r\nfoo \nfoo /.+foo/ afoo \nfoo ** Failers \r\nfoo /.+foo/ afoo ** Failers \nfoo \r\nfoo /.+foo/s afoo \r\nfoo \nfoo /^$/mg abc\r\rxyz abc\n\rxyz ** Failers abc\r\nxyz /(?m)^$/g+ abc\r\n\r\n /(?m)^$|^\r\n/g+ abc\r\n\r\n /(?m)$/g+ abc\r\n\r\n /abc.$/mgx abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x85 abc9 /^X/m XABC ** Failers XABC\B /(ab|c)(?-1)/BZ abc /xy(?+1)(abc)/BZ xyabcabc ** Failers xyabc /x(?-0)y/ /x(?-1)y/ /x(?+0)y/ /x(?+1)y/ /^(abc)?(?(-1)X|Y)/BZ abcX Y ** Failers abcY /^((?(+1)X|Y)(abc))+/BZ YabcXabc YabcXabcXabc ** Failers XabcXabc /(?(-1)a)/BZ /((?(-1)a))/BZ /((?(-2)a))/BZ /^(?(+1)X|Y)(.)/BZ Y! /(?tom|bon)-\k{A}/ tom-tom bon-bon ** Failers tom-bon /\g{A/ /(?|(abc)|(xyz))/BZ >abc< >xyz< /(x)(?|(abc)|(xyz))(x)/BZ xabcx xxyzx /(x)(?|(abc)(pqr)|(xyz))(x)/BZ xabcpqrx xxyzx /\H++X/BZ ** Failers XXXX /\H+\hY/BZ XXXX Y /\H+ Y/BZ /\h+A/BZ /\v*B/BZ /\V+\x0a/BZ /A+\h/BZ / *\H/BZ /A*\v/BZ /\x0b*\V/BZ /\d+\h/BZ /\d*\v/BZ /S+\h\S+\v/BZ /\w{3,}\h\w+\v/BZ /\h+\d\h+\w\h+\S\h+\H/BZ /\v+\d\v+\w\v+\S\v+\V/BZ /\H+\h\H+\d/BZ /\V+\v\V+\w/BZ /\( (?: [^()]* | (?R) )* \)/x \J1024(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(00)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0) /[\E]AAA/ /[\Q\E]AAA/ /[^\E]AAA/ /[^\Q\E]AAA/ /[\E^]AAA/ /[\Q\E^]AAA/ /A(*PRUNE)B(*SKIP)C(*THEN)D(*COMMIT)E(*F)F(*FAIL)G(?!)H(*ACCEPT)I/BZ /^a+(*FAIL)/C aaaaaa /a+b?c+(*FAIL)/C aaabccc /a+b?(*PRUNE)c+(*FAIL)/C aaabccc /a+b?(*COMMIT)c+(*FAIL)/C aaabccc /a+b?(*SKIP)c+(*FAIL)/C aaabcccaaabccc /a+b?(*THEN)c+(*FAIL)/C aaabccc /a(*MARK)b/ /(?i:A{1,}\6666666666)/ /\g6666666666/ /[\g6666666666]/BZ /(?1)\c[/ /.+A/ \r\nA /\nA/ \r\nA /[\r\n]A/ \r\nA /(\r|\n)A/ \r\nA /a(*CR)b/ /(*CR)a.b/ a\nb ** Failers a\rb /(*CR)a.b/ a\nb ** Failers a\rb /(*LF)a.b/ a\rb ** Failers a\nb /(*CRLF)a.b/ a\rb a\nb ** Failers a\r\nb /(*ANYCRLF)a.b/ ** Failers a\rb a\nb a\r\nb /(*ANY)a.b/ ** Failers a\rb a\nb a\r\nb a\x85b /(*ANY).*/g abc\r\ndef /(*ANYCRLF).*/g abc\r\ndef /(*CRLF).*/g abc\r\ndef /a\Rb/I a\rb a\nb a\r\nb ** Failers a\x85b a\x0bb /a\Rb/I a\rb a\nb a\r\nb a\x85b a\x0bb ** Failers a\x85b\ a\x0bb\ /a\R?b/I a\rb a\nb a\r\nb ** Failers a\x85b a\x0bb /a\R?b/I a\rb a\nb a\r\nb a\x85b a\x0bb ** Failers a\x85b\ a\x0bb\ /a\R{2,4}b/I a\r\n\nb a\n\r\rb a\r\n\r\n\r\n\r\nb ** Failers a\x85\85b a\x0b\0bb /a\R{2,4}b/I a\r\rb a\n\n\nb a\r\n\n\r\rb a\x85\85b a\x0b\0bb ** Failers a\r\r\r\r\rb a\x85\85b\ a\x0b\0bb\ /(*BSR_ANYCRLF)a\Rb/I a\nb a\rb /(*BSR_UNICODE)a\Rb/I a\x85b /(*BSR_ANYCRLF)(*CRLF)a\Rb/I a\nb a\rb /(*CRLF)(*BSR_UNICODE)a\Rb/I a\x85b /(*CRLF)(*BSR_ANYCRLF)(*CR)ab/I /(?)(?&)/ /(?)(?&a)/ /(?)(?&aaaaaaaaaaaaaaaaaaaaaaa)/ /(?+-a)/ /(?-+a)/ /(?(-1))/ /(?(+10))/ /(?(10))/ /(?(+2))()()/ /(?(2))()()/ /\k''/ /\k<>/ /\k{}/ /\k/ /\kabc/ /(?P=)/ /(?P>)/ /(?!\w)(?R)/ /(?=\w)(?R)/ /(?x|y){0}z/ xzxx yzyy ** Failers xxz /(\3)(\1)(a)/ cat /(\3)(\1)(a)/ cat /TA]/ The ACTA] comes /TA]/ The ACTA] comes /(?2)[]a()b](abc)/ abcbabc /(?2)[^]a()b](abc)/ abcbabc /(?1)[]a()b](abc)/ abcbabc ** Failers abcXabc /(?1)[^]a()b](abc)/ abcXabc ** Failers abcbabc /(?2)[]a()b](abc)(xyz)/ xyzbabcxyz /(?&N)[]a(?)](?abc)/ abc)](abc)/ abc ** Failers ab /a[]+b/ ** Failers ab /a[]*+b/ ** Failers ab /a[^]b/ aXb a\nb ** Failers ab /a[^]+b/ aXb a\nX\nXb ** Failers ab /a(?!)b/BZ /(?!)?a/BZ ab /a(*FAIL)+b/ /(abc|pqr|123){0}[xyz]/SI /(?(?=.*b)b|^)/CI adc abc /(?(?=b).*b|^d)/I /(?(?=.*b).*b|^d)/I /xyz/C xyz abcxyz abcxyz\Y ** Failers abc abc\Y abcxypqr abcxypqr\Y /(*NO_START_OPT)xyz/C abcxyz /(*NO_AUTO_POSSESS)a+b/BZ /xyz/CY abcxyz /^"((?(?=[a])[^"])|b)*"$/C "ab" /^"((?(?=[a])[^"])|b)*"$/ "ab" /^X(?5)(a)(?|(b)|(q))(c)(d)Y/ XYabcdY /^X(?&N)(a)(?|(b)|(q))(c)(d)(?Y)/ XYabcdY /Xa{2,4}b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /Xa{2,4}?b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /Xa{2,4}+b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\d{2,4}b/ X\P X3\P X33\P X333\P X3333\P /X\d{2,4}?b/ X\P X3\P X33\P X333\P X3333\P /X\d{2,4}+b/ X\P X3\P X33\P X333\P X3333\P /X\D{2,4}b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\D{2,4}?b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\D{2,4}+b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[abc]{2,4}b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[abc]{2,4}?b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[abc]{2,4}+b/ X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[^a]{2,4}b/ X\P Xz\P Xzz\P Xzzz\P Xzzzz\P /X[^a]{2,4}?b/ X\P Xz\P Xzz\P Xzzz\P Xzzzz\P /X[^a]{2,4}+b/ X\P Xz\P Xzz\P Xzzz\P Xzzzz\P /(Y)X\1{2,4}b/ YX\P YXY\P YXYY\P YXYYY\P YXYYYY\P /(Y)X\1{2,4}?b/ YX\P YXY\P YXYY\P YXYYY\P YXYYYY\P /(Y)X\1{2,4}+b/ YX\P YXY\P YXYY\P YXYYY\P YXYYYY\P /\++\KZ|\d+X|9+Y/ ++++123999\P ++++123999Y\P ++++Z1234\P /Z(*F)/ Z\P ZA\P /Z(?!)/ Z\P ZA\P /dog(sbody)?/ dogs\P dogs\P\P /dog(sbody)??/ dogs\P dogs\P\P /dog|dogsbody/ dogs\P dogs\P\P /dogsbody|dog/ dogs\P dogs\P\P /\bthe cat\b/ the cat\P the cat\P\P /abc/ abc\P abc\P\P /abc\K123/ xyzabc123pqr xyzabc12\P xyzabc12\P\P /(?<=abc)123/ xyzabc123pqr xyzabc12\P xyzabc12\P\P /\babc\b/ +++abc+++ +++ab\P +++ab\P\P /(?&word)(?&element)(?(DEFINE)(?<[^m][^>]>[^<])(?\w*+))/BZ /(?&word)(?&element)(?(DEFINE)(?<[^\d][^>]>[^<])(?\w*+))/BZ /(ab)(x(y)z(cd(*ACCEPT)))pq/BZ /abc\K/+ abcdef abcdef\N\N xyzabcdef\N\N ** Failers abcdef\N xyzabcdef\N /^(?:(?=abc)|abc\K)/+ abcdef abcdef\N\N ** Failers abcdef\N /a?b?/+ xyz xyzabc xyzabc\N xyzabc\N\N xyz\N\N ** Failers xyz\N /^a?b?/+ xyz xyzabc ** Failers xyzabc\N xyzabc\N\N xyz\N\N xyz\N /^(?a|b\gc)/ aaaa bacxxx bbaccxxx bbbacccxx /^(?a|b\g'name'c)/ aaaa bacxxx bbaccxxx bbbacccxx /^(a|b\g<1>c)/ aaaa bacxxx bbaccxxx bbbacccxx /^(a|b\g'1'c)/ aaaa bacxxx bbaccxxx bbbacccxx /^(a|b\g'-1'c)/ aaaa bacxxx bbaccxxx bbbacccxx /(^(a|b\g<-1>c))/ aaaa bacxxx bbaccxxx bbbacccxx /(?-i:\g)(?i:(?a))/ XaaX XAAX /(?i:\g)(?-i:(?a))/ XaaX ** Failers XAAX /(?-i:\g<+1>)(?i:(a))/ XaaX XAAX /(?=(?(?#simplesyntax)\$(?[a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(?:\[(?[a-zA-Z0-9_\x{7f}-\x{ff}]+|\$\g)\]|->\g(\(.*?\))?)?|(?#simple syntax withbraces)\$\{(?:\g(?\[(?:\g|'(?:\\.|[^'\\])*'|"(?:\g|\\.|[^"\\])*")\])?|\g|\$\{\g\})\}|(?#complexsyntax)\{(?\$(?\g(\g*|\(.*?\))?)(?:->\g)*|\$\g|\$\{\g\})\}))\{/ /(?a|b|c)\g*/ abc accccbbb /^X(?7)(a)(?|(b)|(q)(r)(s))(c)(d)(Y)/ XYabcdY /(?<=b(?1)|zzz)(a)/ xbaax xzzzax /(a)(?<=b\1)/ /(a)(?<=b+(?1))/ /(a+)(?<=b(?1))/ /(a(?<=b(?1)))/ /(?<=b(?1))xyz/ /(?<=b(?1))xyz(b+)pqrstuvew/ /(a|bc)\1/SI /(a|bc)\1{2,3}/SI /(a|bc)(?1)/SI /(a|b\1)(a|b\1)/SI /(a|b\1){2}/SI /(a|bbbb\1)(a|bbbb\1)/SI /(a|bbbb\1){2}/SI /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/SI /]{0,})>]{0,})>([\d]{0,}\.)(.*)((
    ([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/isIS "(?>.*/)foo"SI /(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /xSI /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/iSI /(?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb)))/SI /A)|(?
    B))/I AB\Ca BA\Ca /(?|(?A)|(?B))/ /(?:a(? (?')|(?")) | b(? (?')|(?")) ) (?('quote')[a-z]+|[0-9]+)/JIx a"aaaaa b"aaaaa ** Failers b"11111 a"11111 /^(?|(a)(b)(c)(?d)|(?e)) (?('D')X|Y)/JDZx abcdX eX ** Failers abcdY ey /(?a) (b)(c) (?d (?(R&A)$ | (?4)) )/JDZx abcdd ** Failers abcdde /abcd*/ xxxxabcd\P xxxxabcd\P\P /abcd*/i xxxxabcd\P xxxxabcd\P\P XXXXABCD\P XXXXABCD\P\P /abc\d*/ xxxxabc1\P xxxxabc1\P\P /(a)bc\1*/ xxxxabca\P xxxxabca\P\P /abc[de]*/ xxxxabcde\P xxxxabcde\P\P /-- This is not in the Perl-compatible test because Perl seems currently to be broken and not behaving as specified in that it *does* bumpalong after hitting (*COMMIT). --/ /(?1)(A(*COMMIT)|B)D/ ABD XABD BAD ABXABD ** Failers ABX BAXBAD /(\3)(\1)(a)/ cat /(\3)(\1)(a)/SI cat /(\3)(\1)(a)/SI cat /i(?(DEFINE)(?a))/SI i /()i(?(1)a)/SI ia /(?i)a(?-i)b|c/BZ XabX XAbX CcC ** Failers XABX /(?i)a(?s)b|c/BZ /(?i)a(?s-i)b|c/BZ /^(ab(c\1)d|x){2}$/BZ xabcxd /^(?&t)*+(?(DEFINE)(?.))$/BZ /^(?&t)*(?(DEFINE)(?.))$/BZ / -- This one is here because Perl gives the match as "b" rather than "ab". I believe this to be a Perl bug. --/ /(?>a\Kb)z|(ab)/ ab /(?P(?P0|)|(?P>L2)(?P>L1))/ /abc(*MARK:)pqr/ /abc(*:)pqr/ /abc(*FAIL:123)xyz/ /--- This should, and does, fail. In Perl, it does not, which I think is a bug because replacing the B in the pattern by (B|D) does make it fail. ---/ /A(*COMMIT)B/+K ACABX /--- These should be different, but in Perl they are not, which I think is a bug in Perl. ---/ /A(*THEN)B|A(*THEN)C/K AC /A(*PRUNE)B|A(*PRUNE)C/K AC /--- Mark names can be duplicated. Perl doesn't give a mark for this one, though PCRE does. ---/ /^A(*:A)B|^X(*:A)Y/K ** Failers XAQQ /--- COMMIT at the start of a pattern should be the same as an anchor. Perl optimizations defeat this. So does the PCRE optimization unless we disable it with \Y. ---/ /(*COMMIT)ABC/ ABCDEFG ** Failers DEFGABC\Y /^(ab (c+(*THEN)cd) | xyz)/x abcccd /^(ab (c+(*PRUNE)cd) | xyz)/x abcccd /^(ab (c+(*FAIL)cd) | xyz)/x abcccd /--- Perl gets some of these wrong ---/ /(?>.(*ACCEPT))*?5/ abcde /(.(*ACCEPT))*?5/ abcde /(.(*ACCEPT))5/ abcde /(.(*ACCEPT))*5/ abcde /A\NB./BZ ACBD *** Failers A\nB ACB\n /A\NB./sBZ ACBD ACB\n *** Failers A\nB /A\NB/ A\nB A\rB ** Failers A\r\nB /\R+b/BZ /\R+\n/BZ /\R+\d/BZ /\d*\R/BZ /\s*\R/BZ \x20\x0a \x20\x0d \x20\x0d\x0a /\S*\R/BZ a\x0a /X\h*\R/BZ X\x20\x0a /X\H*\R/BZ X\x0d\x0a /X\H+\R/BZ X\x0d\x0a /X\H++\R/BZ X\x0d\x0a /(?<=abc)def/ abc\P\P /abc$/ abc abc\P abc\P\P /abc$/m abc abc\n abc\P\P abc\n\P\P abc\P abc\n\P /abc\z/ abc abc\P abc\P\P /abc\Z/ abc abc\P abc\P\P /abc\b/ abc abc\P abc\P\P /abc\B/ abc abc\P abc\P\P /.+/ abc\>0 abc\>1 abc\>2 abc\>3 abc\>4 abc\>-4 /^\cģ/ /(?P(?P=abn)xxx)/BZ /(a\1z)/BZ /(?P(?P=abn)(?(?P=axn)xxx)/BZ /(?P(?P=axn)xxx)(?yy)/BZ /-- These tests are here because Perl gets the first one wrong. --/ /(\R*)(.)/s \r\n \r\r\n\n\r \r\r\n\n\r\n /(\R)*(.)/s \r\n \r\r\n\n\r \r\r\n\n\r\n /((?>\r\n|\n|\x0b|\f|\r|\x85)*)(.)/s \r\n \r\r\n\n\r \r\r\n\n\r\n /-- --/ /^abc$/BZ /^abc$/BZm /^(a)*+(\w)/S aaaaX ** Failers aaaa /^(?:a)*+(\w)/S aaaaX ** Failers aaaa /(a)++1234/SDZ /([abc])++1234/SI /(?<=(abc)+)X/ /(^ab)/I /(^ab)++/I /(^ab|^)+/I /(^ab|^)++/I /(?:^ab)/I /(?:^ab)++/I /(?:^ab|^)+/I /(?:^ab|^)++/I /(.*ab)/I /(.*ab)++/I /(.*ab|.*)+/I /(.*ab|.*)++/I /(?:.*ab)/I /(?:.*ab)++/I /(?:.*ab|.*)+/I /(?:.*ab|.*)++/I /(?=a)[bcd]/I /((?=a))[bcd]/I /((?=a))+[bcd]/I /((?=a))++[bcd]/I /(?=a+)[bcd]/iI /(?=a+?)[bcd]/iI /(?=a++)[bcd]/iI /(?=a{3})[bcd]/iI /(abc)\1+/S /-- Perl doesn't get these right IMO (the 3rd is PCRE-specific) --/ /(?1)(?:(b(*ACCEPT))){0}/ b /(?1)(?:(b(*ACCEPT))){0}c/ bc ** Failers b /(?1)(?:((*ACCEPT))){0}c/ c c\N /^.*?(?(?=a)a|b(*THEN)c)/ ba /^.*?(?(?=a)a|bc)/ ba /^.*?(?(?=a)a(*THEN)b|c)/ ac /^.*?(?(?=a)a(*THEN)b)c/ ac /^.*?(a(*THEN)b)c/ aabc /^.*? (?1) c (?(DEFINE)(a(*THEN)b))/x aabc /^.*?(a(*THEN)b|z)c/ aabc /^.*?(z|a(*THEN)b)c/ aabc /-- --/ /-- These studied versions are here because they are not Perl-compatible; the studying means the mark is not seen. --/ /(*MARK:A)(*SKIP:B)(C|X)/KS C D /(*:A)A+(*SKIP:A)(B|Z)/KS AAAC /-- --/ "(?=a*(*ACCEPT)b)c" c c\N /(?1)c(?(DEFINE)((*ACCEPT)b))/ c c\N /(?>(*ACCEPT)b)c/ c c\N /(?:(?>(a)))+a%/++ %aa% /(a)b|ac/++SS ac\O3 /(a)(b)x|abc/++ abc\O6 /(a)bc|(a)(b)\2/ \O3abc \O4abc /(?(DEFINE)(a(?2)|b)(b(?1)|a))(?:(?1)|(?2))/SI /(a(?2)|b)(b(?1)|a)(?:(?1)|(?2))/SI /(a(?2)|b)(b(?1)|a)(?1)(?2)/SI /(abc)(?1)/SI /^(?>a)++/ aa\M aaaaaaaaa\M /(a)(?1)++/ aa\M aaaaaaaaa\M /(?:(foo)|(bar)|(baz))X/SS= bazfooX foobazbarX barfooX bazX foobarbazX bazfooX\O0 bazfooX\O2 bazfooX\O4 bazfooX\O6 bazfooX\O8 bazfooX\O10 /(?=abc){3}abc/BZ /(?=abc)+abc/BZ /(?=abc)++abc/BZ /(?=abc){0}xyz/BZ /(?=(a))?./BZ /(?=(a))??./BZ /^(?=(a)){0}b(?1)/BZ /(?(DEFINE)(a))?b(?1)/BZ /^(?=(?1))?[az]([abc])d/BZ /^(?!a){0}\w+/BZ /(?<=(abc))?xyz/BZ /[:a[:abc]b:]/BZ /((?2))((?1))/SS abc /((?(R2)a+|(?1)b))/SS aaaabcde /(?(R)a*(?1)|((?R))b)/SS aaaabcde /(a+|(?R)b)/ /^(a(*:A)(d|e(*:B))z|aeq)/C adz aez aeqwerty /.(*F)/ \P\Pabc /\btype\b\W*?\btext\b\W*?\bjavascript\b/IS /\btype\b\W*?\btext\b\W*?\bjavascript\b|\burl\b\W*?\bshell:|a+)(?>(z+))\w/BZ aaaazzzzb ** Failers aazz /(.)(\1|a(?2))/ bab /\1|(.)(?R)\1/ cbbbc /(.)((?(1)c|a)|a(?2))/ baa /(?P(?P=abn)xxx)/BZ /(a\1z)/BZ /^(?>a+)(?>b+)(?>c+)(?>d+)(?>e+)/ \Maabbccddee /^(?>(a+))(?>(b+))(?>(c+))(?>(d+))(?>(e+))/ \Maabbccddee /^(?>(a+))(?>b+)(?>(c+))(?>d+)(?>(e+))/ \Maabbccddee /^a\x41z/ aAz *** Failers ax41z /^a[m\x41]z/ aAz /^a\x1z/ ax1z /^a\u0041z/ aAz *** Failers au0041z /^a[m\u0041]z/ aAz /^a\u041z/ au041z *** Failers aAz /^a\U0041z/ aU0041z *** Failers aAz /(?(?=c)c|d)++Y/BZ /(?(?=c)c|d)*+Y/BZ /a[\NB]c/ aNc /a[B-\Nc]/ /a[B\Nc]/ /(a)(?2){0,1999}?(b)/ /(a)(?(DEFINE)(b))(?2){0,1999}?(?2)/ /--- This test, with something more complicated than individual letters, causes different behaviour in Perl. Perhaps it disables some optimization; no tag is passed back for the failures, whereas in PCRE there is a tag. ---/ /(A|P)(*:A)(B|P) | (X|P)(X|P)(*:B)(Y|P)/xK AABC XXYZ ** Failers XAQQ XAQQXZZ AXQQQ AXXQQQ /-- Perl doesn't give marks for these, though it does if the alternatives are replaced by single letters. --/ /(b|q)(*:m)f|a(*:n)w/K aw ** Failers abc /(q|b)(*:m)f|a(*:n)w/K aw ** Failers abc /-- After a partial match, the behaviour is as for a failure. --/ /^a(*:X)bcde/K abc\P /-- These are here because Perl doesn't return a mark, except for the first --/ /(?=(*:x))(q|)/K+ abc /(?=(*:x))((*:y)q|)/K+ abc /(?=(*:x))(?:(*:y)q|)/K+ abc /(?=(*:x))(?>(*:y)q|)/K+ abc /(?=a(*:x))(?!a(*:y)c)/K+ ab /(?=a(*:x))(?=a(*:y)c|)/K+ ab /(..)\1/ ab\P aba\P abab\P /(..)\1/i ab\P abA\P aBAb\P /(..)\1{2,}/ ab\P aba\P abab\P ababa\P ababab\P ababab\P\P abababa\P abababa\P\P /(..)\1{2,}/i ab\P aBa\P aBAb\P AbaBA\P abABAb\P aBAbaB\P\P abABabA\P abaBABa\P\P /(..)\1{2,}?x/i ab\P abA\P aBAb\P abaBA\P abAbaB\P abaBabA\P abAbABaBx\P /^(..)\1/ aba\P /^(..)\1{2,3}x/ aba\P ababa\P ababa\P\P abababx ababababx /^(..)\1{2,3}?x/ aba\P ababa\P ababa\P\P abababx ababababx /^(..)(\1{2,3})ab/ abababab /^\R/ \r\P \r\P\P /^\R{2,3}x/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P \r\rx \r\r\rx /^\R{2,3}?x/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P \r\rx \r\r\rx /^\R?x/ \r\P \r\P\P x \rx /^\R+x/ \r\P \r\P\P \r\n\P \r\n\P\P \rx /^a$/ a\r\P a\r\P\P /^a$/m a\r\P a\r\P\P /^(a$|a\r)/ a\r\P a\r\P\P /^(a$|a\r)/m a\r\P a\r\P\P /./ \r\P \r\P\P /.{2,3}/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /.{2,3}?/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P "AB(C(D))(E(F))?(?(?=\2)(?=\4))" ABCDGHI\O03 /-- These are all run as real matches in test 1; here we are just checking the settings of the anchored and startline bits. --/ /(?>.*?a)(?<=ba)/I /(?:.*?a)(?<=ba)/I /.*?a(*PRUNE)b/I /.*?a(*PRUNE)b/sI /^a(*PRUNE)b/sI /.*?a(*SKIP)b/I /(?>.*?a)b/sI /(?>.*?a)b/I /(?>^a)b/sI /(?>.*?)(?<=(abcd)|(wxyz))/I /(?>.*)(?<=(abcd)|(wxyz))/I "(?>.*)foo"I "(?>.*?)foo"I /(?>^abc)/mI /(?>.*abc)/mI /(?:.*abc)/mI /-- Check PCRE_STUDY_EXTRA_NEEDED --/ /.?/S-I /.?/S!I /(?:(a)+(?C1)bb|aa(?C2)b)/ aab\C+ /(?:(a)++(?C1)bb|aa(?C2)b)/ aab\C+ /(?:(?>(a))(?C1)bb|aa(?C2)b)/ aab\C+ /(?:(?1)(?C1)x|ab(?C2))((a)){0}/ aab\C+ /(?1)(?C1)((a)(?C2)){0}/ aab\C+ /(?:(a)+(?C1)bb|aa(?C2)b)++/ aab\C+ aab\C+\O2 /(ab)x|ab/ ab\O3 ab\O2 /(ab)/ ab\O3 ab\O2 /(?<=123)(*MARK:xx)abc/K xxxx123a\P\P xxxx123a\P /123\Kabc/ xxxx123a\P\P xxxx123a\P /^(?(?=a)aa|bb)/C bb /(?C1)^(?C2)(?(?C99)(?=(?C3)a(?C4))(?C5)a(?C6)a(?C7)|(?C8)b(?C9)b(?C10))(?C11)/ bb /-- Perl seems to have a bug with this one --/ /aaaaa(*COMMIT)(*PRUNE)b|a+c/ aaaaaac /-- Here are some that Perl treats differently because of the way it handles backtracking verbs. --/ /(?!a(*COMMIT)b)ac|ad/ ac ad /^(?!a(*THEN)b|ac)../ ac ad /^(?=a(*THEN)b|ac)/ ac /\A.*?(?:a|b(*THEN)c)/ ba /\A.*?(?:a|b(*THEN)c)++/ ba /\A.*?(?:a|b(*THEN)c|d)/ ba /(?:(a(*MARK:X)a+(*SKIP:X)b)){0}(?:(?1)|aac)/ aac /\A.*?(a|b(*THEN)c)/ ba /^(A(*THEN)B|A(*THEN)D)/ AD /(?!b(*THEN)a)bn|bnn/ bnn /(?(?=b(*SKIP)a)bn|bnn)/ bnn /(?=b(*THEN)a|)bn|bnn/ bnn /-------------------------/ /(*LIMIT_MATCH=12bc)abc/ /(*LIMIT_MATCH=4294967290)abc/ /(*LIMIT_RECURSION=4294967280)abc/I /(a+)*zz/ aaaaaaaaaaaaaz aaaaaaaaaaaaaz\q3000 /(a+)*zz/S- aaaaaaaaaaaaaz\Q10 /(*LIMIT_MATCH=3000)(a+)*zz/I aaaaaaaaaaaaaz aaaaaaaaaaaaaz\q60000 /(*LIMIT_MATCH=60000)(*LIMIT_MATCH=3000)(a+)*zz/I aaaaaaaaaaaaaz /(*LIMIT_MATCH=60000)(a+)*zz/I aaaaaaaaaaaaaz aaaaaaaaaaaaaz\q3000 /(*LIMIT_RECURSION=10)(a+)*zz/IS- aaaaaaaaaaaaaz aaaaaaaaaaaaaz\Q1000 /(*LIMIT_RECURSION=10)(*LIMIT_RECURSION=1000)(a+)*zz/IS- aaaaaaaaaaaaaz /(*LIMIT_RECURSION=1000)(a+)*zz/IS- aaaaaaaaaaaaaz aaaaaaaaaaaaaz\Q10 /-- This test causes a segfault with Perl 5.18.0 --/ /^(?=(a)){0}b(?1)/ backgammon /(?|(?f)|(?b))/JI /(?abc)(?z)\k()/JDZS /a*[bcd]/BZ /[bcd]*a/BZ /-- A complete set of tests for auto-possessification of character types --/ /\D+\D \D+\d \D+\S \D+\s \D+\W \D+\w \D+. \D+\C \D+\R \D+\H \D+\h \D+\V \D+\v \D+\Z \D+\z \D+$/BZx /\d+\D \d+\d \d+\S \d+\s \d+\W \d+\w \d+. \d+\C \d+\R \d+\H \d+\h \d+\V \d+\v \d+\Z \d+\z \d+$/BZx /\S+\D \S+\d \S+\S \S+\s \S+\W \S+\w \S+. \S+\C \S+\R \S+\H \S+\h \S+\V \S+\v \S+\Z \S+\z \S+$/BZx /\s+\D \s+\d \s+\S \s+\s \s+\W \s+\w \s+. \s+\C \s+\R \s+\H \s+\h \s+\V \s+\v \s+\Z \s+\z \s+$/BZx /\W+\D \W+\d \W+\S \W+\s \W+\W \W+\w \W+. \W+\C \W+\R \W+\H \W+\h \W+\V \W+\v \W+\Z \W+\z \W+$/BZx /\w+\D \w+\d \w+\S \w+\s \w+\W \w+\w \w+. \w+\C \w+\R \w+\H \w+\h \w+\V \w+\v \w+\Z \w+\z \w+$/BZx /\C+\D \C+\d \C+\S \C+\s \C+\W \C+\w \C+. \C+\C \C+\R \C+\H \C+\h \C+\V \C+\v \C+\Z \C+\z \C+$/BZx /\R+\D \R+\d \R+\S \R+\s \R+\W \R+\w \R+. \R+\C \R+\R \R+\H \R+\h \R+\V \R+\v \R+\Z \R+\z \R+$/BZx /\H+\D \H+\d \H+\S \H+\s \H+\W \H+\w \H+. \H+\C \H+\R \H+\H \H+\h \H+\V \H+\v \H+\Z \H+\z \H+$/BZx /\h+\D \h+\d \h+\S \h+\s \h+\W \h+\w \h+. \h+\C \h+\R \h+\H \h+\h \h+\V \h+\v \h+\Z \h+\z \h+$/BZx /\V+\D \V+\d \V+\S \V+\s \V+\W \V+\w \V+. \V+\C \V+\R \V+\H \V+\h \V+\V \V+\v \V+\Z \V+\z \V+$/BZx /\v+\D \v+\d \v+\S \v+\s \v+\W \v+\w \v+. \v+\C \v+\R \v+\H \v+\h \v+\V \v+\v \v+\Z \v+\z \v+$/BZx / a+\D a+\d a+\S a+\s a+\W a+\w a+. a+\C a+\R a+\H a+\h a+\V a+\v a+\Z a+\z a+$/BZx /\n+\D \n+\d \n+\S \n+\s \n+\W \n+\w \n+. \n+\C \n+\R \n+\H \n+\h \n+\V \n+\v \n+\Z \n+\z \n+$/BZx / .+\D .+\d .+\S .+\s .+\W .+\w .+. .+\C .+\R .+\H .+\h .+\V .+\v .+\Z .+\z .+$/BZx / .+\D .+\d .+\S .+\s .+\W .+\w .+. .+\C .+\R .+\H .+\h .+\V .+\v .+\Z .+\z .+$/BZxs /\D+$ \d+$ \S+$ \s+$ \W+$ \w+$ \C+$ \R+$ \H+$ \h+$ \V+$ \v+$ a+$ \n+$ .+$ .+$/BZxm /(?=a+)a(a+)++a/BZ /a+(bb|cc)a+(?:bb|cc)a+(?>bb|cc)a+(?:bb|cc)+a+(aa)a+(?:bb|aa)/BZ /a+(bb|cc)?#a+(?:bb|cc)??#a+(?:bb|cc)?+#a+(?:bb|cc)*#a+(bb|cc)?a#a+(?:aa)?/BZ /a+(?:bb)?a#a+(?:|||)#a+(?:|b)a#a+(?:|||)?a/BZ /[ab]*/BZ aaaa /[ab]*?/BZ aaaa /[ab]?/BZ aaaa /[ab]??/BZ aaaa /[ab]+/BZ aaaa /[ab]+?/BZ aaaa /[ab]{2,3}/BZ aaaa /[ab]{2,3}?/BZ aaaa /[ab]{2,}/BZ aaaa /[ab]{2,}?/BZ aaaa /\d+\s{0,5}=\s*\S?=\w{0,4}\W*/BZ /[a-d]{5,12}[e-z0-9]*#[^a-z]+[b-y]*a[2-7]?[^0-9a-z]+/BZ /[a-z]*\s#[ \t]?\S#[a-c]*\S#[C-G]+?\d#[4-8]*\D#[4-9,]*\D#[!$]{0,5}\w#[M-Xf-l]+\W#[a-c,]?\W/BZ /a+(aa|bb)*c#a*(bb|cc)*a#a?(bb|cc)*d#[a-f]*(g|hh)*f/BZ /[a-f]*(g|hh|i)*i#[a-x]{4,}(y{0,6})*y#[a-k]+(ll|mm)+n/BZ /[a-f]*(?>gg|hh)+#[a-f]*(?>gg|hh)?#[a-f]*(?>gg|hh)*a#[a-f]*(?>gg|hh)*h/BZ /[a-c]*d/DZS /[a-c]+d/DZS /[a-c]?d/DZS /[a-c]{4,6}d/DZS /[a-c]{0,6}d/DZS /-- End of special auto-possessive tests --/ /^A\o{1239}B/ A\123B /^A\oB/ /^A\x{zz}B/ /^A\x{12Z/ /^A\x{/ /[ab]++/BZO /[^ab]*+/BZO /a{4}+/BZO /a{4}+/BZOi /[a-[:digit:]]+/ /[A-[:digit:]]+/ /[a-[.xxx.]]+/ /[a-[=xxx=]]+/ /[a-[!xxx!]]+/ /[A-[!xxx!]]+/ A]]] /[a-\d]+/ /(?<0abc>xx)/ /(?&1abc)xx(?<1abc>y)/ /(?xx)/ /(?'0abc'xx)/ /(?P<0abc>xx)/ /\k<5ghj>/ /\k'5ghj'/ /\k{2fgh}/ /(?P=8yuki)/ /\g{4df}/ /(?&1abc)xx(?<1abc>y)/ /(?P>1abc)xx(?<1abc>y)/ /\g'3gh'/ /\g<5fg>/ /(?(<4gh>)abc)/ /(?('4gh')abc)/ /(?(4gh)abc)/ /(?(R&6yh)abc)/ /(((a\2)|(a*)\g<-1>))*a?/BZ /-- Test the ugly "start or end of word" compatibility syntax --/ /[[:<:]]red[[:>:]]/BZ little red riding hood a /red/ thing red is a colour put it all on red ** Failers no reduction Alfred Winifred /[a[:<:]] should give error/ /(?=ab\K)/+ abcd /abcd/f xx\nxabcd / -- Test stack check external calls --/ /(((((a)))))/Q0 /(((((a)))))/Q1 /(((((a)))))/Q /^\w+(?>\s*)(?<=\w)/BZ /\othing/ /\o{}/ /\o{whatever}/ /\xthing/ /\x{}/ /\x{whatever}/ "((?=(?(?=(?(?=(?(?=()))))))))" a "(?(?=)==)(((((((((?=)))))))))" a /^(?:(a)|b)(?(1)A|B)/I aA123\O3 aA123\O6 '^(?:(?a)|b)(?()A|B)' aA123\O3 aA123\O6 '^(?)(?:(?a)|b)(?()A|B)'J aA123\O3 aA123\O6 '^(?:(?X)|)(?:(?a)|b)\k{AA}'J aa123\O3 aa123\O6 /(?(?J)(?1(111111)11|)1|1|)(?()1)/ /(?(?=0)?)+/ /(?(?=0)(?=00)?00765)/ 00765 /(?(?=0)(?=00)?00765|(?!3).56)/ 00765 456 ** Failers 356 '^(a)*+(\w)' g g\O3 '^(?:a)*+(\w)' g g\O3 //C \O\C+ "((?2){0,1999}())?" /((?+1)(\1))/BZ /(?(?!)a|b)/ bbb aaa "((?2)+)((?1))" "(?(?.*!.*)?)" "X((?2)()*+){2}+"BZ "X((?2)()*+){2}"BZ "(?<=((?2))((?1)))" /(?<=\Ka)/g+ aaaaa /(?<=\Ka)/G+ aaaaa /((?2){73}(?2))((?1))/ /.((?2)(?R)\1)()/BZ /(?1)()((((((\1++))\x85)+)|))/ /(\9*+(?2);\3++()2|)++{/ /\V\x85\9*+((?2)\3++()2)*:2/ /(((?(R)){0,2}) (?''((?'R')((?'R')))))/J /(((?(X)){0,2}) (?''((?'X')((?'X')))))/J /(((?(R)){0,2}) (?''((?'X')((?'R')))))/ "(?J)(?'d'(?'d'\g{d}))" ".*?\h.+.\.+\R*?\xd(?i)(?=!(?=b`b`b`\`b\xa9b!)`\a`bbbbbbbbbbbbb`bbbbbbbbbbbb*R\x85bbbbbbb\C?{((?2)(?))(( \H){8(?<=(?1){29}\xa8bbbb\x16\xd\xc6^($(?1)/ /a[[:punct:]b]/BZ /L(?#(|++)(?J:(?)(?))(?)/ \O\CC /(?=a\K)/ ring bpattingbobnd $ 1,oern cou \rb\L /(?<=((?C)0))/ 9010 abcd /((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/ /\N(?(?C)0?!.)*/ /(?abc)(?(R)xyz)/BZ /(?abc)(?(R)xyz)/BZ /(?=.*[A-Z])/I "(?<=(a))\1?b" ab aaab "(?=(a))\1?b" ab aaab /(?(?=^))b/ abc /-- End of testinput2 --/ ================================================ FILE: src/pcre/testdata/testinput20 ================================================ /-- These DFA tests are for the handling of characters greater than 255 in 16- or 32-bit, non-UTF mode. --/ /^\x{ffff}+/i \x{ffff} /^\x{ffff}?/i \x{ffff} /^\x{ffff}*/i \x{ffff} /^\x{ffff}{3}/i \x{ffff}\x{ffff}\x{ffff} /^\x{ffff}{0,3}/i \x{ffff} /-- End of testinput20 --/ ================================================ FILE: src/pcre/testdata/testinput21 ================================================ /-- Tests for reloading pre-compiled patterns. The first one gives an error right away, and can be any old pattern compiled in 8-bit mode ("abc" is typical). The others require the link size to be 2. */x (?:[AaLl]+)[^xX-]*?)(?P[\x{150}-\x{250}\x{300}]| [^\x{800}aAs-uS-U\x{d800}-\x{dfff}])++[^#\b\x{500}\x{1000}]{3,5}$ /x In 16-bit mode with options: S>testdata/saved16LE-1 FS>testdata/saved16BE-1 In 32-bit mode with options: S>testdata/saved32LE-1 FS>testdata/saved32BE-1 --%x [aZ\x{400}-\x{10ffff}]{4,} [\x{f123}\x{10039}\x{20000}-\x{21234}]?| [A-Cx-z\x{100000}-\x{1000a7}\x{101234}]) (?[^az])/x In 16-bit mode with options: S8>testdata/saved16LE-2 FS8>testdata/saved16BE-2 In 32-bit mode with options: S8>testdata/saved32LE-2 FS8>testdata/saved32BE-2 --%8x >>\xaa<<< >>>\xba<<< /[\W]+/Lfr_FR >>>\xaa<<< >>>\xba<<< /[^[:alpha:]]+/Lfr_FR >>>\xaa<<< >>>\xba<<< /\w+/Lfr_FR >>>\xaa<<< >>>\xba<<< /[\w]+/Lfr_FR >>>\xaa<<< >>>\xba<<< /[[:alpha:]]+/Lfr_FR >>>\xaa<<< >>>\xba<<< /[[:alpha:]][[:lower:]][[:upper:]]/DZLfr_FR /-- End of testinput3 --/ ================================================ FILE: src/pcre/testdata/testinput4 ================================================ /-- This set of tests is for UTF support, excluding Unicode properties. It is compatible with all versions of Perl >= 5.10 and both the 8-bit and 16-bit PCRE libraries. --/ < forbid 9?=ABCDEFfGILMNPTUWXZ< /a.b/8 acb a\x7fb a\x{100}b *** Failers a\nb /a(.{3})b/8 a\x{4000}xyb a\x{4000}\x7fyb a\x{4000}\x{100}yb *** Failers a\x{4000}b ac\ncb /a(.*?)(.)/ a\xc0\x88b /a(.*?)(.)/8 a\x{100}b /a(.*)(.)/ a\xc0\x88b /a(.*)(.)/8 a\x{100}b /a(.)(.)/ a\xc0\x92bcd /a(.)(.)/8 a\x{240}bcd /a(.?)(.)/ a\xc0\x92bcd /a(.?)(.)/8 a\x{240}bcd /a(.??)(.)/ a\xc0\x92bcd /a(.??)(.)/8 a\x{240}bcd /a(.{3})b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b *** Failers a\x{1234}b ac\ncb /a(.{3,})b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b *** Failers a\x{1234}b /a(.{3,}?)b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b *** Failers a\x{1234}b /a(.{3,5})b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b axbxxbcdefghijb axxxxxbcdefghijb *** Failers a\x{1234}b axxxxxxbcdefghijb /a(.{3,5}?)b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b axbxxbcdefghijb axxxxxbcdefghijb *** Failers a\x{1234}b axxxxxxbcdefghijb /^[a\x{c0}]/8 *** Failers \x{100} /(?<=aXb)cd/8 aXbcd /(?<=a\x{100}b)cd/8 a\x{100}bcd /(?<=a\x{100000}b)cd/8 a\x{100000}bcd /(?:\x{100}){3}b/8 \x{100}\x{100}\x{100}b *** Failers \x{100}\x{100}b /\x{ab}/8 \x{ab} \xc2\xab *** Failers \x00{ab} /(?<=(.))X/8 WXYZ \x{256}XYZ *** Failers XYZ /[^a]+/8g bcd \x{100}aY\x{256}Z /^[^a]{2}/8 \x{100}bc /^[^a]{2,}/8 \x{100}bcAa /^[^a]{2,}?/8 \x{100}bca /[^a]+/8ig bcd \x{100}aY\x{256}Z /^[^a]{2}/8i \x{100}bc /^[^a]{2,}/8i \x{100}bcAa /^[^a]{2,}?/8i \x{100}bca /\x{100}{0,0}/8 abcd /\x{100}?/8 abcd \x{100}\x{100} /\x{100}{0,3}/8 \x{100}\x{100} \x{100}\x{100}\x{100}\x{100} /\x{100}*/8 abce \x{100}\x{100}\x{100}\x{100} /\x{100}{1,1}/8 abcd\x{100}\x{100}\x{100}\x{100} /\x{100}{1,3}/8 abcd\x{100}\x{100}\x{100}\x{100} /\x{100}+/8 abcd\x{100}\x{100}\x{100}\x{100} /\x{100}{3}/8 abcd\x{100}\x{100}\x{100}XX /\x{100}{3,5}/8 abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX /\x{100}{3,}/8 abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX /(?<=a\x{100}{2}b)X/8+ Xyyya\x{100}\x{100}bXzzz /\D*/8 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /\D*/8 \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} /\D/8 1X2 1\x{100}2 />\S/8 > >X Y > >\x{100} Y /\d/8 \x{100}3 /\s/8 \x{100} X /\D+/8 12abcd34 *** Failers 1234 /\D{2,3}/8 12abcd34 12ab34 *** Failers 1234 12a34 /\D{2,3}?/8 12abcd34 12ab34 *** Failers 1234 12a34 /\d+/8 12abcd34 *** Failers /\d{2,3}/8 12abcd34 1234abcd *** Failers 1.4 /\d{2,3}?/8 12abcd34 1234abcd *** Failers 1.4 /\S+/8 12abcd34 *** Failers \ \ /\S{2,3}/8 12abcd34 1234abcd *** Failers \ \ /\S{2,3}?/8 12abcd34 1234abcd *** Failers \ \ />\s+ <34 *** Failers />\s{2,3} \s{2,3}? \xff< /[\xff]/8 >\x{ff}< /[^\xFF]/ XYZ /[^\xff]/8 XYZ \x{123} /^[ac]*b/8 xb /^[ac\x{100}]*b/8 xb /^[^x]*b/8i xb /^[^x]*b/8 xb /^\d*b/8 xb /(|a)/g8 catac a\x{256}a /^\x{85}$/8i \x{85} /^ሴ/8 ሴ /^\ሴ/8 ሴ "(?s)(.{1,5})"8 abcdefg ab /a*\x{100}*\w/8 a /\S\S/8g A\x{a3}BC /\S{2}/8g A\x{a3}BC /\W\W/8g +\x{a3}== /\W{2}/8g +\x{a3}== /\S/8g \x{442}\x{435}\x{441}\x{442} /[\S]/8g \x{442}\x{435}\x{441}\x{442} /\D/8g \x{442}\x{435}\x{441}\x{442} /[\D]/8g \x{442}\x{435}\x{441}\x{442} /\W/8g \x{2442}\x{2435}\x{2441}\x{2442} /[\W]/8g \x{2442}\x{2435}\x{2441}\x{2442} /[\S\s]*/8 abc\n\r\x{442}\x{435}\x{441}\x{442}xyz /[\x{41f}\S]/8g \x{442}\x{435}\x{441}\x{442} /.[^\S]./8g abc def\x{442}\x{443}xyz\npqr /.[^\S\n]./8g abc def\x{442}\x{443}xyz\npqr /[[:^alnum:]]/8g +\x{2442} /[[:^alpha:]]/8g +\x{2442} /[[:^ascii:]]/8g A\x{442} /[[:^blank:]]/8g A\x{442} /[[:^cntrl:]]/8g A\x{442} /[[:^digit:]]/8g A\x{442} /[[:^graph:]]/8g \x19\x{e01ff} /[[:^lower:]]/8g A\x{422} /[[:^print:]]/8g \x{19}\x{e01ff} /[[:^punct:]]/8g A\x{442} /[[:^space:]]/8g A\x{442} /[[:^upper:]]/8g a\x{442} /[[:^word:]]/8g +\x{2442} /[[:^xdigit:]]/8g M\x{442} /[^ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸŹŻŽƁƂƄƆƇƉƊƋƎƏƐƑƓƔƖƗƘƜƝƟƠƢƤƦƧƩƬƮƯƱƲƳƵƷƸƼDŽLJNJǍǏǑǓǕǗǙǛǞǠǢǤǦǨǪǬǮDZǴǶǷǸǺǼǾȀȂȄȆȈȊȌȎȐȒȔȖȘȚȜȞȠȢȤȦȨȪȬȮȰȲȺȻȽȾɁΆΈΉΊΌΎΏΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫϒϓϔϘϚϜϞϠϢϤϦϨϪϬϮϴϷϹϺϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎҐҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾӀӁӃӅӇӉӋӍӐӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӶӸԀԂԄԆԈԊԌԎԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖႠႡႢႣႤႥႦႧႨႩႪႫႬႭႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅḀḂḄḆḈḊḌḎḐḒḔḖḘḚḜḞḠḢḤḦḨḪḬḮḰḲḴḶḸḺḼḾṀṂṄṆṈṊṌṎṐṒṔṖṘṚṜṞṠṢṤṦṨṪṬṮṰṲṴṶṸṺṼṾẀẂẄẆẈẊẌẎẐẒẔẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼẾỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỬỮỰỲỴỶỸἈἉἊἋἌἍἎἏἘἙἚἛἜἝἨἩἪἫἬἭἮἯἸἹἺἻἼἽἾἿὈὉὊὋὌὍὙὛὝὟὨὩὪὫὬὭὮὯᾸᾹᾺΆῈΈῊΉῘῙῚΊῨῩῪΎῬῸΌῺΏabcdefghijklmnopqrstuvwxyzªµºßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıijĵķĸĺļľŀłńņňʼnŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźżžſƀƃƅƈƌƍƒƕƙƚƛƞơƣƥƨƪƫƭưƴƶƹƺƽƾƿdžljnjǎǐǒǔǖǘǚǜǝǟǡǣǥǧǩǫǭǯǰdzǵǹǻǽǿȁȃȅȇȉȋȍȏȑȓȕȗșțȝȟȡȣȥȧȩȫȭȯȱȳȴȵȶȷȸȹȼȿɀɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώϐϑϕϖϗϙϛϝϟϡϣϥϧϩϫϭϯϰϱϲϳϵϸϻϼабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿҁҋҍҏґғҕҗҙқҝҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӂӄӆӈӊӌӎӑӓӕӗәӛӝӟӡӣӥӧөӫӭӯӱӳӵӷӹԁԃԅԇԉԋԍԏաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḁḃḅḇḉḋḍḏḑḓḕḗḙḛḝḟḡḣḥḧḩḫḭḯḱḳḵḷḹḻḽḿṁṃṅṇṉṋṍṏṑṓṕṗṙṛṝṟṡṣṥṧṩṫṭṯṱṳṵṷṹṻṽṿẁẃẅẇẉẋẍẏẑẓẕẖẗẘẙẚẛạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹἀἁἂἃἄἅἆἇἐἑἒἓἔἕἠἡἢἣἤἥἦἧἰἱἲἳἴἵἶἷὀὁὂὃὄὅὐὑὒὓὔὕὖὗὠὡὢὣὤὥὦὧὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷιῂῃῄῆῇῐῑῒΐῖῗῠῡῢΰῤῥῦῧῲῳῴῶῷⲁⲃⲅⲇⲉⲋⲍⲏⲑⲓⲕⲗⲙⲛⲝⲟⲡⲣⲥⲧⲩⲫⲭⲯⲱⲳⲵⲷⲹⲻⲽⲿⳁⳃⳅⳇⳉⳋⳍⳏⳑⳓⳕⳗⳙⳛⳝⳟⳡⳣⳤⴀⴁⴂⴃⴄⴅⴆⴇⴈⴉⴊⴋⴌⴍⴎⴏⴐⴑⴒⴓⴔⴕⴖⴗⴘⴙⴚⴛⴜⴝⴞⴟⴠⴡⴢⴣⴤⴥfffiflffifflſtstﬓﬔﬕﬖﬗ\d-_^]/8 /^[^d]*?$/ abc /^[^d]*?$/8 abc /^[^d]*?$/i abc /^[^d]*?$/8i abc /(?i)[\xc3\xa9\xc3\xbd]|[\xc3\xa9\xc3\xbdA]/8 /^[a\x{c0}]b/8 \x{c0}b /^([a\x{c0}]*?)aa/8 a\x{c0}aaaa/ /^([a\x{c0}]*?)aa/8 a\x{c0}aaaa/ a\x{c0}a\x{c0}aaa/ /^([a\x{c0}]*)aa/8 a\x{c0}aaaa/ a\x{c0}a\x{c0}aaa/ /^([a\x{c0}]*)a\x{c0}/8 a\x{c0}aaaa/ a\x{c0}a\x{c0}aaa/ /A*/g8 AAB\x{123}BAA /(abc)\1/8i abc /(abc)\1/8 abc /a(*:a\x{1234}b)/8K abc /a(*:a£b)/8K abc /-- Noncharacters --/ /./8 \x{fffe} \x{ffff} \x{1fffe} \x{1ffff} \x{2fffe} \x{2ffff} \x{3fffe} \x{3ffff} \x{4fffe} \x{4ffff} \x{5fffe} \x{5ffff} \x{6fffe} \x{6ffff} \x{7fffe} \x{7ffff} \x{8fffe} \x{8ffff} \x{9fffe} \x{9ffff} \x{afffe} \x{affff} \x{bfffe} \x{bffff} \x{cfffe} \x{cffff} \x{dfffe} \x{dffff} \x{efffe} \x{effff} \x{ffffe} \x{fffff} \x{10fffe} \x{10ffff} \x{fdd0} \x{fdd1} \x{fdd2} \x{fdd3} \x{fdd4} \x{fdd5} \x{fdd6} \x{fdd7} \x{fdd8} \x{fdd9} \x{fdda} \x{fddb} \x{fddc} \x{fddd} \x{fdde} \x{fddf} \x{fde0} \x{fde1} \x{fde2} \x{fde3} \x{fde4} \x{fde5} \x{fde6} \x{fde7} \x{fde8} \x{fde9} \x{fdea} \x{fdeb} \x{fdec} \x{fded} \x{fdee} \x{fdef} /^\d*\w{4}/8 1234 123 /^[^b]*\w{4}/8 aaaa aaa /^[^b]*\w{4}/8i aaaa aaa /^\x{100}*.{4}/8 \x{100}\x{100}\x{100}\x{100} \x{100}\x{100}\x{100} /^\x{100}*.{4}/8i \x{100}\x{100}\x{100}\x{100} \x{100}\x{100}\x{100} /^a+[a\x{200}]/8 aa /^.\B.\B./8 \x{10123}\x{10124}\x{10125} /^#[^\x{ffff}]#[^\x{ffff}]#[^\x{ffff}]#/8 #\x{10000}#\x{100}#\x{10ffff}# "[\S\V\H]"8 /\C(\W?ſ)'?{{/8 \\C(\\W?ſ)'?{{ /[^\x{100}-\x{ffff}]*[\x80-\xff]/8 \x{99}\x{99}\x{99} /-- End of testinput4 --/ ================================================ FILE: src/pcre/testdata/testinput5 ================================================ /-- This set of tests checks the API, internals, and non-Perl stuff for UTF support, excluding Unicode properties. However, tests that give different results in 8-bit and 16-bit modes are excluded (see tests 16 and 17). --/ < forbid W /\x{110000}/8DZ /\o{4200000}/8DZ /\x{ffffffff}/8 /\o{37777777777}/8 /\x{100000000}/8 /\o{77777777777}/8 /\x{d800}/8 /\o{154000}/8 /\x{dfff}/8 /\o{157777}/8 /\x{d7ff}/8 /\o{153777}/8 /\x{e000}/8 /\o{170000}/8 /^\x{100}a\x{1234}/8 \x{100}a\x{1234}bcd /\x{0041}\x{2262}\x{0391}\x{002e}/DZ8 \x{0041}\x{2262}\x{0391}\x{002e} /.{3,5}X/DZ8 \x{212ab}\x{212ab}\x{212ab}\x{861}X /.{3,5}?/DZ8 \x{212ab}\x{212ab}\x{212ab}\x{861} /(?<=\C)X/8 Should produce an error diagnostic /^[ab]/8DZ bar *** Failers c \x{ff} \x{100} /^[^ab]/8DZ c \x{ff} \x{100} *** Failers aaa /\x{100}*(\d+|"(?1)")/8 1234 "1234" \x{100}1234 "\x{100}1234" \x{100}\x{100}12ab \x{100}\x{100}"12" *** Failers \x{100}\x{100}abcd /\x{100}*/8DZ /a\x{100}*/8DZ /ab\x{100}*/8DZ /\x{100}*A/8DZ A /\x{100}*\d(?R)/8DZ /[Z\x{100}]/8DZ Z\x{100} \x{100} \x{100}Z *** Failers /[\x{200}-\x{100}]/8 /[Ā-Ą]/8 \x{100} \x{104} *** Failers \x{105} \x{ff} /[z-\x{100}]/8DZ /[z\Qa-d]Ā\E]/8DZ \x{100} Ā /[\xFF]/DZ >\xff< /[^\xFF]/DZ /[Ä-Ü]/8 Ö # Matches without Study \x{d6} /[Ä-Ü]/8S Ö <-- Same with Study \x{d6} /[\x{c4}-\x{dc}]/8 Ö # Matches without Study \x{d6} /[\x{c4}-\x{dc}]/8S Ö <-- Same with Study \x{d6} /[^\x{100}]abc(xyz(?1))/8DZ /[ab\x{100}]abc(xyz(?1))/8DZ /(\x{100}(b(?2)c))?/DZ8 /(\x{100}(b(?2)c)){0,2}/DZ8 /(\x{100}(b(?1)c))?/DZ8 /(\x{100}(b(?1)c)){0,2}/DZ8 /\W/8 A.B A\x{100}B /\w/8 \x{100}X /^\ሴ/8DZ /\x{100}*\d/8DZ /\x{100}*\s/8DZ /\x{100}*\w/8DZ /\x{100}*\D/8DZ /\x{100}*\S/8DZ /\x{100}*\W/8DZ /()()()()()()()()()() ()()()()()()()()()() ()()()()()()()()()() ()()()()()()()()()() A (x) (?41) B/8x AxxB /^[\x{100}\E-\Q\E\x{150}]/BZ8 /^[\QĀ\E-\QŐ\E]/BZ8 /^abc./mgx8 abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x{0085}abc7 \x{2028}abc8 \x{2029}abc9 JUNK /abc.$/mgx8 abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x{0085} abc7\x{2028} abc8\x{2029} abc9 /^a\Rb/8 a\nb a\rb a\r\nb a\x0bb a\x0cb a\x{85}b a\x{2028}b a\x{2029}b ** Failers a\n\rb /^a\R*b/8 ab a\nb a\rb a\r\nb a\x0bb a\x0c\x{2028}\x{2029}b a\x{85}b a\n\rb a\n\r\x{85}\x0cb /^a\R+b/8 a\nb a\rb a\r\nb a\x0bb a\x0c\x{2028}\x{2029}b a\x{85}b a\n\rb a\n\r\x{85}\x0cb ** Failers ab /^a\R{1,3}b/8 a\nb a\n\rb a\n\r\x{85}b a\r\n\r\nb a\r\n\r\n\r\nb a\n\r\n\rb a\n\n\r\nb ** Failers a\n\n\n\rb a\r /\H\h\V\v/8 X X\x0a X\x09X\x0b ** Failers \x{a0} X\x0a /\H*\h+\V?\v{3,4}/8 \x09\x20\x{a0}X\x0a\x0b\x0c\x0d\x0a \x09\x20\x{a0}\x0a\x0b\x0c\x0d\x0a \x09\x20\x{a0}\x0a\x0b\x0c ** Failers \x09\x20\x{a0}\x0a\x0b /\H\h\V\v/8 \x{3001}\x{3000}\x{2030}\x{2028} X\x{180e}X\x{85} ** Failers \x{2009} X\x0a /\H*\h+\V?\v{3,4}/8 \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x0c\x0d\x0a \x09\x{205f}\x{a0}\x0a\x{2029}\x0c\x{2028}\x0a \x09\x20\x{202f}\x0a\x0b\x0c ** Failers \x09\x{200a}\x{a0}\x{2028}\x0b /[\h]/8BZ >\x{1680} /[\h]{3,}/8BZ >\x{1680}\x{180e}\x{2000}\x{2003}\x{200a}\x{202f}\x{205f}\x{3000}< /[\v]/8BZ /[\H]/8BZ /[\V]/8BZ /.*$/8 \x{1ec5} /a\Rb/I8 a\rb a\nb a\r\nb ** Failers a\x{85}b a\x0bb /a\Rb/I8 a\rb a\nb a\r\nb a\x{85}b a\x0bb ** Failers a\x{85}b\ a\x0bb\ /a\R?b/I8 a\rb a\nb a\r\nb ** Failers a\x{85}b a\x0bb /a\R?b/I8 a\rb a\nb a\r\nb a\x{85}b a\x0bb ** Failers a\x{85}b\ a\x0bb\ /.*a.*=.b.*/8 QQQ\x{2029}ABCaXYZ=!bPQR ** Failers a\x{2029}b \x61\xe2\x80\xa9\x62 /[[:a\x{100}b:]]/8 /a[^]b/8 a\x{1234}b a\nb ** Failers ab /a[^]+b/8 aXb a\nX\nX\x{1234}b ** Failers ab /(\x{de})\1/ \x{de}\x{de} /X/8f A\x{1ec5}ABCXYZ /Xa{2,4}b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /Xa{2,4}?b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /Xa{2,4}+b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\x{123}{2,4}b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X\x{123}{2,4}?b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X\x{123}{2,4}+b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X\x{123}{2,4}b/8 Xx\P X\x{123}x\P X\x{123}\x{123}x\P X\x{123}\x{123}\x{123}x\P X\x{123}\x{123}\x{123}\x{123}x\P /X\x{123}{2,4}?b/8 Xx\P X\x{123}x\P X\x{123}\x{123}x\P X\x{123}\x{123}\x{123}x\P X\x{123}\x{123}\x{123}\x{123}x\P /X\x{123}{2,4}+b/8 Xx\P X\x{123}x\P X\x{123}\x{123}x\P X\x{123}\x{123}\x{123}x\P X\x{123}\x{123}\x{123}\x{123}x\P /X\d{2,4}b/8 X\P X3\P X33\P X333\P X3333\P /X\d{2,4}?b/8 X\P X3\P X33\P X333\P X3333\P /X\d{2,4}+b/8 X\P X3\P X33\P X333\P X3333\P /X\D{2,4}b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\D{2,4}?b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\D{2,4}+b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X\D{2,4}b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X\D{2,4}?b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X\D{2,4}+b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X[abc]{2,4}b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[abc]{2,4}?b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[abc]{2,4}+b/8 X\P Xa\P Xaa\P Xaaa\P Xaaaa\P /X[abc\x{123}]{2,4}b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X[abc\x{123}]{2,4}?b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X[abc\x{123}]{2,4}+b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X[^a]{2,4}b/8 X\P Xz\P Xzz\P Xzzz\P Xzzzz\P /X[^a]{2,4}?b/8 X\P Xz\P Xzz\P Xzzz\P Xzzzz\P /X[^a]{2,4}+b/8 X\P Xz\P Xzz\P Xzzz\P Xzzzz\P /X[^a]{2,4}b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X[^a]{2,4}?b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /X[^a]{2,4}+b/8 X\P X\x{123}\P X\x{123}\x{123}\P X\x{123}\x{123}\x{123}\P X\x{123}\x{123}\x{123}\x{123}\P /(Y)X\1{2,4}b/8 YX\P YXY\P YXYY\P YXYYY\P YXYYYY\P /(Y)X\1{2,4}?b/8 YX\P YXY\P YXYY\P YXYYY\P YXYYYY\P /(Y)X\1{2,4}+b/8 YX\P YXY\P YXYY\P YXYYY\P YXYYYY\P /(\x{123})X\1{2,4}b/8 \x{123}X\P \x{123}X\x{123}\P \x{123}X\x{123}\x{123}\P \x{123}X\x{123}\x{123}\x{123}\P \x{123}X\x{123}\x{123}\x{123}\x{123}\P /(\x{123})X\1{2,4}?b/8 \x{123}X\P \x{123}X\x{123}\P \x{123}X\x{123}\x{123}\P \x{123}X\x{123}\x{123}\x{123}\P \x{123}X\x{123}\x{123}\x{123}\x{123}\P /(\x{123})X\1{2,4}+b/8 \x{123}X\P \x{123}X\x{123}\P \x{123}X\x{123}\x{123}\P \x{123}X\x{123}\x{123}\x{123}\P \x{123}X\x{123}\x{123}\x{123}\x{123}\P /\bthe cat\b/8 the cat\P the cat\P\P /abcd*/8 xxxxabcd\P xxxxabcd\P\P /abcd*/i8 xxxxabcd\P xxxxabcd\P\P XXXXABCD\P XXXXABCD\P\P /abc\d*/8 xxxxabc1\P xxxxabc1\P\P /(a)bc\1*/8 xxxxabca\P xxxxabca\P\P /abc[de]*/8 xxxxabcde\P xxxxabcde\P\P /X\W{3}X/8 \PX /\sxxx\s/8T1 AB\x{85}xxx\x{a0}XYZ AB\x{a0}xxx\x{85}XYZ /\S \S/8T1 \x{a2} \x{84} 'A#хц'8xBZ 'A#хц PQ'8xBZ /a+#хaa z#XX?/8xBZ /a+#хaa z#х?/8xBZ /\g{A}xxx#bXX(?'A'123) (?'A'456)/8xBZ /\g{A}xxx#bх(?'A'123) (?'A'456)/8xBZ /^\cģ/8 /(\R*)(.)/s8 \r\n \r\r\n\n\r \r\r\n\n\r\n /(\R)*(.)/s8 \r\n \r\r\n\n\r \r\r\n\n\r\n /[^\x{1234}]+/iS8I /[^\x{1234}]+?/iS8I /[^\x{1234}]++/iS8I /[^\x{1234}]{2}/iS8I // /f.*/ \P\Pfor /f.*/s \P\Pfor /f.*/8 \P\Pfor /f.*/8s \P\Pfor /\x{d7ff}\x{e000}/8 /\x{d800}/8 /\x{dfff}/8 /\h+/8 \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\x{a0}\x{2000} /[\h\x{e000}]+/8BZ \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\x{a0}\x{2000} /\H+/8 \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} \x{a0}\x{3000}\x{9f}\x{a1}\x{2fff}\x{3001} /[\H\x{d7ff}]+/8BZ \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} \x{a0}\x{3000}\x{9f}\x{a1}\x{2fff}\x{3001} /\v+/8 \x{2027}\x{2030}\x{2028}\x{2029} \x09\x0e\x{84}\x{86}\x{85}\x0a\x0b\x0c\x0d /[\v\x{e000}]+/8BZ \x{2027}\x{2030}\x{2028}\x{2029} \x09\x0e\x{84}\x{86}\x{85}\x0a\x0b\x0c\x0d /\V+/8 \x{2028}\x{2029}\x{2027}\x{2030} \x{85}\x0a\x0b\x0c\x0d\x09\x0e\x{84}\x{86} /[\V\x{d7ff}]+/8BZ \x{2028}\x{2029}\x{2027}\x{2030} \x{85}\x0a\x0b\x0c\x0d\x09\x0e\x{84}\x{86} /\R+/8 \x{2027}\x{2030}\x{2028}\x{2029} \x09\x0e\x{84}\x{86}\x{85}\x0a\x0b\x0c\x0d /(..)\1/8 ab\P aba\P abab\P /(..)\1/8i ab\P abA\P aBAb\P /(..)\1{2,}/8 ab\P aba\P abab\P ababa\P ababab\P ababab\P\P abababa\P abababa\P\P /(..)\1{2,}/8i ab\P aBa\P aBAb\P AbaBA\P abABAb\P aBAbaB\P\P abABabA\P abaBABa\P\P /(..)\1{2,}?x/8i ab\P abA\P aBAb\P abaBA\P abAbaB\P abaBabA\P abAbABaBx\P /./8 \r\P \r\P\P /.{2,3}/8 \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /.{2,3}?/8 \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /[^\x{100}][^\x{1234}][^\x{ffff}][^\x{10000}][^\x{10ffff}]/8BZ /[^\x{100}][^\x{1234}][^\x{ffff}][^\x{10000}][^\x{10ffff}]/8BZi /[^\x{100}]*[^\x{10000}]+[^\x{10ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{fffff}]{5,6}+/8BZ /[^\x{100}]*[^\x{10000}]+[^\x{10ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{fffff}]{5,6}+/8BZi /(?<=\x{1234}\x{1234})\bxy/I8 /(?8BZ /[\u0100-\u0200]/8BZ /\ud800/8 /^a+[a\x{200}]/8BZ aa /[b-d\x{200}-\x{250}]*[ae-h]?#[\x{200}-\x{250}]{0,8}[\x00-\xff]*#[\x{200}-\x{250}]+[a-z]/8BZ /[^\xff]*PRUNE:\x{100}abc(xyz(?1))/8DZ /(?<=\K\x{17f})/8g+ \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} /(?<=\K\x{17f})/8G+ \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} /\C[^\v]+\x80/8 [AΏBŀC] /\C[^\d]+\x80/8 [AΏBŀC] /-- End of testinput5 --/ ================================================ FILE: src/pcre/testdata/testinput6 ================================================ /-- This set of tests is for Unicode property support. It is compatible with Perl >= 5.15. --/ < forbid 9?=ABCDEFfGILMNPTUXZ< /^\pC\pL\pM\pN\pP\pS\pZ\s+/8W >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} /^>\pZ+/8W >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} /^>[[:space:]]*/8W >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} /^>[[:blank:]]*/8W >\x{20}\x{a0}\x{1680}\x{180e}\x{2000}\x{202f}\x{9}\x{b}\x{2028} /^[[:alpha:]]*/8W Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d} /^[[:alnum:]]*/8W Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee} /^[[:cntrl:]]*/8W \x{0}\x{09}\x{1f}\x{7f}\x{9f} /^[[:graph:]]*/8W A\x{a1}\x{a0} /^[[:print:]]*/8W A z\x{a0}\x{a1} /^[[:punct:]]*/8W .+\x{a1}\x{a0} /\p{Zs}*?\R/ ** Failers a\xFCb /\p{Zs}*\R/ ** Failers a\xFCb /ⱥ/8i ⱥ Ⱥx Ⱥ /[ⱥ]/8i ⱥ Ⱥx Ⱥ /Ⱥ/8i Ⱥ ⱥ /-- These are tests for extended grapheme clusters --/ /^\X/8+ G\x{34e}\x{34e}X \x{34e}\x{34e}X \x04X \x{1100}X \x{1100}\x{34e}X \x{1b04}\x{1b04}X *These match up to the roman letters \x{1111}\x{1111}L,L \x{1111}\x{1111}\x{1169}L,L,V \x{1111}\x{ae4c}L, LV \x{1111}\x{ad89}L, LVT \x{1111}\x{ae4c}\x{1169}L, LV, V \x{1111}\x{ae4c}\x{1169}\x{1169}L, LV, V, V \x{1111}\x{ae4c}\x{1169}\x{11fe}L, LV, V, T \x{1111}\x{ad89}\x{11fe}L, LVT, T \x{1111}\x{ad89}\x{11fe}\x{11fe}L, LVT, T, T \x{ad89}\x{11fe}\x{11fe}LVT, T, T *These match just the first codepoint (invalid sequence) \x{1111}\x{11fe}L, T \x{ae4c}\x{1111}LV, L \x{ae4c}\x{ae4c}LV, LV \x{ae4c}\x{ad89}LV, LVT \x{1169}\x{1111}V, L \x{1169}\x{ae4c}V, LV \x{1169}\x{ad89}V, LVT \x{ad89}\x{1111}LVT, L \x{ad89}\x{1169}LVT, V \x{ad89}\x{ae4c}LVT, LV \x{ad89}\x{ad89}LVT, LVT \x{11fe}\x{1111}T, L \x{11fe}\x{1169}T, V \x{11fe}\x{ae4c}T, LV \x{11fe}\x{ad89}T, LVT *Test extend and spacing mark \x{1111}\x{ae4c}\x{0711}L, LV, extend \x{1111}\x{ae4c}\x{1b04}L, LV, spacing mark \x{1111}\x{ae4c}\x{1b04}\x{0711}\x{1b04}L, LV, spacing mark, extend, spacing mark *Test CR, LF, and control \x0d\x{0711}CR, extend \x0d\x{1b04}CR, spacingmark \x0a\x{0711}LF, extend \x0a\x{1b04}LF, spacingmark \x0b\x{0711}Control, extend \x09\x{1b04}Control, spacingmark *There are no Prepend characters, so we can't test Prepend, CR /^(?>\X{2})X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X /^\X{2,4}X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X /^\X{2,4}?X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X /\X*Z/8Y A\x{300} /\X*(.)/8Y A\x{1111}\x{ae4c}\x{1169} /\X?abc/8Y \xff\x7f\x00\x00\x03\x00\x41\xcc\x80\x41\x{300}\x61\x62\x63\x00\>06\? /-- --/ /\x{1e9e}+/8i \x{1e9e}\x{00df} /[z\x{1e9e}]+/8i \x{1e9e}\x{00df} /\x{00df}+/8i \x{1e9e}\x{00df} /[z\x{00df}]+/8i \x{1e9e}\x{00df} /\x{1f88}+/8i \x{1f88}\x{1f80} /[z\x{1f88}]+/8i \x{1f88}\x{1f80} /-- Characters with more than one other case; test in classes --/ /[z\x{00b5}]+/8i \x{00b5}\x{039c}\x{03bc} /[z\x{039c}]+/8i \x{00b5}\x{039c}\x{03bc} /[z\x{03bc}]+/8i \x{00b5}\x{039c}\x{03bc} /[z\x{00c5}]+/8i \x{00c5}\x{00e5}\x{212b} /[z\x{00e5}]+/8i \x{00c5}\x{00e5}\x{212b} /[z\x{212b}]+/8i \x{00c5}\x{00e5}\x{212b} /[z\x{01c4}]+/8i \x{01c4}\x{01c5}\x{01c6} /[z\x{01c5}]+/8i \x{01c4}\x{01c5}\x{01c6} /[z\x{01c6}]+/8i \x{01c4}\x{01c5}\x{01c6} /[z\x{01c7}]+/8i \x{01c7}\x{01c8}\x{01c9} /[z\x{01c8}]+/8i \x{01c7}\x{01c8}\x{01c9} /[z\x{01c9}]+/8i \x{01c7}\x{01c8}\x{01c9} /[z\x{01ca}]+/8i \x{01ca}\x{01cb}\x{01cc} /[z\x{01cb}]+/8i \x{01ca}\x{01cb}\x{01cc} /[z\x{01cc}]+/8i \x{01ca}\x{01cb}\x{01cc} /[z\x{01f1}]+/8i \x{01f1}\x{01f2}\x{01f3} /[z\x{01f2}]+/8i \x{01f1}\x{01f2}\x{01f3} /[z\x{01f3}]+/8i \x{01f1}\x{01f2}\x{01f3} /[z\x{0345}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /[z\x{0399}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /[z\x{03b9}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /[z\x{1fbe}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /[z\x{0392}]+/8i \x{0392}\x{03b2}\x{03d0} /[z\x{03b2}]+/8i \x{0392}\x{03b2}\x{03d0} /[z\x{03d0}]+/8i \x{0392}\x{03b2}\x{03d0} /[z\x{0395}]+/8i \x{0395}\x{03b5}\x{03f5} /[z\x{03b5}]+/8i \x{0395}\x{03b5}\x{03f5} /[z\x{03f5}]+/8i \x{0395}\x{03b5}\x{03f5} /[z\x{0398}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /[z\x{03b8}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /[z\x{03d1}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /[z\x{03f4}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /[z\x{039a}]+/8i \x{039a}\x{03ba}\x{03f0} /[z\x{03ba}]+/8i \x{039a}\x{03ba}\x{03f0} /[z\x{03f0}]+/8i \x{039a}\x{03ba}\x{03f0} /[z\x{03a0}]+/8i \x{03a0}\x{03c0}\x{03d6} /[z\x{03c0}]+/8i \x{03a0}\x{03c0}\x{03d6} /[z\x{03d6}]+/8i \x{03a0}\x{03c0}\x{03d6} /[z\x{03a1}]+/8i \x{03a1}\x{03c1}\x{03f1} /[z\x{03c1}]+/8i \x{03a1}\x{03c1}\x{03f1} /[z\x{03f1}]+/8i \x{03a1}\x{03c1}\x{03f1} /[z\x{03a3}]+/8i \x{03A3}\x{03C2}\x{03C3} /[z\x{03c2}]+/8i \x{03A3}\x{03C2}\x{03C3} /[z\x{03c3}]+/8i \x{03A3}\x{03C2}\x{03C3} /[z\x{03a6}]+/8i \x{03a6}\x{03c6}\x{03d5} /[z\x{03c6}]+/8i \x{03a6}\x{03c6}\x{03d5} /[z\x{03d5}]+/8i \x{03a6}\x{03c6}\x{03d5} /[z\x{03c9}]+/8i \x{03c9}\x{03a9}\x{2126} /[z\x{03a9}]+/8i \x{03c9}\x{03a9}\x{2126} /[z\x{2126}]+/8i \x{03c9}\x{03a9}\x{2126} /[z\x{1e60}]+/8i \x{1e60}\x{1e61}\x{1e9b} /[z\x{1e61}]+/8i \x{1e60}\x{1e61}\x{1e9b} /[z\x{1e9b}]+/8i \x{1e60}\x{1e61}\x{1e9b} /-- Perl 5.12.4 gets these wrong, but 5.15.3 is OK --/ /[z\x{004b}]+/8i \x{004b}\x{006b}\x{212a} /[z\x{006b}]+/8i \x{004b}\x{006b}\x{212a} /[z\x{212a}]+/8i \x{004b}\x{006b}\x{212a} /[z\x{0053}]+/8i \x{0053}\x{0073}\x{017f} /[z\x{0073}]+/8i \x{0053}\x{0073}\x{017f} /[z\x{017f}]+/8i \x{0053}\x{0073}\x{017f} /-- --/ /(ΣΆΜΟΣ) \1/8i ΣΆΜΟΣ ΣΆΜΟΣ ΣΆΜΟΣ σάμος σάμος σάμος σάμος σάμοσ σάμος ΣΆΜΟΣ /(σάμος) \1/8i ΣΆΜΟΣ ΣΆΜΟΣ ΣΆΜΟΣ σάμος σάμος σάμος σάμος σάμοσ σάμος ΣΆΜΟΣ /(ΣΆΜΟΣ) \1*/8i ΣΆΜΟΣ\x20 ΣΆΜΟΣ ΣΆΜΟΣσάμοςσάμος /-- Perl matches these --/ /\x{00b5}+/8i \x{00b5}\x{039c}\x{03bc} /\x{039c}+/8i \x{00b5}\x{039c}\x{03bc} /\x{03bc}+/8i \x{00b5}\x{039c}\x{03bc} /\x{00c5}+/8i \x{00c5}\x{00e5}\x{212b} /\x{00e5}+/8i \x{00c5}\x{00e5}\x{212b} /\x{212b}+/8i \x{00c5}\x{00e5}\x{212b} /\x{01c4}+/8i \x{01c4}\x{01c5}\x{01c6} /\x{01c5}+/8i \x{01c4}\x{01c5}\x{01c6} /\x{01c6}+/8i \x{01c4}\x{01c5}\x{01c6} /\x{01c7}+/8i \x{01c7}\x{01c8}\x{01c9} /\x{01c8}+/8i \x{01c7}\x{01c8}\x{01c9} /\x{01c9}+/8i \x{01c7}\x{01c8}\x{01c9} /\x{01ca}+/8i \x{01ca}\x{01cb}\x{01cc} /\x{01cb}+/8i \x{01ca}\x{01cb}\x{01cc} /\x{01cc}+/8i \x{01ca}\x{01cb}\x{01cc} /\x{01f1}+/8i \x{01f1}\x{01f2}\x{01f3} /\x{01f2}+/8i \x{01f1}\x{01f2}\x{01f3} /\x{01f3}+/8i \x{01f1}\x{01f2}\x{01f3} /\x{0345}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{0399}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{03b9}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{1fbe}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} /\x{0392}+/8i \x{0392}\x{03b2}\x{03d0} /\x{03b2}+/8i \x{0392}\x{03b2}\x{03d0} /\x{03d0}+/8i \x{0392}\x{03b2}\x{03d0} /\x{0395}+/8i \x{0395}\x{03b5}\x{03f5} /\x{03b5}+/8i \x{0395}\x{03b5}\x{03f5} /\x{03f5}+/8i \x{0395}\x{03b5}\x{03f5} /\x{0398}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{03b8}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{03d1}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{03f4}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} /\x{039a}+/8i \x{039a}\x{03ba}\x{03f0} /\x{03ba}+/8i \x{039a}\x{03ba}\x{03f0} /\x{03f0}+/8i \x{039a}\x{03ba}\x{03f0} /\x{03a0}+/8i \x{03a0}\x{03c0}\x{03d6} /\x{03c0}+/8i \x{03a0}\x{03c0}\x{03d6} /\x{03d6}+/8i \x{03a0}\x{03c0}\x{03d6} /\x{03a1}+/8i \x{03a1}\x{03c1}\x{03f1} /\x{03c1}+/8i \x{03a1}\x{03c1}\x{03f1} /\x{03f1}+/8i \x{03a1}\x{03c1}\x{03f1} /\x{03a3}+/8i \x{03A3}\x{03C2}\x{03C3} /\x{03c2}+/8i \x{03A3}\x{03C2}\x{03C3} /\x{03c3}+/8i \x{03A3}\x{03C2}\x{03C3} /\x{03a6}+/8i \x{03a6}\x{03c6}\x{03d5} /\x{03c6}+/8i \x{03a6}\x{03c6}\x{03d5} /\x{03d5}+/8i \x{03a6}\x{03c6}\x{03d5} /\x{03c9}+/8i \x{03c9}\x{03a9}\x{2126} /\x{03a9}+/8i \x{03c9}\x{03a9}\x{2126} /\x{2126}+/8i \x{03c9}\x{03a9}\x{2126} /\x{1e60}+/8i \x{1e60}\x{1e61}\x{1e9b} /\x{1e61}+/8i \x{1e60}\x{1e61}\x{1e9b} /\x{1e9b}+/8i \x{1e60}\x{1e61}\x{1e9b} /\x{1e9e}+/8i \x{1e9e}\x{00df} /\x{00df}+/8i \x{1e9e}\x{00df} /\x{1f88}+/8i \x{1f88}\x{1f80} /\x{1f80}+/8i \x{1f88}\x{1f80} /-- Perl 5.12.4 gets these wrong, but 5.15.3 is OK --/ /\x{004b}+/8i \x{004b}\x{006b}\x{212a} /\x{006b}+/8i \x{004b}\x{006b}\x{212a} /\x{212a}+/8i \x{004b}\x{006b}\x{212a} /\x{0053}+/8i \x{0053}\x{0073}\x{017f} /\x{0073}+/8i \x{0053}\x{0073}\x{017f} /\x{017f}+/8i \x{0053}\x{0073}\x{017f} /^\p{Any}*\d{4}/8 1234 123 /^\X*\w{4}/8 1234 123 /^A\s+Z/8W A\x{2005}Z A\x{85}\x{180e}\x{2005}Z /^A[\s]+Z/8W A\x{2005}Z A\x{85}\x{180e}\x{2005}Z /^[[:graph:]]+$/8W Letter:ABC Mark:\x{300}\x{1d172}\x{1d17b} Number:9\x{660} Punctuation:\x{66a},; Symbol:\x{6de}<>\x{fffc} Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} \x{feff} \x{fff9}\x{fffa}\x{fffb} \x{110bd} \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} \x{e0001} \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} ** Failers \x{09} \x{0a} \x{1D} \x{20} \x{85} \x{a0} \x{61c} \x{1680} \x{180e} \x{2028} \x{2029} \x{202f} \x{2065} \x{2066} \x{2067} \x{2068} \x{2069} \x{3000} \x{e0002} \x{e001f} \x{e0080} /^[[:print:]]+$/8W Space: \x{a0} \x{1680}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005} \x{2006}\x{2007}\x{2008}\x{2009}\x{200a} \x{202f}\x{205f} \x{3000} Letter:ABC Mark:\x{300}\x{1d172}\x{1d17b} Number:9\x{660} Punctuation:\x{66a},; Symbol:\x{6de}<>\x{fffc} Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} \x{180e} \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} \x{202f} \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} \x{feff} \x{fff9}\x{fffa}\x{fffb} \x{110bd} \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} \x{e0001} \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} ** Failers \x{09} \x{1D} \x{85} \x{61c} \x{2028} \x{2029} \x{2065} \x{2066} \x{2067} \x{2068} \x{2069} \x{e0002} \x{e001f} \x{e0080} /^[[:punct:]]+$/8W \$+<=>^`|~ !\"#%&'()*,-./:;?@[\\]_{} \x{a1}\x{a7} \x{37e} ** Failers abcde /^[[:^graph:]]+$/8W \x{09}\x{0a}\x{1D}\x{20}\x{85}\x{a0}\x{61c}\x{1680}\x{180e} \x{2028}\x{2029}\x{202f}\x{2065}\x{2066}\x{2067}\x{2068}\x{2069} \x{3000}\x{e0002}\x{e001f}\x{e0080} ** Failers Letter:ABC Mark:\x{300}\x{1d172}\x{1d17b} Number:9\x{660} Punctuation:\x{66a},; Symbol:\x{6de}<>\x{fffc} Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} \x{feff} \x{fff9}\x{fffa}\x{fffb} \x{110bd} \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} \x{e0001} \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} /^[[:^print:]]+$/8W \x{09}\x{1D}\x{85}\x{61c}\x{2028}\x{2029}\x{2065}\x{2066}\x{2067} \x{2068}\x{2069}\x{e0002}\x{e001f}\x{e0080} ** Failers Space: \x{a0} \x{1680}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005} \x{2006}\x{2007}\x{2008}\x{2009}\x{200a} \x{202f}\x{205f} \x{3000} Letter:ABC Mark:\x{300}\x{1d172}\x{1d17b} Number:9\x{660} Punctuation:\x{66a},; Symbol:\x{6de}<>\x{fffc} Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} \x{180e} \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} \x{202f} \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} \x{feff} \x{fff9}\x{fffa}\x{fffb} \x{110bd} \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} \x{e0001} \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} /^[[:^punct:]]+$/8W abcde ** Failers \$+<=>^`|~ !\"#%&'()*,-./:;?@[\\]_{} \x{a1}\x{a7} \x{37e} /[RST]+/8iW Ss\x{17f} /[R-T]+/8iW Ss\x{17f} /[q-u]+/8iW Ss\x{17f} /^s?c/mi8 scat /[A-`]/i8 abcdefghijklmno /\C\X*QT/8 Ӆ\x0aT /[\pS#moq]/ = /[[:punct:]]/8W \xc2\xb4 \x{b4} /[[:^ascii:]]/8W \x{100} \x{200} \x{300} \x{37e} a 9 g /[[:^ascii:]\w]/8W a 9 g \x{100} \x{200} \x{300} \x{37e} /[\w[:^ascii:]]/8W a 9 g \x{100} \x{200} \x{300} \x{37e} /[^[:ascii:]\W]/8W a 9 g \x{100} \x{200} \x{300} \x{37e} /[[:^ascii:]a]/8W a 9 g \x{100} \x{200} \x{37e} /[^[:^ascii:]\d]/8W a ~ 0 \a \x{7f} \x{389} \x{20ac} /(?=.*b)\pL/ 11bb /(?(?=.*b)(?=.*b)\pL|.*c)/ 11bb /-- End of testinput6 --/ ================================================ FILE: src/pcre/testdata/testinput7 ================================================ /-- These tests for Unicode property support test PCRE's API and show some of the compiled code. They are not Perl-compatible. --/ /[\p{L}]/DZ /[\p{^L}]/DZ /[\P{L}]/DZ /[\P{^L}]/DZ /[abc\p{L}\x{0660}]/8DZ /[\p{Nd}]/8DZ 1234 /[\p{Nd}+-]+/8DZ 1234 12-34 12+\x{661}-34 ** Failers abcd /[\x{105}-\x{109}]/8iDZ \x{104} \x{105} \x{109} ** Failers \x{100} \x{10a} /[z-\x{100}]/8iDZ Z z \x{39c} \x{178} | \x{80} \x{ff} \x{100} \x{101} ** Failers \x{102} Y y /[z-\x{100}]/8DZi /(?:[\PPa*]*){8,}/ /[\P{Any}]/BZ /[\P{Any}\E]/BZ /(\P{Yi}+\277)/ /(\P{Yi}+\277)?/ /(?<=\P{Yi}{3}A)X/ /\p{Yi}+(\P{Yi}+)(?1)/ /(\P{Yi}{2}\277)?/ /[\P{Yi}A]/ /[\P{Yi}\P{Yi}\P{Yi}A]/ /[^\P{Yi}A]/ /[^\P{Yi}\P{Yi}\P{Yi}A]/ /(\P{Yi}*\277)*/ /(\P{Yi}*?\277)*/ /(\p{Yi}*+\277)*/ /(\P{Yi}?\277)*/ /(\P{Yi}??\277)*/ /(\p{Yi}?+\277)*/ /(\P{Yi}{0,3}\277)*/ /(\P{Yi}{0,3}?\277)*/ /(\p{Yi}{0,3}+\277)*/ /\p{Zl}{2,3}+/8BZ 

 \x{2028}\x{2028}\x{2028} /\p{Zl}/8BZ /\p{Lu}{3}+/8BZ /\pL{2}+/8BZ /\p{Cc}{2}+/8BZ /^\p{Cf}/8 \x{180e} \x{061c} \x{2066} \x{2067} \x{2068} \x{2069} /^\p{Cs}/8 \?\x{dfff} ** Failers \x{09f} /^\p{Mn}/8 \x{1a1b} /^\p{Pe}/8 \x{2309} \x{230b} /^\p{Ps}/8 \x{2308} \x{230a} /^\p{Sc}+/8 $\x{a2}\x{a3}\x{a4}\x{a5}\x{a6} \x{9f2} ** Failers X \x{2c2} /^\p{Zs}/8 \ \ \x{a0} \x{1680} \x{2000} \x{2001} ** Failers \x{2028} \x{200d} /-- These are here rather than in test 6 because Perl has problems with the negative versions of the properties and behaves has changed how it behaves for caseless matching. --/ /\p{^Lu}/8i 1234 ** Failers ABC /\P{Lu}/8i 1234 ** Failers ABC /\p{Ll}/8i a Az ** Failers ABC /\p{Lu}/8i A a\x{10a0}B ** Failers a \x{1d00} /\p{Lu}/8i A aZ ** Failers abc /[\x{c0}\x{391}]/8i \x{c0} \x{e0} /-- The next two are special cases where the lengths of the different cases of the same character differ. The first went wrong with heap frame storage; the second was broken in all cases. --/ /^\x{023a}+?(\x{0130}+)/8i \x{023a}\x{2c65}\x{0130} /^\x{023a}+([^X])/8i \x{023a}\x{2c65}X /\x{c0}+\x{116}+/8i \x{c0}\x{e0}\x{116}\x{117} /[\x{c0}\x{116}]+/8i \x{c0}\x{e0}\x{116}\x{117} /(\x{de})\1/8i \x{de}\x{de} \x{de}\x{fe} \x{fe}\x{fe} \x{fe}\x{de} /^\x{c0}$/8i \x{c0} \x{e0} /^\x{e0}$/8i \x{c0} \x{e0} /-- The next two should be Perl-compatible, but it fails to match \x{e0}. PCRE will match it only with UCP support, because without that it has no notion of case for anything other than the ASCII letters. --/ /((?i)[\x{c0}])/8 \x{c0} \x{e0} /(?i:[\x{c0}])/8 \x{c0} \x{e0} /-- These are PCRE's extra properties to help with Unicodizing \d etc. --/ /^\p{Xan}/8 ABCD 1234 \x{6ca} \x{a6c} \x{10a7} ** Failers _ABC /^\p{Xan}+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ ** Failers _ABC /^\p{Xan}+?/8 \x{6ca}\x{a6c}\x{10a7}_ /^\p{Xan}*/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xan}{2,9}/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xan}{2,9}?/8 \x{6ca}\x{a6c}\x{10a7}_ /^[\p{Xan}]/8 ABCD1234_ 1234abcd_ \x{6ca} \x{a6c} \x{10a7} ** Failers _ABC /^[\p{Xan}]+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ ** Failers _ABC /^>\p{Xsp}/8 >\x{1680}\x{2028}\x{0b} >\x{a0} ** Failers \x{0b} /^>\p{Xsp}+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}+?/8 >\x{1680}\x{2028}\x{0b} /^>\p{Xsp}*/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}{2,9}/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}{2,9}?/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>[\p{Xsp}]/8 >\x{2028}\x{0b} /^>[\p{Xsp}]+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}/8 >\x{1680}\x{2028}\x{0b} >\x{a0} ** Failers \x{0b} /^>\p{Xps}+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}+?/8 >\x{1680}\x{2028}\x{0b} /^>\p{Xps}*/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}?/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>[\p{Xps}]/8 >\x{2028}\x{0b} /^>[\p{Xps}]+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^\p{Xwd}/8 ABCD 1234 \x{6ca} \x{a6c} \x{10a7} _ABC ** Failers [] /^\p{Xwd}+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}+?/8 \x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}*/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}{2,9}/8 A_B12\x{6ca}\x{a6c}\x{10a7} /^\p{Xwd}{2,9}?/8 \x{6ca}\x{a6c}\x{10a7}_ /^[\p{Xwd}]/8 ABCD1234_ 1234abcd_ \x{6ca} \x{a6c} \x{10a7} _ABC ** Failers [] /^[\p{Xwd}]+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /-- A check not in UTF-8 mode --/ /^[\p{Xwd}]+/ ABCD1234_ /-- Some negative checks --/ /^[\P{Xwd}]+/8 !.+\x{019}\x{35a}AB /^[\p{^Xwd}]+/8 !.+\x{019}\x{35a}AB /[\D]/WBZ8 1\x{3c8}2 /[\d]/WBZ8 >\x{6f4}< /[\S]/WBZ8 \x{1680}\x{6f4}\x{1680} /[\s]/WBZ8 >\x{1680}< /[\W]/WBZ8 A\x{1712}B /[\w]/WBZ8 >\x{1723}< /\D/WBZ8 1\x{3c8}2 /\d/WBZ8 >\x{6f4}< /\S/WBZ8 \x{1680}\x{6f4}\x{1680} /\s/WBZ8 >\x{1680}> /\W/WBZ8 A\x{1712}B /\w/WBZ8 >\x{1723}< /[[:alpha:]]/WBZ /[[:lower:]]/WBZ /[[:upper:]]/WBZ /[[:alnum:]]/WBZ /[[:ascii:]]/WBZ /[[:cntrl:]]/WBZ /[[:digit:]]/WBZ /[[:graph:]]/WBZ /[[:print:]]/WBZ /[[:punct:]]/WBZ /[[:space:]]/WBZ /[[:word:]]/WBZ /[[:xdigit:]]/WBZ /-- Unicode properties for \b abd \B --/ /\b...\B/8W abc_ \x{37e}abc\x{376} \x{37e}\x{376}\x{371}\x{393}\x{394} !\x{c0}++\x{c1}\x{c2} !\x{c0}+++++ /-- Without PCRE_UCP, non-ASCII always fail, even if < 256 --/ /\b...\B/8 abc_ ** Failers \x{37e}abc\x{376} \x{37e}\x{376}\x{371}\x{393}\x{394} !\x{c0}++\x{c1}\x{c2} !\x{c0}+++++ /-- With PCRE_UCP, non-UTF8 chars that are < 256 still check properties --/ /\b...\B/W abc_ !\x{c0}++\x{c1}\x{c2} !\x{c0}+++++ /-- Some of these are silly, but they check various combinations --/ /[[:^alpha:][:^cntrl:]]+/8WBZ 123 abc /[[:^cntrl:][:^alpha:]]+/8WBZ 123 abc /[[:alpha:]]+/8WBZ abc /[[:^alpha:]\S]+/8WBZ 123 abc /[^\d]+/8WBZ abc123 abc\x{123} \x{660}abc /\p{Lu}+9\p{Lu}+B\p{Lu}+b/BZ /\p{^Lu}+9\p{^Lu}+B\p{^Lu}+b/BZ /\P{Lu}+9\P{Lu}+B\P{Lu}+b/BZ /\p{Han}+X\p{Greek}+\x{370}/BZ8 /\p{Xan}+!\p{Xan}+A/BZ /\p{Xsp}+!\p{Xsp}\t/BZ /\p{Xps}+!\p{Xps}\t/BZ /\p{Xwd}+!\p{Xwd}_/BZ /A+\p{N}A+\dB+\p{N}*B+\d*/WBZ /-- These behaved oddly in Perl, so they are kept in this test --/ /(\x{23a}\x{23a}\x{23a})?\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65} /(ȺȺȺ)?\1/8i ȺȺȺⱥⱥ /(\x{23a}\x{23a}\x{23a})?\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} /(ȺȺȺ)?\1/8i ȺȺȺⱥⱥⱥ /(\x{23a}\x{23a}\x{23a})\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65} /(ȺȺȺ)\1/8i ȺȺȺⱥⱥ /(\x{23a}\x{23a}\x{23a})\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} /(ȺȺȺ)\1/8i ȺȺȺⱥⱥⱥ /(\x{2c65}\x{2c65})\1/8i \x{2c65}\x{2c65}\x{23a}\x{23a} /(ⱥⱥ)\1/8i ⱥⱥȺȺ /(\x{23a}\x{23a}\x{23a})\1Y/8i X\x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65}YZ /(\x{2c65}\x{2c65})\1Y/8i X\x{2c65}\x{2c65}\x{23a}\x{23a}YZ /-- --/ /-- These scripts weren't yet in Perl when I added Unicode 6.0.0 to PCRE --/ /^[\p{Batak}]/8 \x{1bc0} \x{1bff} ** Failers \x{1bf4} /^[\p{Brahmi}]/8 \x{11000} \x{1106f} ** Failers \x{1104e} /^[\p{Mandaic}]/8 \x{840} \x{85e} ** Failers \x{85c} \x{85d} /-- --/ /(\X*)(.)/s8 A\x{300} /^S(\X*)e(\X*)$/8 Stéréo /^\X/8 ́réo /^a\X41z/ aX41z *** Failers aAz /(?<=ab\Cde)X/8 /\X/ a\P a\P\P /\Xa/ aa\P aa\P\P /\X{2}/ aa\P aa\P\P /\X+a/ a\P aa\P aa\P\P /\X+?a/ a\P ab\P aa\P aa\P\P aba\P /-- These Unicode 6.1.0 scripts are not known to Perl. --/ /\p{Chakma}\d/8W \x{11100}\x{1113c} /\p{Takri}\d/8W \x{11680}\x{116c0} /^\X/8 A\P A\P\P A\x{300}\x{301}\P A\x{300}\x{301}\P\P A\x{301}\P A\x{301}\P\P /^\X{2,3}/8 A\P A\P\P AA\P AA\P\P A\x{300}\x{301}\P A\x{300}\x{301}\P\P A\x{300}\x{301}A\x{300}\x{301}\P A\x{300}\x{301}A\x{300}\x{301}\P\P /^\X{2}/8 AA\P AA\P\P A\x{300}\x{301}A\x{300}\x{301}\P A\x{300}\x{301}A\x{300}\x{301}\P\P /^\X+/8 AA\P AA\P\P /^\X+?Z/8 AA\P AA\P\P /A\x{3a3}B/8iDZ /\x{3a3}B/8iDZ /[\x{3a3}]/8iBZ /[^\x{3a3}]/8iBZ /[\x{3a3}]+/8iBZ /[^\x{3a3}]+/8iBZ /a*\x{3a3}/8iBZ /\x{3a3}+a/8iBZ /\x{3a3}*\x{3c2}/8iBZ /\x{3a3}{3}/8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} /\x{3a3}{2,4}/8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} /\x{3a3}{2,4}?/8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} /\x{3a3}+./8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} /\x{3a3}++./8i+ ** Failers \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} /\x{3a3}*\x{3c2}/8iBZ /[^\x{3a3}]*\x{3c2}/8iBZ /[^a]*\x{3c2}/8iBZ /ist/8iBZ ikt /is+t/8i iSs\x{17f}t ikt /is+?t/8i ikt /is?t/8i ikt /is{2}t/8i iskt /-- This property is a PCRE special --/ /^\p{Xuc}/8 $abc @abc `abc \x{1234}abc ** Failers abc /^\p{Xuc}+/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}+?/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}+?\*/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}++/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}{3,5}/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\p{Xuc}{3,5}?/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^[\p{Xuc}]/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^[\p{Xuc}]+/8 $@`\x{a0}\x{1234}\x{e000}** ** Failers \x{9f} /^\P{Xuc}/8 abc ** Failers $abc @abc `abc \x{1234}abc /^[\P{Xuc}]/8 abc ** Failers $abc @abc `abc \x{1234}abc /-- Some auto-possessification tests --/ /\pN+\z/BZ /\PN+\z/BZ /\pN+/BZ /\PN+/BZ /\p{Any}+\p{Any} \p{Any}+\P{Any} \p{Any}+\p{L&} \p{Any}+\p{L} \p{Any}+\p{Lu} \p{Any}+\p{Han} \p{Any}+\p{Xan} \p{Any}+\p{Xsp} \p{Any}+\p{Xps} \p{Xwd}+\p{Any} \p{Any}+\p{Xuc}/BWZx /\p{L&}+\p{Any} \p{L&}+\p{L&} \P{L&}+\p{L&} \p{L&}+\p{L} \p{L&}+\p{Lu} \p{L&}+\p{Han} \p{L&}+\p{Xan} \p{L&}+\P{Xan} \p{L&}+\p{Xsp} \p{L&}+\p{Xps} \p{Xwd}+\p{L&} \p{L&}+\p{Xuc}/BWZx /\p{N}+\p{Any} \p{N}+\p{L&} \p{N}+\p{L} \p{N}+\P{L} \p{N}+\P{N} \p{N}+\p{Lu} \p{N}+\p{Han} \p{N}+\p{Xan} \p{N}+\p{Xsp} \p{N}+\p{Xps} \p{Xwd}+\p{N} \p{N}+\p{Xuc}/BWZx /\p{Lu}+\p{Any} \p{Lu}+\p{L&} \p{Lu}+\p{L} \p{Lu}+\p{Lu} \P{Lu}+\p{Lu} \p{Lu}+\p{Nd} \p{Lu}+\P{Nd} \p{Lu}+\p{Han} \p{Lu}+\p{Xan} \p{Lu}+\p{Xsp} \p{Lu}+\p{Xps} \p{Xwd}+\p{Lu} \p{Lu}+\p{Xuc}/BWZx /\p{Han}+\p{Lu} \p{Han}+\p{L&} \p{Han}+\p{L} \p{Han}+\p{Lu} \p{Han}+\p{Arabic} \p{Arabic}+\p{Arabic} \p{Han}+\p{Xan} \p{Han}+\p{Xsp} \p{Han}+\p{Xps} \p{Xwd}+\p{Han} \p{Han}+\p{Xuc}/BWZx /\p{Xan}+\p{Any} \p{Xan}+\p{L&} \P{Xan}+\p{L&} \p{Xan}+\p{L} \p{Xan}+\p{Lu} \p{Xan}+\p{Han} \p{Xan}+\p{Xan} \p{Xan}+\P{Xan} \p{Xan}+\p{Xsp} \p{Xan}+\p{Xps} \p{Xwd}+\p{Xan} \p{Xan}+\p{Xuc}/BWZx /\p{Xsp}+\p{Any} \p{Xsp}+\p{L&} \p{Xsp}+\p{L} \p{Xsp}+\p{Lu} \p{Xsp}+\p{Han} \p{Xsp}+\p{Xan} \p{Xsp}+\p{Xsp} \P{Xsp}+\p{Xsp} \p{Xsp}+\p{Xps} \p{Xwd}+\p{Xsp} \p{Xsp}+\p{Xuc}/BWZx /\p{Xwd}+\p{Any} \p{Xwd}+\p{L&} \p{Xwd}+\p{L} \p{Xwd}+\p{Lu} \p{Xwd}+\p{Han} \p{Xwd}+\p{Xan} \p{Xwd}+\p{Xsp} \p{Xwd}+\p{Xps} \p{Xwd}+\p{Xwd} \p{Xwd}+\P{Xwd} \p{Xwd}+\p{Xuc}/BWZx /\p{Xuc}+\p{Any} \p{Xuc}+\p{L&} \p{Xuc}+\p{L} \p{Xuc}+\p{Lu} \p{Xuc}+\p{Han} \p{Xuc}+\p{Xan} \p{Xuc}+\p{Xsp} \p{Xuc}+\p{Xps} \p{Xwd}+\p{Xuc} \p{Xuc}+\p{Xuc} \p{Xuc}+\P{Xuc}/BWZx /\p{N}+\p{Ll} \p{N}+\p{Nd} \p{N}+\P{Nd}/BWZx /\p{Xan}+\p{L} \p{Xan}+\p{N} \p{Xan}+\p{C} \p{Xan}+\P{L} \P{Xan}+\p{N} \p{Xan}+\P{C}/BWZx /\p{L}+\p{Xan} \p{N}+\p{Xan} \p{C}+\p{Xan} \P{L}+\p{Xan} \p{N}+\p{Xan} \P{C}+\p{Xan} \p{L}+\P{Xan}/BWZx /\p{Xan}+\p{Lu} \p{Xan}+\p{Nd} \p{Xan}+\p{Cc} \p{Xan}+\P{Ll} \P{Xan}+\p{No} \p{Xan}+\P{Cf}/BWZx /\p{Lu}+\p{Xan} \p{Nd}+\p{Xan} \p{Cs}+\p{Xan} \P{Lt}+\p{Xan} \p{Nl}+\p{Xan} \P{Cc}+\p{Xan} \p{Lt}+\P{Xan}/BWZx /\w+\p{P} \w+\p{Po} \w+\s \p{Xan}+\s \s+\p{Xan} \s+\w/BWZx /\w+\P{P} \W+\p{Po} \w+\S \P{Xan}+\s \s+\P{Xan} \s+\W/BWZx /\w+\p{Po} \w+\p{Pc} \W+\p{Po} \W+\p{Pc} \w+\P{Po} \w+\P{Pc}/BWZx /\p{Nl}+\p{Xan} \P{Nl}+\p{Xan} \p{Nl}+\P{Xan} \P{Nl}+\P{Xan}/BWZx /\p{Xan}+\p{Nl} \P{Xan}+\p{Nl} \p{Xan}+\P{Nl} \P{Xan}+\P{Nl}/BWZx /\p{Xan}+\p{Nd} \P{Xan}+\p{Nd} \p{Xan}+\P{Nd} \P{Xan}+\P{Nd}/BWZx /-- End auto-possessification tests --/ /\w+/8CWBZ abcd /[\p{N}]?+/BZO /[\p{L}ab]{2,3}+/BZO /\D+\X \d+\X \S+\X \s+\X \W+\X \w+\X \C+\X \R+\X \H+\X \h+\X \V+\X \v+\X a+\X \n+\X .+\X/BZx /.+\X/BZxs /\X+$/BZxm /\X+\D \X+\d \X+\S \X+\s \X+\W \X+\w \X+. \X+\C \X+\R \X+\H \X+\h \X+\V \X+\v \X+\X \X+\Z \X+\z \X+$/BZx /\d+\s{0,5}=\s*\S?=\w{0,4}\W*/8WBZ /[RST]+/8iWBZ /[R-T]+/8iWBZ /[Q-U]+/8iWBZ /^s?c/mi8I scat /a[[:punct:]b]/WBZ /a[[:punct:]b]/8WBZ /a[b[:punct:]]/8WBZ /L(?#(|++3 *** Failers xyzabc xyzabc\>2 /x\dy\Dz/ x9yzz x0y+z *** Failers xyz xxy0z /x\sy\Sz/ x yzz x y+z *** Failers xyz xxyyz /x\wy\Wz/ xxy+z *** Failers xxy0z x+y+z /x.y/ x+y x-y *** Failers x\ny /x.y/s x+y x-y x\ny /(a.b(?s)c.d|x.y)p.q/ a+bc+dp+q a+bc\ndp+q x\nyp+q *** Failers a\nbc\ndp+q a+bc\ndp\nq x\nyp\nq /a\d\z/ ba0 *** Failers ba0\n ba0\ncd /a\d\z/m ba0 *** Failers ba0\n ba0\ncd /a\d\Z/ ba0 ba0\n *** Failers ba0\ncd /a\d\Z/m ba0 ba0\n *** Failers ba0\ncd /a\d$/ ba0 ba0\n *** Failers ba0\ncd /a\d$/m ba0 ba0\n ba0\ncd *** Failers /abc/i abc aBc ABC /[^a]/ abcd /ab?\w/ abz abbz azz /x{0,3}yz/ ayzq axyzq axxyz axxxyzq axxxxyzq *** Failers ax axx /x{3}yz/ axxxyzq axxxxyzq *** Failers ax axx ayzq axyzq axxyz /x{2,3}yz/ axxyz axxxyzq axxxxyzq *** Failers ax axx ayzq axyzq /[^a]+/O bac bcdefax *** Failers aaaaa /[^a]*/O bac bcdefax *** Failers aaaaa /[^a]{3,5}/O xyz awxyza abcdefa abcdefghijk *** Failers axya axa aaaaa /\d*/ 1234b567 xyz /\D*/ a1234b567 xyz /\d+/ ab1234c56 *** Failers xyz /\D+/ ab123c56 *** Failers 789 /\d?A/ 045ABC ABC *** Failers XYZ /\D?A/ ABC BAC 9ABC *** Failers /a+/ aaaa /^.*xyz/ xyz ggggggggxyz /^.+xyz/ abcdxyz axyz *** Failers xyz /^.?xyz/ xyz cxyz /^\d{2,3}X/ 12X 123X *** Failers X 1X 1234X /^[abcd]\d/ a45 b93 c99z d04 *** Failers e45 abcd abcd1234 1234 /^[abcd]*\d/ a45 b93 c99z d04 abcd1234 1234 *** Failers e45 abcd /^[abcd]+\d/ a45 b93 c99z d04 abcd1234 *** Failers 1234 e45 abcd /^a+X/ aX aaX /^[abcd]?\d/ a45 b93 c99z d04 1234 *** Failers abcd1234 e45 /^[abcd]{2,3}\d/ ab45 bcd93 *** Failers 1234 a36 abcd1234 ee45 /^(abc)*\d/ abc45 abcabcabc45 42xyz *** Failers /^(abc)+\d/ abc45 abcabcabc45 *** Failers 42xyz /^(abc)?\d/ abc45 42xyz *** Failers abcabcabc45 /^(abc){2,3}\d/ abcabc45 abcabcabc45 *** Failers abcabcabcabc45 abc45 42xyz /1(abc|xyz)2(?1)3/ 1abc2abc3456 1abc2xyz3456 /^(a*\w|ab)=(a*\w|ab)/ ab=ab /^(a*\w|ab)=(?1)/ ab=ab /^([^()]|\((?1)*\))*$/ abc a(b)c a(b(c))d *** Failers) a(b(c)d /^>abc>([^()]|\((?1)*\))*abc>123abc>1(2)3abc>(1(2)3)a*)\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9876 *** Failers aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/x <> hij> hij> def> *** Failers 3 *** Failers defabcxyz /^abcdef/ ab\P abcde\P abcdef\P *** Failers abx\P /^a{2,4}\d+z/ a\P aa\P aa2\P aaa\P aaa23\P aaaa12345\P aa0z\P aaaa4444444444444z\P *** Failers az\P aaaaa\P a56\P /^abcdef/ abc\P def\R /(?<=foo)bar/ xyzfo\P foob\P\>2 foobar...\R\P\>4 xyzfo\P foobar\>2 *** Failers xyzfo\P obar\R /(ab*(cd|ef))+X/ adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkj\P\Z lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefa\P\B\Z cdabbbbbbbb\P\R\B\Z efabbbbbbbbbbbbbbbb\P\R\B\Z bbbbbbbbbbbbcdXyasdfadf\P\R\B\Z /(a|b)/SF>testsavedregex >>aaabxyzpqrrrabbxyyyypqAzz >aaaabxyzpqrrrabbxyyyypqAzz >>>>abcxyzpqrrrabbxyyyypqAzz *** Failers abxyzpqrrabbxyyyypqAzz abxyzpqrrrrabbxyyyypqAzz abxyzpqrrrabxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyypqAzz aaabcxyzpqrrrabbxyyyypqqqqqqqAzz /^(abc){1,2}zz/ abczz abcabczz *** Failers zz abcabcabczz >>abczz /^(b+?|a){1,2}?c/ bc bbc bbbc bac bbac aac abbbbbbbbbbbc bbbbbbbbbbbac *** Failers aaac abbbbbbbbbbbac /^(b+|a){1,2}c/ bc bbc bbbc bac bbac aac abbbbbbbbbbbc bbbbbbbbbbbac *** Failers aaac abbbbbbbbbbbac /^(b+|a){1,2}?bc/ bbc /^(b*|ba){1,2}?bc/ babc bbabc bababc *** Failers bababbc babababc /^(ba|b*){1,2}?bc/ babc bbabc bababc *** Failers bababbc babababc /^\ca\cA\c[\c{\c:/ \x01\x01\e;z /^[ab\]cde]/ athing bthing ]thing cthing dthing ething *** Failers fthing [thing \\thing /^[]cde]/ ]thing cthing dthing ething *** Failers athing fthing /^[^ab\]cde]/ fthing [thing \\thing *** Failers athing bthing ]thing cthing dthing ething /^[^]cde]/ athing fthing *** Failers ]thing cthing dthing ething /^\/ /^/ /^[0-9]+$/ 0 1 2 3 4 5 6 7 8 9 10 100 *** Failers abc /^.*nter/ enter inter uponter /^xxx[0-9]+$/ xxx0 xxx1234 *** Failers xxx /^.+[0-9][0-9][0-9]$/ x123 xx123 123456 *** Failers 123 x1234 /^.+?[0-9][0-9][0-9]$/ x123 xx123 123456 *** Failers 123 x1234 /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ abc!pqr=apquxz.ixr.zzz.ac.uk *** Failers !pqr=apquxz.ixr.zzz.ac.uk abc!=apquxz.ixr.zzz.ac.uk abc!pqr=apquxz:ixr.zzz.ac.uk abc!pqr=apquxz.ixr.zzz.ac.ukk /:/ Well, we need a colon: somewhere *** Fail if we don't /([\da-f:]+)$/i 0abc abc fed E :: 5f03:12C0::932e fed def Any old stuff *** Failers 0zzz gzzz fed\x20 Any old rubbish /^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ .1.2.3 A.12.123.0 *** Failers .1.2.3333 1.2.3 1234.2.3 /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( 1 IN SOA non-sp1 non-sp2 ( *** Failers 1IN SOA non-sp1 non-sp2( /^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ a. Z. 2. ab-c.pq-r. sxk.zzz.ac.uk. x-.y-. *** Failers -abc.peq. /^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ *.a *.b0-a *.c3-b.c *.c-a.b-c *** Failers *.0 *.a- *.a-b.c- *.c-a.0-c /^(?=ab(de))(abd)(e)/ abde /^(?!(ab)de|x)(abd)(f)/ abdf /^(?=(ab(cd)))(ab)/ abcd /^[\da-f](\.[\da-f])*$/i a.b.c.d A.B.C.D a.b.c.1.2.3.C /^\".*\"\s*(;.*)?$/ \"1234\" \"abcd\" ; \"\" ; rhubarb *** Failers \"1234\" : things /^$/ \ *** Failers / ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x ab c *** Failers abc ab cde /(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ ab c *** Failers abc ab cde /^ a\ b[c ]d $/x a bcd a b d *** Failers abcd ab d /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ abcdefhijklm /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ abcdefhijklm /^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ a+ Z0+\x08\n\x1d\x12 /^[.^$|()*+?{,}]+/ .^\$(*+)|{?,?} /^a*\w/ z az aaaz a aa aaaa a+ aa+ /^a*?\w/ z az aaaz a aa aaaa a+ aa+ /^a+\w/ az aaaz aa aaaa aa+ /^a+?\w/ az aaaz aa aaaa aa+ /^\d{8}\w{2,}/ 1234567890 12345678ab 12345678__ *** Failers 1234567 /^[aeiou\d]{4,5}$/ uoie 1234 12345 aaaaa *** Failers 123456 /^[aeiou\d]{4,5}?/ uoie 1234 12345 aaaaa 123456 /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ From abcd Mon Sep 01 12:33:02 1997 /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ From abcd Mon Sep 01 12:33:02 1997 From abcd Mon Sep 1 12:33:02 1997 *** Failers From abcd Sep 01 12:33:02 1997 /^12.34/s 12\n34 12\r34 /\w+(?=\t)/ the quick brown\t fox /foo(?!bar)(.*)/ foobar is foolish see? /(?:(?!foo)...|^.{0,2})bar(.*)/ foobar crowbar etc barrel 2barrel A barrel /^(\D*)(?=\d)(?!123)/ abc456 *** Failers abc123 /^1234(?# test newlines inside)/ 1234 /^1234 #comment in extended re /x 1234 /#rhubarb abcd/x abcd /^abcd#rhubarb/x abcd /(?!^)abc/ the abc *** Failers abc /(?=^)abc/ abc *** Failers the abc /^[ab]{1,3}(ab*|b)/O aabbbbb /^[ab]{1,3}?(ab*|b)/O aabbbbb /^[ab]{1,3}?(ab*?|b)/O aabbbbb /^[ab]{1,3}(ab*?|b)/O aabbbbb / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /x Alan Other user\@dom.ain \"A. Other\" (a comment) A. Other (a comment) \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) # leading word [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces (?: (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) | " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " ) # "special" comment or quoted string [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" )* < [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # < (?: @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* (?: , [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* )* # additional domains : [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address spec > # > # name and address ) /x Alan Other user\@dom.ain \"A. Other\" (a comment) A. Other (a comment) \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay A missing angle a\rb *** Failers a\nb /abc$/ abc abc\n *** Failers abc\ndef /(abc)\123/ abc\x53 /(abc)\223/ abc\x93 /(abc)\323/ abc\xd3 /(abc)\100/ abc\x40 abc\100 /(abc)\1000/ abc\x400 abc\x40\x30 abc\1000 abc\100\x30 abc\100\060 abc\100\60 /^A\8B\9C$/ A8B9C *** Failers A\08B\09C /^[A\8B\9C]+$/ A8B9C *** Failers A8B9C\x00 /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12\123/ abcdefghijk\12S /ab\idef/ abidef /a{0}bc/ bc /(a|(bc)){0,0}?xyz/ xyz /abc[\10]de/ abc\010de /abc[\1]de/ abc\1de /(abc)[\1]de/ abc\1de /(?s)a.b/ a\nb /^([^a])([^\b])([^c]*)([^d]{3,4})/ baNOTccccd baNOTcccd baNOTccd bacccd *** Failers anything b\bc baccd /[^a]/ Abc /[^a]/i Abc /[^a]+/ AAAaAbc /[^a]+/i AAAaAbc /[^a]+/ bbb\nccc /[^k]$/ abc *** Failers abk /[^k]{2,3}$/ abc kbc kabc *** Failers abk akb akk /^\d{8,}\@.+[^k]$/ 12345678\@a.b.c.d 123456789\@x.y.z *** Failers 12345678\@x.y.uk 1234567\@a.b.c.d /[^a]/ aaaabcd aaAabcd /[^a]/i aaaabcd aaAabcd /[^az]/ aaaabcd aaAabcd /[^az]/i aaaabcd aaAabcd /\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377/ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377 /P[^*]TAIRE[^*]{1,6}?LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx /P[^*]TAIRE[^*]{1,}?LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx /(\.\d\d[1-9]?)\d+/ 1.230003938 1.875000282 1.235 /(\.\d\d((?=0)|\d(?=\d)))/ 1.230003938 1.875000282 *** Failers 1.235 /a(?)b/ ab /\b(foo)\s+(\w+)/i Food is on the foo table /foo(.*)bar/ The food is under the bar in the barn. /foo(.*?)bar/ The food is under the bar in the barn. /(.*)(\d*)/O I have 2 numbers: 53147 /(.*)(\d+)/ I have 2 numbers: 53147 /(.*?)(\d*)/O I have 2 numbers: 53147 /(.*?)(\d+)/ I have 2 numbers: 53147 /(.*)(\d+)$/ I have 2 numbers: 53147 /(.*?)(\d+)$/ I have 2 numbers: 53147 /(.*)\b(\d+)$/ I have 2 numbers: 53147 /(.*\D)(\d+)$/ I have 2 numbers: 53147 /^\D*(?!123)/ ABC123 /^(\D*)(?=\d)(?!123)/ ABC445 *** Failers ABC123 /^[W-]46]/ W46]789 -46]789 *** Failers Wall Zebra 42 [abcd] ]abcd[ /^[W-\]46]/ W46]789 Wall Zebra Xylophone 42 [abcd] ]abcd[ \\backslash *** Failers -46]789 well /\d\d\/\d\d\/\d\d\d\d/ 01/01/2000 /word (?:[a-zA-Z0-9]+ ){0,10}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark /word (?:[a-zA-Z0-9]+ ){0,300}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope /^(a){0,0}/ bcd abc aab /^(a){0,1}/ bcd abc aab /^(a){0,2}/ bcd abc aab /^(a){0,3}/ bcd abc aab aaa /^(a){0,}/ bcd abc aab aaa aaaaaaaa /^(a){1,1}/ bcd abc aab /^(a){1,2}/ bcd abc aab /^(a){1,3}/ bcd abc aab aaa /^(a){1,}/ bcd abc aab aaa aaaaaaaa /.*\.gif/ borfle\nbib.gif\nno /.{0,}\.gif/ borfle\nbib.gif\nno /.*\.gif/m borfle\nbib.gif\nno /.*\.gif/s borfle\nbib.gif\nno /.*\.gif/ms borfle\nbib.gif\nno /.*$/ borfle\nbib.gif\nno /.*$/m borfle\nbib.gif\nno /.*$/s borfle\nbib.gif\nno /.*$/ms borfle\nbib.gif\nno /.*$/ borfle\nbib.gif\nno\n /.*$/m borfle\nbib.gif\nno\n /.*$/s borfle\nbib.gif\nno\n /.*$/ms borfle\nbib.gif\nno\n /(.*X|^B)/ abcde\n1234Xyz BarFoo *** Failers abcde\nBar /(.*X|^B)/m abcde\n1234Xyz BarFoo abcde\nBar /(.*X|^B)/s abcde\n1234Xyz BarFoo *** Failers abcde\nBar /(.*X|^B)/ms abcde\n1234Xyz BarFoo abcde\nBar /(?s)(.*X|^B)/ abcde\n1234Xyz BarFoo *** Failers abcde\nBar /(?s:.*X|^B)/ abcde\n1234Xyz BarFoo *** Failers abcde\nBar /^.*B/ **** Failers abc\nB /(?s)^.*B/ abc\nB /(?m)^.*B/ abc\nB /(?ms)^.*B/ abc\nB /(?ms)^B/ abc\nB /(?s)B$/ B\n /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ 123456654321 /^\d\d\d\d\d\d\d\d\d\d\d\d/ 123456654321 /^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/ 123456654321 /^[abc]{12}/ abcabcabcabc /^[a-c]{12}/ abcabcabcabc /^(a|b|c){12}/ abcabcabcabc /^[abcdefghijklmnopqrstuvwxy0123456789]/ n *** Failers z /abcde{0,0}/ abcd *** Failers abce /ab[cd]{0,0}e/ abe *** Failers abcde /ab(c){0,0}d/ abd *** Failers abcd /a(b*)/ a ab abbbb *** Failers bbbbb /ab\d{0}e/ abe *** Failers ab1e /"([^\\"]+|\\.)*"/ the \"quick\" brown fox \"the \\\"quick\\\" brown fox\" /.*?/g+ abc /\b/g+ abc /\b/+g abc //g abc /]{0,})>]{0,})>([\d]{0,}\.)(.*)((
    ([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is 43.
    Word Processor
    (N-1286)
    Lega lstaff.comCA - Statewide /a[^a]b/ acb a\nb /a.b/ acb *** Failers a\nb /a[^a]b/s acb a\nb /a.b/s acb a\nb /^(b+?|a){1,2}?c/ bac bbac bbbac bbbbac bbbbbac /^(b+|a){1,2}?c/ bac bbac bbbac bbbbac bbbbbac /(?!\A)x/m x\nb\n a\bx\n /\x0{ab}/ \0{ab} /(A|B)*?CD/ CD /(A|B)*CD/ CD /(?.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ "(?>.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo /(?>(\.\d\d[1-9]?))\d+/ 1.230003938 1.875000282 *** Failers 1.235 /^((?>\w+)|(?>\s+))*$/ now is the time for all good men to come to the aid of the party *** Failers this is not a line with only words and spaces! /(\d+)(\w)/ 12345a 12345+ /((?>\d+))(\w)/ 12345a *** Failers 12345+ /(?>a+)b/ aaab /((?>a+)b)/ aaab /(?>(a+))b/ aaab /(?>b)+/ aaabbbccc /(?>a+|b+|c+)*c/ aaabbbbccccd /(a+|b+|c+)*c/ aaabbbbccccd /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x /\(((?>[^()]+)|\([^()]+\))+\)/ (abc) (abc(def)xyz) *** Failers ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /a(?-i)b/i ab Ab *** Failers aB AB /(a (?x)b c)d e/ a bcd e *** Failers a b cd e abcd e a bcde /(a b(?x)c d (?-x)e f)/ a bcde f *** Failers abcdef /(a(?i)b)c/ abc aBc *** Failers abC aBC Abc ABc ABC AbC /a(?i:b)c/ abc aBc *** Failers ABC abC aBC /a(?i:b)*c/ aBc aBBc *** Failers aBC aBBC /a(?=b(?i)c)\w\wd/ abcd abCd *** Failers aBCd abcD /(?s-i:more.*than).*million/i more than million more than MILLION more \n than Million *** Failers MORE THAN MILLION more \n than \n million /(?:(?s-i)more.*than).*million/i more than million more than MILLION more \n than Million *** Failers MORE THAN MILLION more \n than \n million /(?>a(?i)b+)+c/ abc aBbc aBBc *** Failers Abc abAb abbC /(?=a(?i)b)\w\wc/ abc aBc *** Failers Ab abC aBC /(?<=a(?i)b)(\w\w)c/ abxxc aBxxc *** Failers Abxxc ABxxc abxxC /^(?(?=abc)\w{3}:|\d\d)$/ abc: 12 *** Failers 123 xyz /^(?(?!abc)\d\d|\w{3}:)$/ abc: 12 *** Failers 123 xyz /(?(?<=foo)bar|cat)/ foobar cat fcat focat *** Failers foocat /(?(?a*)*/ a aa aaaa /(abc|)+/ abc abcabc abcabcabc xyz /([a]*)*/ a aaaaa /([ab]*)*/ a b ababab aaaabcde bbbb /([^a]*)*/ b bbbb aaa /([^ab]*)*/ cccc abab /([a]*?)*/ a aaaa /([ab]*?)*/ a b abab baba /([^a]*?)*/ b bbbb aaa /([^ab]*?)*/ c cccc baba /(?>a*)*/ a aaabcde /((?>a*))*/ aaaaa aabbaa /((?>a*?))*/ aaaaa aabbaa /(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x 12-sep-98 12-09-98 *** Failers sep-12-98 /(?i:saturday|sunday)/ saturday sunday Saturday Sunday SATURDAY SUNDAY SunDay /(a(?i)bc|BB)x/ abcx aBCx bbx BBx *** Failers abcX aBCX bbX BBX /^([ab](?i)[cd]|[ef])/ ac aC bD elephant Europe frog France *** Failers Africa /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ ab aBd xy xY zebra Zambesi *** Failers aCD XY /(?<=foo\n)^bar/m foo\nbar *** Failers bar baz\nbar /(?<=(?]&/ <&OUT /(?:(f)(o)(o)|(b)(a)(r))*/ foobar /(?<=a)b/ ab *** Failers cb b /(?a+)ab/ /(?>a+)b/ aaab /([[:]+)/ a:[b]: /([[=]+)/ a=[b]= /([[.]+)/ a.[b]. /((?>a+)b)/ aaab /(?>(a+))b/ aaab /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x /a\Z/ *** Failers aaab a\nb\n /b\Z/ a\nb\n /b\z/ /b\Z/ a\nb /b\z/ a\nb *** Failers /(?>.*)(?<=(abcd|wxyz))/ alphabetabcd endingwxyz *** Failers a rather long string that doesn't end with one of them /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark /word (?>[a-zA-Z0-9]+ ){0,30}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope /(?<=\d{3}(?!999))foo/ 999foo 123999foo *** Failers 123abcfoo /(?<=(?!...999)\d{3})foo/ 999foo 123999foo *** Failers 123abcfoo /(?<=\d{3}(?!999)...)foo/ 123abcfoo 123456foo *** Failers 123999foo /(?<=\d{3}...)(?Z)+|A)*/ ZABCDEFG /((?>)+|A)*/ ZABCDEFG /a*/g abbab /^[\d-a]/ abcde -things 0digit *** Failers bcdef /[[:space:]]+/ > \x09\x0a\x0c\x0d\x0b< /[[:blank:]]+/ > \x09\x0a\x0c\x0d\x0b< /[\s]+/ > \x09\x0a\x0c\x0d\x0b< /\s+/ > \x09\x0a\x0c\x0d\x0b< /a b/x ab /(?!\A)x/m a\nxb\n /(?!^)x/m a\nxb\n /abc\Qabc\Eabc/ abcabcabc /abc\Q(*+|\Eabc/ abc(*+|abc / abc\Q abc\Eabc/x abc abcabc *** Failers abcabcabc /abc#comment \Q#not comment literal\E/x abc#not comment\n literal /abc#comment \Q#not comment literal/x abc#not comment\n literal /abc#comment \Q#not comment literal\E #more comment /x abc#not comment\n literal /abc#comment \Q#not comment literal\E #more comment/x abc#not comment\n literal /\Qabc\$xyz\E/ abc\\\$xyz /\Qabc\E\$\Qxyz\E/ abc\$xyz /\Gabc/ abc *** Failers xyzabc /\Gabc./g abc1abc2xyzabc3 /abc./g abc1abc2xyzabc3 /a(?x: b c )d/ XabcdY *** Failers Xa b c d Y /((?x)x y z | a b c)/ XabcY AxyzB /(?i)AB(?-i)C/ XabCY *** Failers XabcY /((?i)AB(?-i)C|D)E/ abCE DE *** Failers abcE abCe dE De /[z\Qa-d]\E]/ z a - d ] *** Failers b /[\z\C]/ z C /\M/ M /(a+)*b/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /(?i)reg(?:ul(?:[a]|ae)r|ex)/ REGular regulaer Regex regulr /[--]+/ /(?<=Z)X./ \x84XAZXB /^(?(2)a|(1)(2))+$/ 123a /(?<=a|bbbb)c/ ac bbbbc /abc/SS>testsavedregex testsavedregex testsavedregex testsavedregex xyz\r\nabc\ xyz\rabc\ xyz\r\nabc\ ** Failers xyz\nabc\ xyz\r\nabc\ xyz\nabc\ xyz\rabc\ xyz\rabc\ /abc$/m xyzabc xyzabc\n xyzabc\npqr xyzabc\r\ xyzabc\rpqr\ xyzabc\r\n\ xyzabc\r\npqr\ ** Failers xyzabc\r xyzabc\rpqr xyzabc\r\n xyzabc\r\npqr /^abc/m xyz\rabcdef xyz\nabcdef\ ** Failers xyz\nabcdef /^abc/m xyz\nabcdef xyz\rabcdef\ ** Failers xyz\rabcdef /^abc/m xyz\r\nabcdef xyz\rabcdef\ ** Failers xyz\rabcdef /.*/ abc\ndef abc\rdef abc\r\ndef \abc\ndef \abc\rdef \abc\r\ndef \abc\ndef \abc\rdef \abc\r\ndef /\w+(.)(.)?def/s abc\ndef abc\rdef abc\r\ndef /^\w+=.*(\\\n.*)*/ abc=xyz\\\npqr /^(a()*)*/ aaaa /^(?:a(?:(?:))*)*/ aaaa /^(a()+)+/ aaaa /^(?:a(?:(?:))+)+/ aaaa /(a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /(?>a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /(?:a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /^a.b/ a\rb a\nb\ ** Failers a\nb a\nb\ a\rb\ a\rb\ /^abc./mgx abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x85abc7 JUNK /abc.$/mgx abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x85 abc9 /^a\Rb/ a\nb a\rb a\r\nb a\x0bb a\x0cb a\x85b ** Failers a\n\rb /^a\R*b/ ab a\nb a\rb a\r\nb a\x0bb a\x0cb a\x85b a\n\rb a\n\r\x85\x0cb /^a\R+b/ a\nb a\rb a\r\nb a\x0bb a\x0cb a\x85b a\n\rb a\n\r\x85\x0cb ** Failers ab /^a\R{1,3}b/ a\nb a\n\rb a\n\r\x85b a\r\n\r\nb a\r\n\r\n\r\nb a\n\r\n\rb a\n\n\r\nb ** Failers a\n\n\n\rb a\r /^a[\R]b/ aRb ** Failers a\nb /.+foo/ afoo ** Failers \r\nfoo \nfoo /.+foo/ afoo \nfoo ** Failers \r\nfoo /.+foo/ afoo ** Failers \nfoo \r\nfoo /.+foo/s afoo \r\nfoo \nfoo /^$/mg abc\r\rxyz abc\n\rxyz ** Failers abc\r\nxyz /^X/m XABC ** Failers XABC\B /(?m)^$/g+ abc\r\n\r\n /(?m)^$|^\r\n/g+ abc\r\n\r\n /(?m)$/g+ abc\r\n\r\n /(?|(abc)|(xyz))/ >abc< >xyz< /(x)(?|(abc)|(xyz))(x)/ xabcx xxyzx /(x)(?|(abc)(pqr)|(xyz))(x)/ xabcpqrx xxyzx /(?|(abc)|(xyz))(?1)/ abcabc xyzabc ** Failers xyzxyz /\H\h\V\v/ X X\x0a X\x09X\x0b ** Failers \xa0 X\x0a /\H*\h+\V?\v{3,4}/ \x09\x20\xa0X\x0a\x0b\x0c\x0d\x0a \x09\x20\xa0\x0a\x0b\x0c\x0d\x0a \x09\x20\xa0\x0a\x0b\x0c ** Failers \x09\x20\xa0\x0a\x0b /\H{3,4}/ XY ABCDE XY PQR ST /.\h{3,4}./ XY AB PQRS /\h*X\h?\H+Y\H?Z/ >XNNNYZ > X NYQZ ** Failers >XYZ > X NY Z /\v*X\v?Y\v+Z\V*\x0a\V+\x0b\V{2,3}\x0c/ >XY\x0aZ\x0aA\x0bNN\x0c >\x0a\x0dX\x0aY\x0a\x0bZZZ\x0aAAA\x0bNNN\x0c /.+A/ \r\nA /\nA/ \r\nA /[\r\n]A/ \r\nA /(\r|\n)A/ \r\nA /a\Rb/I a\rb a\nb a\r\nb ** Failers a\x85b a\x0bb /a\Rb/I a\rb a\nb a\r\nb a\x85b a\x0bb ** Failers a\x85b\ a\x0bb\ /a\R?b/I a\rb a\nb a\r\nb ** Failers a\x85b a\x0bb /a\R?b/I a\rb a\nb a\r\nb a\x85b a\x0bb ** Failers a\x85b\ a\x0bb\ /a\R{2,4}b/I a\r\n\nb a\n\r\rb a\r\n\r\n\r\n\r\nb ** Failers a\x85\85b a\x0b\0bb /a\R{2,4}b/I a\r\rb a\n\n\nb a\r\n\n\r\rb a\x85\85b a\x0b\0bb ** Failers a\r\r\r\r\rb a\x85\85b\ a\x0b\0bb\ /a(?!)|\wbc/ abc /a[]b/ ** Failers ab /a[]+b/ ** Failers ab /a[]*+b/ ** Failers ab /a[^]b/ aXb a\nb ** Failers ab /a[^]+b/ aXb a\nX\nXb ** Failers ab /X$/E X ** Failers X\n /X$/ X X\n /xyz/C xyz abcxyz abcxyz\Y ** Failers abc abc\Y abcxypqr abcxypqr\Y /(*NO_START_OPT)xyz/C abcxyz /(?C)ab/ ab \C-ab /ab/C ab \C-ab /^"((?(?=[a])[^"])|b)*"$/C "ab" \C-"ab" /\d+X|9+Y/ ++++123999\P ++++123999Y\P /Z(*F)/ Z\P ZA\P /Z(?!)/ Z\P ZA\P /dog(sbody)?/ dogs\P dogs\P\P /dog(sbody)??/ dogs\P dogs\P\P /dog|dogsbody/ dogs\P dogs\P\P /dogsbody|dog/ dogs\P dogs\P\P /Z(*F)Q|ZXY/ Z\P ZA\P X\P /\bthe cat\b/ the cat\P the cat\P\P /dog(sbody)?/ dogs\D\P body\D\R /dog(sbody)?/ dogs\D\P\P body\D\R /abc/ abc\P abc\P\P /abc\K123/ xyzabc123pqr /(?<=abc)123/ xyzabc123pqr xyzabc12\P xyzabc12\P\P /\babc\b/ +++abc+++ +++ab\P +++ab\P\P /(?=C)/g+ ABCDECBA /(abc|def|xyz)/I terhjk;abcdaadsfe the quick xyz brown fox \Yterhjk;abcdaadsfe \Ythe quick xyz brown fox ** Failers thejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd \Ythejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd /(abc|def|xyz)/SI terhjk;abcdaadsfe the quick xyz brown fox \Yterhjk;abcdaadsfe \Ythe quick xyz brown fox ** Failers thejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd \Ythejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd /abcd*/+ xxxxabcd\P xxxxabcd\P\P dddxxx\R xxxxabcd\P\P xxx\R /abcd*/i xxxxabcd\P xxxxabcd\P\P XXXXABCD\P XXXXABCD\P\P /abc\d*/ xxxxabc1\P xxxxabc1\P\P /abc[de]*/ xxxxabcde\P xxxxabcde\P\P /(?:(?1)|B)(A(*F)|C)/ ABCD CCD ** Failers CAD /^(?:(?1)|B)(A(*F)|C)/ CCD BCD ** Failers ABCD CAD BAD /^(?!a(*SKIP)b)/ ac /^(?=a(*SKIP)b|ac)/ ** Failers ac /^(?=a(*THEN)b|ac)/ ac /^(?=a(*PRUNE)b)/ ab ** Failers ac /^(?(?!a(*SKIP)b))/ ac /(?<=abc)def/ abc\P\P /abc$/ abc abc\P abc\P\P /abc$/m abc abc\n abc\P\P abc\n\P\P abc\P abc\n\P /abc\z/ abc abc\P abc\P\P /abc\Z/ abc abc\P abc\P\P /abc\b/ abc abc\P abc\P\P /abc\B/ abc abc\P abc\P\P /.+/ abc\>0 abc\>1 abc\>2 abc\>3 abc\>4 abc\>-4 /^(?:a)++\w/ aaaab ** Failers aaaa bbb /^(?:aa|(?:a)++\w)/ aaaab aaaa ** Failers bbb /^(?:a)*+\w/ aaaab bbb ** Failers aaaa /^(a)++\w/ aaaab ** Failers aaaa bbb /^(a|)++\w/ aaaab ** Failers aaaa bbb /(?=abc){3}abc/+ abcabcabc ** Failers xyz /(?=abc)+abc/+ abcabcabc ** Failers xyz /(?=abc)++abc/+ abcabcabc ** Failers xyz /(?=abc){0}xyz/ xyz /(?=abc){1}xyz/ ** Failers xyz /(?=(a))?./ ab bc /(?=(a))??./ ab bc /^(?=(a)){0}b(?1)/ backgammon /^(?=(?1))?[az]([abc])d/ abd zcdxx /^(?!a){0}\w+/ aaaaa /(?<=(abc))?xyz/ abcxyz pqrxyz /((?2))((?1))/ abc /(?(R)a+|(?R)b)/ aaaabcde /(?(R)a+|((?R))b)/ aaaabcde /((?(R)a+|(?1)b))/ aaaabcde /((?(R2)a+|(?1)b))/ aaaabcde /(?(R)a*(?1)|((?R))b)/ aaaabcde /(a+)/O \O6aaaa \O8aaaa /ab\Cde/ abXde /(?<=ab\Cde)X/ abZdeX /^\R/ \r\P \r\P\P /^\R{2,3}x/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P \r\rx \r\r\rx /^\R{2,3}?x/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P \r\rx \r\r\rx /^\R?x/ \r\P \r\P\P x \rx /^\R+x/ \r\P \r\P\P \r\n\P \r\n\P\P \rx /^a$/ a\r\P a\r\P\P /^a$/m a\r\P a\r\P\P /^(a$|a\r)/ a\r\P a\r\P\P /^(a$|a\r)/m a\r\P a\r\P\P /./ \r\P \r\P\P /.{2,3}/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /.{2,3}?/ \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /-- Test simple validity check for restarts --/ /abcdef/ abc\R /)(.)|(?R))++)*F>/ text text xxxxx text F> text2 more text. /^(?>.{4})abc|^\w\w.xabcd/ xxxxabcd xx\xa0xabcd /^(.{4}){2}+abc|^\w\w.x\w\w\w\wabcd/ xxxxxxxxabcd xx\xa0xxxxxabcd /abcd/ abcd\O0 /-- These tests show up auto-possessification --/ /[ab]*/ aaaa /[ab]*?/ aaaa /[ab]?/ aaaa /[ab]??/ aaaa /[ab]+/ aaaa /[ab]+?/ aaaa /[ab]{2,3}/ aaaa /[ab]{2,3}?/ aaaa /[ab]{2,}/ aaaa /[ab]{2,}?/ aaaa '\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED '\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED /(?(?!)a|b)/ bbb aaa /()()a+/O= aaa\D a\D /(02-)?[0-9]{3}-[0-9]{3}/ 02-123-123 /-- End of testinput8 --/ ================================================ FILE: src/pcre/testdata/testinput9 ================================================ /-- This set of tests checks UTF-8 support with the DFA matching functionality of pcre_dfa_exec(), excluding Unicode property support. The -dfa flag must be used with pcretest when running it. --/ < forbid W /\x{100}ab/8 \x{100}ab /a\x{100}*b/8 ab a\x{100}b a\x{100}\x{100}b /a\x{100}+b/8 a\x{100}b a\x{100}\x{100}b *** Failers ab /\bX/8 Xoanon +Xoanon \x{300}Xoanon *** Failers YXoanon /\BX/8 YXoanon *** Failers Xoanon +Xoanon \x{300}Xoanon /X\b/8 X+oanon ZX\x{300}oanon FAX *** Failers Xoanon /X\B/8 Xoanon *** Failers X+oanon ZX\x{300}oanon FAX /[^a]/8 abcd a\x{100} /^[abc\x{123}\x{400}-\x{402}]{2,3}\d/8 ab99 \x{123}\x{123}45 \x{400}\x{401}\x{402}6 *** Failers d99 \x{123}\x{122}4 \x{400}\x{403}6 \x{400}\x{401}\x{402}\x{402}6 /a.b/8 acb a\x7fb a\x{100}b *** Failers a\nb /a(.{3})b/8 a\x{4000}xyb a\x{4000}\x7fyb a\x{4000}\x{100}yb *** Failers a\x{4000}b ac\ncb /a(.*?)(.)/ a\xc0\x88b /a(.*?)(.)/8 a\x{100}b /a(.*)(.)/ a\xc0\x88b /a(.*)(.)/8 a\x{100}b /a(.)(.)/ a\xc0\x92bcd /a(.)(.)/8 a\x{240}bcd /a(.?)(.)/ a\xc0\x92bcd /a(.?)(.)/8 a\x{240}bcd /a(.??)(.)/ a\xc0\x92bcd /a(.??)(.)/8 a\x{240}bcd /a(.{3})b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b *** Failers a\x{1234}b ac\ncb /a(.{3,})b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b *** Failers a\x{1234}b /a(.{3,}?)b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b *** Failers a\x{1234}b /a(.{3,5})b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b axbxxbcdefghijb axxxxxbcdefghijb *** Failers a\x{1234}b axxxxxxbcdefghijb /a(.{3,5}?)b/8 a\x{1234}xyb a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb a\x{1234}\x{4321}\x{3412}\x{3421}b axbxxbcdefghijb axxxxxbcdefghijb *** Failers a\x{1234}b axxxxxxbcdefghijb /^[a\x{c0}]/8 *** Failers \x{100} /(?<=aXb)cd/8 aXbcd /(?<=a\x{100}b)cd/8 a\x{100}bcd /(?<=a\x{100000}b)cd/8 a\x{100000}bcd /(?:\x{100}){3}b/8 \x{100}\x{100}\x{100}b *** Failers \x{100}\x{100}b /\x{ab}/8 \x{ab} \xc2\xab *** Failers \x00{ab} /(?<=(.))X/8 WXYZ \x{256}XYZ *** Failers XYZ /[^a]+/8g bcd \x{100}aY\x{256}Z /^[^a]{2}/8 \x{100}bc /^[^a]{2,}/8 \x{100}bcAa /^[^a]{2,}?/8 \x{100}bca /[^a]+/8ig bcd \x{100}aY\x{256}Z /^[^a]{2}/8i \x{100}bc /^[^a]{2,}/8i \x{100}bcAa /^[^a]{2,}?/8i \x{100}bca /\x{100}{0,0}/8 abcd /\x{100}?/8 abcd \x{100}\x{100} /\x{100}{0,3}/8 \x{100}\x{100} \x{100}\x{100}\x{100}\x{100} /\x{100}*/8 abce \x{100}\x{100}\x{100}\x{100} /\x{100}{1,1}/8 abcd\x{100}\x{100}\x{100}\x{100} /\x{100}{1,3}/8 abcd\x{100}\x{100}\x{100}\x{100} /\x{100}+/8 abcd\x{100}\x{100}\x{100}\x{100} /\x{100}{3}/8 abcd\x{100}\x{100}\x{100}XX /\x{100}{3,5}/8 abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX /\x{100}{3,}/8O abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX /(?<=a\x{100}{2}b)X/8 Xyyya\x{100}\x{100}bXzzz /\D*/8O aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /\D*/8O \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} /\D/8 1X2 1\x{100}2 />\S/8 > >X Y > >\x{100} Y /\d/8 \x{100}3 /\s/8 \x{100} X /\D+/8 12abcd34 *** Failers 1234 /\D{2,3}/8 12abcd34 12ab34 *** Failers 1234 12a34 /\D{2,3}?/8 12abcd34 12ab34 *** Failers 1234 12a34 /\d+/8 12abcd34 *** Failers /\d{2,3}/8 12abcd34 1234abcd *** Failers 1.4 /\d{2,3}?/8 12abcd34 1234abcd *** Failers 1.4 /\S+/8 12abcd34 *** Failers \ \ /\S{2,3}/8 12abcd34 1234abcd *** Failers \ \ /\S{2,3}?/8 12abcd34 1234abcd *** Failers \ \ />\s+ <34 *** Failers />\s{2,3} \s{2,3}? \xff< /[\xff]/8 >\x{ff}< /[^\xFF]/ XYZ /[^\xff]/8 XYZ \x{123} /^[ac]*b/8 xb /^[ac\x{100}]*b/8 xb /^[^x]*b/8i xb /^[^x]*b/8 xb /^\d*b/8 xb /(|a)/g8 catac a\x{256}a /^\x{85}$/8i \x{85} /^abc./mgx8 abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x{0085}abc7 \x{2028}abc8 \x{2029}abc9 JUNK /abc.$/mgx8 abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x{0085} abc7\x{2028} abc8\x{2029} abc9 /^a\Rb/8 a\nb a\rb a\r\nb a\x0bb a\x0cb a\x{85}b a\x{2028}b a\x{2029}b ** Failers a\n\rb /^a\R*b/8 ab a\nb a\rb a\r\nb a\x0bb a\x0c\x{2028}\x{2029}b a\x{85}b a\n\rb a\n\r\x{85}\x0cb /^a\R+b/8 a\nb a\rb a\r\nb a\x0bb a\x0c\x{2028}\x{2029}b a\x{85}b a\n\rb a\n\r\x{85}\x0cb ** Failers ab /^a\R{1,3}b/8 a\nb a\n\rb a\n\r\x{85}b a\r\n\r\nb a\r\n\r\n\r\nb a\n\r\n\rb a\n\n\r\nb ** Failers a\n\n\n\rb a\r /\h+\V?\v{3,4}/8O \x09\x20\x{a0}X\x0a\x0b\x0c\x0d\x0a /\V?\v{3,4}/8O \x20\x{a0}X\x0a\x0b\x0c\x0d\x0a /\h+\V?\v{3,4}/8O >\x09\x20\x{a0}X\x0a\x0a\x0a< /\V?\v{3,4}/8O >\x09\x20\x{a0}X\x0a\x0a\x0a< /\H\h\V\v/8 X X\x0a X\x09X\x0b ** Failers \x{a0} X\x0a /\H*\h+\V?\v{3,4}/8O \x09\x20\x{a0}X\x0a\x0b\x0c\x0d\x0a \x09\x20\x{a0}\x0a\x0b\x0c\x0d\x0a \x09\x20\x{a0}\x0a\x0b\x0c ** Failers \x09\x20\x{a0}\x0a\x0b /\H\h\V\v/8 \x{3001}\x{3000}\x{2030}\x{2028} X\x{180e}X\x{85} ** Failers \x{2009} X\x0a /\H*\h+\V?\v{3,4}/8O \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x0c\x0d\x0a \x09\x{205f}\x{a0}\x0a\x{2029}\x0c\x{2028}\x0a \x09\x20\x{202f}\x0a\x0b\x0c ** Failers \x09\x{200a}\x{a0}\x{2028}\x0b /a\Rb/I8 a\rb a\nb a\r\nb ** Failers a\x{85}b a\x0bb /a\Rb/I8 a\rb a\nb a\r\nb a\x{85}b a\x0bb ** Failers a\x{85}b\ a\x0bb\ /a\R?b/I8 a\rb a\nb a\r\nb ** Failers a\x{85}b a\x0bb /a\R?b/I8 a\rb a\nb a\r\nb a\x{85}b a\x0bb ** Failers a\x{85}b\ a\x0bb\ /X/8f A\x{1ec5}ABCXYZ /abcd*/8 xxxxabcd\P xxxxabcd\P\P /abcd*/i8 xxxxabcd\P xxxxabcd\P\P XXXXABCD\P XXXXABCD\P\P /abc\d*/8 xxxxabc1\P xxxxabc1\P\P /abc[de]*/8 xxxxabcde\P xxxxabcde\P\P /\bthe cat\b/8 the cat\P the cat\P\P /ab\Cde/8 abXde /(?<=ab\Cde)X/8 /./8 \r\P \r\P\P /.{2,3}/8 \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /.{2,3}?/8 \r\P \r\P\P \r\r\P \r\r\P\P \r\r\r\P \r\r\r\P\P /[^\x{100}]/8 \x{100}\x{101}X /[^\x{100}]+/8 \x{100}\x{101}X /-- End of testinput9 --/ ================================================ FILE: src/pcre/testdata/testinputEBC ================================================ /-- This is a specialized test for checking, when PCRE is compiled with the EBCDIC option but in an ASCII environment, that newline and white space functionality is working. It catches cases where explicit values such as 0x0a have been used instead of names like CHAR_LF. Needless to say, it is not a genuine EBCDIC test! In patterns, alphabetic characters that follow a backslash must be in EBCDIC code. In data, newlines and other spacing characters must be in EBCDIC, but can be specified as escapes. --/ /-- Test default newline and variations --/ /^A/m ABC 12\x15ABC /^A/m 12\x15ABC 12\x0dABC 12\x0d\x15ABC 12\x25ABC /^A/m 12\x15ABC 12\x0dABC 12\x0d\x15ABC ** Fail 12\x25ABC /-- Test \h --/ /^A\/ A B A\x41B /-- Test \H --/ /^A\/ AB A\x42B ** Fail A B A\x41B /-- Test \R --/ /^A\/ A\x15B A\x0dB A\x25B A\x0bB A\x0cB ** Fail A B /-- Test \v --/ /^A\/ A\x15B A\x0dB A\x25B A\x0bB A\x0cB ** Fail A B /-- Test \V --/ /^A\/ A B ** Fail A\x15B A\x0dB A\x25B A\x0bB A\x0cB /-- For repeated items, use an atomic group so that the output is the same for DFA matching (otherwise it may show multiple matches). --/ /-- Test \h+ --/ /^A(?>\+)/ A B /-- Test \H+ --/ /^A(?>\+)/ AB ** Fail A B /-- Test \R+ --/ /^A(?>\+)/ A\x15B A\x0dB A\x25B A\x0bB A\x0cB ** Fail A B /-- Test \v+ --/ /^A(?>\+)/ A\x15B A\x0dB A\x25B A\x0bB A\x0cB ** Fail A B /-- Test \V+ --/ /^A(?>\+)/ A B ** Fail A\x15B A\x0dB A\x25B A\x0bB A\x0cB /-- End --/ ================================================ FILE: src/pcre/testdata/testoutput1 ================================================ /-- This set of tests is for features that are compatible with all versions of Perl >= 5.10, in non-UTF-8 mode. It should run clean for the 8-bit, 16-bit, and 32-bit PCRE libraries. --/ < forbid 89?=ABCDEFfGILMNPTUWXZ< /the quick brown fox/ the quick brown fox 0: the quick brown fox The quick brown FOX No match What do you know about the quick brown fox? 0: the quick brown fox What do you know about THE QUICK BROWN FOX? No match /The quick brown fox/i the quick brown fox 0: the quick brown fox The quick brown FOX 0: The quick brown FOX What do you know about the quick brown fox? 0: the quick brown fox What do you know about THE QUICK BROWN FOX? 0: THE QUICK BROWN FOX /abcd\t\n\r\f\a\e\071\x3b\$\\\?caxyz/ abcd\t\n\r\f\a\e9;\$\\?caxyz 0: abcd\x09\x0a\x0d\x0c\x07\x1b9;$\?caxyz /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/ abxyzpqrrrabbxyyyypqAzz 0: abxyzpqrrrabbxyyyypqAzz abxyzpqrrrabbxyyyypqAzz 0: abxyzpqrrrabbxyyyypqAzz aabxyzpqrrrabbxyyyypqAzz 0: aabxyzpqrrrabbxyyyypqAzz aaabxyzpqrrrabbxyyyypqAzz 0: aaabxyzpqrrrabbxyyyypqAzz aaaabxyzpqrrrabbxyyyypqAzz 0: aaaabxyzpqrrrabbxyyyypqAzz abcxyzpqrrrabbxyyyypqAzz 0: abcxyzpqrrrabbxyyyypqAzz aabcxyzpqrrrabbxyyyypqAzz 0: aabcxyzpqrrrabbxyyyypqAzz aaabcxyzpqrrrabbxyyyypAzz 0: aaabcxyzpqrrrabbxyyyypAzz aaabcxyzpqrrrabbxyyyypqAzz 0: aaabcxyzpqrrrabbxyyyypqAzz aaabcxyzpqrrrabbxyyyypqqAzz 0: aaabcxyzpqrrrabbxyyyypqqAzz aaabcxyzpqrrrabbxyyyypqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqAzz aaabcxyzpqrrrabbxyyyypqqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqqAzz aaabcxyzpqrrrabbxyyyypqqqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqqqAzz aaabcxyzpqrrrabbxyyyypqqqqqqAzz 0: aaabcxyzpqrrrabbxyyyypqqqqqqAzz aaaabcxyzpqrrrabbxyyyypqAzz 0: aaaabcxyzpqrrrabbxyyyypqAzz abxyzzpqrrrabbxyyyypqAzz 0: abxyzzpqrrrabbxyyyypqAzz aabxyzzzpqrrrabbxyyyypqAzz 0: aabxyzzzpqrrrabbxyyyypqAzz aaabxyzzzzpqrrrabbxyyyypqAzz 0: aaabxyzzzzpqrrrabbxyyyypqAzz aaaabxyzzzzpqrrrabbxyyyypqAzz 0: aaaabxyzzzzpqrrrabbxyyyypqAzz abcxyzzpqrrrabbxyyyypqAzz 0: abcxyzzpqrrrabbxyyyypqAzz aabcxyzzzpqrrrabbxyyyypqAzz 0: aabcxyzzzpqrrrabbxyyyypqAzz aaabcxyzzzzpqrrrabbxyyyypqAzz 0: aaabcxyzzzzpqrrrabbxyyyypqAzz aaaabcxyzzzzpqrrrabbxyyyypqAzz 0: aaaabcxyzzzzpqrrrabbxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyypqAzz 0: aaaabcxyzzzzpqrrrabbbxyyyypqAzz aaaabcxyzzzzpqrrrabbbxyyyyypqAzz 0: aaaabcxyzzzzpqrrrabbbxyyyyypqAzz aaabcxyzpqrrrabbxyyyypABzz 0: aaabcxyzpqrrrabbxyyyypABzz aaabcxyzpqrrrabbxyyyypABBzz 0: aaabcxyzpqrrrabbxyyyypABBzz >>>aaabxyzpqrrrabbxyyyypqAzz 0: aaabxyzpqrrrabbxyyyypqAzz >aaaabxyzpqrrrabbxyyyypqAzz 0: aaaabxyzpqrrrabbxyyyypqAzz >>>>abcxyzpqrrrabbxyyyypqAzz 0: abcxyzpqrrrabbxyyyypqAzz *** Failers No match abxyzpqrrabbxyyyypqAzz No match abxyzpqrrrrabbxyyyypqAzz No match abxyzpqrrrabxyyyypqAzz No match aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz No match aaaabcxyzzzzpqrrrabbbxyyypqAzz No match aaabcxyzpqrrrabbxyyyypqqqqqqqAzz No match /^(abc){1,2}zz/ abczz 0: abczz 1: abc abcabczz 0: abcabczz 1: abc *** Failers No match zz No match abcabcabczz No match >>abczz No match /^(b+?|a){1,2}?c/ bc 0: bc 1: b bbc 0: bbc 1: b bbbc 0: bbbc 1: bb bac 0: bac 1: a bbac 0: bbac 1: a aac 0: aac 1: a abbbbbbbbbbbc 0: abbbbbbbbbbbc 1: bbbbbbbbbbb bbbbbbbbbbbac 0: bbbbbbbbbbbac 1: a *** Failers No match aaac No match abbbbbbbbbbbac No match /^(b+|a){1,2}c/ bc 0: bc 1: b bbc 0: bbc 1: bb bbbc 0: bbbc 1: bbb bac 0: bac 1: a bbac 0: bbac 1: a aac 0: aac 1: a abbbbbbbbbbbc 0: abbbbbbbbbbbc 1: bbbbbbbbbbb bbbbbbbbbbbac 0: bbbbbbbbbbbac 1: a *** Failers No match aaac No match abbbbbbbbbbbac No match /^(b+|a){1,2}?bc/ bbc 0: bbc 1: b /^(b*|ba){1,2}?bc/ babc 0: babc 1: ba bbabc 0: bbabc 1: ba bababc 0: bababc 1: ba *** Failers No match bababbc No match babababc No match /^(ba|b*){1,2}?bc/ babc 0: babc 1: ba bbabc 0: bbabc 1: ba bababc 0: bababc 1: ba *** Failers No match bababbc No match babababc No match /^\ca\cA\c[;\c:/ \x01\x01\e;z 0: \x01\x01\x1b;z /^[ab\]cde]/ athing 0: a bthing 0: b ]thing 0: ] cthing 0: c dthing 0: d ething 0: e *** Failers No match fthing No match [thing No match \\thing No match /^[]cde]/ ]thing 0: ] cthing 0: c dthing 0: d ething 0: e *** Failers No match athing No match fthing No match /^[^ab\]cde]/ fthing 0: f [thing 0: [ \\thing 0: \ *** Failers 0: * athing No match bthing No match ]thing No match cthing No match dthing No match ething No match /^[^]cde]/ athing 0: a fthing 0: f *** Failers 0: * ]thing No match cthing No match dthing No match ething No match /^\/ 0: \x81 /^/ 0: \xff /^[0-9]+$/ 0 0: 0 1 0: 1 2 0: 2 3 0: 3 4 0: 4 5 0: 5 6 0: 6 7 0: 7 8 0: 8 9 0: 9 10 0: 10 100 0: 100 *** Failers No match abc No match /^.*nter/ enter 0: enter inter 0: inter uponter 0: uponter /^xxx[0-9]+$/ xxx0 0: xxx0 xxx1234 0: xxx1234 *** Failers No match xxx No match /^.+[0-9][0-9][0-9]$/ x123 0: x123 xx123 0: xx123 123456 0: 123456 *** Failers No match 123 No match x1234 0: x1234 /^.+?[0-9][0-9][0-9]$/ x123 0: x123 xx123 0: xx123 123456 0: 123456 *** Failers No match 123 No match x1234 0: x1234 /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ abc!pqr=apquxz.ixr.zzz.ac.uk 0: abc!pqr=apquxz.ixr.zzz.ac.uk 1: abc 2: pqr *** Failers No match !pqr=apquxz.ixr.zzz.ac.uk No match abc!=apquxz.ixr.zzz.ac.uk No match abc!pqr=apquxz:ixr.zzz.ac.uk No match abc!pqr=apquxz.ixr.zzz.ac.ukk No match /:/ Well, we need a colon: somewhere 0: : *** Fail if we don't No match /([\da-f:]+)$/i 0abc 0: 0abc 1: 0abc abc 0: abc 1: abc fed 0: fed 1: fed E 0: E 1: E :: 0: :: 1: :: 5f03:12C0::932e 0: 5f03:12C0::932e 1: 5f03:12C0::932e fed def 0: def 1: def Any old stuff 0: ff 1: ff *** Failers No match 0zzz No match gzzz No match fed\x20 No match Any old rubbish No match /^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ .1.2.3 0: .1.2.3 1: 1 2: 2 3: 3 A.12.123.0 0: A.12.123.0 1: 12 2: 123 3: 0 *** Failers No match .1.2.3333 No match 1.2.3 No match 1234.2.3 No match /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( 0: 1 IN SOA non-sp1 non-sp2( 1: 1 2: non-sp1 3: non-sp2 1 IN SOA non-sp1 non-sp2 ( 0: 1 IN SOA non-sp1 non-sp2 ( 1: 1 2: non-sp1 3: non-sp2 *** Failers No match 1IN SOA non-sp1 non-sp2( No match /^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ a. 0: a. Z. 0: Z. 2. 0: 2. ab-c.pq-r. 0: ab-c.pq-r. 1: .pq-r sxk.zzz.ac.uk. 0: sxk.zzz.ac.uk. 1: .uk x-.y-. 0: x-.y-. 1: .y- *** Failers No match -abc.peq. No match /^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ *.a 0: *.a *.b0-a 0: *.b0-a 1: 0-a *.c3-b.c 0: *.c3-b.c 1: 3-b 2: .c *.c-a.b-c 0: *.c-a.b-c 1: -a 2: .b-c 3: -c *** Failers No match *.0 No match *.a- No match *.a-b.c- No match *.c-a.0-c No match /^(?=ab(de))(abd)(e)/ abde 0: abde 1: de 2: abd 3: e /^(?!(ab)de|x)(abd)(f)/ abdf 0: abdf 1: 2: abd 3: f /^(?=(ab(cd)))(ab)/ abcd 0: ab 1: abcd 2: cd 3: ab /^[\da-f](\.[\da-f])*$/i a.b.c.d 0: a.b.c.d 1: .d A.B.C.D 0: A.B.C.D 1: .D a.b.c.1.2.3.C 0: a.b.c.1.2.3.C 1: .C /^\".*\"\s*(;.*)?$/ \"1234\" 0: "1234" \"abcd\" ; 0: "abcd" ; 1: ; \"\" ; rhubarb 0: "" ; rhubarb 1: ; rhubarb *** Failers No match \"1234\" : things No match /^$/ \ 0: *** Failers No match / ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x ab c 0: ab c *** Failers No match abc No match ab cde No match /(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ ab c 0: ab c *** Failers No match abc No match ab cde No match /^ a\ b[c ]d $/x a bcd 0: a bcd a b d 0: a b d *** Failers No match abcd No match ab d No match /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ abcdefhijklm 0: abcdefhijklm 1: abc 2: bc 3: c 4: def 5: ef 6: f 7: hij 8: ij 9: j 10: klm 11: lm 12: m /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ abcdefhijklm 0: abcdefhijklm 1: bc 2: c 3: ef 4: f 5: ij 6: j 7: lm 8: m /^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ a+ Z0+\x08\n\x1d\x12 0: a+ Z0+\x08\x0a\x1d\x12 /^[.^$|()*+?{,}]+/ .^\$(*+)|{?,?} 0: .^$(*+)|{?,?} /^a*\w/ z 0: z az 0: az aaaz 0: aaaz a 0: a aa 0: aa aaaa 0: aaaa a+ 0: a aa+ 0: aa /^a*?\w/ z 0: z az 0: a aaaz 0: a a 0: a aa 0: a aaaa 0: a a+ 0: a aa+ 0: a /^a+\w/ az 0: az aaaz 0: aaaz aa 0: aa aaaa 0: aaaa aa+ 0: aa /^a+?\w/ az 0: az aaaz 0: aa aa 0: aa aaaa 0: aa aa+ 0: aa /^\d{8}\w{2,}/ 1234567890 0: 1234567890 12345678ab 0: 12345678ab 12345678__ 0: 12345678__ *** Failers No match 1234567 No match /^[aeiou\d]{4,5}$/ uoie 0: uoie 1234 0: 1234 12345 0: 12345 aaaaa 0: aaaaa *** Failers No match 123456 No match /^[aeiou\d]{4,5}?/ uoie 0: uoie 1234 0: 1234 12345 0: 1234 aaaaa 0: aaaa 123456 0: 1234 /\A(abc|def)=(\1){2,3}\Z/ abc=abcabc 0: abc=abcabc 1: abc 2: abc def=defdefdef 0: def=defdefdef 1: def 2: def *** Failers No match abc=defdef No match /^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\11*(\3\4)\1(?#)2$/ abcdefghijkcda2 0: abcdefghijkcda2 1: a 2: b 3: c 4: d 5: e 6: f 7: g 8: h 9: i 10: j 11: k 12: cd abcdefghijkkkkcda2 0: abcdefghijkkkkcda2 1: a 2: b 3: c 4: d 5: e 6: f 7: g 8: h 9: i 10: j 11: k 12: cd /(cat(a(ract|tonic)|erpillar)) \1()2(3)/ cataract cataract23 0: cataract cataract23 1: cataract 2: aract 3: ract 4: 5: 3 catatonic catatonic23 0: catatonic catatonic23 1: catatonic 2: atonic 3: tonic 4: 5: 3 caterpillar caterpillar23 0: caterpillar caterpillar23 1: caterpillar 2: erpillar 3: 4: 5: 3 /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ From abcd Mon Sep 01 12:33:02 1997 0: From abcd Mon Sep 01 12:33 1: abcd /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ From abcd Mon Sep 01 12:33:02 1997 0: From abcd Mon Sep 01 12:33 1: Sep From abcd Mon Sep 1 12:33:02 1997 0: From abcd Mon Sep 1 12:33 1: Sep *** Failers No match From abcd Sep 01 12:33:02 1997 No match /^12.34/s 12\n34 0: 12\x0a34 12\r34 0: 12\x0d34 /\w+(?=\t)/ the quick brown\t fox 0: brown /foo(?!bar)(.*)/ foobar is foolish see? 0: foolish see? 1: lish see? /(?:(?!foo)...|^.{0,2})bar(.*)/ foobar crowbar etc 0: rowbar etc 1: etc barrel 0: barrel 1: rel 2barrel 0: 2barrel 1: rel A barrel 0: A barrel 1: rel /^(\D*)(?=\d)(?!123)/ abc456 0: abc 1: abc *** Failers No match abc123 No match /^1234(?# test newlines inside)/ 1234 0: 1234 /^1234 #comment in extended re /x 1234 0: 1234 /#rhubarb abcd/x abcd 0: abcd /^abcd#rhubarb/x abcd 0: abcd /^(a)\1{2,3}(.)/ aaab 0: aaab 1: a 2: b aaaab 0: aaaab 1: a 2: b aaaaab 0: aaaaa 1: a 2: a aaaaaab 0: aaaaa 1: a 2: a /(?!^)abc/ the abc 0: abc *** Failers No match abc No match /(?=^)abc/ abc 0: abc *** Failers No match the abc No match /^[ab]{1,3}(ab*|b)/ aabbbbb 0: aabb 1: b /^[ab]{1,3}?(ab*|b)/ aabbbbb 0: aabbbbb 1: abbbbb /^[ab]{1,3}?(ab*?|b)/ aabbbbb 0: aa 1: a /^[ab]{1,3}(ab*?|b)/ aabbbbb 0: aabb 1: b / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /x Alan Other 0: Alan Other 0: user@dom.ain user\@dom.ain 0: user@dom.ain \"A. Other\" (a comment) 0: "A. Other" (a comment) A. Other (a comment) 0: Other (a comment) \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) # leading word [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces (?: (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) | " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " ) # "special" comment or quoted string [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" )* < [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # < (?: @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* (?: , [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* )* # additional domains : [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address spec > # > # name and address ) /x Alan Other 0: Alan Other 0: user@dom.ain user\@dom.ain 0: user@dom.ain \"A. Other\" (a comment) 0: "A. Other" A. Other (a comment) 0: Other \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay A missing angle ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff /P[^*]TAIRE[^*]{1,6}?LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx 0: PSTAIREISLL /P[^*]TAIRE[^*]{1,}?LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx 0: PSTAIREISLL /(\.\d\d[1-9]?)\d+/ 1.230003938 0: .230003938 1: .23 1.875000282 0: .875000282 1: .875 1.235 0: .235 1: .23 /(\.\d\d((?=0)|\d(?=\d)))/ 1.230003938 0: .23 1: .23 2: 1.875000282 0: .875 1: .875 2: 5 *** Failers No match 1.235 No match /a(?)b/ ab 0: ab /\b(foo)\s+(\w+)/i Food is on the foo table 0: foo table 1: foo 2: table /foo(.*)bar/ The food is under the bar in the barn. 0: food is under the bar in the bar 1: d is under the bar in the /foo(.*?)bar/ The food is under the bar in the barn. 0: food is under the bar 1: d is under the /(.*)(\d*)/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 53147 2: /(.*)(\d+)/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 5314 2: 7 /(.*?)(\d*)/ I have 2 numbers: 53147 0: 1: 2: /(.*?)(\d+)/ I have 2 numbers: 53147 0: I have 2 1: I have 2: 2 /(.*)(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 5314 2: 7 /(.*?)(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 2: 53147 /(.*)\b(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 2: 53147 /(.*\D)(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 numbers: 2: 53147 /^\D*(?!123)/ ABC123 0: AB /^(\D*)(?=\d)(?!123)/ ABC445 0: ABC 1: ABC *** Failers No match ABC123 No match /^[W-]46]/ W46]789 0: W46] -46]789 0: -46] *** Failers No match Wall No match Zebra No match 42 No match [abcd] No match ]abcd[ No match /^[W-\]46]/ W46]789 0: W Wall 0: W Zebra 0: Z Xylophone 0: X 42 0: 4 [abcd] 0: [ ]abcd[ 0: ] \\backslash 0: \ *** Failers No match -46]789 No match well No match /\d\d\/\d\d\/\d\d\d\d/ 01/01/2000 0: 01/01/2000 /word (?:[a-zA-Z0-9]+ ){0,10}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark No match /word (?:[a-zA-Z0-9]+ ){0,300}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope No match /^(a){0,0}/ bcd 0: abc 0: aab 0: /^(a){0,1}/ bcd 0: abc 0: a 1: a aab 0: a 1: a /^(a){0,2}/ bcd 0: abc 0: a 1: a aab 0: aa 1: a /^(a){0,3}/ bcd 0: abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a /^(a){0,}/ bcd 0: abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a aaaaaaaa 0: aaaaaaaa 1: a /^(a){1,1}/ bcd No match abc 0: a 1: a aab 0: a 1: a /^(a){1,2}/ bcd No match abc 0: a 1: a aab 0: aa 1: a /^(a){1,3}/ bcd No match abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a /^(a){1,}/ bcd No match abc 0: a 1: a aab 0: aa 1: a aaa 0: aaa 1: a aaaaaaaa 0: aaaaaaaa 1: a /.*\.gif/ borfle\nbib.gif\nno 0: bib.gif /.{0,}\.gif/ borfle\nbib.gif\nno 0: bib.gif /.*\.gif/m borfle\nbib.gif\nno 0: bib.gif /.*\.gif/s borfle\nbib.gif\nno 0: borfle\x0abib.gif /.*\.gif/ms borfle\nbib.gif\nno 0: borfle\x0abib.gif /.*$/ borfle\nbib.gif\nno 0: no /.*$/m borfle\nbib.gif\nno 0: borfle /.*$/s borfle\nbib.gif\nno 0: borfle\x0abib.gif\x0ano /.*$/ms borfle\nbib.gif\nno 0: borfle\x0abib.gif\x0ano /.*$/ borfle\nbib.gif\nno\n 0: no /.*$/m borfle\nbib.gif\nno\n 0: borfle /.*$/s borfle\nbib.gif\nno\n 0: borfle\x0abib.gif\x0ano\x0a /.*$/ms borfle\nbib.gif\nno\n 0: borfle\x0abib.gif\x0ano\x0a /(.*X|^B)/ abcde\n1234Xyz 0: 1234X 1: 1234X BarFoo 0: B 1: B *** Failers No match abcde\nBar No match /(.*X|^B)/m abcde\n1234Xyz 0: 1234X 1: 1234X BarFoo 0: B 1: B abcde\nBar 0: B 1: B /(.*X|^B)/s abcde\n1234Xyz 0: abcde\x0a1234X 1: abcde\x0a1234X BarFoo 0: B 1: B *** Failers No match abcde\nBar No match /(.*X|^B)/ms abcde\n1234Xyz 0: abcde\x0a1234X 1: abcde\x0a1234X BarFoo 0: B 1: B abcde\nBar 0: B 1: B /(?s)(.*X|^B)/ abcde\n1234Xyz 0: abcde\x0a1234X 1: abcde\x0a1234X BarFoo 0: B 1: B *** Failers No match abcde\nBar No match /(?s:.*X|^B)/ abcde\n1234Xyz 0: abcde\x0a1234X BarFoo 0: B *** Failers No match abcde\nBar No match /^.*B/ **** Failers No match abc\nB No match /(?s)^.*B/ abc\nB 0: abc\x0aB /(?m)^.*B/ abc\nB 0: B /(?ms)^.*B/ abc\nB 0: abc\x0aB /(?ms)^B/ abc\nB 0: B /(?s)B$/ B\n 0: B /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ 123456654321 0: 123456654321 /^\d\d\d\d\d\d\d\d\d\d\d\d/ 123456654321 0: 123456654321 /^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/ 123456654321 0: 123456654321 /^[abc]{12}/ abcabcabcabc 0: abcabcabcabc /^[a-c]{12}/ abcabcabcabc 0: abcabcabcabc /^(a|b|c){12}/ abcabcabcabc 0: abcabcabcabc 1: c /^[abcdefghijklmnopqrstuvwxy0123456789]/ n 0: n *** Failers No match z No match /abcde{0,0}/ abcd 0: abcd *** Failers No match abce No match /ab[cd]{0,0}e/ abe 0: abe *** Failers No match abcde No match /ab(c){0,0}d/ abd 0: abd *** Failers No match abcd No match /a(b*)/ a 0: a 1: ab 0: ab 1: b abbbb 0: abbbb 1: bbbb *** Failers 0: a 1: bbbbb No match /ab\d{0}e/ abe 0: abe *** Failers No match ab1e No match /"([^\\"]+|\\.)*"/ the \"quick\" brown fox 0: "quick" 1: quick \"the \\\"quick\\\" brown fox\" 0: "the \"quick\" brown fox" 1: brown fox /.*?/g+ abc 0: 0+ abc 0: a 0+ bc 0: 0+ bc 0: b 0+ c 0: 0+ c 0: c 0+ 0: 0+ /\b/g+ abc 0: 0+ abc 0: 0+ /\b/+g abc 0: 0+ abc 0: 0+ //g abc 0: 0: 0: 0: /]{0,})>]{0,})>([\d]{0,}\.)(.*)((
    ([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is 43.Word Processor
    (N-1286)
    Lega lstaff.comCA - Statewide 0: 43.Word Processor
    (N-1286)
    Lega lstaff.comCA - Statewide 1: BGCOLOR='#DBE9E9' 2: align=left valign=top 3: 43. 4: Word Processor
    (N-1286) 5: 6: 7: 8: align=left valign=top 9: Lega lstaff.com 10: align=left valign=top 11: CA - Statewide /a[^a]b/ acb 0: acb a\nb 0: a\x0ab /a.b/ acb 0: acb *** Failers No match a\nb No match /a[^a]b/s acb 0: acb a\nb 0: a\x0ab /a.b/s acb 0: acb a\nb 0: a\x0ab /^(b+?|a){1,2}?c/ bac 0: bac 1: a bbac 0: bbac 1: a bbbac 0: bbbac 1: a bbbbac 0: bbbbac 1: a bbbbbac 0: bbbbbac 1: a /^(b+|a){1,2}?c/ bac 0: bac 1: a bbac 0: bbac 1: a bbbac 0: bbbac 1: a bbbbac 0: bbbbac 1: a bbbbbac 0: bbbbbac 1: a /(?!\A)x/m x\nb\n No match a\bx\n 0: x /\x0{ab}/ \0{ab} 0: \x00{ab} /(A|B)*?CD/ CD 0: CD /(A|B)*CD/ CD 0: CD /(AB)*?\1/ ABABAB 0: ABAB 1: AB /(AB)*\1/ ABABAB 0: ABABAB 1: AB /(?.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ No match "(?>.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo 0: /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo /(?>(\.\d\d[1-9]?))\d+/ 1.230003938 0: .230003938 1: .23 1.875000282 0: .875000282 1: .875 *** Failers No match 1.235 No match /^((?>\w+)|(?>\s+))*$/ now is the time for all good men to come to the aid of the party 0: now is the time for all good men to come to the aid of the party 1: party *** Failers No match this is not a line with only words and spaces! No match /(\d+)(\w)/ 12345a 0: 12345a 1: 12345 2: a 12345+ 0: 12345 1: 1234 2: 5 /((?>\d+))(\w)/ 12345a 0: 12345a 1: 12345 2: a *** Failers No match 12345+ No match /(?>a+)b/ aaab 0: aaab /((?>a+)b)/ aaab 0: aaab 1: aaab /(?>(a+))b/ aaab 0: aaab 1: aaa /(?>b)+/ aaabbbccc 0: bbb /(?>a+|b+|c+)*c/ aaabbbbccccd 0: aaabbbbc /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x 0: abc(ade)ufh()()x 1: x /\(((?>[^()]+)|\([^()]+\))+\)/ (abc) 0: (abc) 1: abc (abc(def)xyz) 0: (abc(def)xyz) 1: xyz *** Failers No match ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /a(?-i)b/i ab 0: ab Ab 0: Ab *** Failers No match aB No match AB No match /(a (?x)b c)d e/ a bcd e 0: a bcd e 1: a bc *** Failers No match a b cd e No match abcd e No match a bcde No match /(a b(?x)c d (?-x)e f)/ a bcde f 0: a bcde f 1: a bcde f *** Failers No match abcdef No match /(a(?i)b)c/ abc 0: abc 1: ab aBc 0: aBc 1: aB *** Failers No match abC No match aBC No match Abc No match ABc No match ABC No match AbC No match /a(?i:b)c/ abc 0: abc aBc 0: aBc *** Failers No match ABC No match abC No match aBC No match /a(?i:b)*c/ aBc 0: aBc aBBc 0: aBBc *** Failers No match aBC No match aBBC No match /a(?=b(?i)c)\w\wd/ abcd 0: abcd abCd 0: abCd *** Failers No match aBCd No match abcD No match /(?s-i:more.*than).*million/i more than million 0: more than million more than MILLION 0: more than MILLION more \n than Million 0: more \x0a than Million *** Failers No match MORE THAN MILLION No match more \n than \n million No match /(?:(?s-i)more.*than).*million/i more than million 0: more than million more than MILLION 0: more than MILLION more \n than Million 0: more \x0a than Million *** Failers No match MORE THAN MILLION No match more \n than \n million No match /(?>a(?i)b+)+c/ abc 0: abc aBbc 0: aBbc aBBc 0: aBBc *** Failers No match Abc No match abAb No match abbC No match /(?=a(?i)b)\w\wc/ abc 0: abc aBc 0: aBc *** Failers No match Ab No match abC No match aBC No match /(?<=a(?i)b)(\w\w)c/ abxxc 0: xxc 1: xx aBxxc 0: xxc 1: xx *** Failers No match Abxxc No match ABxxc No match abxxC No match /(?:(a)|b)(?(1)A|B)/ aA 0: aA 1: a bB 0: bB *** Failers No match aB No match bA No match /^(a)?(?(1)a|b)+$/ aa 0: aa 1: a b 0: b bb 0: bb *** Failers No match ab No match /^(?(?=abc)\w{3}:|\d\d)$/ abc: 0: abc: 12 0: 12 *** Failers No match 123 No match xyz No match /^(?(?!abc)\d\d|\w{3}:)$/ abc: 0: abc: 12 0: 12 *** Failers No match 123 No match xyz No match /(?(?<=foo)bar|cat)/ foobar 0: bar cat 0: cat fcat 0: cat focat 0: cat *** Failers No match foocat No match /(?(?a*)*/ a 0: a aa 0: aa aaaa 0: aaaa /(abc|)+/ abc 0: abc 1: abcabc 0: abcabc 1: abcabcabc 0: abcabcabc 1: xyz 0: 1: /([a]*)*/ a 0: a 1: aaaaa 0: aaaaa 1: /([ab]*)*/ a 0: a 1: b 0: b 1: ababab 0: ababab 1: aaaabcde 0: aaaab 1: bbbb 0: bbbb 1: /([^a]*)*/ b 0: b 1: bbbb 0: bbbb 1: aaa 0: 1: /([^ab]*)*/ cccc 0: cccc 1: abab 0: 1: /([a]*?)*/ a 0: 1: aaaa 0: 1: /([ab]*?)*/ a 0: 1: b 0: 1: abab 0: 1: baba 0: 1: /([^a]*?)*/ b 0: 1: bbbb 0: 1: aaa 0: 1: /([^ab]*?)*/ c 0: 1: cccc 0: 1: baba 0: 1: /(?>a*)*/ a 0: a aaabcde 0: aaa /((?>a*))*/ aaaaa 0: aaaaa 1: aabbaa 0: aa 1: /((?>a*?))*/ aaaaa 0: 1: aabbaa 0: 1: /(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x 12-sep-98 0: 12-sep-98 12-09-98 0: 12-09-98 *** Failers No match sep-12-98 No match /(?<=(foo))bar\1/ foobarfoo 0: barfoo 1: foo foobarfootling 0: barfoo 1: foo *** Failers No match foobar No match barfoo No match /(?i:saturday|sunday)/ saturday 0: saturday sunday 0: sunday Saturday 0: Saturday Sunday 0: Sunday SATURDAY 0: SATURDAY SUNDAY 0: SUNDAY SunDay 0: SunDay /(a(?i)bc|BB)x/ abcx 0: abcx 1: abc aBCx 0: aBCx 1: aBC bbx 0: bbx 1: bb BBx 0: BBx 1: BB *** Failers No match abcX No match aBCX No match bbX No match BBX No match /^([ab](?i)[cd]|[ef])/ ac 0: ac 1: ac aC 0: aC 1: aC bD 0: bD 1: bD elephant 0: e 1: e Europe 0: E 1: E frog 0: f 1: f France 0: F 1: F *** Failers No match Africa No match /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ ab 0: ab 1: ab aBd 0: aBd 1: aBd xy 0: xy 1: xy xY 0: xY 1: xY zebra 0: z 1: z Zambesi 0: Z 1: Z *** Failers No match aCD No match XY No match /(?<=foo\n)^bar/m foo\nbar 0: bar *** Failers No match bar No match baz\nbar No match /(?<=(?]&/ <&OUT 0: <& /^(a\1?){4}$/ aaaaaaaaaa 0: aaaaaaaaaa 1: aaaa *** Failers No match AB No match aaaaaaaaa No match aaaaaaaaaaa No match /^(a(?(1)\1)){4}$/ aaaaaaaaaa 0: aaaaaaaaaa 1: aaaa *** Failers No match aaaaaaaaa No match aaaaaaaaaaa No match /(?:(f)(o)(o)|(b)(a)(r))*/ foobar 0: foobar 1: f 2: o 3: o 4: b 5: a 6: r /(?<=a)b/ ab 0: b *** Failers No match cb No match b No match /(? 2: abcd xy:z:::abcd 0: xy:z:::abcd 1: xy:z::: 2: abcd /^[^bcd]*(c+)/ aexycd 0: aexyc 1: c /(a*)b+/ caab 0: aab 1: aa /([\w:]+::)?(\w+)$/ abcd 0: abcd 1: 2: abcd xy:z:::abcd 0: xy:z:::abcd 1: xy:z::: 2: abcd *** Failers 0: Failers 1: 2: Failers abcd: No match abcd: No match /^[^bcd]*(c+)/ aexycd 0: aexyc 1: c /(>a+)ab/ /(?>a+)b/ aaab 0: aaab /([[:]+)/ a:[b]: 0: :[ 1: :[ /([[=]+)/ a=[b]= 0: =[ 1: =[ /([[.]+)/ a.[b]. 0: .[ 1: .[ /((?>a+)b)/ aaab 0: aaab 1: aaab /(?>(a+))b/ aaab 0: aaab 1: aaa /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x 0: abc(ade)ufh()()x 1: x /a\Z/ *** Failers No match aaab No match a\nb\n No match /b\Z/ a\nb\n 0: b /b\z/ /b\Z/ a\nb 0: b /b\z/ a\nb 0: b *** Failers No match /^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$/ a 0: a 1: abc 0: abc 1: a-b 0: a-b 1: 0-9 0: 0-9 1: a.b 0: a.b 1: 5.6.7 0: 5.6.7 1: the.quick.brown.fox 0: the.quick.brown.fox 1: a100.b200.300c 0: a100.b200.300c 1: 12-ab.1245 0: 12-ab.1245 1: *** Failers No match \ No match .a No match -a No match a- No match a. No match a_b No match a.- No match a.. No match ab..bc No match the.quick.brown.fox- No match the.quick.brown.fox. No match the.quick.brown.fox_ No match the.quick.brown.fox+ No match /(?>.*)(?<=(abcd|wxyz))/ alphabetabcd 0: alphabetabcd 1: abcd endingwxyz 0: endingwxyz 1: wxyz *** Failers No match a rather long string that doesn't end with one of them No match /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark No match /word (?>[a-zA-Z0-9]+ ){0,30}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope No match /(?<=\d{3}(?!999))foo/ 999foo 0: foo 123999foo 0: foo *** Failers No match 123abcfoo No match /(?<=(?!...999)\d{3})foo/ 999foo 0: foo 123999foo 0: foo *** Failers No match 123abcfoo No match /(?<=\d{3}(?!999)...)foo/ 123abcfoo 0: foo 123456foo 0: foo *** Failers No match 123999foo No match /(?<=\d{3}...)(? 2: 3: abcd
    2: 3: abcd \s*)=(?>\s*) # find 2: 3: abcd Z)+|A)*/ ZABCDEFG 0: ZA 1: A /((?>)+|A)*/ ZABCDEFG 0: 1: /a*/g abbab 0: a 0: 0: 0: a 0: 0: /^[\d-a]/ abcde 0: a -things 0: - 0digit 0: 0 *** Failers No match bcdef No match /[[:space:]]+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09\x0a\x0c\x0d\x0b /[[:blank:]]+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09 /[\s]+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09\x0a\x0c\x0d\x0b /\s+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09\x0a\x0c\x0d\x0b /a b/x ab 0: ab /(?!\A)x/m a\nxb\n 0: x /(?!^)x/m a\nxb\n No match /abc\Qabc\Eabc/ abcabcabc 0: abcabcabc /abc\Q(*+|\Eabc/ abc(*+|abc 0: abc(*+|abc / abc\Q abc\Eabc/x abc abcabc 0: abc abcabc *** Failers No match abcabcabc No match /abc#comment \Q#not comment literal\E/x abc#not comment\n literal 0: abc#not comment\x0a literal /abc#comment \Q#not comment literal/x abc#not comment\n literal 0: abc#not comment\x0a literal /abc#comment \Q#not comment literal\E #more comment /x abc#not comment\n literal 0: abc#not comment\x0a literal /abc#comment \Q#not comment literal\E #more comment/x abc#not comment\n literal 0: abc#not comment\x0a literal /\Qabc\$xyz\E/ abc\\\$xyz 0: abc\$xyz /\Qabc\E\$\Qxyz\E/ abc\$xyz 0: abc$xyz /\Gabc/ abc 0: abc *** Failers No match xyzabc No match /\Gabc./g abc1abc2xyzabc3 0: abc1 0: abc2 /abc./g abc1abc2xyzabc3 0: abc1 0: abc2 0: abc3 /a(?x: b c )d/ XabcdY 0: abcd *** Failers No match Xa b c d Y No match /((?x)x y z | a b c)/ XabcY 0: abc 1: abc AxyzB 0: xyz 1: xyz /(?i)AB(?-i)C/ XabCY 0: abC *** Failers No match XabcY No match /((?i)AB(?-i)C|D)E/ abCE 0: abCE 1: abC DE 0: DE 1: D *** Failers No match abcE No match abCe No match dE No match De No match /(.*)\d+\1/ abc123abc 0: abc123abc 1: abc abc123bc 0: bc123bc 1: bc /(.*)\d+\1/s abc123abc 0: abc123abc 1: abc abc123bc 0: bc123bc 1: bc /((.*))\d+\1/ abc123abc 0: abc123abc 1: abc 2: abc abc123bc 0: bc123bc 1: bc 2: bc /-- This tests for an IPv6 address in the form where it can have up to eight components, one and only one of which is empty. This must be an internal component. --/ /^(?!:) # colon disallowed at start (?: # start of item (?: [0-9a-f]{1,4} | # 1-4 hex digits or (?(1)0 | () ) ) # if null previously matched, fail; else null : # followed by colon ){1,7} # end item; 1-7 of them required [0-9a-f]{1,4} $ # final hex number at end of string (?(1)|.) # check that there was an empty component /xi a123::a123 0: a123::a123 1: a123:b342::abcd 0: a123:b342::abcd 1: a123:b342::324e:abcd 0: a123:b342::324e:abcd 1: a123:ddde:b342::324e:abcd 0: a123:ddde:b342::324e:abcd 1: a123:ddde:b342::324e:dcba:abcd 0: a123:ddde:b342::324e:dcba:abcd 1: a123:ddde:9999:b342::324e:dcba:abcd 0: a123:ddde:9999:b342::324e:dcba:abcd 1: *** Failers No match 1:2:3:4:5:6:7:8 No match a123:bce:ddde:9999:b342::324e:dcba:abcd No match a123::9999:b342::324e:dcba:abcd No match abcde:2:3:4:5:6:7:8 No match ::1 No match abcd:fee0:123:: No match :1 No match 1: No match /[z\Qa-d]\E]/ z 0: z a 0: a - 0: - d 0: d ] 0: ] *** Failers 0: a b No match /[\z\C]/ z 0: z C 0: C /\M/ M 0: M /(a+)*b/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /(?i)reg(?:ul(?:[a]|ae)r|ex)/ REGular 0: REGular regulaer 0: regulaer Regex 0: Regex regulr 0: regul\xe4r /[--]+/ 0: \xc5\xe6\xe5\xe4\xe0 0: \xc5\xe6\xe5\xe4\xff 0: \xc5\xe6\xe5\xe4\xc0 0: \xc5\xe6\xe5\xe4\xdf /(?<=Z)X./ \x84XAZXB 0: XB /ab cd (?x) de fg/ ab cd defg 0: ab cd defg /ab cd(?x) de fg/ ab cddefg 0: ab cddefg ** Failers No match abcddefg No match /(? 2: D 0: D 1: 2: /(a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 1: /(?>a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /(?:a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /\Z/g abc\n 0: 0: /^(?s)(?>.*)(? 2: a /(?>(a))b|(a)c/ ac 0: ac 1: 2: a /(?=(a))ab|(a)c/ ac 0: ac 1: 2: a /((?>(a))b|(a)c)/ ac 0: ac 1: ac 2: 3: a /((?>(a))b|(a)c)++/ ac 0: ac 1: ac 2: 3: a /(?:(?>(a))b|(a)c)++/ ac 0: ac 1: 2: a /(?=(?>(a))b|(a)c)(..)/ ac 0: ac 1: 2: a 3: ac /(?>(?>(a))b|(a)c)/ ac 0: ac 1: 2: a /(?:(?>([ab])))+a=/+ =ba= 0: ba= 0+ 1: b /(?>([ab]))+a=/+ =ba= 0: ba= 0+ 1: b /((?>(a+)b)+(aabab))/ aaaabaaabaabab 0: aaaabaaabaabab 1: aaaabaaabaabab 2: aaa 3: aabab /(?>a+|ab)+?c/ aabc No match /(?>a+|ab)+c/ aabc No match /(?:a+|ab)+c/ aabc 0: aabc /(?(?=(a))a)/ a 0: a 1: a /(?(?=(a))a)(b)/ ab 0: ab 1: a 2: b /^(?:a|ab)++c/ aaaabc No match /^(?>a|ab)++c/ aaaabc No match /^(?:a|ab)+c/ aaaabc 0: aaaabc /(?=abc){3}abc/+ abcabcabc 0: abc 0+ abcabc ** Failers No match xyz No match /(?=abc)+abc/+ abcabcabc 0: abc 0+ abcabc ** Failers No match xyz No match /(?=abc)++abc/+ abcabcabc 0: abc 0+ abcabc ** Failers No match xyz No match /(?=abc){0}xyz/ xyz 0: xyz /(?=abc){1}xyz/ ** Failers No match xyz No match /(?=(a))?./ ab 0: a 1: a bc 0: b /(?=(a))??./ ab 0: a bc 0: b /^(?=(?1))?[az]([abc])d/ abd 0: abd 1: b zcdxx 0: zcd 1: c /^(?!a){0}\w+/ aaaaa 0: aaaaa /(?<=(abc))?xyz/ abcxyz 0: xyz 1: abc pqrxyz 0: xyz /^[\g]+/ ggg<<>> 0: ggg<<>> ** Failers No match \\ga No match /^[\ga]+/ gggagagaxyz 0: gggagaga /^[:a[:digit:]]+/ aaaa444:::Z 0: aaaa444::: /^[:a[:digit:]:b]+/ aaaa444:::bbbZ 0: aaaa444:::bbb /[:a]xxx[b:]/ :xxx: 0: :xxx: /(?<=a{2})b/i xaabc 0: b ** Failers No match xabc No match /(?XNNNYZ 0: XNNNYZ > X NYQZ 0: X NYQZ ** Failers No match >XYZ No match > X NY Z No match /\v*X\v?Y\v+Z\V*\x0a\V+\x0b\V{2,3}\x0c/ >XY\x0aZ\x0aA\x0bNN\x0c 0: XY\x0aZ\x0aA\x0bNN\x0c >\x0a\x0dX\x0aY\x0a\x0bZZZ\x0aAAA\x0bNNN\x0c 0: \x0a\x0dX\x0aY\x0a\x0bZZZ\x0aAAA\x0bNNN\x0c /(foo)\Kbar/ foobar 0: bar 1: foo /(foo)(\Kbar|baz)/ foobar 0: bar 1: foo 2: bar foobaz 0: foobaz 1: foo 2: baz /(foo\Kbar)baz/ foobarbaz 0: barbaz 1: foobar /abc\K|def\K/g+ Xabcdefghi 0: 0+ defghi 0: 0+ ghi /ab\Kc|de\Kf/g+ Xabcdefghi 0: c 0+ defghi 0: f 0+ ghi /(?=C)/g+ ABCDECBA 0: 0+ CDECBA 0: 0+ CBA /^abc\K/+ abcdef 0: 0+ def ** Failers No match defabcxyz No match /^(a(b))\1\g1\g{1}\g-1\g{-1}\g{-02}Z/ ababababbbabZXXXX 0: ababababbbabZ 1: ab 2: b /(?tom|bon)-\g{A}/ tom-tom 0: tom-tom 1: tom bon-bon 0: bon-bon 1: bon /(^(a|b\g{-1}))/ bacxxx No match /(?|(abc)|(xyz))\1/ abcabc 0: abcabc 1: abc xyzxyz 0: xyzxyz 1: xyz ** Failers No match abcxyz No match xyzabc No match /(?|(abc)|(xyz))(?1)/ abcabc 0: abcabc 1: abc xyzabc 0: xyzabc 1: xyz ** Failers No match xyzxyz No match /^X(?5)(a)(?|(b)|(q))(c)(d)(Y)/ XYabcdY 0: XYabcdY 1: a 2: b 3: c 4: d 5: Y /^X(?7)(a)(?|(b|(r)(s))|(q))(c)(d)(Y)/ XYabcdY 0: XYabcdY 1: a 2: b 3: 4: 5: c 6: d 7: Y /^X(?7)(a)(?|(b|(?|(r)|(t))(s))|(q))(c)(d)(Y)/ XYabcdY 0: XYabcdY 1: a 2: b 3: 4: 5: c 6: d 7: Y /(?'abc'\w+):\k{2}/ a:aaxyz 0: a:aa 1: a ab:ababxyz 0: ab:abab 1: ab ** Failers No match a:axyz No match ab:abxyz No match /(?'abc'\w+):\g{abc}{2}/ a:aaxyz 0: a:aa 1: a ab:ababxyz 0: ab:abab 1: ab ** Failers No match a:axyz No match ab:abxyz No match /^(?a)? (?()b|c) (?('ab')d|e)/x abd 0: abd 1: a ce 0: ce /^(a.)\g-1Z/ aXaXZ 0: aXaXZ 1: aX /^(a.)\g{-1}Z/ aXaXZ 0: aXaXZ 1: aX /^(?(DEFINE) (? a) (? b) ) (?&A) (?&B) /x abcd 0: ab /(?(?&NAME_PAT))\s+(?(?&ADDRESS_PAT)) (?(DEFINE) (?[a-z]+) (?\d+) )/x metcalfe 33 0: metcalfe 33 1: metcalfe 2: 33 /(?(DEFINE)(?2[0-4]\d|25[0-5]|1\d\d|[1-9]?\d))\b(?&byte)(\.(?&byte)){3}/ 1.2.3.4 0: 1.2.3.4 1: 2: .4 131.111.10.206 0: 131.111.10.206 1: 2: .206 10.0.0.0 0: 10.0.0.0 1: 2: .0 ** Failers No match 10.6 No match 455.3.4.5 No match /\b(?&byte)(\.(?&byte)){3}(?(DEFINE)(?2[0-4]\d|25[0-5]|1\d\d|[1-9]?\d))/ 1.2.3.4 0: 1.2.3.4 1: .4 131.111.10.206 0: 131.111.10.206 1: .206 10.0.0.0 0: 10.0.0.0 1: .0 ** Failers No match 10.6 No match 455.3.4.5 No match /^(\w++|\s++)*$/ now is the time for all good men to come to the aid of the party 0: now is the time for all good men to come to the aid of the party 1: party *** Failers No match this is not a line with only words and spaces! No match /(\d++)(\w)/ 12345a 0: 12345a 1: 12345 2: a *** Failers No match 12345+ No match /a++b/ aaab 0: aaab /(a++b)/ aaab 0: aaab 1: aaab /(a++)b/ aaab 0: aaab 1: aaa /([^()]++|\([^()]*\))+/ ((abc(ade)ufh()()x 0: abc(ade)ufh()()x 1: x /\(([^()]++|\([^()]+\))+\)/ (abc) 0: (abc) 1: abc (abc(def)xyz) 0: (abc(def)xyz) 1: xyz *** Failers No match ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /^([^()]|\((?1)*\))*$/ abc 0: abc 1: c a(b)c 0: a(b)c 1: c a(b(c))d 0: a(b(c))d 1: d *** Failers) No match a(b(c)d No match /^>abc>([^()]|\((?1)*\))*abc>123abc>123abc>1(2)3abc>1(2)3abc>(1(2)3)abc>(1(2)3) 2: 3: Satanoscillatemymetallicsonatas 4: S AmanaplanacanalPanama 0: AmanaplanacanalPanama 1: 2: 3: AmanaplanacanalPanama 4: A AblewasIereIsawElba 0: AblewasIereIsawElba 1: 2: 3: AblewasIereIsawElba 4: A *** Failers No match Thequickbrownfox No match /^(\d+|\((?1)([+*-])(?1)\)|-(?1))$/ 12 0: 12 1: 12 (((2+2)*-3)-7) 0: (((2+2)*-3)-7) 1: (((2+2)*-3)-7) 2: - -12 0: -12 1: -12 *** Failers No match ((2+2)*-3)-7) No match /^(x(y|(?1){2})z)/ xyz 0: xyz 1: xyz 2: y xxyzxyzz 0: xxyzxyzz 1: xxyzxyzz 2: xyzxyz *** Failers No match xxyzz No match xxyzxyzxyzz No match /((< (?: (?(R) \d++ | [^<>]*+) | (?2)) * >))/x <> 0: <> 1: <> 2: <> 0: 1: 2: hij> 0: hij> 1: hij> 2: hij> hij> 0: 1: 2: def> 0: def> 1: def> 2: def> 0: <> 1: <> 2: <> *** Failers No match 2: 3: Satan, oscillate my metallic sonatas 4: S A man, a plan, a canal: Panama! 0: A man, a plan, a canal: Panama! 1: 2: 3: A man, a plan, a canal: Panama 4: A Able was I ere I saw Elba. 0: Able was I ere I saw Elba. 1: 2: 3: Able was I ere I saw Elba 4: A *** Failers No match The quick brown fox No match /^((.)(?1)\2|.)$/ a 0: a 1: a aba 0: aba 1: aba 2: a aabaa 0: aabaa 1: aabaa 2: a abcdcba 0: abcdcba 1: abcdcba 2: a pqaabaaqp 0: pqaabaaqp 1: pqaabaaqp 2: p ablewasiereisawelba 0: ablewasiereisawelba 1: ablewasiereisawelba 2: a rhubarb No match the quick brown fox No match /(a)(?<=b(?1))/ baz 0: a 1: a ** Failers No match caz No match /(?<=b(?1))(a)/ zbaaz 0: a 1: a ** Failers No match aaa No match /(?a)(?<=b(?&X))/ baz 0: a 1: a /^(?|(abc)|(def))\1/ abcabc 0: abcabc 1: abc defdef 0: defdef 1: def ** Failers No match abcdef No match defabc No match /^(?|(abc)|(def))(?1)/ abcabc 0: abcabc 1: abc defabc 0: defabc 1: def ** Failers No match defdef No match abcdef No match /(?:a(? (?')|(?")) |b(? (?')|(?")) ) (?('quote')[a-z]+|[0-9]+)/xJ a\"aaaaa 0: a"aaaaa 1: " 2: 3: " b\"aaaaa 0: b"aaaaa 1: 2: 3: 4: " 5: 6: " ** Failers No match b\"11111 No match /(?:(?1)|B)(A(*F)|C)/ ABCD 0: BC 1: C CCD 0: CC 1: C ** Failers No match CAD No match /^(?:(?1)|B)(A(*F)|C)/ CCD 0: CC 1: C BCD 0: BC 1: C ** Failers No match ABCD No match CAD No match BAD No match /(?:(?1)|B)(A(*ACCEPT)XX|C)D/ AAD 0: AA 1: A ACD 0: ACD 1: C BAD 0: BA 1: A BCD 0: BCD 1: C BAX 0: BA 1: A ** Failers No match ACX No match ABC No match /(?(DEFINE)(A))B(?1)C/ BAC 0: BAC /(?(DEFINE)((A)\2))B(?1)C/ BAAC 0: BAAC /(? \( ( [^()]++ | (?&pn) )* \) )/x (ab(cd)ef) 0: (ab(cd)ef) 1: (ab(cd)ef) 2: ef /^(?=a(*SKIP)b|ac)/ ** Failers No match ac No match /^(?=a(*PRUNE)b)/ ab 0: ** Failers No match ac No match /^(?=a(*ACCEPT)b)/ ac 0: /(?>a\Kb)/ ab 0: b /((?>a\Kb))/ ab 0: b 1: ab /(a\Kb)/ ab 0: b 1: ab /^a\Kcz|ac/ ac 0: ac /(?>a\Kbz|ab)/ ab 0: ab /^(?&t)(?(DEFINE)(?a\Kb))$/ ab 0: b /^([^()]|\((?1)*\))*$/ a(b)c 0: a(b)c 1: c a(b(c)d)e 0: a(b(c)d)e 1: e /(?P(?P0)(?P>L1)|(?P>L2))/ 0 0: 0 1: 0 00 0: 00 1: 00 2: 0 0000 0: 0000 1: 0000 2: 0 /(?P(?P0)|(?P>L2)(?P>L1))/ 0 0: 0 1: 0 2: 0 00 0: 0 1: 0 2: 0 0000 0: 0 1: 0 2: 0 /--- This one does fail, as expected, in Perl. It needs the complex item at the end of the pattern. A single letter instead of (B|D) makes it not fail, which I think is a Perl bug. --- / /A(*COMMIT)(B|D)/ ACABX No match /--- Check the use of names for failure ---/ /^(A(*PRUNE:A)B|C(*PRUNE:B)D)/K ** Failers No match AC No match, mark = A CB No match, mark = B /--- Force no study, otherwise mark is not seen. The studied version is in test 2 because it isn't Perl-compatible. ---/ /(*MARK:A)(*SKIP:B)(C|X)/KSS C 0: C 1: C MK: A D No match, mark = A /^(A(*THEN:A)B|C(*THEN:B)D)/K ** Failers No match CB No match, mark = B /^(?:A(*THEN:A)B|C(*THEN:B)D)/K CB No match, mark = B /^(?>A(*THEN:A)B|C(*THEN:B)D)/K CB No match, mark = B /--- This should succeed, as the skip causes bump to offset 1 (the mark). Note that we have to have something complicated such as (B|Z) at the end because, for Perl, a simple character somehow causes an unwanted optimization to mess with the handling of backtracking verbs. ---/ /A(*MARK:A)A+(*SKIP:A)(B|Z) | AC/xK AAAC 0: AC /--- Test skipping over a non-matching mark. ---/ /A(*MARK:A)A+(*MARK:B)(*SKIP:A)(B|Z) | AC/xK AAAC 0: AC /--- Check shorthand for MARK ---/ /A(*:A)A+(*SKIP:A)(B|Z) | AC/xK AAAC 0: AC /--- Don't loop! Force no study, otherwise mark is not seen. ---/ /(*:A)A+(*SKIP:A)(B|Z)/KSS AAAC No match, mark = A /--- This should succeed, as a non-existent skip name disables the skip ---/ /A(*MARK:A)A+(*SKIP:B)(B|Z) | AC/xK AAAC 0: AC /A(*MARK:A)A+(*SKIP:B)(B|Z) | AC(*:B)/xK AAAC 0: AC MK: B /--- COMMIT at the start of a pattern should act like an anchor. Again, however, we need the complication for Perl. ---/ /(*COMMIT)(A|P)(B|P)(C|P)/ ABCDEFG 0: ABC 1: A 2: B 3: C ** Failers No match DEFGABC No match /--- COMMIT inside an atomic group can't stop backtracking over the group. ---/ /(\w+)(?>b(*COMMIT))\w{2}/ abbb 0: abbb 1: a /(\w+)b(*COMMIT)\w{2}/ abbb No match /--- Check opening parens in comment when seeking forward reference. ---/ /(?&t)(?#()(?(DEFINE)(?a))/ bac 0: a /--- COMMIT should override THEN ---/ /(?>(*COMMIT)(?>yes|no)(*THEN)(*F))?/ yes No match /(?>(*COMMIT)(yes|no)(*THEN)(*F))?/ yes No match /b?(*SKIP)c/ bc 0: bc abc 0: bc /(*SKIP)bc/ a No match /(*SKIP)b/ a No match /(?P(?P=abn)xxx|)+/ xxx 0: 1: /(?i:([^b]))(?1)/ aa 0: aa 1: a aA 0: aA 1: a ** Failers 0: ** 1: * ab No match aB No match Ba No match ba No match /^(?&t)*+(?(DEFINE)(?a))\w$/ aaaaaaX 0: aaaaaaX ** Failers No match aaaaaa No match /^(?&t)*(?(DEFINE)(?a))\w$/ aaaaaaX 0: aaaaaaX aaaaaa 0: aaaaaa /^(a)*+(\w)/ aaaaX 0: aaaaX 1: a 2: X YZ 0: Y 1: 2: Y ** Failers No match aaaa No match /^(?:a)*+(\w)/ aaaaX 0: aaaaX 1: X YZ 0: Y 1: Y ** Failers No match aaaa No match /^(a)++(\w)/ aaaaX 0: aaaaX 1: a 2: X ** Failers No match aaaa No match YZ No match /^(?:a)++(\w)/ aaaaX 0: aaaaX 1: X ** Failers No match aaaa No match YZ No match /^(a)?+(\w)/ aaaaX 0: aa 1: a 2: a YZ 0: Y 1: 2: Y /^(?:a)?+(\w)/ aaaaX 0: aa 1: a YZ 0: Y 1: Y /^(a){2,}+(\w)/ aaaaX 0: aaaaX 1: a 2: X ** Failers No match aaa No match YZ No match /^(?:a){2,}+(\w)/ aaaaX 0: aaaaX 1: X ** Failers No match aaa No match YZ No match /(a|)*(?1)b/ b 0: b 1: ab 0: ab 1: aab 0: aab 1: /(a)++(?1)b/ ** Failers No match ab No match aab No match /(a)*+(?1)b/ ** Failers No match ab No match aab No match /(?1)(?:(b)){0}/ b 0: b /(foo ( \( ((?:(?> [^()]+ )|(?2))*) \) ) )/x foo(bar(baz)+baz(bop)) 0: foo(bar(baz)+baz(bop)) 1: foo(bar(baz)+baz(bop)) 2: (bar(baz)+baz(bop)) 3: bar(baz)+baz(bop) /(A (A|B(*ACCEPT)|C) D)(E)/x AB 0: AB 1: AB 2: B /\A.*?(a|bc)/ ba 0: ba 1: a /\A.*?(?:a|bc)++/ ba 0: ba /\A.*?(a|bc)++/ ba 0: ba 1: a /\A.*?(?:a|bc|d)/ ba 0: ba /(?:(b))++/ beetle 0: b 1: b /(?(?=(a(*ACCEPT)z))a)/ a 0: a 1: a /^(a)(?1)+ab/ aaaab 0: aaaab 1: a /^(a)(?1)++ab/ aaaab No match /^(?=a(*:M))aZ/K aZbc 0: aZ MK: M /^(?!(*:M)b)aZ/K aZbc 0: aZ /(?(DEFINE)(a))?b(?1)/ backgammon 0: ba /^\N+/ abc\ndef 0: abc /^\N{1,}/ abc\ndef 0: abc /(?(R)a+|(?R)b)/ aaaabcde 0: aaaab /(?(R)a+|((?R))b)/ aaaabcde 0: aaaab 1: aaaa /((?(R)a+|(?1)b))/ aaaabcde 0: aaaab 1: aaaab /((?(R1)a+|(?1)b))/ aaaabcde 0: aaaab 1: aaaab /((?(R)a|(?1)))*/ aaa 0: aaa 1: a /((?(R)a|(?1)))+/ aaa 0: aaa 1: a /a(*:any name)/K abc 0: a MK: any \x0aname /(?>(?&t)c|(?&t))(?(DEFINE)(?a|b(*PRUNE)c))/ a 0: a ba 0: a bba 0: a /--- Checking revised (*THEN) handling ---/ /--- Capture ---/ /^.*? (a(*THEN)b) c/x aabc No match /^.*? (a(*THEN)b|(*F)) c/x aabc 0: aabc 1: ab /^.*? ( (a(*THEN)b) | (*F) ) c/x aabc 0: aabc 1: ab 2: ab /^.*? ( (a(*THEN)b) ) c/x aabc No match /--- Non-capture ---/ /^.*? (?:a(*THEN)b) c/x aabc No match /^.*? (?:a(*THEN)b|(*F)) c/x aabc 0: aabc /^.*? (?: (?:a(*THEN)b) | (*F) ) c/x aabc 0: aabc /^.*? (?: (?:a(*THEN)b) ) c/x aabc No match /--- Atomic ---/ /^.*? (?>a(*THEN)b) c/x aabc No match /^.*? (?>a(*THEN)b|(*F)) c/x aabc 0: aabc /^.*? (?> (?>a(*THEN)b) | (*F) ) c/x aabc 0: aabc /^.*? (?> (?>a(*THEN)b) ) c/x aabc No match /--- Possessive capture ---/ /^.*? (a(*THEN)b)++ c/x aabc No match /^.*? (a(*THEN)b|(*F))++ c/x aabc 0: aabc 1: ab /^.*? ( (a(*THEN)b)++ | (*F) )++ c/x aabc 0: aabc 1: ab 2: ab /^.*? ( (a(*THEN)b)++ )++ c/x aabc No match /--- Possessive non-capture ---/ /^.*? (?:a(*THEN)b)++ c/x aabc No match /^.*? (?:a(*THEN)b|(*F))++ c/x aabc 0: aabc /^.*? (?: (?:a(*THEN)b)++ | (*F) )++ c/x aabc 0: aabc /^.*? (?: (?:a(*THEN)b)++ )++ c/x aabc No match /--- Condition assertion ---/ /^(?(?=a(*THEN)b)ab|ac)/ ac 0: ac /--- Condition ---/ /^.*?(?(?=a)a|b(*THEN)c)/ ba No match /^.*?(?:(?(?=a)a|b(*THEN)c)|d)/ ba 0: ba /^.*?(?(?=a)a(*THEN)b|c)/ ac No match /--- Assertion ---/ /^.*(?=a(*THEN)b)/ aabc 0: a /------------------------------/ /(?>a(*:m))/imsxSK a 0: a MK: m /(?>(a)(*:m))/imsxSK a 0: a 1: a MK: m /(?<=a(*ACCEPT)b)c/ xacd 0: c /(?<=(a(*ACCEPT)b))c/ xacd 0: c 1: a /(?<=(a(*COMMIT)b))c/ xabcd 0: c 1: ab ** Failers No match xacd No match /(? 2: /(another)?(\1+)test/ hello world test No match /(a(*COMMIT)b){0}a(?1)|aac/ aac 0: aac /((?:a?)*)*c/ aac 0: aac 1: /((?>a?)*)*c/ aac 0: aac 1: /(?>.*?a)(?<=ba)/ aba 0: ba /(?:.*?a)(?<=ba)/ aba 0: aba /.*?a(*PRUNE)b/ aab 0: ab /.*?a(*PRUNE)b/s aab 0: ab /^a(*PRUNE)b/s aab No match /.*?a(*SKIP)b/ aab 0: ab /(?>.*?a)b/s aab 0: ab /(?>.*?a)b/ aab 0: ab /(?>^a)b/s aab No match /(?>.*?)(?<=(abcd)|(wxyz))/ alphabetabcd 0: 1: abcd endingwxyz 0: 1: 2: wxyz /(?>.*)(?<=(abcd)|(wxyz))/ alphabetabcd 0: alphabetabcd 1: abcd endingwxyz 0: endingwxyz 1: 2: wxyz "(?>.*)foo" abcdfooxyz No match "(?>.*?)foo" abcdfooxyz 0: foo /(?:(a(*PRUNE)b)){0}(?:(?1)|ac)/ ac 0: ac /(?:(a(*SKIP)b)){0}(?:(?1)|ac)/ ac 0: ac /(?<=(*SKIP)ac)a/ aa No match /A(*MARK:A)A+(*SKIP:B)(B|Z) | AC/xK AAAC 0: AC /a(*SKIP:m)x|ac(*:n)(*SKIP:n)d|ac/K acacd 0: acd MK: n /A(*SKIP:m)x|A(*SKIP:n)x|AB/K AB 0: AB /((*SKIP:r)d){0}a(*SKIP:m)x|ac(*:n)|ac/K acacd 0: ac MK: n /-- Tests that try to figure out how Perl works. My hypothesis is that the first verb that is backtracked onto is the one that acts. This seems to be the case almost all the time, but there is one exception that is perhaps a bug. --/ /-- This matches "aaaac"; each PRUNE advances one character until the subject no longer starts with 5 'a's. --/ /aaaaa(*PRUNE)b|a+c/ aaaaaac 0: aaaac /-- Putting SKIP in front of PRUNE makes no difference, as it is never backtracked onto, whether or not it has a label. --/ /aaaaa(*SKIP)(*PRUNE)b|a+c/ aaaaaac 0: aaaac /aaaaa(*SKIP:N)(*PRUNE)b|a+c/ aaaaaac 0: aaaac /aaaa(*:N)a(*SKIP:N)(*PRUNE)b|a+c/ aaaaaac 0: aaaac /-- Putting THEN in front makes no difference. */ /aaaaa(*THEN)(*PRUNE)b|a+c/ aaaaaac 0: aaaac /-- However, putting COMMIT in front of the prune changes it to "no match". I think this is inconsistent and possibly a bug. For the moment, running this test is moved out of the Perl-compatible file. --/ /aaaaa(*COMMIT)(*PRUNE)b|a+c/ /---- OK, lets play the same game again using SKIP instead of PRUNE. ----/ /-- This matches "ac" because SKIP forces the next match to start on the sixth "a". --/ /aaaaa(*SKIP)b|a+c/ aaaaaac 0: ac /-- Putting PRUNE in front makes no difference. --/ /aaaaa(*PRUNE)(*SKIP)b|a+c/ aaaaaac 0: ac /-- Putting THEN in front makes no difference. --/ /aaaaa(*THEN)(*SKIP)b|a+c/ aaaaaac 0: ac /-- In this case, neither does COMMIT. This still matches "ac". --/ /aaaaa(*COMMIT)(*SKIP)b|a+c/ aaaaaac 0: ac /-- This gives "no match", as expected. --/ /aaaaa(*COMMIT)b|a+c/ aaaaaac No match /------ Tests using THEN ------/ /-- This matches "aaaaaac", as expected. --/ /aaaaa(*THEN)b|a+c/ aaaaaac 0: aaaaaac /-- Putting SKIP in front makes no difference. --/ /aaaaa(*SKIP)(*THEN)b|a+c/ aaaaaac 0: aaaaaac /-- Putting PRUNE in front makes no difference. --/ /aaaaa(*PRUNE)(*THEN)b|a+c/ aaaaaac 0: aaaaaac /-- Putting COMMIT in front makes no difference. --/ /aaaaa(*COMMIT)(*THEN)b|a+c/ aaaaaac 0: aaaaaac /-- End of "priority" tests --/ /aaaaa(*:m)(*PRUNE:m)(*SKIP:m)m|a+/ aaaaaa 0: a /aaaaa(*:m)(*MARK:m)(*PRUNE)(*SKIP:m)m|a+/ aaaaaa 0: a /aaaaa(*:n)(*PRUNE:m)(*SKIP:m)m|a+/ aaaaaa 0: aaaa /aaaaa(*:n)(*MARK:m)(*PRUNE)(*SKIP:m)m|a+/ aaaaaa 0: a /a(*MARK:A)aa(*PRUNE:A)a(*SKIP:A)b|a+c/ aaaac 0: aac /a(*MARK:A)aa(*MARK:A)a(*SKIP:A)b|a+c/ aaaac 0: ac /aaa(*PRUNE:A)a(*SKIP:A)b|a+c/ aaaac 0: aac /aaa(*MARK:A)a(*SKIP:A)b|a+c/ aaaac 0: ac /a(*:m)a(*COMMIT)(*SKIP:m)b|a+c/K aaaaaac 0: ac /.?(a|b(*THEN)c)/ ba 0: ba 1: a /(a(*COMMIT)b)c|abd/ abc 0: abc 1: ab abd No match /(?=a(*COMMIT)b)abc|abd/ abc 0: abc abd 0: abd /(?>a(*COMMIT)b)c|abd/ abc 0: abc abd 0: abd /a(?=b(*COMMIT)c)[^d]|abd/ abd No match abc 0: ab /a(?=bc).|abd/ abd 0: abd abc 0: ab /a(?>b(*COMMIT)c)d|abd/ abceabd No match /a(?>bc)d|abd/ abceabd 0: abd /(?>a(*COMMIT)b)c|abd/ abd 0: abd /(?>a(*COMMIT)c)d|abd/ abd No match /((?=a(*COMMIT)b)ab|ac){0}(?:(?1)|a(c))/ ac 0: ac 1: 2: c /-- These tests were formerly in test 2, but changes in PCRE and Perl have made them compatible. --/ /^(a)?(?(1)a|b)+$/ *** Failers No match a No match /(?=a\Kb)ab/ ab 0: b /(?!a\Kb)ac/ ac 0: ac /^abc(?<=b\Kc)d/ abcd 0: cd /^abc(?b))/K abc 0: b MK: m(m /(*PRUNE:m(m)(?&y)(?(DEFINE)(?b))/K abc 0: b MK: m(m /(*SKIP:m(m)(?&y)(?(DEFINE)(?b))/K abc 0: b /(*THEN:m(m)(?&y)(?(DEFINE)(?b))/K abc 0: b MK: m(m /^\d*\w{4}/ 1234 0: 1234 123 No match /^[^b]*\w{4}/ aaaa 0: aaaa aaa No match /^[^b]*\w{4}/i aaaa 0: aaaa aaa No match /^a*\w{4}/ aaaa 0: aaaa aaa No match /^a*\w{4}/i aaaa 0: aaaa aaa No match /(?(?=ab)ab)/+ ca 0: 0+ ca cd 0: 0+ cd /(?:(?foo)|(?bar))\k/J foofoo 0: foofoo 1: foo barbar 0: barbar 1: 2: bar /(?A)(?:(?foo)|(?bar))\k/J AfooA 0: AfooA 1: A 2: foo AbarA 0: AbarA 1: A 2: 3: bar ** Failers No match Afoofoo No match Abarbar No match /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( 0: 1 IN SOA non-sp1 non-sp2( 1: 1 2: non-sp1 3: non-sp2 /^ (?:(?A)|(?'B'B)(?A)) (?('A')x) (?()y)$/xJ Ax 0: Ax 1: A BAxy 0: BAxy 1: 2: B 3: A /^A\xZ/ A\0Z 0: A\x00Z /^A\o{123}B/ A\123B 0: ASB / ^ a + + b $ /x aaaab 0: aaaab / ^ a + #comment + b $ /x aaaab 0: aaaab / ^ a + #comment #comment + b $ /x aaaab 0: aaaab / ^ (?> a + ) b $ /x aaaab 0: aaaab / ^ ( a + ) + + \w $ /x aaaab 0: aaaab 1: aaaa /(?:a\Kb)*+/+ ababc 0: b 0+ c /(?>a\Kb)*/+ ababc 0: b 0+ c /(?:a\Kb)*/+ ababc 0: b 0+ c /(a\Kb)*+/+ ababc 0: b 0+ c 1: ab /(a\Kb)*/+ ababc 0: b 0+ c 1: ab /(?:x|(?:(xx|yy)+|x|x|x|x|x)|a|a|a)bc/ acb No match '\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER '\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER '\A(?:[^\"]++|\"(?:[^\"]++|\"\")++\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER '\A([^\"1]++|[\"2]([^\"3]*+|[\"4][\"5])*+[\"6])++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER 1: AFTER 2: /^\w+(?>\s*)(?<=\w)/ test test 0: tes /(?Pa)(?Pb)/gJ abbaba 0: ab 1: a 2: b 0: ab 1: a 2: b /(?Pa)(?Pb)(?P=same)/gJ abbaba 0: aba 1: a 2: b /(?P=same)?(?Pa)(?Pb)/gJ abbaba 0: ab 1: a 2: b 0: ab 1: a 2: b /(?:(?P=same)?(?:(?Pa)|(?Pb))(?P=same))+/gJ bbbaaabaabb 0: bbbaaaba 1: a 2: b 0: bb 1: 2: b /(?:(?P=same)?(?:(?P=same)(?Pa)(?P=same)|(?P=same)?(?Pb)(?P=same)){2}(?P=same)(?Pc)(?P=same)){2}(?Pz)?/gJ bbbaaaccccaaabbbcc No match /(?Pa)?(?Pb)?(?()c|d)*l/ acl 0: acl 1: a bdl 0: bdl 1: 2: b adl 0: dl bcl 0: l /\sabc/ \x{0b}abc 0: \x0babc /[\Qa]\E]+/ aa]] 0: aa]] /[\Q]a\E]+/ aa]] 0: aa]] /(?:((abcd))|(((?:(?:(?:(?:abc|(?:abcdef))))b)abcdefghi)abc)|((*ACCEPT)))/ 1234abcd 0: 1: 2: 3: 4: 5: /(\2)(\1)/ "Z*(|d*){216}" "(?1)(?#?'){8}(a)" baaaaaaaaac 0: aaaaaaaaa 1: a "(?|(\k'Pm')|(?'Pm'))" abcd 0: 1: /(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[,;:])(?=.{8,16})(?!.*[\s])/ \ Fred:099 0: /(?=.*X)X$/ \ X 0: X /X+(?#comment)?/ >XXX< 0: X / (? \w+ )* \. /xi pokus. 0: pokus. 1: pokus /(?(DEFINE) (? \w+ ) ) (?&word)* \./xi pokus. 0: pokus. /(?(DEFINE) (? \w+ ) ) ( (?&word)* ) \./xi pokus. 0: pokus. 1: 2: pokus /(?&word)* (?(DEFINE) (? \w+ ) ) \./xi pokus. 0: pokus. /(?&word)* \. (? \w+ )/xi pokus.hokus 0: pokus.hokus 1: hokus /-- End of testinput1 --/ ================================================ FILE: src/pcre/testdata/testoutput10 ================================================ /-- This set of tests check Unicode property support with the DFA matching functionality of pcre_dfa_exec(). The -dfa flag must be used with pcretest when running it. --/ /\pL\P{Nd}/8 AB 0: AB *** Failers 0: Fa A0 No match 00 No match /\X./8 AB 0: AB A\x{300}BC 0: A\x{300}B A\x{300}\x{301}\x{302}BC 0: A\x{300}\x{301}\x{302}B *** Failers 0: ** \x{300} No match /\X\X/8 ABC 0: AB A\x{300}B\x{300}\x{301}C 0: A\x{300}B\x{300}\x{301} A\x{300}\x{301}\x{302}BC 0: A\x{300}\x{301}\x{302}B *** Failers 0: ** \x{300} No match /^\pL+/8 abcd 0: abcd a 0: a *** Failers No match /^\PL+/8 1234 0: 1234 = 0: = *** Failers 0: *** abcd No match /^\X+/8 abcdA\x{300}\x{301}\x{302} 0: abcdA\x{300}\x{301}\x{302} A\x{300}\x{301}\x{302} 0: A\x{300}\x{301}\x{302} A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302} 0: A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302} a 0: a *** Failers 0: *** Failers \x{300}\x{301}\x{302} 0: \x{300}\x{301}\x{302} /\X?abc/8 abc 0: abc A\x{300}abc 0: A\x{300}abc A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz 0: A\x{300}abc \x{300}abc 0: \x{300}abc *** Failers No match /^\X?abc/8 abc 0: abc A\x{300}abc 0: A\x{300}abc *** Failers No match A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz No match \x{300}abc 0: \x{300}abc /\X*abc/8 abc 0: abc A\x{300}abc 0: A\x{300}abc A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz 0: A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abc \x{300}abc 0: \x{300}abc *** Failers No match /^\X*abc/8 abc 0: abc A\x{300}abc 0: A\x{300}abc A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abcxyz 0: A\x{300}\x{301}\x{302}A\x{300}A\x{300}A\x{300}abc *** Failers No match \x{300}abc 0: \x{300}abc /^\pL?=./8 A=b 0: A=b =c 0: =c *** Failers No match 1=2 No match AAAA=b No match /^\pL*=./8 AAAA=b 0: AAAA=b =c 0: =c *** Failers No match 1=2 No match /^\X{2,3}X/8 A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X 0: A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X 0: A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X *** Failers No match X No match A\x{300}\x{301}\x{302}X No match A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}A\x{300}\x{301}\x{302}X No match /^\pC\pL\pM\pN\pP\pS\pZ\p{Xsp}/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680} ** Failers No match \x{0b} No match /^>\p{Xsp}+/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028} 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680} 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0} 4: > \x{09}\x{0a}\x{0c}\x{0d} 5: > \x{09}\x{0a}\x{0c} 6: > \x{09}\x{0a} 7: > \x{09} 8: > /^>\p{Xsp}*/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028} 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680} 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0} 4: > \x{09}\x{0a}\x{0c}\x{0d} 5: > \x{09}\x{0a}\x{0c} 6: > \x{09}\x{0a} 7: > \x{09} 8: > 9: > /^>\p{Xsp}{2,9}/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028} 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680} 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0} 4: > \x{09}\x{0a}\x{0c}\x{0d} 5: > \x{09}\x{0a}\x{0c} 6: > \x{09}\x{0a} 7: > \x{09} /^>[\p{Xsp}]/8O >\x{2028}\x{0b} 0: >\x{2028} /^>[\p{Xsp}]+/8O > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028} 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680} 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0} 4: > \x{09}\x{0a}\x{0c}\x{0d} 5: > \x{09}\x{0a}\x{0c} 6: > \x{09}\x{0a} 7: > \x{09} 8: > /^>\p{Xps}/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680} >\x{a0} 0: >\x{a0} ** Failers No match \x{0b} No match /^>\p{Xps}+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}+?/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680}\x{2028}\x{0b} 1: >\x{1680}\x{2028} 2: >\x{1680} /^>\p{Xps}*/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}?/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 1: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028} 2: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680} 3: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0} 4: > \x{09}\x{0a}\x{0c}\x{0d} 5: > \x{09}\x{0a}\x{0c} 6: > \x{09}\x{0a} 7: > \x{09} /^>[\p{Xps}]/8 >\x{2028}\x{0b} 0: >\x{2028} /^>[\p{Xps}]+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^\p{Xwd}/8 ABCD 0: A 1234 0: 1 \x{6ca} 0: \x{6ca} \x{a6c} 0: \x{a6c} \x{10a7} 0: \x{10a7} _ABC 0: _ ** Failers No match [] No match /^\p{Xwd}+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}*/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}{2,9}/8 A_12\x{6ca}\x{a6c}\x{10a7} 0: A_12\x{6ca}\x{a6c}\x{10a7} /^[\p{Xwd}]/8 ABCD1234_ 0: A 1234abcd_ 0: 1 \x{6ca} 0: \x{6ca} \x{a6c} 0: \x{a6c} \x{10a7} 0: \x{10a7} _ABC 0: _ ** Failers No match [] No match /^[\p{Xwd}]+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /-- Unicode properties for \b abd \B --/ /\b...\B/8W abc_ 0: abc \x{37e}abc\x{376} 0: abc \x{37e}\x{376}\x{371}\x{393}\x{394} 0: \x{376}\x{371}\x{393} !\x{c0}++\x{c1}\x{c2} 0: ++\x{c1} !\x{c0}+++++ 0: \x{c0}++ /-- Without PCRE_UCP, non-ASCII always fail, even if < 256 --/ /\b...\B/8 abc_ 0: abc ** Failers 0: Fai \x{37e}abc\x{376} No match \x{37e}\x{376}\x{371}\x{393}\x{394} No match !\x{c0}++\x{c1}\x{c2} No match !\x{c0}+++++ No match /-- With PCRE_UCP, non-UTF8 chars that are < 256 still check properties --/ /\b...\B/W abc_ 0: abc !\x{c0}++\x{c1}\x{c2} 0: ++\xc1 !\x{c0}+++++ 0: \xc0++ /-- Caseless single negated characters > 127 need UCP support --/ /[^\x{100}]/8i \x{100}\x{101}X 0: X /[^\x{100}]+/8i \x{100}\x{101}XX 0: XX /^\X/8 A\P 0: A A\P\P Partial match: A A\x{300}\x{301}\P 0: A\x{300}\x{301} A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301} A\x{301}\P 0: A\x{301} A\x{301}\P\P Partial match: A\x{301} /^\X{2,3}/8 A\P Partial match: A A\P\P Partial match: A AA\P 0: AA AA\P\P Partial match: AA A\x{300}\x{301}\P Partial match: A\x{300}\x{301} A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301} A\x{300}\x{301}A\x{300}\x{301}\P 0: A\x{300}\x{301}A\x{300}\x{301} A\x{300}\x{301}A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301}A\x{300}\x{301} /^\X{2}/8 AA\P 0: AA AA\P\P Partial match: AA A\x{300}\x{301}A\x{300}\x{301}\P 0: A\x{300}\x{301}A\x{300}\x{301} A\x{300}\x{301}A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301}A\x{300}\x{301} /^\X+/8 AA\P 0: AA AA\P\P Partial match: AA /^\X+?Z/8 AA\P Partial match: AA AA\P\P Partial match: AA /-- These are tests for extended grapheme clusters --/ /^\X/8+ G\x{34e}\x{34e}X 0: G\x{34e}\x{34e} 0+ X \x{34e}\x{34e}X 0: \x{34e}\x{34e} 0+ X \x04X 0: \x{04} 0+ X \x{1100}X 0: \x{1100} 0+ X \x{1100}\x{34e}X 0: \x{1100}\x{34e} 0+ X \x{1b04}\x{1b04}X 0: \x{1b04}\x{1b04} 0+ X *These match up to the roman letters 0: * 0+ These match up to the roman letters \x{1111}\x{1111}L,L 0: \x{1111}\x{1111} 0+ L,L \x{1111}\x{1111}\x{1169}L,L,V 0: \x{1111}\x{1111}\x{1169} 0+ L,L,V \x{1111}\x{ae4c}L, LV 0: \x{1111}\x{ae4c} 0+ L, LV \x{1111}\x{ad89}L, LVT 0: \x{1111}\x{ad89} 0+ L, LVT \x{1111}\x{ae4c}\x{1169}L, LV, V 0: \x{1111}\x{ae4c}\x{1169} 0+ L, LV, V \x{1111}\x{ae4c}\x{1169}\x{1169}L, LV, V, V 0: \x{1111}\x{ae4c}\x{1169}\x{1169} 0+ L, LV, V, V \x{1111}\x{ae4c}\x{1169}\x{11fe}L, LV, V, T 0: \x{1111}\x{ae4c}\x{1169}\x{11fe} 0+ L, LV, V, T \x{1111}\x{ad89}\x{11fe}L, LVT, T 0: \x{1111}\x{ad89}\x{11fe} 0+ L, LVT, T \x{1111}\x{ad89}\x{11fe}\x{11fe}L, LVT, T, T 0: \x{1111}\x{ad89}\x{11fe}\x{11fe} 0+ L, LVT, T, T \x{ad89}\x{11fe}\x{11fe}LVT, T, T 0: \x{ad89}\x{11fe}\x{11fe} 0+ LVT, T, T *These match just the first codepoint (invalid sequence) 0: * 0+ These match just the first codepoint (invalid sequence) \x{1111}\x{11fe}L, T 0: \x{1111} 0+ \x{11fe}L, T \x{ae4c}\x{1111}LV, L 0: \x{ae4c} 0+ \x{1111}LV, L \x{ae4c}\x{ae4c}LV, LV 0: \x{ae4c} 0+ \x{ae4c}LV, LV \x{ae4c}\x{ad89}LV, LVT 0: \x{ae4c} 0+ \x{ad89}LV, LVT \x{1169}\x{1111}V, L 0: \x{1169} 0+ \x{1111}V, L \x{1169}\x{ae4c}V, LV 0: \x{1169} 0+ \x{ae4c}V, LV \x{1169}\x{ad89}V, LVT 0: \x{1169} 0+ \x{ad89}V, LVT \x{ad89}\x{1111}LVT, L 0: \x{ad89} 0+ \x{1111}LVT, L \x{ad89}\x{1169}LVT, V 0: \x{ad89} 0+ \x{1169}LVT, V \x{ad89}\x{ae4c}LVT, LV 0: \x{ad89} 0+ \x{ae4c}LVT, LV \x{ad89}\x{ad89}LVT, LVT 0: \x{ad89} 0+ \x{ad89}LVT, LVT \x{11fe}\x{1111}T, L 0: \x{11fe} 0+ \x{1111}T, L \x{11fe}\x{1169}T, V 0: \x{11fe} 0+ \x{1169}T, V \x{11fe}\x{ae4c}T, LV 0: \x{11fe} 0+ \x{ae4c}T, LV \x{11fe}\x{ad89}T, LVT 0: \x{11fe} 0+ \x{ad89}T, LVT *Test extend and spacing mark 0: * 0+ Test extend and spacing mark \x{1111}\x{ae4c}\x{0711}L, LV, extend 0: \x{1111}\x{ae4c}\x{711} 0+ L, LV, extend \x{1111}\x{ae4c}\x{1b04}L, LV, spacing mark 0: \x{1111}\x{ae4c}\x{1b04} 0+ L, LV, spacing mark \x{1111}\x{ae4c}\x{1b04}\x{0711}\x{1b04}L, LV, spacing mark, extend, spacing mark 0: \x{1111}\x{ae4c}\x{1b04}\x{711}\x{1b04} 0+ L, LV, spacing mark, extend, spacing mark *Test CR, LF, and control 0: * 0+ Test CR, LF, and control \x0d\x{0711}CR, extend 0: \x{0d} 0+ \x{711}CR, extend \x0d\x{1b04}CR, spacingmark 0: \x{0d} 0+ \x{1b04}CR, spacingmark \x0a\x{0711}LF, extend 0: \x{0a} 0+ \x{711}LF, extend \x0a\x{1b04}LF, spacingmark 0: \x{0a} 0+ \x{1b04}LF, spacingmark \x0b\x{0711}Control, extend 0: \x{0b} 0+ \x{711}Control, extend \x09\x{1b04}Control, spacingmark 0: \x{09} 0+ \x{1b04}Control, spacingmark *There are no Prepend characters, so we can't test Prepend, CR 0: * 0+ There are no Prepend characters, so we can't test Prepend, CR /^(?>\X{2})X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ /^\X{2,4}X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ /^\X{2,4}?X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ /-- --/ /\x{1e9e}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /[z\x{1e9e}]+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{00df}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /[z\x{00df}]+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{1f88}+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /[z\x{1f88}]+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /-- Perl matches these --/ /\x{00b5}+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /\x{039c}+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /\x{03bc}+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /\x{00c5}+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /\x{00e5}+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /\x{212b}+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /\x{01c4}+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /\x{01c5}+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /\x{01c6}+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /\x{01c7}+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /\x{01c8}+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /\x{01c9}+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /\x{01ca}+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /\x{01cb}+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /\x{01cc}+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /\x{01f1}+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /\x{01f2}+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /\x{01f3}+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /\x{0345}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{0399}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{03b9}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{1fbe}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{0392}+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /\x{03b2}+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /\x{03d0}+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /\x{0395}+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /\x{03b5}+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /\x{03f5}+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /\x{0398}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{03b8}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{03d1}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{03f4}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{039a}+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /\x{03ba}+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /\x{03f0}+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /\x{03a0}+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /\x{03c0}+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /\x{03d6}+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /\x{03a1}+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /\x{03c1}+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /\x{03f1}+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /\x{03a3}+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /\x{03c2}+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /\x{03c3}+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /\x{03a6}+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /\x{03c6}+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /\x{03d5}+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /\x{03c9}+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /\x{03a9}+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /\x{2126}+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /\x{1e60}+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /\x{1e61}+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /\x{1e9b}+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /\x{1e9e}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{00df}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{1f88}+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /\x{1f80}+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /\x{004b}+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /\x{006b}+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /\x{212a}+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /\x{0053}+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /\x{0073}+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /\x{017f}+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /ist/8i ikt No match /is+t/8i iSs\x{17f}t 0: iSs\x{17f}t ikt No match /is+?t/8i ikt No match /is?t/8i ikt No match /is{2}t/8i iskt No match /^\p{Xuc}/8 $abc 0: $ @abc 0: @ `abc 0: ` \x{1234}abc 0: \x{1234} ** Failers No match abc No match /^\p{Xuc}+/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} ** Failers No match \x{9f} No match /^\p{Xuc}+?/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} 1: $@`\x{a0}\x{1234} 2: $@`\x{a0} 3: $@` 4: $@ 5: $ ** Failers No match \x{9f} No match /^\p{Xuc}+?\*/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000}* ** Failers No match \x{9f} No match /^\p{Xuc}++/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} ** Failers No match \x{9f} No match /^\p{Xuc}{3,5}/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234} ** Failers No match \x{9f} No match /^\p{Xuc}{3,5}?/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234} 1: $@`\x{a0} 2: $@` ** Failers No match \x{9f} No match /^[\p{Xuc}]/8 $@`\x{a0}\x{1234}\x{e000}** 0: $ ** Failers No match \x{9f} No match /^[\p{Xuc}]+/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} ** Failers No match \x{9f} No match /^\P{Xuc}/8 abc 0: a ** Failers 0: * $abc No match @abc No match `abc No match \x{1234}abc No match /^[\P{Xuc}]/8 abc 0: a ** Failers 0: * $abc No match @abc No match `abc No match \x{1234}abc No match /^A\s+Z/8W A\x{2005}Z 0: A\x{2005}Z A\x{85}\x{180e}\x{2005}Z 0: A\x{85}\x{180e}\x{2005}Z /^A[\s]+Z/8W A\x{2005}Z 0: A\x{2005}Z A\x{85}\x{180e}\x{2005}Z 0: A\x{85}\x{180e}\x{2005}Z /-- End of testinput10 --/ ================================================ FILE: src/pcre/testdata/testoutput11-16 ================================================ /-- These are a few representative patterns whose lengths and offsets are to be shown when the link size is 2. This is just a doublecheck test to ensure the sizes don't go horribly wrong when something is changed. The pattern contents are all themselves checked in other tests. Unicode, including property support, is required for these tests. --/ /((?i)b)/BM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 5 CBra 1 5 /i b 7 5 Ket 9 9 Ket 11 End ------------------------------------------------------------------ /(?s)(.*X|^B)/BM Memory allocation (code space): 38 ------------------------------------------------------------------ 0 16 Bra 2 7 CBra 1 5 AllAny* 7 X 9 5 Alt 11 ^ 12 B 14 12 Ket 16 16 Ket 18 End ------------------------------------------------------------------ /(?s:.*X|^B)/BM Memory allocation (code space): 36 ------------------------------------------------------------------ 0 15 Bra 2 6 Bra 4 AllAny* 6 X 8 5 Alt 10 ^ 11 B 13 11 Ket 15 15 Ket 17 End ------------------------------------------------------------------ /^[[:alnum:]]/BM Memory allocation (code space): 46 ------------------------------------------------------------------ 0 20 Bra 2 ^ 3 [0-9A-Za-z] 20 20 Ket 22 End ------------------------------------------------------------------ /#/IxMD Memory allocation (code space): 10 ------------------------------------------------------------------ 0 2 Bra 2 2 Ket 4 End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string Options: extended No first char No need char /a#/IxMD Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 a 4 4 Ket 6 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended First char = 'a' No need char /x?+/BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 x?+ 4 4 Ket 6 End ------------------------------------------------------------------ /x++/BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 x++ 4 4 Ket 6 End ------------------------------------------------------------------ /x{1,3}+/BM Memory allocation (code space): 20 ------------------------------------------------------------------ 0 7 Bra 2 x 4 x{0,2}+ 7 7 Ket 9 End ------------------------------------------------------------------ /(x)*+/BM Memory allocation (code space): 26 ------------------------------------------------------------------ 0 10 Bra 2 Braposzero 3 5 CBraPos 1 6 x 8 5 KetRpos 10 10 Ket 12 End ------------------------------------------------------------------ /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/BM Memory allocation (code space): 142 ------------------------------------------------------------------ 0 68 Bra 2 ^ 3 63 CBra 1 6 5 CBra 2 9 a+ 11 5 Ket 13 21 CBra 3 16 [ab]+? 34 21 Ket 36 21 CBra 4 39 [bc]+ 57 21 Ket 59 5 CBra 5 62 \w*+ 64 5 Ket 66 63 Ket 68 68 Ket 70 End ------------------------------------------------------------------ |8J\$WE\<\.rX\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM Memory allocation (code space): 1648 ------------------------------------------------------------------ 0 821 Bra 2 8J$WE<.rX+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X 820 \b 821 821 Ket 823 End ------------------------------------------------------------------ |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM Memory allocation (code space): 1628 ------------------------------------------------------------------ 0 811 Bra 2 $<.X+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X 810 \b 811 811 Ket 813 End ------------------------------------------------------------------ /(a(?1)b)/BM Memory allocation (code space): 32 ------------------------------------------------------------------ 0 13 Bra 2 9 CBra 1 5 a 7 2 Recurse 9 b 11 9 Ket 13 13 Ket 15 End ------------------------------------------------------------------ /(a(?1)+b)/BM Memory allocation (code space): 40 ------------------------------------------------------------------ 0 17 Bra 2 13 CBra 1 5 a 7 4 Once 9 2 Recurse 11 4 KetRmax 13 b 15 13 Ket 17 17 Ket 19 End ------------------------------------------------------------------ /a(?Pb|c)d(?Pe)/BM Memory allocation (code space): 80 ------------------------------------------------------------------ 0 24 Bra 2 a 4 5 CBra 1 7 b 9 4 Alt 11 c 13 9 Ket 15 d 17 5 CBra 2 20 e 22 5 Ket 24 24 Ket 26 End ------------------------------------------------------------------ /(?:a(?Pc(?Pd)))(?Pa)/BM Memory allocation (code space): 73 ------------------------------------------------------------------ 0 29 Bra 2 18 Bra 4 a 6 12 CBra 1 9 c 11 5 CBra 2 14 d 16 5 Ket 18 12 Ket 20 18 Ket 22 5 CBra 3 25 a 27 5 Ket 29 29 Ket 31 End ------------------------------------------------------------------ /(?Pa)...(?P=a)bbb(?P>a)d/BM Memory allocation (code space): 93 ------------------------------------------------------------------ 0 24 Bra 2 5 CBra 1 5 a 7 5 Ket 9 Any 10 Any 11 Any 12 \1 14 bbb 20 2 Recurse 22 d 24 24 Ket 26 End ------------------------------------------------------------------ /abc(?C255)de(?C)f/BM Memory allocation (code space): 50 ------------------------------------------------------------------ 0 22 Bra 2 abc 8 Callout 255 10 1 12 de 16 Callout 0 16 1 20 f 22 22 Ket 24 End ------------------------------------------------------------------ /abcde/CBM Memory allocation (code space): 78 ------------------------------------------------------------------ 0 36 Bra 2 Callout 255 0 1 6 a 8 Callout 255 1 1 12 b 14 Callout 255 2 1 18 c 20 Callout 255 3 1 24 d 26 Callout 255 4 1 30 e 32 Callout 255 5 0 36 36 Ket 38 End ------------------------------------------------------------------ /\x{100}/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{100} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{1000}/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{1000} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{10000}/8BM Memory allocation (code space): 16 ------------------------------------------------------------------ 0 5 Bra 2 \x{10000} 5 5 Ket 7 End ------------------------------------------------------------------ /\x{100000}/8BM Memory allocation (code space): 16 ------------------------------------------------------------------ 0 5 Bra 2 \x{100000} 5 5 Ket 7 End ------------------------------------------------------------------ /\x{10ffff}/8BM Memory allocation (code space): 16 ------------------------------------------------------------------ 0 5 Bra 2 \x{10ffff} 5 5 Ket 7 End ------------------------------------------------------------------ /\x{110000}/8BM Failed: character value in \x{} or \o{} is too large at offset 9 /[\x{ff}]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{ff} 4 4 Ket 6 End ------------------------------------------------------------------ /[\x{100}]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{100} 4 4 Ket 6 End ------------------------------------------------------------------ /\x80/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x80 4 4 Ket 6 End ------------------------------------------------------------------ /\xff/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{ff} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{0041}\x{2262}\x{0391}\x{002e}/D8M Memory allocation (code space): 26 ------------------------------------------------------------------ 0 10 Bra 2 A\x{2262}\x{391}. 10 10 Ket 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = '.' /\x{D55c}\x{ad6d}\x{C5B4}/D8M Memory allocation (code space): 22 ------------------------------------------------------------------ 0 8 Bra 2 \x{d55c}\x{ad6d}\x{c5b4} 8 8 Ket 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d55c} Need char = \x{c5b4} /\x{65e5}\x{672c}\x{8a9e}/D8M Memory allocation (code space): 22 ------------------------------------------------------------------ 0 8 Bra 2 \x{65e5}\x{672c}\x{8a9e} 8 8 Ket 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{65e5} Need char = \x{8a9e} /[\x{100}]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{100} 4 4 Ket 6 End ------------------------------------------------------------------ /[Z\x{100}]/8BM Memory allocation (code space): 54 ------------------------------------------------------------------ 0 24 Bra 2 [Z\x{100}] 24 24 Ket 26 End ------------------------------------------------------------------ /^[\x{100}\E-\Q\E\x{150}]/B8M Memory allocation (code space): 26 ------------------------------------------------------------------ 0 10 Bra 2 ^ 3 [\x{100}-\x{150}] 10 10 Ket 12 End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E]/B8M Memory allocation (code space): 26 ------------------------------------------------------------------ 0 10 Bra 2 ^ 3 [\x{100}-\x{150}] 10 10 Ket 12 End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E/B8M Failed: missing terminating ] for character class at offset 13 /[\p{L}]/BM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 [\p{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\p{^L}]/BM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 [\P{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\P{L}]/BM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 [\P{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\P{^L}]/BM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 [\p{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[abc\p{L}\x{0660}]/8BM Memory allocation (code space): 60 ------------------------------------------------------------------ 0 27 Bra 2 [a-c\p{L}\x{660}] 27 27 Ket 29 End ------------------------------------------------------------------ /[\p{Nd}]/8BM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 [\p{Nd}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\p{Nd}+-]+/8BM Memory allocation (code space): 58 ------------------------------------------------------------------ 0 26 Bra 2 [+\-\p{Nd}]++ 26 26 Ket 28 End ------------------------------------------------------------------ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iBM Memory allocation (code space): 32 ------------------------------------------------------------------ 0 13 Bra 2 /i A\x{391}\x{10427}\x{ff3a}\x{1fb0} 13 13 Ket 15 End ------------------------------------------------------------------ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8BM Memory allocation (code space): 32 ------------------------------------------------------------------ 0 13 Bra 2 A\x{391}\x{10427}\x{ff3a}\x{1fb0} 13 13 Ket 15 End ------------------------------------------------------------------ /[\x{105}-\x{109}]/8iBM Memory allocation (code space): 24 ------------------------------------------------------------------ 0 9 Bra 2 [\x{104}-\x{109}] 9 9 Ket 11 End ------------------------------------------------------------------ /( ( (?(1)0|) )* )/xBM Memory allocation (code space): 52 ------------------------------------------------------------------ 0 23 Bra 2 19 CBra 1 5 Brazero 6 13 SCBra 2 9 6 Cond 11 1 Cond ref 13 0 15 2 Alt 17 8 Ket 19 13 KetRmax 21 19 Ket 23 23 Ket 25 End ------------------------------------------------------------------ /( (?(1)0|)* )/xBM Memory allocation (code space): 42 ------------------------------------------------------------------ 0 18 Bra 2 14 CBra 1 5 Brazero 6 6 SCond 8 1 Cond ref 10 0 12 2 Alt 14 8 KetRmax 16 14 Ket 18 18 Ket 20 End ------------------------------------------------------------------ /[a]/BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 a 4 4 Ket 6 End ------------------------------------------------------------------ /[a]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 a 4 4 Ket 6 End ------------------------------------------------------------------ /[\xaa]/BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{aa} 4 4 Ket 6 End ------------------------------------------------------------------ /[\xaa]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 \x{aa} 4 4 Ket 6 End ------------------------------------------------------------------ /[^a]/BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 [^a] 4 4 Ket 6 End ------------------------------------------------------------------ /[^a]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 [^a] 4 4 Ket 6 End ------------------------------------------------------------------ /[^\xaa]/BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 [^\x{aa}] 4 4 Ket 6 End ------------------------------------------------------------------ /[^\xaa]/8BM Memory allocation (code space): 14 ------------------------------------------------------------------ 0 4 Bra 2 [^\x{aa}] 4 4 Ket 6 End ------------------------------------------------------------------ /[^\d]/8WB ------------------------------------------------------------------ 0 9 Bra 2 [^\p{Nd}] 9 9 Ket 11 End ------------------------------------------------------------------ /[[:^alpha:][:^cntrl:]]+/8WB ------------------------------------------------------------------ 0 30 Bra 2 [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ 30 30 Ket 32 End ------------------------------------------------------------------ /[[:^cntrl:][:^alpha:]]+/8WB ------------------------------------------------------------------ 0 30 Bra 2 [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ 30 30 Ket 32 End ------------------------------------------------------------------ /[[:alpha:]]+/8WB ------------------------------------------------------------------ 0 10 Bra 2 [\p{L}]++ 10 10 Ket 12 End ------------------------------------------------------------------ /[[:^alpha:]\S]+/8WB ------------------------------------------------------------------ 0 13 Bra 2 [\P{L}\P{Xsp}]++ 13 13 Ket 15 End ------------------------------------------------------------------ /abc(d|e)(*THEN)x(123(*THEN)4|567(b|q)(*THEN)xx)/B ------------------------------------------------------------------ 0 60 Bra 2 abc 8 5 CBra 1 11 d 13 4 Alt 15 e 17 9 Ket 19 *THEN 20 x 22 12 CBra 2 25 123 31 *THEN 32 4 34 24 Alt 36 567 42 5 CBra 3 45 b 47 4 Alt 49 q 51 9 Ket 53 *THEN 54 xx 58 36 Ket 60 60 Ket 62 End ------------------------------------------------------------------ /(((a\2)|(a*)\g<-1>))*a?/B ------------------------------------------------------------------ 0 39 Bra 2 Brazero 3 32 SCBra 1 6 27 Once 8 12 CBra 2 11 7 CBra 3 14 a 16 \2 18 7 Ket 20 11 Alt 22 5 CBra 4 25 a* 27 5 Ket 29 22 Recurse 31 23 Ket 33 27 Ket 35 32 KetRmax 37 a?+ 39 39 Ket 41 End ------------------------------------------------------------------ /((?+1)(\1))/B ------------------------------------------------------------------ 0 20 Bra 2 16 Once 4 12 CBra 1 7 9 Recurse 9 5 CBra 2 12 \1 14 5 Ket 16 12 Ket 18 16 Ket 20 20 Ket 22 End ------------------------------------------------------------------ /.((?2)(?R)\1)()/B ------------------------------------------------------------------ 0 23 Bra 2 Any 3 13 Once 5 9 CBra 1 8 18 Recurse 10 0 Recurse 12 \1 14 9 Ket 16 13 Ket 18 3 CBra 2 21 3 Ket 23 23 Ket 25 End ------------------------------------------------------------------ /([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/ Failed: regular expression is too complicated at offset 490 /-- End of testinput11 --/ ================================================ FILE: src/pcre/testdata/testoutput11-32 ================================================ /-- These are a few representative patterns whose lengths and offsets are to be shown when the link size is 2. This is just a doublecheck test to ensure the sizes don't go horribly wrong when something is changed. The pattern contents are all themselves checked in other tests. Unicode, including property support, is required for these tests. --/ /((?i)b)/BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 5 CBra 1 5 /i b 7 5 Ket 9 9 Ket 11 End ------------------------------------------------------------------ /(?s)(.*X|^B)/BM Memory allocation (code space): 76 ------------------------------------------------------------------ 0 16 Bra 2 7 CBra 1 5 AllAny* 7 X 9 5 Alt 11 ^ 12 B 14 12 Ket 16 16 Ket 18 End ------------------------------------------------------------------ /(?s:.*X|^B)/BM Memory allocation (code space): 72 ------------------------------------------------------------------ 0 15 Bra 2 6 Bra 4 AllAny* 6 X 8 5 Alt 10 ^ 11 B 13 11 Ket 15 15 Ket 17 End ------------------------------------------------------------------ /^[[:alnum:]]/BM Memory allocation (code space): 60 ------------------------------------------------------------------ 0 12 Bra 2 ^ 3 [0-9A-Za-z] 12 12 Ket 14 End ------------------------------------------------------------------ /#/IxMD Memory allocation (code space): 20 ------------------------------------------------------------------ 0 2 Bra 2 2 Ket 4 End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string Options: extended No first char No need char /a#/IxMD Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 a 4 4 Ket 6 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended First char = 'a' No need char /x?+/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 x?+ 4 4 Ket 6 End ------------------------------------------------------------------ /x++/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 x++ 4 4 Ket 6 End ------------------------------------------------------------------ /x{1,3}+/BM Memory allocation (code space): 40 ------------------------------------------------------------------ 0 7 Bra 2 x 4 x{0,2}+ 7 7 Ket 9 End ------------------------------------------------------------------ /(x)*+/BM Memory allocation (code space): 52 ------------------------------------------------------------------ 0 10 Bra 2 Braposzero 3 5 CBraPos 1 6 x 8 5 KetRpos 10 10 Ket 12 End ------------------------------------------------------------------ /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/BM Memory allocation (code space): 220 ------------------------------------------------------------------ 0 52 Bra 2 ^ 3 47 CBra 1 6 5 CBra 2 9 a+ 11 5 Ket 13 13 CBra 3 16 [ab]+? 26 13 Ket 28 13 CBra 4 31 [bc]+ 41 13 Ket 43 5 CBra 5 46 \w*+ 48 5 Ket 50 47 Ket 52 52 Ket 54 End ------------------------------------------------------------------ |8J\$WE\<\.rX\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM Memory allocation (code space): 3296 ------------------------------------------------------------------ 0 821 Bra 2 8J$WE<.rX+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X 820 \b 821 821 Ket 823 End ------------------------------------------------------------------ |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM Memory allocation (code space): 3256 ------------------------------------------------------------------ 0 811 Bra 2 $<.X+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X 810 \b 811 811 Ket 813 End ------------------------------------------------------------------ /(a(?1)b)/BM Memory allocation (code space): 64 ------------------------------------------------------------------ 0 13 Bra 2 9 CBra 1 5 a 7 2 Recurse 9 b 11 9 Ket 13 13 Ket 15 End ------------------------------------------------------------------ /(a(?1)+b)/BM Memory allocation (code space): 80 ------------------------------------------------------------------ 0 17 Bra 2 13 CBra 1 5 a 7 4 Once 9 2 Recurse 11 4 KetRmax 13 b 15 13 Ket 17 17 Ket 19 End ------------------------------------------------------------------ /a(?Pb|c)d(?Pe)/BM Memory allocation (code space): 186 ------------------------------------------------------------------ 0 24 Bra 2 a 4 5 CBra 1 7 b 9 4 Alt 11 c 13 9 Ket 15 d 17 5 CBra 2 20 e 22 5 Ket 24 24 Ket 26 End ------------------------------------------------------------------ /(?:a(?Pc(?Pd)))(?Pa)/BM Memory allocation (code space): 155 ------------------------------------------------------------------ 0 29 Bra 2 18 Bra 4 a 6 12 CBra 1 9 c 11 5 CBra 2 14 d 16 5 Ket 18 12 Ket 20 18 Ket 22 5 CBra 3 25 a 27 5 Ket 29 29 Ket 31 End ------------------------------------------------------------------ /(?Pa)...(?P=a)bbb(?P>a)d/BM Memory allocation (code space): 189 ------------------------------------------------------------------ 0 24 Bra 2 5 CBra 1 5 a 7 5 Ket 9 Any 10 Any 11 Any 12 \1 14 bbb 20 2 Recurse 22 d 24 24 Ket 26 End ------------------------------------------------------------------ /abc(?C255)de(?C)f/BM Memory allocation (code space): 100 ------------------------------------------------------------------ 0 22 Bra 2 abc 8 Callout 255 10 1 12 de 16 Callout 0 16 1 20 f 22 22 Ket 24 End ------------------------------------------------------------------ /abcde/CBM Memory allocation (code space): 156 ------------------------------------------------------------------ 0 36 Bra 2 Callout 255 0 1 6 a 8 Callout 255 1 1 12 b 14 Callout 255 2 1 18 c 20 Callout 255 3 1 24 d 26 Callout 255 4 1 30 e 32 Callout 255 5 0 36 36 Ket 38 End ------------------------------------------------------------------ /\x{100}/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{100} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{1000}/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{1000} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{10000}/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{10000} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{100000}/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{100000} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{10ffff}/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{10ffff} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{110000}/8BM Failed: character value in \x{} or \o{} is too large at offset 9 /[\x{ff}]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{ff} 4 4 Ket 6 End ------------------------------------------------------------------ /[\x{100}]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{100} 4 4 Ket 6 End ------------------------------------------------------------------ /\x80/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x80 4 4 Ket 6 End ------------------------------------------------------------------ /\xff/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{ff} 4 4 Ket 6 End ------------------------------------------------------------------ /\x{0041}\x{2262}\x{0391}\x{002e}/D8M Memory allocation (code space): 52 ------------------------------------------------------------------ 0 10 Bra 2 A\x{2262}\x{391}. 10 10 Ket 12 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = '.' /\x{D55c}\x{ad6d}\x{C5B4}/D8M Memory allocation (code space): 44 ------------------------------------------------------------------ 0 8 Bra 2 \x{d55c}\x{ad6d}\x{c5b4} 8 8 Ket 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d55c} Need char = \x{c5b4} /\x{65e5}\x{672c}\x{8a9e}/D8M Memory allocation (code space): 44 ------------------------------------------------------------------ 0 8 Bra 2 \x{65e5}\x{672c}\x{8a9e} 8 8 Ket 10 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{65e5} Need char = \x{8a9e} /[\x{100}]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{100} 4 4 Ket 6 End ------------------------------------------------------------------ /[Z\x{100}]/8BM Memory allocation (code space): 76 ------------------------------------------------------------------ 0 16 Bra 2 [Z\x{100}] 16 16 Ket 18 End ------------------------------------------------------------------ /^[\x{100}\E-\Q\E\x{150}]/B8M Memory allocation (code space): 52 ------------------------------------------------------------------ 0 10 Bra 2 ^ 3 [\x{100}-\x{150}] 10 10 Ket 12 End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E]/B8M Memory allocation (code space): 52 ------------------------------------------------------------------ 0 10 Bra 2 ^ 3 [\x{100}-\x{150}] 10 10 Ket 12 End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E/B8M Failed: missing terminating ] for character class at offset 13 /[\p{L}]/BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 [\p{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\p{^L}]/BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 [\P{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\P{L}]/BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 [\P{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\P{^L}]/BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 [\p{L}] 9 9 Ket 11 End ------------------------------------------------------------------ /[abc\p{L}\x{0660}]/8BM Memory allocation (code space): 88 ------------------------------------------------------------------ 0 19 Bra 2 [a-c\p{L}\x{660}] 19 19 Ket 21 End ------------------------------------------------------------------ /[\p{Nd}]/8BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 [\p{Nd}] 9 9 Ket 11 End ------------------------------------------------------------------ /[\p{Nd}+-]+/8BM Memory allocation (code space): 84 ------------------------------------------------------------------ 0 18 Bra 2 [+\-\p{Nd}]++ 18 18 Ket 20 End ------------------------------------------------------------------ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iBM Memory allocation (code space): 60 ------------------------------------------------------------------ 0 12 Bra 2 /i A\x{391}\x{10427}\x{ff3a}\x{1fb0} 12 12 Ket 14 End ------------------------------------------------------------------ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8BM Memory allocation (code space): 60 ------------------------------------------------------------------ 0 12 Bra 2 A\x{391}\x{10427}\x{ff3a}\x{1fb0} 12 12 Ket 14 End ------------------------------------------------------------------ /[\x{105}-\x{109}]/8iBM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 9 Bra 2 [\x{104}-\x{109}] 9 9 Ket 11 End ------------------------------------------------------------------ /( ( (?(1)0|) )* )/xBM Memory allocation (code space): 104 ------------------------------------------------------------------ 0 23 Bra 2 19 CBra 1 5 Brazero 6 13 SCBra 2 9 6 Cond 11 1 Cond ref 13 0 15 2 Alt 17 8 Ket 19 13 KetRmax 21 19 Ket 23 23 Ket 25 End ------------------------------------------------------------------ /( (?(1)0|)* )/xBM Memory allocation (code space): 84 ------------------------------------------------------------------ 0 18 Bra 2 14 CBra 1 5 Brazero 6 6 SCond 8 1 Cond ref 10 0 12 2 Alt 14 8 KetRmax 16 14 Ket 18 18 Ket 20 End ------------------------------------------------------------------ /[a]/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 a 4 4 Ket 6 End ------------------------------------------------------------------ /[a]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 a 4 4 Ket 6 End ------------------------------------------------------------------ /[\xaa]/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{aa} 4 4 Ket 6 End ------------------------------------------------------------------ /[\xaa]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 \x{aa} 4 4 Ket 6 End ------------------------------------------------------------------ /[^a]/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 [^a] 4 4 Ket 6 End ------------------------------------------------------------------ /[^a]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 [^a] 4 4 Ket 6 End ------------------------------------------------------------------ /[^\xaa]/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 [^\x{aa}] 4 4 Ket 6 End ------------------------------------------------------------------ /[^\xaa]/8BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 4 Bra 2 [^\x{aa}] 4 4 Ket 6 End ------------------------------------------------------------------ /[^\d]/8WB ------------------------------------------------------------------ 0 9 Bra 2 [^\p{Nd}] 9 9 Ket 11 End ------------------------------------------------------------------ /[[:^alpha:][:^cntrl:]]+/8WB ------------------------------------------------------------------ 0 21 Bra 2 [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ 21 21 Ket 23 End ------------------------------------------------------------------ /[[:^cntrl:][:^alpha:]]+/8WB ------------------------------------------------------------------ 0 21 Bra 2 [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ 21 21 Ket 23 End ------------------------------------------------------------------ /[[:alpha:]]+/8WB ------------------------------------------------------------------ 0 10 Bra 2 [\p{L}]++ 10 10 Ket 12 End ------------------------------------------------------------------ /[[:^alpha:]\S]+/8WB ------------------------------------------------------------------ 0 13 Bra 2 [\P{L}\P{Xsp}]++ 13 13 Ket 15 End ------------------------------------------------------------------ /abc(d|e)(*THEN)x(123(*THEN)4|567(b|q)(*THEN)xx)/B ------------------------------------------------------------------ 0 60 Bra 2 abc 8 5 CBra 1 11 d 13 4 Alt 15 e 17 9 Ket 19 *THEN 20 x 22 12 CBra 2 25 123 31 *THEN 32 4 34 24 Alt 36 567 42 5 CBra 3 45 b 47 4 Alt 49 q 51 9 Ket 53 *THEN 54 xx 58 36 Ket 60 60 Ket 62 End ------------------------------------------------------------------ /(((a\2)|(a*)\g<-1>))*a?/B ------------------------------------------------------------------ 0 39 Bra 2 Brazero 3 32 SCBra 1 6 27 Once 8 12 CBra 2 11 7 CBra 3 14 a 16 \2 18 7 Ket 20 11 Alt 22 5 CBra 4 25 a* 27 5 Ket 29 22 Recurse 31 23 Ket 33 27 Ket 35 32 KetRmax 37 a?+ 39 39 Ket 41 End ------------------------------------------------------------------ /((?+1)(\1))/B ------------------------------------------------------------------ 0 20 Bra 2 16 Once 4 12 CBra 1 7 9 Recurse 9 5 CBra 2 12 \1 14 5 Ket 16 12 Ket 18 16 Ket 20 20 Ket 22 End ------------------------------------------------------------------ /.((?2)(?R)\1)()/B ------------------------------------------------------------------ 0 23 Bra 2 Any 3 13 Once 5 9 CBra 1 8 18 Recurse 10 0 Recurse 12 \1 14 9 Ket 16 13 Ket 18 3 CBra 2 21 3 Ket 23 23 Ket 25 End ------------------------------------------------------------------ /([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/ Failed: missing ) at offset 509 /-- End of testinput11 --/ ================================================ FILE: src/pcre/testdata/testoutput11-8 ================================================ /-- These are a few representative patterns whose lengths and offsets are to be shown when the link size is 2. This is just a doublecheck test to ensure the sizes don't go horribly wrong when something is changed. The pattern contents are all themselves checked in other tests. Unicode, including property support, is required for these tests. --/ /((?i)b)/BM Memory allocation (code space): 17 ------------------------------------------------------------------ 0 13 Bra 3 7 CBra 1 8 /i b 10 7 Ket 13 13 Ket 16 End ------------------------------------------------------------------ /(?s)(.*X|^B)/BM Memory allocation (code space): 25 ------------------------------------------------------------------ 0 21 Bra 3 9 CBra 1 8 AllAny* 10 X 12 6 Alt 15 ^ 16 B 18 15 Ket 21 21 Ket 24 End ------------------------------------------------------------------ /(?s:.*X|^B)/BM Memory allocation (code space): 23 ------------------------------------------------------------------ 0 19 Bra 3 7 Bra 6 AllAny* 8 X 10 6 Alt 13 ^ 14 B 16 13 Ket 19 19 Ket 22 End ------------------------------------------------------------------ /^[[:alnum:]]/BM Memory allocation (code space): 41 ------------------------------------------------------------------ 0 37 Bra 3 ^ 4 [0-9A-Za-z] 37 37 Ket 40 End ------------------------------------------------------------------ /#/IxMD Memory allocation (code space): 7 ------------------------------------------------------------------ 0 3 Bra 3 3 Ket 6 End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string Options: extended No first char No need char /a#/IxMD Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 a 5 5 Ket 8 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended First char = 'a' No need char /x?+/BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 x?+ 5 5 Ket 8 End ------------------------------------------------------------------ /x++/BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 x++ 5 5 Ket 8 End ------------------------------------------------------------------ /x{1,3}+/BM Memory allocation (code space): 13 ------------------------------------------------------------------ 0 9 Bra 3 x 5 x{0,2}+ 9 9 Ket 12 End ------------------------------------------------------------------ /(x)*+/BM Memory allocation (code space): 18 ------------------------------------------------------------------ 0 14 Bra 3 Braposzero 4 7 CBraPos 1 9 x 11 7 KetRpos 14 14 Ket 17 End ------------------------------------------------------------------ /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/BM Memory allocation (code space): 120 ------------------------------------------------------------------ 0 116 Bra 3 ^ 4 109 CBra 1 9 7 CBra 2 14 a+ 16 7 Ket 19 39 CBra 3 24 [ab]+? 58 39 Ket 61 39 CBra 4 66 [bc]+ 100 39 Ket 103 7 CBra 5 108 \w*+ 110 7 Ket 113 109 Ket 116 116 Ket 119 End ------------------------------------------------------------------ |8J\$WE\<\.rX\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM Memory allocation (code space): 826 ------------------------------------------------------------------ 0 822 Bra 3 8J$WE<.rX+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X 821 \b 822 822 Ket 825 End ------------------------------------------------------------------ |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|BM Memory allocation (code space): 816 ------------------------------------------------------------------ 0 812 Bra 3 $<.X+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X 811 \b 812 812 Ket 815 End ------------------------------------------------------------------ /(a(?1)b)/BM Memory allocation (code space): 22 ------------------------------------------------------------------ 0 18 Bra 3 12 CBra 1 8 a 10 3 Recurse 13 b 15 12 Ket 18 18 Ket 21 End ------------------------------------------------------------------ /(a(?1)+b)/BM Memory allocation (code space): 28 ------------------------------------------------------------------ 0 24 Bra 3 18 CBra 1 8 a 10 6 Once 13 3 Recurse 16 6 KetRmax 19 b 21 18 Ket 24 24 Ket 27 End ------------------------------------------------------------------ /a(?Pb|c)d(?Pe)/BM Memory allocation (code space): 36 ------------------------------------------------------------------ 0 32 Bra 3 a 5 7 CBra 1 10 b 12 5 Alt 15 c 17 12 Ket 20 d 22 7 CBra 2 27 e 29 7 Ket 32 32 Ket 35 End ------------------------------------------------------------------ /(?:a(?Pc(?Pd)))(?Pa)/BM Memory allocation (code space): 45 ------------------------------------------------------------------ 0 41 Bra 3 25 Bra 6 a 8 17 CBra 1 13 c 15 7 CBra 2 20 d 22 7 Ket 25 17 Ket 28 25 Ket 31 7 CBra 3 36 a 38 7 Ket 41 41 Ket 44 End ------------------------------------------------------------------ /(?Pa)...(?P=a)bbb(?P>a)d/BM Memory allocation (code space): 62 ------------------------------------------------------------------ 0 30 Bra 3 7 CBra 1 8 a 10 7 Ket 13 Any 14 Any 15 Any 16 \1 19 bbb 25 3 Recurse 28 d 30 30 Ket 33 End ------------------------------------------------------------------ /abc(?C255)de(?C)f/BM Memory allocation (code space): 31 ------------------------------------------------------------------ 0 27 Bra 3 abc 9 Callout 255 10 1 15 de 19 Callout 0 16 1 25 f 27 27 Ket 30 End ------------------------------------------------------------------ /abcde/CBM Memory allocation (code space): 53 ------------------------------------------------------------------ 0 49 Bra 3 Callout 255 0 1 9 a 11 Callout 255 1 1 17 b 19 Callout 255 2 1 25 c 27 Callout 255 3 1 33 d 35 Callout 255 4 1 41 e 43 Callout 255 5 0 49 49 Ket 52 End ------------------------------------------------------------------ /\x{100}/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{100} 6 6 Ket 9 End ------------------------------------------------------------------ /\x{1000}/8BM Memory allocation (code space): 11 ------------------------------------------------------------------ 0 7 Bra 3 \x{1000} 7 7 Ket 10 End ------------------------------------------------------------------ /\x{10000}/8BM Memory allocation (code space): 12 ------------------------------------------------------------------ 0 8 Bra 3 \x{10000} 8 8 Ket 11 End ------------------------------------------------------------------ /\x{100000}/8BM Memory allocation (code space): 12 ------------------------------------------------------------------ 0 8 Bra 3 \x{100000} 8 8 Ket 11 End ------------------------------------------------------------------ /\x{10ffff}/8BM Memory allocation (code space): 12 ------------------------------------------------------------------ 0 8 Bra 3 \x{10ffff} 8 8 Ket 11 End ------------------------------------------------------------------ /\x{110000}/8BM Failed: character value in \x{} or \o{} is too large at offset 9 /[\x{ff}]/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{ff} 6 6 Ket 9 End ------------------------------------------------------------------ /[\x{100}]/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{100} 6 6 Ket 9 End ------------------------------------------------------------------ /\x80/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{80} 6 6 Ket 9 End ------------------------------------------------------------------ /\xff/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{ff} 6 6 Ket 9 End ------------------------------------------------------------------ /\x{0041}\x{2262}\x{0391}\x{002e}/D8M Memory allocation (code space): 18 ------------------------------------------------------------------ 0 14 Bra 3 A\x{2262}\x{391}. 14 14 Ket 17 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = '.' /\x{D55c}\x{ad6d}\x{C5B4}/D8M Memory allocation (code space): 19 ------------------------------------------------------------------ 0 15 Bra 3 \x{d55c}\x{ad6d}\x{c5b4} 15 15 Ket 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ed} Need char = \x{b4} /\x{65e5}\x{672c}\x{8a9e}/D8M Memory allocation (code space): 19 ------------------------------------------------------------------ 0 15 Bra 3 \x{65e5}\x{672c}\x{8a9e} 15 15 Ket 18 End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{e6} Need char = \x{9e} /[\x{100}]/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{100} 6 6 Ket 9 End ------------------------------------------------------------------ /[Z\x{100}]/8BM Memory allocation (code space): 47 ------------------------------------------------------------------ 0 43 Bra 3 [Z\x{100}] 43 43 Ket 46 End ------------------------------------------------------------------ /^[\x{100}\E-\Q\E\x{150}]/B8M Memory allocation (code space): 18 ------------------------------------------------------------------ 0 14 Bra 3 ^ 4 [\x{100}-\x{150}] 14 14 Ket 17 End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E]/B8M Memory allocation (code space): 18 ------------------------------------------------------------------ 0 14 Bra 3 ^ 4 [\x{100}-\x{150}] 14 14 Ket 17 End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E/B8M Failed: missing terminating ] for character class at offset 15 /[\p{L}]/BM Memory allocation (code space): 15 ------------------------------------------------------------------ 0 11 Bra 3 [\p{L}] 11 11 Ket 14 End ------------------------------------------------------------------ /[\p{^L}]/BM Memory allocation (code space): 15 ------------------------------------------------------------------ 0 11 Bra 3 [\P{L}] 11 11 Ket 14 End ------------------------------------------------------------------ /[\P{L}]/BM Memory allocation (code space): 15 ------------------------------------------------------------------ 0 11 Bra 3 [\P{L}] 11 11 Ket 14 End ------------------------------------------------------------------ /[\P{^L}]/BM Memory allocation (code space): 15 ------------------------------------------------------------------ 0 11 Bra 3 [\p{L}] 11 11 Ket 14 End ------------------------------------------------------------------ /[abc\p{L}\x{0660}]/8BM Memory allocation (code space): 50 ------------------------------------------------------------------ 0 46 Bra 3 [a-c\p{L}\x{660}] 46 46 Ket 49 End ------------------------------------------------------------------ /[\p{Nd}]/8BM Memory allocation (code space): 15 ------------------------------------------------------------------ 0 11 Bra 3 [\p{Nd}] 11 11 Ket 14 End ------------------------------------------------------------------ /[\p{Nd}+-]+/8BM Memory allocation (code space): 48 ------------------------------------------------------------------ 0 44 Bra 3 [+\-\p{Nd}]++ 44 44 Ket 47 End ------------------------------------------------------------------ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iBM Memory allocation (code space): 25 ------------------------------------------------------------------ 0 21 Bra 3 /i A\x{391}\x{10427}\x{ff3a}\x{1fb0} 21 21 Ket 24 End ------------------------------------------------------------------ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8BM Memory allocation (code space): 25 ------------------------------------------------------------------ 0 21 Bra 3 A\x{391}\x{10427}\x{ff3a}\x{1fb0} 21 21 Ket 24 End ------------------------------------------------------------------ /[\x{105}-\x{109}]/8iBM Memory allocation (code space): 17 ------------------------------------------------------------------ 0 13 Bra 3 [\x{104}-\x{109}] 13 13 Ket 16 End ------------------------------------------------------------------ /( ( (?(1)0|) )* )/xBM Memory allocation (code space): 38 ------------------------------------------------------------------ 0 34 Bra 3 28 CBra 1 8 Brazero 9 19 SCBra 2 14 8 Cond 17 1 Cond ref 20 0 22 3 Alt 25 11 Ket 28 19 KetRmax 31 28 Ket 34 34 Ket 37 End ------------------------------------------------------------------ /( (?(1)0|)* )/xBM Memory allocation (code space): 30 ------------------------------------------------------------------ 0 26 Bra 3 20 CBra 1 8 Brazero 9 8 SCond 12 1 Cond ref 15 0 17 3 Alt 20 11 KetRmax 23 20 Ket 26 26 Ket 29 End ------------------------------------------------------------------ /[a]/BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 a 5 5 Ket 8 End ------------------------------------------------------------------ /[a]/8BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 a 5 5 Ket 8 End ------------------------------------------------------------------ /[\xaa]/BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 \x{aa} 5 5 Ket 8 End ------------------------------------------------------------------ /[\xaa]/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 \x{aa} 6 6 Ket 9 End ------------------------------------------------------------------ /[^a]/BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 [^a] 5 5 Ket 8 End ------------------------------------------------------------------ /[^a]/8BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 [^a] 5 5 Ket 8 End ------------------------------------------------------------------ /[^\xaa]/BM Memory allocation (code space): 9 ------------------------------------------------------------------ 0 5 Bra 3 [^\x{aa}] 5 5 Ket 8 End ------------------------------------------------------------------ /[^\xaa]/8BM Memory allocation (code space): 10 ------------------------------------------------------------------ 0 6 Bra 3 [^\x{aa}] 6 6 Ket 9 End ------------------------------------------------------------------ /[^\d]/8WB ------------------------------------------------------------------ 0 11 Bra 3 [^\p{Nd}] 11 11 Ket 14 End ------------------------------------------------------------------ /[[:^alpha:][:^cntrl:]]+/8WB ------------------------------------------------------------------ 0 51 Bra 3 [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ 51 51 Ket 54 End ------------------------------------------------------------------ /[[:^cntrl:][:^alpha:]]+/8WB ------------------------------------------------------------------ 0 51 Bra 3 [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ 51 51 Ket 54 End ------------------------------------------------------------------ /[[:alpha:]]+/8WB ------------------------------------------------------------------ 0 12 Bra 3 [\p{L}]++ 12 12 Ket 15 End ------------------------------------------------------------------ /[[:^alpha:]\S]+/8WB ------------------------------------------------------------------ 0 15 Bra 3 [\P{L}\P{Xsp}]++ 15 15 Ket 18 End ------------------------------------------------------------------ /abc(d|e)(*THEN)x(123(*THEN)4|567(b|q)(*THEN)xx)/B ------------------------------------------------------------------ 0 73 Bra 3 abc 9 7 CBra 1 14 d 16 5 Alt 19 e 21 12 Ket 24 *THEN 25 x 27 14 CBra 2 32 123 38 *THEN 39 4 41 29 Alt 44 567 50 7 CBra 3 55 b 57 5 Alt 60 q 62 12 Ket 65 *THEN 66 xx 70 43 Ket 73 73 Ket 76 End ------------------------------------------------------------------ /(((a\2)|(a*)\g<-1>))*a?/B ------------------------------------------------------------------ 0 57 Bra 3 Brazero 4 48 SCBra 1 9 40 Once 12 18 CBra 2 17 10 CBra 3 22 a 24 \2 27 10 Ket 30 16 Alt 33 7 CBra 4 38 a* 40 7 Ket 43 33 Recurse 46 34 Ket 49 40 Ket 52 48 KetRmax 55 a?+ 57 57 Ket 60 End ------------------------------------------------------------------ /((?+1)(\1))/B ------------------------------------------------------------------ 0 31 Bra 3 25 Once 6 19 CBra 1 11 14 Recurse 14 8 CBra 2 19 \1 22 8 Ket 25 19 Ket 28 25 Ket 31 31 Ket 34 End ------------------------------------------------------------------ /.((?2)(?R)\1)()/B ------------------------------------------------------------------ 0 35 Bra 3 Any 4 20 Once 7 14 CBra 1 12 27 Recurse 15 0 Recurse 18 \1 21 14 Ket 24 20 Ket 27 5 CBra 2 32 5 Ket 35 35 Ket 38 End ------------------------------------------------------------------ /([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00]([00](*ACCEPT)/ Failed: missing ) at offset 509 /-- End of testinput11 --/ ================================================ FILE: src/pcre/testdata/testoutput12 ================================================ /-- This test is run only when JIT support is available. It checks for a successful and an unsuccessful JIT compile and save and restore behaviour, and a couple of things that are different with JIT. --/ /abc/S+I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' Subject length lower bound = 3 No starting char list JIT study was successful /(?(?C1)(?=a)a)/S+I Capturing subpattern count = 0 May match empty string No options No first char No need char Study returned NULL JIT study was not successful /(?(?C1)(?=a)a)/S!+I Capturing subpattern count = 0 May match empty string No options No first char No need char Subject length lower bound = -1 No starting char list JIT study was not successful /b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*/S+I Capturing subpattern count = 0 May match empty string No options No first char No need char Study returned NULL JIT study was not successful /abc/S+I>testsavedregex Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' Subject length lower bound = 3 No starting char list JIT study was successful Compiled pattern written to testsavedregex Study data written to testsavedregex b)c/PN abc Matched with REG_NOSUB /a?|b?/P abc 0: a ** Failers 0: ddd\N No match: POSIX code 17: match failed /\w+A/P CDAAAAB 0: CDAAAA /\w+A/PU CDAAAAB 0: CDA /\Biss\B/I+P Mississippi 0: iss 0+ issippi /abc/\P Failed: POSIX code 9: bad escape sequence at offset 4 /-- End of POSIX tests --/ /a\Cb/ aXb 0: aXb a\nb 0: a\x0ab ** Failers (too big char) No match A\x{123}B ** Character \x{123} is greater than 255 and UTF-8 mode is not enabled. ** Truncation will probably give the wrong result. No match A\o{443}B ** Character \x{123} is greater than 255 and UTF-8 mode is not enabled. ** Truncation will probably give the wrong result. No match /\x{100}/I Failed: character value in \x{} or \o{} is too large at offset 6 /\o{400}/I Failed: character value in \x{} or \o{} is too large at offset 6 / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /xSI Capturing subpattern count = 0 Contains explicit CR or LF match Options: extended No first char No need char Subject length lower bound = 3 Starting chars: \x09 \x20 ! " # $ % & ' ( * + - / 0 1 2 3 4 5 6 7 8 9 = ? A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f /-- Although this saved pattern was compiled with link-size=2, it does no harm to run this test with other link sizes because it is going to generated a "compiled in wrong mode" error as soon as it is loaded, so the link size does not matter. --/ \x09< 0: \x09 /[\h]+/BZ ------------------------------------------------------------------ Bra [\x09 \xa0]++ Ket End ------------------------------------------------------------------ >\x09\x20\xa0< 0: \x09 \xa0 /[\v]/BZ ------------------------------------------------------------------ Bra [\x0a-\x0d\x85] Ket End ------------------------------------------------------------------ /[\H]/BZ ------------------------------------------------------------------ Bra [\x00-\x08\x0a-\x1f!-\x9f\xa1-\xff] Ket End ------------------------------------------------------------------ /[^\h]/BZ ------------------------------------------------------------------ Bra [\x00-\x08\x0a-\x1f!-\x9f\xa1-\xff] (neg) Ket End ------------------------------------------------------------------ /[\V]/BZ ------------------------------------------------------------------ Bra [\x00-\x09\x0e-\x84\x86-\xff] Ket End ------------------------------------------------------------------ /[\x0a\V]/BZ ------------------------------------------------------------------ Bra [\x00-\x0a\x0e-\x84\x86-\xff] Ket End ------------------------------------------------------------------ /\777/I Failed: octal value is greater than \377 in 8-bit non-UTF-8 mode at offset 3 /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF)XX/K Failed: name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN) at offset 259 /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE)XX/K XX 0: XX MK: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE /\u0100/ Failed: character value in \u.... sequence is too large at offset 5 /[\u0100-\u0200]/ Failed: character value in \u.... sequence is too large at offset 6 /[^\x00-a]{12,}[^b-\xff]*/BZ ------------------------------------------------------------------ Bra [b-\xff] (neg){12,}+ [\x00-a] (neg)*+ Ket End ------------------------------------------------------------------ /[^\s]*\s* [^\W]+\W+ [^\d]*?\d0 [^\d\w]{4,6}?\w*A/BZ ------------------------------------------------------------------ Bra [\x00-\x08\x0e-\x1f!-\xff] (neg)*+ \s* [0-9A-Z_a-z]++ \W+ [\x00-/:-\xff] (neg)*+ \d 0 [\x00-/:-@[-^`{-\xff] (neg){4,6}+ \w* A Ket End ------------------------------------------------------------------ /(?'ABC'[bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar](*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/ /-- End of testinput14 --/ ================================================ FILE: src/pcre/testdata/testoutput15 ================================================ /-- This set of tests is for UTF-8 support but not Unicode property support, and is relevant only to the 8-bit library. --/ < forbid W /X(\C{3})/8 X\x{1234} 0: X\x{1234} 1: \x{1234} /X(\C{4})/8 X\x{1234}YZ 0: X\x{1234}Y 1: \x{1234}Y /X\C*/8 XYZabcdce 0: XYZabcdce /X\C*?/8 XYZabcde 0: X /X\C{3,5}/8 Xabcdefg 0: Xabcde X\x{1234} 0: X\x{1234} X\x{1234}YZ 0: X\x{1234}YZ X\x{1234}\x{512} 0: X\x{1234}\x{512} X\x{1234}\x{512}YZ 0: X\x{1234}\x{512} /X\C{3,5}?/8 Xabcdefg 0: Xabc X\x{1234} 0: X\x{1234} X\x{1234}YZ 0: X\x{1234} X\x{1234}\x{512} 0: X\x{1234} /a\Cb/8 aXb 0: aXb a\nb 0: a\x{0a}b /a\C\Cb/8 a\x{100}b 0: a\x{100}b /ab\Cde/8 abXde 0: abXde /a\C\Cb/8 a\x{100}b 0: a\x{100}b ** Failers No match a\x{12257}b No match /[]/8 Failed: invalid UTF-8 string at offset 1 //8 Failed: invalid UTF-8 string at offset 0 /xxx/8 Failed: invalid UTF-8 string at offset 0 /xxx/8?DZSSO ------------------------------------------------------------------ Bra \X{c0}\X{c0}\X{c0}xxx Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: no_auto_possessify utf no_utf_check First char = \x{c3} Need char = 'x' /badutf/8 \xdf Error -10 (bad UTF-8 string) offset=0 reason=1 \xef Error -10 (bad UTF-8 string) offset=0 reason=2 \xef\x80 Error -10 (bad UTF-8 string) offset=0 reason=1 \xf7 Error -10 (bad UTF-8 string) offset=0 reason=3 \xf7\x80 Error -10 (bad UTF-8 string) offset=0 reason=2 \xf7\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=1 \xfb Error -10 (bad UTF-8 string) offset=0 reason=4 \xfb\x80 Error -10 (bad UTF-8 string) offset=0 reason=3 \xfb\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=2 \xfb\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=1 \xfd Error -10 (bad UTF-8 string) offset=0 reason=5 \xfd\x80 Error -10 (bad UTF-8 string) offset=0 reason=4 \xfd\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=3 \xfd\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=2 \xfd\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=1 \xdf\x7f Error -10 (bad UTF-8 string) offset=0 reason=6 \xef\x7f\x80 Error -10 (bad UTF-8 string) offset=0 reason=6 \xef\x80\x7f Error -10 (bad UTF-8 string) offset=0 reason=7 \xf7\x7f\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=6 \xf7\x80\x7f\x80 Error -10 (bad UTF-8 string) offset=0 reason=7 \xf7\x80\x80\x7f Error -10 (bad UTF-8 string) offset=0 reason=8 \xfb\x7f\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=6 \xfb\x80\x7f\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=7 \xfb\x80\x80\x7f\x80 Error -10 (bad UTF-8 string) offset=0 reason=8 \xfb\x80\x80\x80\x7f Error -10 (bad UTF-8 string) offset=0 reason=9 \xfd\x7f\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=6 \xfd\x80\x7f\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=7 \xfd\x80\x80\x7f\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=8 \xfd\x80\x80\x80\x7f\x80 Error -10 (bad UTF-8 string) offset=0 reason=9 \xfd\x80\x80\x80\x80\x7f Error -10 (bad UTF-8 string) offset=0 reason=10 \xed\xa0\x80 Error -10 (bad UTF-8 string) offset=0 reason=14 \xc0\x8f Error -10 (bad UTF-8 string) offset=0 reason=15 \xe0\x80\x8f Error -10 (bad UTF-8 string) offset=0 reason=16 \xf0\x80\x80\x8f Error -10 (bad UTF-8 string) offset=0 reason=17 \xf8\x80\x80\x80\x8f Error -10 (bad UTF-8 string) offset=0 reason=18 \xfc\x80\x80\x80\x80\x8f Error -10 (bad UTF-8 string) offset=0 reason=19 \x80 Error -10 (bad UTF-8 string) offset=0 reason=20 \xfe Error -10 (bad UTF-8 string) offset=0 reason=21 \xff Error -10 (bad UTF-8 string) offset=0 reason=21 /badutf/8 \xfb\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=11 \xfd\x80\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=12 \xf7\xbf\xbf\xbf Error -10 (bad UTF-8 string) offset=0 reason=13 /shortutf/8 \P\P\xdf Error -25 (short UTF-8 string) offset=0 reason=1 \P\P\xef Error -25 (short UTF-8 string) offset=0 reason=2 \P\P\xef\x80 Error -25 (short UTF-8 string) offset=0 reason=1 \P\P\xf7 Error -25 (short UTF-8 string) offset=0 reason=3 \P\P\xf7\x80 Error -25 (short UTF-8 string) offset=0 reason=2 \P\P\xf7\x80\x80 Error -25 (short UTF-8 string) offset=0 reason=1 \P\P\xfb Error -25 (short UTF-8 string) offset=0 reason=4 \P\P\xfb\x80 Error -25 (short UTF-8 string) offset=0 reason=3 \P\P\xfb\x80\x80 Error -25 (short UTF-8 string) offset=0 reason=2 \P\P\xfb\x80\x80\x80 Error -25 (short UTF-8 string) offset=0 reason=1 \P\P\xfd Error -25 (short UTF-8 string) offset=0 reason=5 \P\P\xfd\x80 Error -25 (short UTF-8 string) offset=0 reason=4 \P\P\xfd\x80\x80 Error -25 (short UTF-8 string) offset=0 reason=3 \P\P\xfd\x80\x80\x80 Error -25 (short UTF-8 string) offset=0 reason=2 \P\P\xfd\x80\x80\x80\x80 Error -25 (short UTF-8 string) offset=0 reason=1 /anything/8 \xc0\x80 Error -10 (bad UTF-8 string) offset=0 reason=15 \xc1\x8f Error -10 (bad UTF-8 string) offset=0 reason=15 \xe0\x9f\x80 Error -10 (bad UTF-8 string) offset=0 reason=16 \xf0\x8f\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=17 \xf8\x87\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=18 \xfc\x83\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=19 \xfe\x80\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=21 \xff\x80\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=21 \xc3\x8f No match \xe0\xaf\x80 No match \xe1\x80\x80 No match \xf0\x9f\x80\x80 No match \xf1\x8f\x80\x80 No match \xf8\x88\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=11 \xf9\x87\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=11 \xfc\x84\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=12 \xfd\x83\x80\x80\x80\x80 Error -10 (bad UTF-8 string) offset=0 reason=12 \?\xf8\x88\x80\x80\x80 No match \?\xf9\x87\x80\x80\x80 No match \?\xfc\x84\x80\x80\x80\x80 No match \?\xfd\x83\x80\x80\x80\x80 No match /\x{100}/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{80} /\x{1000}/8DZ ------------------------------------------------------------------ Bra \x{1000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{e1} Need char = \x{80} /\x{10000}/8DZ ------------------------------------------------------------------ Bra \x{10000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{f0} Need char = \x{80} /\x{100000}/8DZ ------------------------------------------------------------------ Bra \x{100000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{f4} Need char = \x{80} /\x{10ffff}/8DZ ------------------------------------------------------------------ Bra \x{10ffff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{f4} Need char = \x{bf} /[\x{ff}]/8DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c3} Need char = \x{bf} /[\x{100}]/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{80} /\x80/8DZ ------------------------------------------------------------------ Bra \x{80} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c2} Need char = \x{80} /\xff/8DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c3} Need char = \x{bf} /\x{D55c}\x{ad6d}\x{C5B4}/DZ8 ------------------------------------------------------------------ Bra \x{d55c}\x{ad6d}\x{c5b4} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ed} Need char = \x{b4} \x{D55c}\x{ad6d}\x{C5B4} 0: \x{d55c}\x{ad6d}\x{c5b4} /\x{65e5}\x{672c}\x{8a9e}/DZ8 ------------------------------------------------------------------ Bra \x{65e5}\x{672c}\x{8a9e} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{e6} Need char = \x{9e} \x{65e5}\x{672c}\x{8a9e} 0: \x{65e5}\x{672c}\x{8a9e} /\x{80}/DZ8 ------------------------------------------------------------------ Bra \x{80} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c2} Need char = \x{80} /\x{084}/DZ8 ------------------------------------------------------------------ Bra \x{84} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c2} Need char = \x{84} /\x{104}/DZ8 ------------------------------------------------------------------ Bra \x{104} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{84} /\x{861}/DZ8 ------------------------------------------------------------------ Bra \x{861} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{e0} Need char = \x{a1} /\x{212ab}/DZ8 ------------------------------------------------------------------ Bra \x{212ab} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{f0} Need char = \x{ab} /-- This one is here not because it's different to Perl, but because the way the captured single-byte is displayed. (In Perl it becomes a character, and you can't tell the difference.) --/ /X(\C)(.*)/8 X\x{1234} 0: X\x{1234} 1: \x{e1} 2: \x{88}\x{b4} X\nabc 0: X\x{0a}abc 1: \x{0a} 2: abc /-- This one is here because Perl gives out a grumbly error message (quite correctly, but that messes up comparisons). --/ /a\Cb/8 *** Failers No match a\x{100}b No match /[^ab\xC0-\xF0]/8SDZ ------------------------------------------------------------------ Bra [\x00-`c-\xbf\xf1-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff \x{f1} 0: \x{f1} \x{bf} 0: \x{bf} \x{100} 0: \x{100} \x{1000} 0: \x{1000} *** Failers 0: * \x{c0} No match \x{f0} No match /Ā{3,4}/8SDZ ------------------------------------------------------------------ Bra \x{100}{3} \x{100}?+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{80} Subject length lower bound = 3 No starting char list \x{100}\x{100}\x{100}\x{100\x{100} 0: \x{100}\x{100}\x{100} /(\x{100}+|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}++ Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: x \xc4 /(\x{100}*a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}*+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: a x \xc4 /(\x{100}{0,2}a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}{0,2}+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: a x \xc4 /(\x{100}{1,2}a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100} \x{100}{0,1}+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: x \xc4 /\x{100}/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{80} /a\x{100}\x{101}*/8DZ ------------------------------------------------------------------ Bra a\x{100} \x{101}*+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = \x{80} /a\x{100}\x{101}+/8DZ ------------------------------------------------------------------ Bra a\x{100} \x{101}++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = \x{81} /[^\x{c4}]/DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\x{100}]/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{80} \x{100} 0: \x{100} Z\x{100} 0: \x{100} \x{100}Z 0: \x{100} *** Failers No match /[\xff]/DZ8 ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c3} Need char = \x{bf} >\x{ff}< 0: \x{ff} /[^\xff]/8DZ ------------------------------------------------------------------ Bra [^\x{ff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}abc(xyz(?1))/8DZ ------------------------------------------------------------------ Bra \x{100}abc CBra 1 xyz Recurse Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf First char = \x{c4} Need char = 'z' /a\x{1234}b/P8 a\x{1234}b 0: a\x{1234}b /\777/8I Capturing subpattern count = 0 Options: utf First char = \x{c7} Need char = \x{bf} \x{1ff} 0: \x{1ff} \777 0: \x{1ff} /\x{100}+\x{200}/8DZ ------------------------------------------------------------------ Bra \x{100}++ \x{200} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = \x{80} /\x{100}+X/8DZ ------------------------------------------------------------------ Bra \x{100}++ X Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c4} Need char = 'X' /^[\QĀ\E-\QŐ\E/BZ8 Failed: missing terminating ] for character class at offset 15 /-- This tests the stricter UTF-8 check according to RFC 3629. --/ /X/8 \x{d800} Error -10 (bad UTF-8 string) offset=0 reason=14 \x{d800}\? No match \x{da00} Error -10 (bad UTF-8 string) offset=0 reason=14 \x{da00}\? No match \x{dfff} Error -10 (bad UTF-8 string) offset=0 reason=14 \x{dfff}\? No match \x{110000} Error -10 (bad UTF-8 string) offset=0 reason=13 \x{110000}\? No match \x{2000000} Error -10 (bad UTF-8 string) offset=0 reason=11 \x{2000000}\? No match \x{7fffffff} Error -10 (bad UTF-8 string) offset=0 reason=12 \x{7fffffff}\? No match /(*UTF8)\x{1234}/ abcd\x{1234}pqr 0: \x{1234} /(*CRLF)(*UTF)(*BSR_UNICODE)a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode utf Forced newline sequence: CRLF First char = 'a' Need char = 'b' /\h/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x20 \xc2 \xe1 \xe2 \xe3 ABC\x{09} 0: \x{09} ABC\x{20} 0: ABC\x{a0} 0: \x{a0} ABC\x{1680} 0: \x{1680} ABC\x{180e} 0: \x{180e} ABC\x{2000} 0: \x{2000} ABC\x{202f} 0: \x{202f} ABC\x{205f} 0: \x{205f} ABC\x{3000} 0: \x{3000} /\v/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \xc2 \xe2 ABC\x{0a} 0: \x{0a} ABC\x{0b} 0: \x{0b} ABC\x{0c} 0: \x{0c} ABC\x{0d} 0: \x{0d} ABC\x{85} 0: \x{85} ABC\x{2028} 0: \x{2028} /\h*A/SI8 Capturing subpattern count = 0 Options: utf No first char Need char = 'A' Subject length lower bound = 1 Starting chars: \x09 \x20 A \xc2 \xe1 \xe2 \xe3 CDBABC 0: A /\v+A/SI8 Capturing subpattern count = 0 Options: utf No first char Need char = 'A' Subject length lower bound = 2 Starting chars: \x0a \x0b \x0c \x0d \xc2 \xe2 /\s?xxx\s/8SI Capturing subpattern count = 0 Options: utf No first char Need char = 'x' Subject length lower bound = 4 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 x /\sxxx\s/I8ST1 Capturing subpattern count = 0 Options: utf No first char Need char = 'x' Subject length lower bound = 5 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 \xc2 AB\x{85}xxx\x{a0}XYZ 0: \x{85}xxx\x{a0} AB\x{a0}xxx\x{85}XYZ 0: \x{a0}xxx\x{85} /\S \S/I8ST1 Capturing subpattern count = 0 Options: utf No first char Need char = ' ' Subject length lower bound = 3 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff \x{a2} \x{84} 0: \x{a2} \x{84} A Z 0: A Z /a+/8 a\x{123}aa\>1 0: aa a\x{123}aa\>2 Error -11 (bad UTF-8 offset) a\x{123}aa\>3 0: aa a\x{123}aa\>4 0: a a\x{123}aa\>5 No match a\x{123}aa\>6 Error -24 (bad offset value) /\x{1234}+/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: \xe1 /\x{1234}+?/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: \xe1 /\x{1234}++/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: \xe1 /\x{1234}{2}/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 2 Starting chars: \xe1 /[^\x{c4}]/8DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /X+\x{200}/8DZ ------------------------------------------------------------------ Bra X++ \x{200} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'X' Need char = \x{80} /\R/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \xc2 \xe2 /\777/8DZ ------------------------------------------------------------------ Bra \x{1ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{c7} Need char = \x{bf} /\w+\x{C4}/8BZ ------------------------------------------------------------------ Bra \w++ \x{c4} Ket End ------------------------------------------------------------------ a\x{C4}\x{C4} 0: a\x{c4} /\w+\x{C4}/8BZT1 ------------------------------------------------------------------ Bra \w+ \x{c4} Ket End ------------------------------------------------------------------ a\x{C4}\x{C4} 0: a\x{c4}\x{c4} /\W+\x{C4}/8BZ ------------------------------------------------------------------ Bra \W+ \x{c4} Ket End ------------------------------------------------------------------ !\x{C4} 0: !\x{c4} /\W+\x{C4}/8BZT1 ------------------------------------------------------------------ Bra \W++ \x{c4} Ket End ------------------------------------------------------------------ !\x{C4} 0: !\x{c4} /\W+\x{A1}/8BZ ------------------------------------------------------------------ Bra \W+ \x{a1} Ket End ------------------------------------------------------------------ !\x{A1} 0: !\x{a1} /\W+\x{A1}/8BZT1 ------------------------------------------------------------------ Bra \W+ \x{a1} Ket End ------------------------------------------------------------------ !\x{A1} 0: !\x{a1} /X\s+\x{A0}/8BZ ------------------------------------------------------------------ Bra X \s++ \x{a0} Ket End ------------------------------------------------------------------ X\x20\x{A0}\x{A0} 0: X \x{a0} /X\s+\x{A0}/8BZT1 ------------------------------------------------------------------ Bra X \s+ \x{a0} Ket End ------------------------------------------------------------------ X\x20\x{A0}\x{A0} 0: X \x{a0}\x{a0} /\S+\x{A0}/8BZ ------------------------------------------------------------------ Bra \S+ \x{a0} Ket End ------------------------------------------------------------------ X\x{A0}\x{A0} 0: X\x{a0}\x{a0} /\S+\x{A0}/8BZT1 ------------------------------------------------------------------ Bra \S++ \x{a0} Ket End ------------------------------------------------------------------ X\x{A0}\x{A0} 0: X\x{a0} /\x{a0}+\s!/8BZ ------------------------------------------------------------------ Bra \x{a0}++ \s ! Ket End ------------------------------------------------------------------ \x{a0}\x20! 0: \x{a0} ! /\x{a0}+\s!/8BZT1 ------------------------------------------------------------------ Bra \x{a0}+ \s ! Ket End ------------------------------------------------------------------ \x{a0}\x20! 0: \x{a0} ! /A/8 \x{ff000041} ** Character \x{ff000041} is greater than 0x7fffffff and so cannot be converted to UTF-8 \x{7f000041} Error -10 (bad UTF-8 string) offset=0 reason=12 /(*UTF8)abc/9 Failed: setting UTF is disabled by the application at offset 0 /abc/89 Failed: setting UTF is disabled by the application at offset 0 //8+L \xf1\xad\xae\xae 0: 0+ \x{6dbae} /-- End of testinput15 --/ ================================================ FILE: src/pcre/testdata/testoutput16 ================================================ /-- This set of tests is run only with the 8-bit library when Unicode property support is available. It starts with tests of the POSIX interface, because that is supported only with the 8-bit library. --/ /\w/P +++\x{c2} No match: POSIX code 17: match failed /\w/WP +++\x{c2} 0: \xc2 /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iDZ ------------------------------------------------------------------ Bra /i A\x{391}\x{10427}\x{ff3a}\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf First char = 'A' (caseless) No need char /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8DZ ------------------------------------------------------------------ Bra A\x{391}\x{10427}\x{ff3a}\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = \x{b0} /AB\x{1fb0}/8DZ ------------------------------------------------------------------ Bra AB\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = \x{b0} /AB\x{1fb0}/8DZi ------------------------------------------------------------------ Bra /i AB\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf First char = 'A' (caseless) Need char = 'B' (caseless) /\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/8iSI Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 17 Starting chars: \xd0 \xd1 \x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f} 0: \x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f} \x{451}\x{440}\x{441}\x{442}\x{443}\x{444}\x{445}\x{446}\x{447}\x{448}\x{449}\x{44a}\x{44b}\x{44c}\x{44d}\x{44e}\x{44f} 0: \x{451}\x{440}\x{441}\x{442}\x{443}\x{444}\x{445}\x{446}\x{447}\x{448}\x{449}\x{44a}\x{44b}\x{44c}\x{44d}\x{44e}\x{44f} /[ⱥ]/8iBZ ------------------------------------------------------------------ Bra /i \x{2c65} Ket End ------------------------------------------------------------------ /[^ⱥ]/8iBZ ------------------------------------------------------------------ Bra /i [^\x{2c65}] Ket End ------------------------------------------------------------------ /\h/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x20 \xa0 /\v/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 /\R/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 /[[:blank:]]/WBZ ------------------------------------------------------------------ Bra [\x09 \xa0] Ket End ------------------------------------------------------------------ /\x{212a}+/i8SI Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: K k \xe2 KKkk\x{212a} 0: KKkk\x{212a} /s+/i8SI Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: S s \xc5 SSss\x{17f} 0: SSss\x{17f} /[\W\p{Any}]/BZ ------------------------------------------------------------------ Bra [\x00-/:-@[-^`{-\xff\p{Any}] Ket End ------------------------------------------------------------------ abc 0: a 123 0: 1 /[\W\pL]/BZ ------------------------------------------------------------------ Bra [\x00-/:-@[-^`{-\xff\p{L}] Ket End ------------------------------------------------------------------ abc 0: a ** Failers 0: * 123 No match /[\D]/8 \x{1d7cf} 0: \x{1d7cf} /[\D\P{Nd}]/8 \x{1d7cf} 0: \x{1d7cf} /[^\D]/8 a9b 0: 9 ** Failers No match \x{1d7cf} No match /[^\D\P{Nd}]/8 a9b 0: 9 \x{1d7cf} 0: \x{1d7cf} ** Failers No match \x{10000} No match /-- End of testinput16 --/ ================================================ FILE: src/pcre/testdata/testoutput17 ================================================ /-- This set of tests is for the 16- and 32-bit library's basic (non-UTF-16 or -32) features that are not compatible with the 8-bit library, or which give different output in 16- or 32-bit mode. --/ < forbid 8W /a\Cb/ aXb 0: aXb a\nb 0: a\x0ab /[^\x{c4}]/DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /\x{100}/I Capturing subpattern count = 0 No options First char = \x{100} No need char / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /xSI Capturing subpattern count = 0 Contains explicit CR or LF match Options: extended No first char No need char Subject length lower bound = 3 Starting chars: \x09 \x20 ! " # $ % & ' ( * + - / 0 1 2 3 4 5 6 7 8 9 = ? A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \xff /[\h]/BZ ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}] Ket End ------------------------------------------------------------------ >\x09< 0: \x09 /[\h]+/BZ ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}]++ Ket End ------------------------------------------------------------------ >\x09\x20\xa0< 0: \x09 \xa0 /[\v]/BZ ------------------------------------------------------------------ Bra [\x0a-\x0d\x85\x{2028}-\x{2029}] Ket End ------------------------------------------------------------------ /[^\h]/BZ ------------------------------------------------------------------ Bra [^\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}] Ket End ------------------------------------------------------------------ /\h+/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x20 \xa0 \xff \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} 0: \x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\xa0\x{2000} 0: \x{200a}\xa0\x{2000} /[\h\x{dc00}]+/BZSI ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}\x{dc00}]++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x20 \xa0 \xff \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} 0: \x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\xa0\x{2000} 0: \x{200a}\xa0\x{2000} /\H+/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 No starting char list \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} 0: \x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} 0: \x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} 0: \x{202e}\x{2030}\x{205e}\x{2060} \xa0\x{3000}\x9f\xa1\x{2fff}\x{3001} 0: \x9f\xa1\x{2fff}\x{3001} /[\H\x{d800}]+/ \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} 0: \x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} 0: \x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} 0: \x{202e}\x{2030}\x{205e}\x{2060} \xa0\x{3000}\x9f\xa1\x{2fff}\x{3001} 0: \x9f\xa1\x{2fff}\x{3001} /\v+/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff \x{2027}\x{2030}\x{2028}\x{2029} 0: \x{2028}\x{2029} \x09\x0e\x84\x86\x85\x0a\x0b\x0c\x0d 0: \x85\x0a\x0b\x0c\x0d /[\v\x{dc00}]+/BZSI ------------------------------------------------------------------ Bra [\x0a-\x0d\x85\x{2028}-\x{2029}\x{dc00}]++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff \x{2027}\x{2030}\x{2028}\x{2029} 0: \x{2028}\x{2029} \x09\x0e\x84\x86\x85\x0a\x0b\x0c\x0d 0: \x85\x0a\x0b\x0c\x0d /\V+/SI Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 No starting char list \x{2028}\x{2029}\x{2027}\x{2030} 0: \x{2027}\x{2030} \x85\x0a\x0b\x0c\x0d\x09\x0e\x84\x86 0: \x09\x0e\x84\x86 /[\V\x{d800}]+/ \x{2028}\x{2029}\x{2027}\x{2030} 0: \x{2027}\x{2030} \x85\x0a\x0b\x0c\x0d\x09\x0e\x84\x86 0: \x09\x0e\x84\x86 /\R+/SI Capturing subpattern count = 0 Options: bsr_unicode No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff \x{2027}\x{2030}\x{2028}\x{2029} 0: \x{2028}\x{2029} \x09\x0e\x84\x86\x85\x0a\x0b\x0c\x0d 0: \x85\x0a\x0b\x0c\x0d /\x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00}/I Capturing subpattern count = 0 No options First char = \x{d800} Need char = \x{dd00} \x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00} 0: \x{d800}\x{d7ff}\x{dc00}\x{dc00}\x{dcff}\x{dd00} /[^\x{80}][^\x{ff}][^\x{100}][^\x{1000}][^\x{ffff}]/BZ ------------------------------------------------------------------ Bra [^\x80] [^\x{ff}] [^\x{100}] [^\x{1000}] [^\x{ffff}] Ket End ------------------------------------------------------------------ /[^\x{80}][^\x{ff}][^\x{100}][^\x{1000}][^\x{ffff}]/BZi ------------------------------------------------------------------ Bra /i [^\x80] /i [^\x{ff}] /i [^\x{100}] /i [^\x{1000}] /i [^\x{ffff}] Ket End ------------------------------------------------------------------ /[^\x{100}]*[^\x{1000}]+[^\x{ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{100}]{5,6}+/BZ ------------------------------------------------------------------ Bra [^\x{100}]* [^\x{1000}]+ [^\x{ffff}]?? [^\x{8000}]{4} [^\x{8000}]* [^\x{7fff}]{2} [^\x{7fff}]{0,7}? [^\x{100}]{5} [^\x{100}]?+ Ket End ------------------------------------------------------------------ /[^\x{100}]*[^\x{1000}]+[^\x{ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{100}]{5,6}+/BZi ------------------------------------------------------------------ Bra /i [^\x{100}]* /i [^\x{1000}]+ /i [^\x{ffff}]?? /i [^\x{8000}]{4} /i [^\x{8000}]* /i [^\x{7fff}]{2} /i [^\x{7fff}]{0,7}? /i [^\x{100}]{5} /i [^\x{100}]?+ Ket End ------------------------------------------------------------------ /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF)XX/K XX 0: XX MK: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF /(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE)XX/K XX 0: XX MK: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE /\u0100/BZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ /[\u0100-\u0200]/BZ ------------------------------------------------------------------ Bra [\x{100}-\x{200}] Ket End ------------------------------------------------------------------ /\ud800/BZ ------------------------------------------------------------------ Bra \x{d800} Ket End ------------------------------------------------------------------ /^\x{ffff}+/i \x{ffff} 0: \x{ffff} /^\x{ffff}?/i \x{ffff} 0: \x{ffff} /^\x{ffff}*/i \x{ffff} 0: \x{ffff} /^\x{ffff}{3}/i \x{ffff}\x{ffff}\x{ffff} 0: \x{ffff}\x{ffff}\x{ffff} /^\x{ffff}{0,3}/i \x{ffff} 0: \x{ffff} /[^\x00-a]{12,}[^b-\xff]*/BZ ------------------------------------------------------------------ Bra [b-\xff] (neg){12,} [\x00-a] (neg)*+ Ket End ------------------------------------------------------------------ /[^\s]*\s* [^\W]+\W+ [^\d]*?\d0 [^\d\w]{4,6}?\w*A/BZ ------------------------------------------------------------------ Bra [\x00-\x08\x0e-\x1f!-\xff] (neg)* \s* [0-9A-Z_a-z]++ \W+ [\x00-/:-\xff] (neg)*? \d 0 [\x00-/:-@[-^`{-\xff] (neg){4,6}? \w* A Ket End ------------------------------------------------------------------ /a*[b-\x{200}]?a#a*[b-\x{200}]?b#[a-f]*[g-\x{200}]*#[g-\x{200}]*[a-c]*#[g-\x{200}]*[a-h]*/BZ ------------------------------------------------------------------ Bra a* [b-\xff\x{100}-\x{200}]?+ a# a*+ [b-\xff\x{100}-\x{200}]? b# [a-f]*+ [g-\xff\x{100}-\x{200}]*+ # [g-\xff\x{100}-\x{200}]*+ [a-c]*+ # [g-\xff\x{100}-\x{200}]* [a-h]*+ Ket End ------------------------------------------------------------------ /^[\x{1234}\x{4321}]{2,4}?/ \x{1234}\x{1234}\x{1234} 0: \x{1234}\x{1234} /(*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)/ /-- End of testinput17 --/ ================================================ FILE: src/pcre/testdata/testoutput18-16 ================================================ /-- This set of tests is for UTF-16 and UTF-32 support, and is relevant only to the 16- and 32-bit libraries. --/ < forbid W /xxx/8?DZSS **Failed: invalid UTF-8 string cannot be converted to UTF-16 /abc/8 ] **Failed: invalid UTF-8 string cannot be used as input in UTF mode /X(\C{3})/8 X\x{11234}Y 0: X\x{11234}Y 1: \x{11234}Y X\x{11234}YZ 0: X\x{11234}Y 1: \x{11234}Y /X(\C{4})/8 X\x{11234}YZ 0: X\x{11234}YZ 1: \x{11234}YZ X\x{11234}YZW 0: X\x{11234}YZ 1: \x{11234}YZ /X\C*/8 XYZabcdce 0: XYZabcdce /X\C*?/8 XYZabcde 0: X /X\C{3,5}/8 Xabcdefg 0: Xabcde X\x{11234}Y 0: X\x{11234}Y X\x{11234}YZ 0: X\x{11234}YZ X\x{11234}\x{512} 0: X\x{11234}\x{512} X\x{11234}\x{512}YZ 0: X\x{11234}\x{512}YZ X\x{11234}\x{512}\x{11234}Z 0: X\x{11234}\x{512}\x{11234} /X\C{3,5}?/8 Xabcdefg 0: Xabc X\x{11234}Y 0: X\x{11234}Y X\x{11234}YZ 0: X\x{11234}Y X\x{11234}\x{512}YZ 0: X\x{11234}\x{512} *** Failers No match X\x{11234} No match /a\Cb/8 aXb 0: aXb a\nb 0: a\x{0a}b /a\C\Cb/8 a\x{12257}b 0: a\x{12257}b a\x{12257}\x{11234}b No match ** Failers No match a\x{100}b No match /ab\Cde/8 abXde 0: abXde /-- Check maximum character size --/ /\x{ffff}/8DZ ------------------------------------------------------------------ Bra \x{ffff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ffff} No need char /\x{10000}/8DZ ------------------------------------------------------------------ Bra \x{10000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d800} Need char = \x{dc00} /\x{100}/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char /\x{1000}/8DZ ------------------------------------------------------------------ Bra \x{1000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{1000} No need char /\x{10000}/8DZ ------------------------------------------------------------------ Bra \x{10000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d800} Need char = \x{dc00} /\x{100000}/8DZ ------------------------------------------------------------------ Bra \x{100000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{dbc0} Need char = \x{dc00} /\x{10ffff}/8DZ ------------------------------------------------------------------ Bra \x{10ffff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{dbff} Need char = \x{dfff} /[\x{ff}]/8DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ff} No need char /[\x{100}]/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char /\x80/8DZ ------------------------------------------------------------------ Bra \x80 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{80} No need char /\xff/8DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ff} No need char /\x{D55c}\x{ad6d}\x{C5B4}/DZ8 ------------------------------------------------------------------ Bra \x{d55c}\x{ad6d}\x{c5b4} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d55c} Need char = \x{c5b4} \x{D55c}\x{ad6d}\x{C5B4} 0: \x{d55c}\x{ad6d}\x{c5b4} /\x{65e5}\x{672c}\x{8a9e}/DZ8 ------------------------------------------------------------------ Bra \x{65e5}\x{672c}\x{8a9e} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{65e5} Need char = \x{8a9e} \x{65e5}\x{672c}\x{8a9e} 0: \x{65e5}\x{672c}\x{8a9e} /\x{80}/DZ8 ------------------------------------------------------------------ Bra \x80 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{80} No need char /\x{084}/DZ8 ------------------------------------------------------------------ Bra \x{84} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{84} No need char /\x{104}/DZ8 ------------------------------------------------------------------ Bra \x{104} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{104} No need char /\x{861}/DZ8 ------------------------------------------------------------------ Bra \x{861} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{861} No need char /\x{212ab}/DZ8 ------------------------------------------------------------------ Bra \x{212ab} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d844} Need char = \x{deab} /-- This one is here not because it's different to Perl, but because the way the captured single-byte is displayed. (In Perl it becomes a character, and you can't tell the difference.) --/ /X(\C)(.*)/8 X\x{1234} 0: X\x{1234} 1: \x{1234} 2: X\nabc 0: X\x{0a}abc 1: \x{0a} 2: abc /-- This one is here because Perl gives out a grumbly error message (quite correctly, but that messes up comparisons). --/ /a\Cb/8 *** Failers No match a\x{100}b 0: a\x{100}b /[^ab\xC0-\xF0]/8SDZ ------------------------------------------------------------------ Bra [\x00-`c-\xbf\xf1-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff \x{f1} 0: \x{f1} \x{bf} 0: \x{bf} \x{100} 0: \x{100} \x{1000} 0: \x{1000} *** Failers 0: * \x{c0} No match \x{f0} No match /Ā{3,4}/8SDZ ------------------------------------------------------------------ Bra \x{100}{3} \x{100}?+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} Need char = \x{100} Subject length lower bound = 3 No starting char list \x{100}\x{100}\x{100}\x{100\x{100} 0: \x{100}\x{100}\x{100} /(\x{100}+|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}++ Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: x \xff /(\x{100}*a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}*+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: a x \xff /(\x{100}{0,2}a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}{0,2}+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: a x \xff /(\x{100}{1,2}a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100} \x{100}{0,1}+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: x \xff /\x{100}/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char /a\x{100}\x{101}*/8DZ ------------------------------------------------------------------ Bra a\x{100} \x{101}*+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = \x{100} /a\x{100}\x{101}+/8DZ ------------------------------------------------------------------ Bra a\x{100} \x{101}++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = \x{101} /[^\x{c4}]/DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\x{100}]/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char \x{100} 0: \x{100} Z\x{100} 0: \x{100} \x{100}Z 0: \x{100} *** Failers No match /[\xff]/DZ8 ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ff} No need char >\x{ff}< 0: \x{ff} /[^\xff]/8DZ ------------------------------------------------------------------ Bra [^\x{ff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}abc(xyz(?1))/8DZ ------------------------------------------------------------------ Bra \x{100}abc CBra 1 xyz Recurse Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf First char = \x{100} Need char = 'z' /\777/8I Capturing subpattern count = 0 Options: utf First char = \x{1ff} No need char \x{1ff} 0: \x{1ff} \777 0: \x{1ff} /\x{100}+\x{200}/8DZ ------------------------------------------------------------------ Bra \x{100}++ \x{200} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} Need char = \x{200} /\x{100}+X/8DZ ------------------------------------------------------------------ Bra \x{100}++ X Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} Need char = 'X' /^[\QĀ\E-\QŐ\E/BZ8 Failed: missing terminating ] for character class at offset 13 /X/8 \x{d800} Error -10 (bad UTF-16 string) offset=0 reason=1 \x{d800}\? No match \x{da00} Error -10 (bad UTF-16 string) offset=0 reason=1 \x{da00}\? No match \x{dc00} Error -10 (bad UTF-16 string) offset=0 reason=3 \x{dc00}\? No match \x{de00} Error -10 (bad UTF-16 string) offset=0 reason=3 \x{de00}\? No match \x{dfff} Error -10 (bad UTF-16 string) offset=0 reason=3 \x{dfff}\? No match \x{110000} ** Failed: character \x{110000} is greater than 0x10ffff and so cannot be converted to UTF-16 \x{d800}\x{1234} Error -10 (bad UTF-16 string) offset=1 reason=2 /(*UTF16)\x{11234}/ abcd\x{11234}pqr 0: \x{11234} /(*UTF)\x{11234}/I Capturing subpattern count = 0 Options: utf First char = \x{d804} Need char = \x{de34} abcd\x{11234}pqr 0: \x{11234} /(*UTF-32)\x{11234}/ Failed: (*VERB) not recognized or malformed at offset 5 /(*CRLF)(*UTF16)(*BSR_UNICODE)a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode utf Forced newline sequence: CRLF First char = 'a' Need char = 'b' /(*CRLF)(*UTF32)(*BSR_UNICODE)a\Rb/I Failed: (*VERB) not recognized or malformed at offset 12 /\h/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x20 \xa0 \xff ABC\x{09} 0: \x{09} ABC\x{20} 0: ABC\x{a0} 0: \x{a0} ABC\x{1680} 0: \x{1680} ABC\x{180e} 0: \x{180e} ABC\x{2000} 0: \x{2000} ABC\x{202f} 0: \x{202f} ABC\x{205f} 0: \x{205f} ABC\x{3000} 0: \x{3000} /\v/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff ABC\x{0a} 0: \x{0a} ABC\x{0b} 0: \x{0b} ABC\x{0c} 0: \x{0c} ABC\x{0d} 0: \x{0d} ABC\x{85} 0: \x{85} ABC\x{2028} 0: \x{2028} /\h*A/SI8 Capturing subpattern count = 0 Options: utf No first char Need char = 'A' Subject length lower bound = 1 Starting chars: \x09 \x20 A \xa0 \xff CDBABC 0: A \x{2000}ABC 0: \x{2000}A /\R*A/SI8 Capturing subpattern count = 0 Options: bsr_unicode utf No first char Need char = 'A' Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d A \x85 \xff CDBABC 0: A \x{2028}A 0: \x{2028}A /\v+A/SI8 Capturing subpattern count = 0 Options: utf No first char Need char = 'A' Subject length lower bound = 2 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff /\s?xxx\s/8SI Capturing subpattern count = 0 Options: utf No first char Need char = 'x' Subject length lower bound = 4 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 x /\sxxx\s/I8ST1 Capturing subpattern count = 0 Options: utf No first char Need char = 'x' Subject length lower bound = 5 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 \x85 \xa0 AB\x{85}xxx\x{a0}XYZ 0: \x{85}xxx\x{a0} AB\x{a0}xxx\x{85}XYZ 0: \x{a0}xxx\x{85} /\S \S/I8ST1 Capturing subpattern count = 0 Options: utf No first char Need char = ' ' Subject length lower bound = 3 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff \x{a2} \x{84} 0: \x{a2} \x{84} A Z 0: A Z /a+/8 a\x{123}aa\>1 0: aa a\x{123}aa\>2 0: aa a\x{123}aa\>3 0: a a\x{123}aa\>4 No match a\x{123}aa\>5 Error -24 (bad offset value) a\x{123}aa\>6 Error -24 (bad offset value) /\x{1234}+/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} No need char Subject length lower bound = 1 No starting char list /\x{1234}+?/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} No need char Subject length lower bound = 1 No starting char list /\x{1234}++/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} No need char Subject length lower bound = 1 No starting char list /\x{1234}{2}/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} Need char = \x{1234} Subject length lower bound = 2 No starting char list /[^\x{c4}]/8DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /X+\x{200}/8DZ ------------------------------------------------------------------ Bra X++ \x{200} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'X' Need char = \x{200} /\R/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff /-- Check bad offset --/ /a/8 \x{10000}\>1 Error -11 (bad UTF-16 offset) \x{10000}ab\>1 Error -11 (bad UTF-16 offset) \x{10000}ab\>2 0: a \x{10000}ab\>3 No match \x{10000}ab\>4 No match \x{10000}ab\>5 Error -24 (bad offset value) //8 Failed: invalid UTF-16 string at offset 0 /\w+\x{C4}/8BZ ------------------------------------------------------------------ Bra \w++ \x{c4} Ket End ------------------------------------------------------------------ a\x{C4}\x{C4} 0: a\x{c4} /\w+\x{C4}/8BZT1 ------------------------------------------------------------------ Bra \w+ \x{c4} Ket End ------------------------------------------------------------------ a\x{C4}\x{C4} 0: a\x{c4}\x{c4} /\W+\x{C4}/8BZ ------------------------------------------------------------------ Bra \W+ \x{c4} Ket End ------------------------------------------------------------------ !\x{C4} 0: !\x{c4} /\W+\x{C4}/8BZT1 ------------------------------------------------------------------ Bra \W++ \x{c4} Ket End ------------------------------------------------------------------ !\x{C4} 0: !\x{c4} /\W+\x{A1}/8BZ ------------------------------------------------------------------ Bra \W+ \x{a1} Ket End ------------------------------------------------------------------ !\x{A1} 0: !\x{a1} /\W+\x{A1}/8BZT1 ------------------------------------------------------------------ Bra \W+ \x{a1} Ket End ------------------------------------------------------------------ !\x{A1} 0: !\x{a1} /X\s+\x{A0}/8BZ ------------------------------------------------------------------ Bra X \s++ \x{a0} Ket End ------------------------------------------------------------------ X\x20\x{A0}\x{A0} 0: X \x{a0} /X\s+\x{A0}/8BZT1 ------------------------------------------------------------------ Bra X \s+ \x{a0} Ket End ------------------------------------------------------------------ X\x20\x{A0}\x{A0} 0: X \x{a0}\x{a0} /\S+\x{A0}/8BZ ------------------------------------------------------------------ Bra \S+ \x{a0} Ket End ------------------------------------------------------------------ X\x{A0}\x{A0} 0: X\x{a0}\x{a0} /\S+\x{A0}/8BZT1 ------------------------------------------------------------------ Bra \S++ \x{a0} Ket End ------------------------------------------------------------------ X\x{A0}\x{A0} 0: X\x{a0} /\x{a0}+\s!/8BZ ------------------------------------------------------------------ Bra \x{a0}++ \s ! Ket End ------------------------------------------------------------------ \x{a0}\x20! 0: \x{a0} ! /\x{a0}+\s!/8BZT1 ------------------------------------------------------------------ Bra \x{a0}+ \s ! Ket End ------------------------------------------------------------------ \x{a0}\x20! 0: \x{a0} ! /(*UTF)abc/9 Failed: setting UTF is disabled by the application at offset 0 /abc/89 Failed: setting UTF is disabled by the application at offset 0 /-- End of testinput18 --/ ================================================ FILE: src/pcre/testdata/testoutput18-32 ================================================ /-- This set of tests is for UTF-16 and UTF-32 support, and is relevant only to the 16- and 32-bit libraries. --/ < forbid W /xxx/8?DZSS **Failed: invalid UTF-8 string cannot be converted to UTF-32 /abc/8 ] **Failed: invalid UTF-8 string cannot be used as input in UTF mode /X(\C{3})/8 X\x{11234}Y No match X\x{11234}YZ 0: X\x{11234}YZ 1: \x{11234}YZ /X(\C{4})/8 X\x{11234}YZ No match X\x{11234}YZW 0: X\x{11234}YZW 1: \x{11234}YZW /X\C*/8 XYZabcdce 0: XYZabcdce /X\C*?/8 XYZabcde 0: X /X\C{3,5}/8 Xabcdefg 0: Xabcde X\x{11234}Y No match X\x{11234}YZ 0: X\x{11234}YZ X\x{11234}\x{512} No match X\x{11234}\x{512}YZ 0: X\x{11234}\x{512}YZ X\x{11234}\x{512}\x{11234}Z 0: X\x{11234}\x{512}\x{11234}Z /X\C{3,5}?/8 Xabcdefg 0: Xabc X\x{11234}Y No match X\x{11234}YZ 0: X\x{11234}YZ X\x{11234}\x{512}YZ 0: X\x{11234}\x{512}Y *** Failers No match X\x{11234} No match /a\Cb/8 aXb 0: aXb a\nb 0: a\x{0a}b /a\C\Cb/8 a\x{12257}b No match a\x{12257}\x{11234}b 0: a\x{12257}\x{11234}b ** Failers No match a\x{100}b No match /ab\Cde/8 abXde 0: abXde /-- Check maximum character size --/ /\x{ffff}/8DZ ------------------------------------------------------------------ Bra \x{ffff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ffff} No need char /\x{10000}/8DZ ------------------------------------------------------------------ Bra \x{10000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{10000} No need char /\x{100}/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char /\x{1000}/8DZ ------------------------------------------------------------------ Bra \x{1000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{1000} No need char /\x{10000}/8DZ ------------------------------------------------------------------ Bra \x{10000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{10000} No need char /\x{100000}/8DZ ------------------------------------------------------------------ Bra \x{100000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100000} No need char /\x{10ffff}/8DZ ------------------------------------------------------------------ Bra \x{10ffff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{10ffff} No need char /[\x{ff}]/8DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ff} No need char /[\x{100}]/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char /\x80/8DZ ------------------------------------------------------------------ Bra \x80 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{80} No need char /\xff/8DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ff} No need char /\x{D55c}\x{ad6d}\x{C5B4}/DZ8 ------------------------------------------------------------------ Bra \x{d55c}\x{ad6d}\x{c5b4} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{d55c} Need char = \x{c5b4} \x{D55c}\x{ad6d}\x{C5B4} 0: \x{d55c}\x{ad6d}\x{c5b4} /\x{65e5}\x{672c}\x{8a9e}/DZ8 ------------------------------------------------------------------ Bra \x{65e5}\x{672c}\x{8a9e} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{65e5} Need char = \x{8a9e} \x{65e5}\x{672c}\x{8a9e} 0: \x{65e5}\x{672c}\x{8a9e} /\x{80}/DZ8 ------------------------------------------------------------------ Bra \x80 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{80} No need char /\x{084}/DZ8 ------------------------------------------------------------------ Bra \x{84} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{84} No need char /\x{104}/DZ8 ------------------------------------------------------------------ Bra \x{104} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{104} No need char /\x{861}/DZ8 ------------------------------------------------------------------ Bra \x{861} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{861} No need char /\x{212ab}/DZ8 ------------------------------------------------------------------ Bra \x{212ab} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{212ab} No need char /-- This one is here not because it's different to Perl, but because the way the captured single-byte is displayed. (In Perl it becomes a character, and you can't tell the difference.) --/ /X(\C)(.*)/8 X\x{1234} 0: X\x{1234} 1: \x{1234} 2: X\nabc 0: X\x{0a}abc 1: \x{0a} 2: abc /-- This one is here because Perl gives out a grumbly error message (quite correctly, but that messes up comparisons). --/ /a\Cb/8 *** Failers No match a\x{100}b 0: a\x{100}b /[^ab\xC0-\xF0]/8SDZ ------------------------------------------------------------------ Bra [\x00-`c-\xbf\xf1-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff \x{f1} 0: \x{f1} \x{bf} 0: \x{bf} \x{100} 0: \x{100} \x{1000} 0: \x{1000} *** Failers 0: * \x{c0} No match \x{f0} No match /Ā{3,4}/8SDZ ------------------------------------------------------------------ Bra \x{100}{3} \x{100}?+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} Need char = \x{100} Subject length lower bound = 3 No starting char list \x{100}\x{100}\x{100}\x{100\x{100} 0: \x{100}\x{100}\x{100} /(\x{100}+|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}++ Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: x \xff /(\x{100}*a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}*+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: a x \xff /(\x{100}{0,2}a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100}{0,2}+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: a x \xff /(\x{100}{1,2}a|x)/8SDZ ------------------------------------------------------------------ Bra CBra 1 \x{100} \x{100}{0,1}+ a Alt x Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: x \xff /\x{100}/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char /a\x{100}\x{101}*/8DZ ------------------------------------------------------------------ Bra a\x{100} \x{101}*+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = \x{100} /a\x{100}\x{101}+/8DZ ------------------------------------------------------------------ Bra a\x{100} \x{101}++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = \x{101} /[^\x{c4}]/DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\x{100}]/8DZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} No need char \x{100} 0: \x{100} Z\x{100} 0: \x{100} \x{100}Z 0: \x{100} *** Failers No match /[\xff]/DZ8 ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{ff} No need char >\x{ff}< 0: \x{ff} /[^\xff]/8DZ ------------------------------------------------------------------ Bra [^\x{ff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}abc(xyz(?1))/8DZ ------------------------------------------------------------------ Bra \x{100}abc CBra 1 xyz Recurse Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf First char = \x{100} Need char = 'z' /\777/8I Capturing subpattern count = 0 Options: utf First char = \x{1ff} No need char \x{1ff} 0: \x{1ff} \777 0: \x{1ff} /\x{100}+\x{200}/8DZ ------------------------------------------------------------------ Bra \x{100}++ \x{200} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} Need char = \x{200} /\x{100}+X/8DZ ------------------------------------------------------------------ Bra \x{100}++ X Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = \x{100} Need char = 'X' /^[\QĀ\E-\QŐ\E/BZ8 Failed: missing terminating ] for character class at offset 13 /X/8 \x{d800} Error -10 (bad UTF-32 string) offset=0 reason=1 \x{d800}\? No match \x{da00} Error -10 (bad UTF-32 string) offset=0 reason=1 \x{da00}\? No match \x{dc00} Error -10 (bad UTF-32 string) offset=0 reason=1 \x{dc00}\? No match \x{de00} Error -10 (bad UTF-32 string) offset=0 reason=1 \x{de00}\? No match \x{dfff} Error -10 (bad UTF-32 string) offset=0 reason=1 \x{dfff}\? No match \x{110000} Error -10 (bad UTF-32 string) offset=0 reason=3 \x{d800}\x{1234} Error -10 (bad UTF-32 string) offset=0 reason=1 /(*UTF16)\x{11234}/ Failed: (*VERB) not recognized or malformed at offset 5 /(*UTF)\x{11234}/I Capturing subpattern count = 0 Options: utf First char = \x{11234} No need char abcd\x{11234}pqr 0: \x{11234} /(*UTF-32)\x{11234}/ Failed: (*VERB) not recognized or malformed at offset 5 /(*CRLF)(*UTF16)(*BSR_UNICODE)a\Rb/I Failed: (*VERB) not recognized or malformed at offset 12 /(*CRLF)(*UTF32)(*BSR_UNICODE)a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode utf Forced newline sequence: CRLF First char = 'a' Need char = 'b' /\h/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x20 \xa0 \xff ABC\x{09} 0: \x{09} ABC\x{20} 0: ABC\x{a0} 0: \x{a0} ABC\x{1680} 0: \x{1680} ABC\x{180e} 0: \x{180e} ABC\x{2000} 0: \x{2000} ABC\x{202f} 0: \x{202f} ABC\x{205f} 0: \x{205f} ABC\x{3000} 0: \x{3000} /\v/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff ABC\x{0a} 0: \x{0a} ABC\x{0b} 0: \x{0b} ABC\x{0c} 0: \x{0c} ABC\x{0d} 0: \x{0d} ABC\x{85} 0: \x{85} ABC\x{2028} 0: \x{2028} /\h*A/SI8 Capturing subpattern count = 0 Options: utf No first char Need char = 'A' Subject length lower bound = 1 Starting chars: \x09 \x20 A \xa0 \xff CDBABC 0: A \x{2000}ABC 0: \x{2000}A /\R*A/SI8 Capturing subpattern count = 0 Options: bsr_unicode utf No first char Need char = 'A' Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d A \x85 \xff CDBABC 0: A \x{2028}A 0: \x{2028}A /\v+A/SI8 Capturing subpattern count = 0 Options: utf No first char Need char = 'A' Subject length lower bound = 2 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff /\s?xxx\s/8SI Capturing subpattern count = 0 Options: utf No first char Need char = 'x' Subject length lower bound = 4 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 x /\sxxx\s/I8ST1 Capturing subpattern count = 0 Options: utf No first char Need char = 'x' Subject length lower bound = 5 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 \x85 \xa0 AB\x{85}xxx\x{a0}XYZ 0: \x{85}xxx\x{a0} AB\x{a0}xxx\x{85}XYZ 0: \x{a0}xxx\x{85} /\S \S/I8ST1 Capturing subpattern count = 0 Options: utf No first char Need char = ' ' Subject length lower bound = 3 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff \x{a2} \x{84} 0: \x{a2} \x{84} A Z 0: A Z /a+/8 a\x{123}aa\>1 0: aa a\x{123}aa\>2 0: aa a\x{123}aa\>3 0: a a\x{123}aa\>4 No match a\x{123}aa\>5 Error -24 (bad offset value) a\x{123}aa\>6 Error -24 (bad offset value) /\x{1234}+/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} No need char Subject length lower bound = 1 No starting char list /\x{1234}+?/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} No need char Subject length lower bound = 1 No starting char list /\x{1234}++/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} No need char Subject length lower bound = 1 No starting char list /\x{1234}{2}/iS8I Capturing subpattern count = 0 Options: caseless utf First char = \x{1234} Need char = \x{1234} Subject length lower bound = 2 No starting char list /[^\x{c4}]/8DZ ------------------------------------------------------------------ Bra [^\x{c4}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /X+\x{200}/8DZ ------------------------------------------------------------------ Bra X++ \x{200} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'X' Need char = \x{200} /\R/SI8 Capturing subpattern count = 0 Options: utf No first char No need char Subject length lower bound = 1 Starting chars: \x0a \x0b \x0c \x0d \x85 \xff /-- Check bad offset --/ /a/8 \x{10000}\>1 No match \x{10000}ab\>1 0: a \x{10000}ab\>2 No match \x{10000}ab\>3 No match \x{10000}ab\>4 Error -24 (bad offset value) \x{10000}ab\>5 Error -24 (bad offset value) //8 **Failed: character value is ill-formed UTF-32 /\w+\x{C4}/8BZ ------------------------------------------------------------------ Bra \w++ \x{c4} Ket End ------------------------------------------------------------------ a\x{C4}\x{C4} 0: a\x{c4} /\w+\x{C4}/8BZT1 ------------------------------------------------------------------ Bra \w+ \x{c4} Ket End ------------------------------------------------------------------ a\x{C4}\x{C4} 0: a\x{c4}\x{c4} /\W+\x{C4}/8BZ ------------------------------------------------------------------ Bra \W+ \x{c4} Ket End ------------------------------------------------------------------ !\x{C4} 0: !\x{c4} /\W+\x{C4}/8BZT1 ------------------------------------------------------------------ Bra \W++ \x{c4} Ket End ------------------------------------------------------------------ !\x{C4} 0: !\x{c4} /\W+\x{A1}/8BZ ------------------------------------------------------------------ Bra \W+ \x{a1} Ket End ------------------------------------------------------------------ !\x{A1} 0: !\x{a1} /\W+\x{A1}/8BZT1 ------------------------------------------------------------------ Bra \W+ \x{a1} Ket End ------------------------------------------------------------------ !\x{A1} 0: !\x{a1} /X\s+\x{A0}/8BZ ------------------------------------------------------------------ Bra X \s++ \x{a0} Ket End ------------------------------------------------------------------ X\x20\x{A0}\x{A0} 0: X \x{a0} /X\s+\x{A0}/8BZT1 ------------------------------------------------------------------ Bra X \s+ \x{a0} Ket End ------------------------------------------------------------------ X\x20\x{A0}\x{A0} 0: X \x{a0}\x{a0} /\S+\x{A0}/8BZ ------------------------------------------------------------------ Bra \S+ \x{a0} Ket End ------------------------------------------------------------------ X\x{A0}\x{A0} 0: X\x{a0}\x{a0} /\S+\x{A0}/8BZT1 ------------------------------------------------------------------ Bra \S++ \x{a0} Ket End ------------------------------------------------------------------ X\x{A0}\x{A0} 0: X\x{a0} /\x{a0}+\s!/8BZ ------------------------------------------------------------------ Bra \x{a0}++ \s ! Ket End ------------------------------------------------------------------ \x{a0}\x20! 0: \x{a0} ! /\x{a0}+\s!/8BZT1 ------------------------------------------------------------------ Bra \x{a0}+ \s ! Ket End ------------------------------------------------------------------ \x{a0}\x20! 0: \x{a0} ! /(*UTF)abc/9 Failed: setting UTF is disabled by the application at offset 0 /abc/89 Failed: setting UTF is disabled by the application at offset 0 /-- End of testinput18 --/ ================================================ FILE: src/pcre/testdata/testoutput19 ================================================ /-- This set of tests is for Unicode property support, relevant only to the 16- and 32-bit library. --/ /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8iDZ ------------------------------------------------------------------ Bra /i A\x{391}\x{10427}\x{ff3a}\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf First char = 'A' (caseless) Need char = \x{1fb0} (caseless) /A\x{391}\x{10427}\x{ff3a}\x{1fb0}/8DZ ------------------------------------------------------------------ Bra A\x{391}\x{10427}\x{ff3a}\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = \x{1fb0} /AB\x{1fb0}/8DZ ------------------------------------------------------------------ Bra AB\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = \x{1fb0} /AB\x{1fb0}/8DZi ------------------------------------------------------------------ Bra /i AB\x{1fb0} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf First char = 'A' (caseless) Need char = \x{1fb0} (caseless) /\x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f}/8iSI Capturing subpattern count = 0 Options: caseless utf First char = \x{401} (caseless) Need char = \x{42f} (caseless) Subject length lower bound = 17 No starting char list \x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f} 0: \x{401}\x{420}\x{421}\x{422}\x{423}\x{424}\x{425}\x{426}\x{427}\x{428}\x{429}\x{42a}\x{42b}\x{42c}\x{42d}\x{42e}\x{42f} \x{451}\x{440}\x{441}\x{442}\x{443}\x{444}\x{445}\x{446}\x{447}\x{448}\x{449}\x{44a}\x{44b}\x{44c}\x{44d}\x{44e}\x{44f} 0: \x{451}\x{440}\x{441}\x{442}\x{443}\x{444}\x{445}\x{446}\x{447}\x{448}\x{449}\x{44a}\x{44b}\x{44c}\x{44d}\x{44e}\x{44f} /[ⱥ]/8iBZ ------------------------------------------------------------------ Bra /i \x{2c65} Ket End ------------------------------------------------------------------ /[^ⱥ]/8iBZ ------------------------------------------------------------------ Bra /i [^\x{2c65}] Ket End ------------------------------------------------------------------ /[[:blank:]]/WBZ ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}] Ket End ------------------------------------------------------------------ /\x{212a}+/i8SI Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: K k \xff KKkk\x{212a} 0: KKkk\x{212a} /s+/i8SI Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 Starting chars: S s \xff SSss\x{17f} 0: SSss\x{17f} /[\D]/8 \x{1d7cf} 0: \x{1d7cf} /[\D\P{Nd}]/8 \x{1d7cf} 0: \x{1d7cf} /[^\D]/8 a9b 0: 9 ** Failers No match \x{1d7cf} No match /[^\D\P{Nd}]/8 a9b 0: 9 \x{1d7cf} 0: \x{1d7cf} ** Failers No match \x{10000} No match /-- End of testinput19 --/ ================================================ FILE: src/pcre/testdata/testoutput2 ================================================ /-- This set of tests is not Perl-compatible. It checks on special features of PCRE's API, error diagnostics, and the compiled code of some patterns. It also checks the non-Perl syntax the PCRE supports (Python, .NET, Oniguruma). Finally, there are some tests where PCRE and Perl differ, either because PCRE can't be compatible, or there is a possible Perl bug. NOTE: This is a non-UTF set of tests. When UTF support is needed, use test 5, and if Unicode Property Support is needed, use test 7. --/ < forbid 8W /(a)b|/I Capturing subpattern count = 1 May match empty string No options No first char No need char /abc/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' abc 0: abc defabc 0: abc \Aabc 0: abc *** Failers No match \Adefabc No match ABC No match /^abc/I Capturing subpattern count = 0 Options: anchored No first char No need char abc 0: abc \Aabc 0: abc *** Failers No match defabc No match \Adefabc No match /a+bc/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' /a*bc/I Capturing subpattern count = 0 No options No first char Need char = 'c' /a{3}bc/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' /(abc|a+z)/I Capturing subpattern count = 1 No options First char = 'a' No need char /^abc$/I Capturing subpattern count = 0 Options: anchored No first char No need char abc 0: abc *** Failers No match def\nabc No match /ab\idef/X Failed: unrecognized character follows \ at offset 3 /(?X)ab\idef/X Failed: unrecognized character follows \ at offset 7 /x{5,4}/ Failed: numbers out of order in {} quantifier at offset 5 /z{65536}/ Failed: number too big in {} quantifier at offset 7 /[abcd/ Failed: missing terminating ] for character class at offset 5 /(?X)[\B]/ Failed: invalid escape sequence in character class at offset 6 /(?X)[\R]/ Failed: invalid escape sequence in character class at offset 6 /(?X)[\X]/ Failed: invalid escape sequence in character class at offset 6 /[\B]/BZ ------------------------------------------------------------------ Bra B Ket End ------------------------------------------------------------------ /[\R]/BZ ------------------------------------------------------------------ Bra R Ket End ------------------------------------------------------------------ /[\X]/BZ ------------------------------------------------------------------ Bra X Ket End ------------------------------------------------------------------ /[z-a]/ Failed: range out of order in character class at offset 3 /^*/ Failed: nothing to repeat at offset 1 /(abc/ Failed: missing ) at offset 4 /(?# abc/ Failed: missing ) after comment at offset 7 /(?z)abc/ Failed: unrecognized character after (? or (?- at offset 2 /.*b/I Capturing subpattern count = 0 No options First char at start or follows newline Need char = 'b' /.*?b/I Capturing subpattern count = 0 No options First char at start or follows newline Need char = 'b' /cat|dog|elephant/I Capturing subpattern count = 0 No options No first char No need char this sentence eventually mentions a cat 0: cat this sentences rambles on and on for a while and then reaches elephant 0: elephant /cat|dog|elephant/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 3 Starting chars: c d e this sentence eventually mentions a cat 0: cat this sentences rambles on and on for a while and then reaches elephant 0: elephant /cat|dog|elephant/IiS Capturing subpattern count = 0 Options: caseless No first char No need char Subject length lower bound = 3 Starting chars: C D E c d e this sentence eventually mentions a CAT cat 0: CAT this sentences rambles on and on for a while to elephant ElePhant 0: elephant /a|[bcd]/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: a b c d /(a|[^\dZ])/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0a \x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff /(a|b)*[\s]/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 a b /(ab\2)/ Failed: reference to non-existent subpattern at offset 6 /{4,5}abc/ Failed: nothing to repeat at offset 4 /(a)(b)(c)\2/I Capturing subpattern count = 3 Max back reference = 2 No options First char = 'a' Need char = 'c' abcb 0: abcb 1: a 2: b 3: c \O0abcb Matched, but too many substrings \O3abcb Matched, but too many substrings 0: abcb \O6abcb Matched, but too many substrings 0: abcb 1: a \O9abcb Matched, but too many substrings 0: abcb 1: a 2: b \O12abcb 0: abcb 1: a 2: b 3: c /(a)bc|(a)(b)\2/I Capturing subpattern count = 3 Max back reference = 2 No options First char = 'a' No need char abc 0: abc 1: a \O0abc Matched, but too many substrings \O3abc Matched, but too many substrings 0: abc \O6abc 0: abc 1: a aba 0: aba 1: 2: a 3: b \O0aba Matched, but too many substrings \O3aba Matched, but too many substrings 0: aba \O6aba Matched, but too many substrings 0: aba 1: \O9aba Matched, but too many substrings 0: aba 1: 2: a \O12aba 0: aba 1: 2: a 3: b /abc$/IE Capturing subpattern count = 0 Options: dollar_endonly First char = 'a' Need char = 'c' abc 0: abc *** Failers No match abc\n No match abc\ndef No match /(a)(b)(c)(d)(e)\6/ Failed: reference to non-existent subpattern at offset 17 /the quick brown fox/I Capturing subpattern count = 0 No options First char = 't' Need char = 'x' the quick brown fox 0: the quick brown fox this is a line with the quick brown fox 0: the quick brown fox /the quick brown fox/IA Capturing subpattern count = 0 Options: anchored No first char No need char the quick brown fox 0: the quick brown fox *** Failers No match this is a line with the quick brown fox No match /ab(?z)cd/ Failed: unrecognized character after (? or (?- at offset 4 /^abc|def/I Capturing subpattern count = 0 No options No first char No need char abcdef 0: abc abcdef\B 0: def /.*((abc)$|(def))/I Capturing subpattern count = 3 No options First char at start or follows newline No need char defabc 0: defabc 1: abc 2: abc \Zdefabc 0: def 1: def 2: 3: def /)/ Failed: unmatched parentheses at offset 0 /a[]b/ Failed: missing terminating ] for character class at offset 4 /[^aeiou ]{3,}/I Capturing subpattern count = 0 No options No first char No need char co-processors, and for 0: -pr /<.*>/I Capturing subpattern count = 0 No options First char = '<' Need char = '>' abcghinop 0: ghi /<.*?>/I Capturing subpattern count = 0 No options First char = '<' Need char = '>' abcghinop 0: /<.*>/IU Capturing subpattern count = 0 Options: ungreedy First char = '<' Need char = '>' abcghinop 0: /(?U)<.*>/I Capturing subpattern count = 0 No options First char = '<' Need char = '>' abcghinop 0: /<.*?>/IU Capturing subpattern count = 0 Options: ungreedy First char = '<' Need char = '>' abcghinop 0: ghi /={3,}/IU Capturing subpattern count = 0 Options: ungreedy First char = '=' Need char = '=' abc========def 0: === /(?U)={3,}?/I Capturing subpattern count = 0 No options First char = '=' Need char = '=' abc========def 0: ======== /(?^abc)/Im Capturing subpattern count = 0 Options: multiline First char at start or follows newline Need char = 'c' abc 0: abc def\nabc 0: abc *** Failers No match defabc No match /(?<=ab(c+)d)ef/ Failed: lookbehind assertion is not fixed length at offset 11 /(?<=ab(?<=c+)d)ef/ Failed: lookbehind assertion is not fixed length at offset 12 /(?<=ab(c|de)f)g/ Failed: lookbehind assertion is not fixed length at offset 13 /The next three are in testinput2 because they have variable length branches/ /(?<=bullock|donkey)-cart/I Capturing subpattern count = 0 Max lookbehind = 7 No options First char = '-' Need char = 't' the bullock-cart 0: -cart a donkey-cart race 0: -cart *** Failers No match cart No match horse-and-cart No match /(?<=ab(?i)x|y|z)/I Capturing subpattern count = 0 Max lookbehind = 3 May match empty string No options No first char No need char /(?>.*)(?<=(abcd)|(xyz))/I Capturing subpattern count = 2 Max lookbehind = 4 May match empty string No options No first char No need char alphabetabcd 0: alphabetabcd 1: abcd endingxyz 0: endingxyz 1: 2: xyz /(?<=ab(?i)x(?-i)y|(?i)z|b)ZZ/I Capturing subpattern count = 0 Max lookbehind = 4 No options First char = 'Z' Need char = 'Z' abxyZZ 0: ZZ abXyZZ 0: ZZ ZZZ 0: ZZ zZZ 0: ZZ bZZ 0: ZZ BZZ 0: ZZ *** Failers No match ZZ No match abXYZZ No match zzz No match bzz No match /(? 3: f 1G a (1) 2G (0) 3G f (1) get substring 4 failed -7 0L adef 1L a 2L 3L f bcdef\G1\G2\G3\G4\L 0: bcdef 1: bc 2: bc 3: f 1G bc (2) 2G bc (2) 3G f (1) get substring 4 failed -7 0L bcdef 1L bc 2L bc 3L f adefghijk\C0 0: adef 1: a 2: 3: f 0C adef (4) /^abc\00def/I Capturing subpattern count = 0 Options: anchored No first char No need char abc\00def\L\C0 0: abc\x00def 0C abc\x00def (7) 0L abc /word ((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )((?:[a-zA-Z0-9]+ )?)?)?)?)?)?)?)?)?otherword/I Capturing subpattern count = 8 Contains explicit CR or LF match No options First char = 'w' Need char = 'd' /.*X/IDZ ------------------------------------------------------------------ Bra Any* X Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char at start or follows newline Need char = 'X' /.*X/IDZs ------------------------------------------------------------------ Bra AllAny* X Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored dotall No first char Need char = 'X' /(.*X|^B)/IDZ ------------------------------------------------------------------ Bra CBra 1 Any* X Alt ^ B Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 No options First char at start or follows newline No need char /(.*X|^B)/IDZs ------------------------------------------------------------------ Bra CBra 1 AllAny* X Alt ^ B Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: anchored dotall No first char No need char /(?s)(.*X|^B)/IDZ ------------------------------------------------------------------ Bra CBra 1 AllAny* X Alt ^ B Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: anchored No first char No need char /(?s:.*X|^B)/IDZ ------------------------------------------------------------------ Bra Bra AllAny* X Alt ^ B Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /\Biss\B/I+ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = 'i' Need char = 's' Mississippi 0: iss 0+ issippi /iss/IG+ Capturing subpattern count = 0 No options First char = 'i' Need char = 's' Mississippi 0: iss 0+ issippi 0: iss 0+ ippi /\Biss\B/IG+ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = 'i' Need char = 's' Mississippi 0: iss 0+ issippi /\Biss\B/Ig+ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = 'i' Need char = 's' Mississippi 0: iss 0+ issippi 0: iss 0+ ippi *** Failers No match Mississippi\A No match /(?<=[Ms])iss/Ig+ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = 'i' Need char = 's' Mississippi 0: iss 0+ issippi 0: iss 0+ ippi /(?<=[Ms])iss/IG+ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = 'i' Need char = 's' Mississippi 0: iss 0+ issippi /^iss/Ig+ Capturing subpattern count = 0 Options: anchored No first char No need char ississippi 0: iss 0+ issippi /.*iss/Ig+ Capturing subpattern count = 0 No options First char at start or follows newline Need char = 's' abciss\nxyzisspqr 0: abciss 0+ \x0axyzisspqr 0: xyziss 0+ pqr /.i./I+g Capturing subpattern count = 0 No options No first char Need char = 'i' Mississippi 0: Mis 0+ sissippi 0: sis 0+ sippi 0: sip 0+ pi Mississippi\A 0: Mis 0+ sissippi 0: sis 0+ sippi 0: sip 0+ pi Missouri river 0: Mis 0+ souri river 0: ri 0+ river 0: riv 0+ er Missouri river\A 0: Mis 0+ souri river /^.is/I+g Capturing subpattern count = 0 Options: anchored No first char No need char Mississippi 0: Mis 0+ sissippi /^ab\n/Ig+ Capturing subpattern count = 0 Contains explicit CR or LF match Options: anchored No first char No need char ab\nab\ncd 0: ab\x0a 0+ ab\x0acd /^ab\n/Img+ Capturing subpattern count = 0 Contains explicit CR or LF match Options: multiline First char at start or follows newline Need char = \x0a ab\nab\ncd 0: ab\x0a 0+ ab\x0acd 0: ab\x0a 0+ cd /abc/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' /abc|bac/I Capturing subpattern count = 0 No options No first char Need char = 'c' /(abc|bac)/I Capturing subpattern count = 1 No options No first char Need char = 'c' /(abc|(c|dc))/I Capturing subpattern count = 2 No options No first char Need char = 'c' /(abc|(d|de)c)/I Capturing subpattern count = 2 No options No first char Need char = 'c' /a*/I Capturing subpattern count = 0 May match empty string No options No first char No need char /a+/I Capturing subpattern count = 0 No options First char = 'a' No need char /(baa|a+)/I Capturing subpattern count = 1 No options No first char Need char = 'a' /a{0,3}/I Capturing subpattern count = 0 May match empty string No options No first char No need char /baa{3,}/I Capturing subpattern count = 0 No options First char = 'b' Need char = 'a' /"([^\\"]+|\\.)*"/I Capturing subpattern count = 1 No options First char = '"' Need char = '"' /(abc|ab[cd])/I Capturing subpattern count = 1 No options First char = 'a' No need char /(a|.)/I Capturing subpattern count = 1 No options No first char No need char /a|ba|\w/I Capturing subpattern count = 0 No options No first char No need char /abc(?=pqr)/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'r' /...(?<=abc)/I Capturing subpattern count = 0 Max lookbehind = 3 No options No first char No need char /abc(?!pqr)/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' /ab./I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /ab[xyz]/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /abc*/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /ab.c*/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /a.c*/I Capturing subpattern count = 0 No options First char = 'a' No need char /.c*/I Capturing subpattern count = 0 No options No first char No need char /ac*/I Capturing subpattern count = 0 No options First char = 'a' No need char /(a.c*|b.c*)/I Capturing subpattern count = 1 No options No first char No need char /a.c*|aba/I Capturing subpattern count = 0 No options First char = 'a' No need char /.+a/I Capturing subpattern count = 0 No options No first char Need char = 'a' /(?=abcda)a.*/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'a' /(?=a)a.*/I Capturing subpattern count = 0 No options First char = 'a' No need char /a(b)*/I Capturing subpattern count = 1 No options First char = 'a' No need char /a\d*/I Capturing subpattern count = 0 No options First char = 'a' No need char /ab\d*/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /a(\d)*/I Capturing subpattern count = 1 No options First char = 'a' No need char /abcde{0,0}/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'd' /ab\d+/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /a(?(1)b)(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' No need char /a(?(1)bag|big)(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' Need char = 'g' /a(?(1)bag|big)*(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' No need char /a(?(1)bag|big)+(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' Need char = 'g' /a(?(1)b..|b..)(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' Need char = 'b' /ab\d{0}e/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'e' /a?b?/I Capturing subpattern count = 0 May match empty string No options No first char No need char a 0: a b 0: b ab 0: ab \ 0: *** Failers 0: \N No match /|-/I Capturing subpattern count = 0 May match empty string No options No first char No need char abcd 0: -abc 0: \Nab-c 0: - *** Failers 0: \Nabc No match /^.?abcd/IS Capturing subpattern count = 0 Options: anchored No first char Need char = 'd' Subject length lower bound = 4 No starting char list /\( # ( at start (?: # Non-capturing bracket (?>[^()]+) # Either a sequence of non-brackets (no backtracking) | # Or (?R) # Recurse - i.e. nested bracketed string )* # Zero or more contents \) # Closing ) /Ix Capturing subpattern count = 0 Options: extended First char = '(' Need char = ')' (abcd) 0: (abcd) (abcd)xyz 0: (abcd) xyz(abcd) 0: (abcd) (ab(xy)cd)pqr 0: (ab(xy)cd) (ab(xycd)pqr 0: (xycd) () abc () 0: () 12(abcde(fsh)xyz(foo(bar))lmno)89 0: (abcde(fsh)xyz(foo(bar))lmno) *** Failers No match abcd No match abcd) No match (abcd No match /\( ( (?>[^()]+) | (?R) )* \) /Ixg Capturing subpattern count = 1 Options: extended First char = '(' Need char = ')' (ab(xy)cd)pqr 0: (ab(xy)cd) 1: cd 1(abcd)(x(y)z)pqr 0: (abcd) 1: abcd 0: (x(y)z) 1: z /\( (?: (?>[^()]+) | (?R) ) \) /Ix Capturing subpattern count = 0 Options: extended First char = '(' Need char = ')' (abcd) 0: (abcd) (ab(xy)cd) 0: (xy) (a(b(c)d)e) 0: (c) ((ab)) 0: ((ab)) *** Failers No match () No match /\( (?: (?>[^()]+) | (?R) )? \) /Ix Capturing subpattern count = 0 Options: extended First char = '(' Need char = ')' () 0: () 12(abcde(fsh)xyz(foo(bar))lmno)89 0: (fsh) /\( ( (?>[^()]+) | (?R) )* \) /Ix Capturing subpattern count = 1 Options: extended First char = '(' Need char = ')' (ab(xy)cd) 0: (ab(xy)cd) 1: cd /\( ( ( (?>[^()]+) | (?R) )* ) \) /Ix Capturing subpattern count = 2 Options: extended First char = '(' Need char = ')' (ab(xy)cd) 0: (ab(xy)cd) 1: ab(xy)cd 2: cd /\( (123)? ( ( (?>[^()]+) | (?R) )* ) \) /Ix Capturing subpattern count = 3 Options: extended First char = '(' Need char = ')' (ab(xy)cd) 0: (ab(xy)cd) 1: 2: ab(xy)cd 3: cd (123ab(xy)cd) 0: (123ab(xy)cd) 1: 123 2: ab(xy)cd 3: cd /\( ( (123)? ( (?>[^()]+) | (?R) )* ) \) /Ix Capturing subpattern count = 3 Options: extended First char = '(' Need char = ')' (ab(xy)cd) 0: (ab(xy)cd) 1: ab(xy)cd 2: 3: cd (123ab(xy)cd) 0: (123ab(xy)cd) 1: 123ab(xy)cd 2: 123 3: cd /\( (((((((((( ( (?>[^()]+) | (?R) )* )))))))))) \) /Ix Capturing subpattern count = 11 Options: extended First char = '(' Need char = ')' (ab(xy)cd) 0: (ab(xy)cd) 1: ab(xy)cd 2: ab(xy)cd 3: ab(xy)cd 4: ab(xy)cd 5: ab(xy)cd 6: ab(xy)cd 7: ab(xy)cd 8: ab(xy)cd 9: ab(xy)cd 10: ab(xy)cd 11: cd /\( ( ( (?>[^()<>]+) | ((?>[^()]+)) | (?R) )* ) \) /Ix Capturing subpattern count = 3 Options: extended First char = '(' Need char = ')' (abcd(xyz

    qrs)123) 0: (abcd(xyz

    qrs)123) 1: abcd(xyz

    qrs)123 2: 123 /\( ( ( (?>[^()]+) | ((?R)) )* ) \) /Ix Capturing subpattern count = 3 Options: extended First char = '(' Need char = ')' (ab(cd)ef) 0: (ab(cd)ef) 1: ab(cd)ef 2: ef 3: (cd) (ab(cd(ef)gh)ij) 0: (ab(cd(ef)gh)ij) 1: ab(cd(ef)gh)ij 2: ij 3: (cd(ef)gh) /^[[:alnum:]]/DZ ------------------------------------------------------------------ Bra ^ [0-9A-Za-z] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:^alnum:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-/:-@[-`{-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:alpha:]]/DZ ------------------------------------------------------------------ Bra ^ [A-Za-z] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:^alpha:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-@[-`{-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /[_[:alpha:]]/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /^[[:ascii:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-\x7f] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:^ascii:]]/DZ ------------------------------------------------------------------ Bra ^ [\x80-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:blank:]]/DZ ------------------------------------------------------------------ Bra ^ [\x09 ] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:^blank:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-\x08\x0a-\x1f!-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /[\n\x0b\x0c\x0d[:blank:]]/IS Capturing subpattern count = 0 Contains explicit CR or LF match No options No first char No need char Subject length lower bound = 1 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 /^[[:cntrl:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-\x1f\x7f] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:digit:]]/DZ ------------------------------------------------------------------ Bra ^ [0-9] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:graph:]]/DZ ------------------------------------------------------------------ Bra ^ [!-~] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:lower:]]/DZ ------------------------------------------------------------------ Bra ^ [a-z] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:print:]]/DZ ------------------------------------------------------------------ Bra ^ [ -~] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:punct:]]/DZ ------------------------------------------------------------------ Bra ^ [!-/:-@[-`{-~] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:space:]]/DZ ------------------------------------------------------------------ Bra ^ [\x09-\x0d ] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:upper:]]/DZ ------------------------------------------------------------------ Bra ^ [A-Z] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:xdigit:]]/DZ ------------------------------------------------------------------ Bra ^ [0-9A-Fa-f] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:word:]]/DZ ------------------------------------------------------------------ Bra ^ [0-9A-Z_a-z] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:^cntrl:]]/DZ ------------------------------------------------------------------ Bra ^ [ -~\x80-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[12[:^digit:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-/12:-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /^[[:^blank:]]/DZ ------------------------------------------------------------------ Bra ^ [\x00-\x08\x0a-\x1f!-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char No need char /[01[:alpha:]%]/DZ ------------------------------------------------------------------ Bra [%01A-Za-z] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[[.ch.]]/I Failed: POSIX collating elements are not supported at offset 1 /[[=ch=]]/I Failed: POSIX collating elements are not supported at offset 1 /[[:rhubarb:]]/I Failed: unknown POSIX class name at offset 3 /[[:upper:]]/Ii Capturing subpattern count = 0 Options: caseless No first char No need char A 0: A a 0: a /[[:lower:]]/Ii Capturing subpattern count = 0 Options: caseless No first char No need char A 0: A a 0: a /((?-i)[[:lower:]])[[:lower:]]/Ii Capturing subpattern count = 1 Options: caseless No first char No need char ab 0: ab 1: a aB 0: aB 1: a *** Failers 0: ai 1: a Ab No match AB No match /[\200-\110]/I Failed: range out of order in character class at offset 9 /^(?(0)f|b)oo/I Failed: invalid condition (?(0) at offset 6 /This one's here because of the large output vector needed/I Capturing subpattern count = 0 No options First char = 'T' Need char = 'd' /(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\d+(?:\s|$))(\w+)\s+(\270)/I Capturing subpattern count = 271 Max back reference = 270 No options No first char No need char \O900 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC 0: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 ABC ABC 1: 1 2: 2 3: 3 4: 4 5: 5 6: 6 7: 7 8: 8 9: 9 10: 10 11: 11 12: 12 13: 13 14: 14 15: 15 16: 16 17: 17 18: 18 19: 19 20: 20 21: 21 22: 22 23: 23 24: 24 25: 25 26: 26 27: 27 28: 28 29: 29 30: 30 31: 31 32: 32 33: 33 34: 34 35: 35 36: 36 37: 37 38: 38 39: 39 40: 40 41: 41 42: 42 43: 43 44: 44 45: 45 46: 46 47: 47 48: 48 49: 49 50: 50 51: 51 52: 52 53: 53 54: 54 55: 55 56: 56 57: 57 58: 58 59: 59 60: 60 61: 61 62: 62 63: 63 64: 64 65: 65 66: 66 67: 67 68: 68 69: 69 70: 70 71: 71 72: 72 73: 73 74: 74 75: 75 76: 76 77: 77 78: 78 79: 79 80: 80 81: 81 82: 82 83: 83 84: 84 85: 85 86: 86 87: 87 88: 88 89: 89 90: 90 91: 91 92: 92 93: 93 94: 94 95: 95 96: 96 97: 97 98: 98 99: 99 100: 100 101: 101 102: 102 103: 103 104: 104 105: 105 106: 106 107: 107 108: 108 109: 109 110: 110 111: 111 112: 112 113: 113 114: 114 115: 115 116: 116 117: 117 118: 118 119: 119 120: 120 121: 121 122: 122 123: 123 124: 124 125: 125 126: 126 127: 127 128: 128 129: 129 130: 130 131: 131 132: 132 133: 133 134: 134 135: 135 136: 136 137: 137 138: 138 139: 139 140: 140 141: 141 142: 142 143: 143 144: 144 145: 145 146: 146 147: 147 148: 148 149: 149 150: 150 151: 151 152: 152 153: 153 154: 154 155: 155 156: 156 157: 157 158: 158 159: 159 160: 160 161: 161 162: 162 163: 163 164: 164 165: 165 166: 166 167: 167 168: 168 169: 169 170: 170 171: 171 172: 172 173: 173 174: 174 175: 175 176: 176 177: 177 178: 178 179: 179 180: 180 181: 181 182: 182 183: 183 184: 184 185: 185 186: 186 187: 187 188: 188 189: 189 190: 190 191: 191 192: 192 193: 193 194: 194 195: 195 196: 196 197: 197 198: 198 199: 199 200: 200 201: 201 202: 202 203: 203 204: 204 205: 205 206: 206 207: 207 208: 208 209: 209 210: 210 211: 211 212: 212 213: 213 214: 214 215: 215 216: 216 217: 217 218: 218 219: 219 220: 220 221: 221 222: 222 223: 223 224: 224 225: 225 226: 226 227: 227 228: 228 229: 229 230: 230 231: 231 232: 232 233: 233 234: 234 235: 235 236: 236 237: 237 238: 238 239: 239 240: 240 241: 241 242: 242 243: 243 244: 244 245: 245 246: 246 247: 247 248: 248 249: 249 250: 250 251: 251 252: 252 253: 253 254: 254 255: 255 256: 256 257: 257 258: 258 259: 259 260: 260 261: 261 262: 262 263: 263 264: 264 265: 265 266: 266 267: 267 268: 268 269: 269 270: ABC 271: ABC /This one's here because Perl does this differently and PCRE can't at present/I Capturing subpattern count = 0 No options First char = 'T' Need char = 't' /(main(O)?)+/I Capturing subpattern count = 2 No options First char = 'm' Need char = 'n' mainmain 0: mainmain 1: main mainOmain 0: mainOmain 1: main 2: O /These are all cases where Perl does it differently (nested captures)/I Capturing subpattern count = 1 No options First char = 'T' Need char = 's' /^(a(b)?)+$/I Capturing subpattern count = 2 Options: anchored No first char No need char aba 0: aba 1: a 2: b /^(aa(bb)?)+$/I Capturing subpattern count = 2 Options: anchored No first char No need char aabbaa 0: aabbaa 1: aa 2: bb /^(aa|aa(bb))+$/I Capturing subpattern count = 2 Options: anchored No first char No need char aabbaa 0: aabbaa 1: aa 2: bb /^(aa(bb)??)+$/I Capturing subpattern count = 2 Options: anchored No first char No need char aabbaa 0: aabbaa 1: aa 2: bb /^(?:aa(bb)?)+$/I Capturing subpattern count = 1 Options: anchored No first char No need char aabbaa 0: aabbaa 1: bb /^(aa(b(b))?)+$/I Capturing subpattern count = 3 Options: anchored No first char No need char aabbaa 0: aabbaa 1: aa 2: bb 3: b /^(?:aa(b(b))?)+$/I Capturing subpattern count = 2 Options: anchored No first char No need char aabbaa 0: aabbaa 1: bb 2: b /^(?:aa(b(?:b))?)+$/I Capturing subpattern count = 1 Options: anchored No first char No need char aabbaa 0: aabbaa 1: bb /^(?:aa(bb(?:b))?)+$/I Capturing subpattern count = 1 Options: anchored No first char No need char aabbbaa 0: aabbbaa 1: bbb /^(?:aa(b(?:bb))?)+$/I Capturing subpattern count = 1 Options: anchored No first char No need char aabbbaa 0: aabbbaa 1: bbb /^(?:aa(?:b(b))?)+$/I Capturing subpattern count = 1 Options: anchored No first char No need char aabbaa 0: aabbaa 1: b /^(?:aa(?:b(bb))?)+$/I Capturing subpattern count = 1 Options: anchored No first char No need char aabbbaa 0: aabbbaa 1: bb /^(aa(b(bb))?)+$/I Capturing subpattern count = 3 Options: anchored No first char No need char aabbbaa 0: aabbbaa 1: aa 2: bbb 3: bb /^(aa(bb(bb))?)+$/I Capturing subpattern count = 3 Options: anchored No first char No need char aabbbbaa 0: aabbbbaa 1: aa 2: bbbb 3: bb /--------------------------------------------------------------------/I Capturing subpattern count = 0 No options First char = '-' Need char = '-' /#/IxDZ ------------------------------------------------------------------ Bra Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string Options: extended No first char No need char /a#/IxDZ ------------------------------------------------------------------ Bra a Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended First char = 'a' No need char /[\s]/DZ ------------------------------------------------------------------ Bra [\x09-\x0d ] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\S]/DZ ------------------------------------------------------------------ Bra [\x00-\x08\x0e-\x1f!-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /a(?i)b/DZ ------------------------------------------------------------------ Bra a /i b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' (caseless) ab 0: ab aB 0: aB *** Failers No match AB No match /(a(?i)b)/DZ ------------------------------------------------------------------ Bra CBra 1 a /i b Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 No options First char = 'a' Need char = 'b' (caseless) ab 0: ab 1: ab aB 0: aB 1: aB *** Failers No match AB No match / (?i)abc/IxDZ ------------------------------------------------------------------ Bra /i abc Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended First char = 'a' (caseless) Need char = 'c' (caseless) /#this is a comment (?i)abc/IxDZ ------------------------------------------------------------------ Bra /i abc Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: extended First char = 'a' (caseless) Need char = 'c' (caseless) /123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/DZ ------------------------------------------------------------------ Bra 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = '1' Need char = '0' /\Q123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890/DZ ------------------------------------------------------------------ Bra 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = '1' Need char = '0' /\Q\E/DZ ------------------------------------------------------------------ Bra Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string No options No first char No need char \ 0: /\Q\Ex/DZ ------------------------------------------------------------------ Bra x Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'x' No need char / \Q\E/DZ ------------------------------------------------------------------ Bra Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = ' ' No need char /a\Q\E/DZ ------------------------------------------------------------------ Bra a Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'a' No need char abc 0: a bca 0: a bac 0: a /a\Q\Eb/DZ ------------------------------------------------------------------ Bra ab Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' abc 0: ab /\Q\Eabc/DZ ------------------------------------------------------------------ Bra abc Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' /x*+\w/DZ ------------------------------------------------------------------ Bra x*+ \w Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char *** Failers 0: F xxxxx No match /x?+/DZ ------------------------------------------------------------------ Bra x?+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string No options No first char No need char /x++/DZ ------------------------------------------------------------------ Bra x++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'x' No need char /x{1,3}+/BZO ------------------------------------------------------------------ Bra x x{0,2}+ Ket End ------------------------------------------------------------------ /x{1,3}+/BZOi ------------------------------------------------------------------ Bra /i x /i x{0,2}+ Ket End ------------------------------------------------------------------ /[^x]{1,3}+/BZO ------------------------------------------------------------------ Bra [^x] [^x]{0,2}+ Ket End ------------------------------------------------------------------ /[^x]{1,3}+/BZOi ------------------------------------------------------------------ Bra /i [^x] /i [^x]{0,2}+ Ket End ------------------------------------------------------------------ /(x)*+/DZ ------------------------------------------------------------------ Bra Braposzero CBraPos 1 x KetRpos Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 May match empty string No options No first char No need char /^(\w++|\s++)*$/I Capturing subpattern count = 1 May match empty string Options: anchored No first char No need char now is the time for all good men to come to the aid of the party 0: now is the time for all good men to come to the aid of the party 1: party *** Failers No match this is not a line with only words and spaces! No match /(\d++)(\w)/I Capturing subpattern count = 2 No options No first char No need char 12345a 0: 12345a 1: 12345 2: a *** Failers No match 12345+ No match /a++b/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' aaab 0: aaab /(a++b)/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'b' aaab 0: aaab 1: aaab /(a++)b/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'b' aaab 0: aaab 1: aaa /([^()]++|\([^()]*\))+/I Capturing subpattern count = 1 No options No first char No need char ((abc(ade)ufh()()x 0: abc(ade)ufh()()x 1: x /\(([^()]++|\([^()]+\))+\)/I Capturing subpattern count = 1 No options First char = '(' Need char = ')' (abc) 0: (abc) 1: abc (abc(def)xyz) 0: (abc(def)xyz) 1: xyz *** Failers No match ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /(abc){1,3}+/DZ ------------------------------------------------------------------ Bra Once CBra 1 abc Ket Brazero Bra CBra 1 abc Ket Brazero CBra 1 abc Ket Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 No options First char = 'a' Need char = 'c' /a+?+/I Failed: nothing to repeat at offset 3 /a{2,3}?+b/I Failed: nothing to repeat at offset 7 /(?U)a+?+/I Failed: nothing to repeat at offset 7 /a{2,3}?+b/IU Failed: nothing to repeat at offset 7 /x(?U)a++b/DZ ------------------------------------------------------------------ Bra x a++ b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'x' Need char = 'b' xaaaab 0: xaaaab /(?U)xa++b/DZ ------------------------------------------------------------------ Bra x a++ b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'x' Need char = 'b' xaaaab 0: xaaaab /^((a+)(?U)([ab]+)(?-U)([bc]+)(\w*))/DZ ------------------------------------------------------------------ Bra ^ CBra 1 CBra 2 a+ Ket CBra 3 [ab]+? Ket CBra 4 [bc]+ Ket CBra 5 \w*+ Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 5 Options: anchored No first char No need char /^x(?U)a+b/DZ ------------------------------------------------------------------ Bra ^ x a++ b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char Need char = 'b' /^x(?U)(a+)b/DZ ------------------------------------------------------------------ Bra ^ x CBra 1 a+? Ket b Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: anchored No first char Need char = 'b' /[.x.]/I Failed: POSIX collating elements are not supported at offset 0 /[=x=]/I Failed: POSIX collating elements are not supported at offset 0 /[:x:]/I Failed: POSIX named classes are supported only within a class at offset 0 /\l/I Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1 /\L/I Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1 /\N{name}/I Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1 /\u/I Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1 /\U/I Failed: PCRE does not support \L, \l, \N{name}, \U, or \u at offset 1 /a{1,3}b/U ab 0: ab /[/I Failed: missing terminating ] for character class at offset 1 /[a-/I Failed: missing terminating ] for character class at offset 3 /[[:space:]/I Failed: missing terminating ] for character class at offset 10 /[\s]/IDZ ------------------------------------------------------------------ Bra [\x09-\x0d ] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[[:space:]]/IDZ ------------------------------------------------------------------ Bra [\x09-\x0d ] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[[:space:]abcde]/IDZ ------------------------------------------------------------------ Bra [\x09-\x0d a-e] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/Ix Capturing subpattern count = 0 Options: extended First char = '<' Need char = '>' <> 0: <> 0: hij> 0: hij> hij> 0: def> 0: def> 0: <> *** Failers No match iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|IDZ ------------------------------------------------------------------ Bra 8J$WE<.rX+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X \b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = '8' Need char = 'X' |\$\<\.X\+ix\[d1b\!H\#\?vV0vrK\:ZH1\=2M\>iV\;\?aPhFB\<\*vW\@QW\@sO9\}cfZA\-i\'w\%hKd6gt1UJP\,15_\#QY\$M\^Mss_U\/\]\&LK9\[5vQub\^w\[KDD\qmj\;2\}YWFdYx\.Ap\]hjCPTP\(n28k\+3\;o\&WXqs\/gOXdr\$\:r\'do0\;b4c\(f_Gr\=\"\\4\)\[01T7ajQJvL\$W\~mL_sS\/4h\:x\*\[ZN\=KLs\&L5zX\/\/\>it\,o\:aU\(\;Z\>pW\&T7oP\'2K\^E\:x9\'c\[\%z\-\,64JQ5AeH_G\#KijUKghQw\^\\vea3a\?kka_G\$8\#\`\*kynsxzBLru\'\]k_\[7FrVx\}\^\=\$blx\>s\-N\%j\;D\*aZDnsw\:YKZ\%Q\.Kne9\#hP\?\+b3\(SOvL\,\^\;\&u5\@\?5C5Bhb\=m\-vEh_L15Jl\]U\)0RP6\{q\%L\^_z5E\'Dw6X\b|IDZ ------------------------------------------------------------------ Bra $<.X+ix[d1b!H#?vV0vrK:ZH1=2M>iV;?aPhFB<*vW@QW@sO9}cfZA-i'w%hKd6gt1UJP,15_#QY$M^Mss_U/]&LK9[5vQub^w[KDDqmj;2}YWFdYx.Ap]hjCPTP(n28k+3;o&WXqs/gOXdr$:r'do0;b4c(f_Gr="\4)[01T7ajQJvL$W~mL_sS/4h:x*[ZN=KLs&L5zX//>it,o:aU(;Z>pW&T7oP'2K^E:x9'c[%z-,64JQ5AeH_G#KijUKghQw^\vea3a?kka_G$8#`*kynsxzBLru']k_[7FrVx}^=$blx>s-N%j;D*aZDnsw:YKZ%Q.Kne9#hP?+b3(SOvL,^;&u5@?5C5Bhb=m-vEh_L15Jl]U)0RP6{q%L^_z5E'Dw6X \b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Max lookbehind = 1 No options First char = '$' Need char = 'X' /(.*)\d+\1/I Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char /(.*)\d+/I Capturing subpattern count = 1 No options First char at start or follows newline No need char /(.*)\d+\1/Is Capturing subpattern count = 1 Max back reference = 1 Options: dotall No first char No need char /(.*)\d+/Is Capturing subpattern count = 1 Options: anchored dotall No first char No need char /(.*(xyz))\d+\2/I Capturing subpattern count = 2 Max back reference = 2 No options First char at start or follows newline Need char = 'z' /((.*))\d+\1/I Capturing subpattern count = 2 Max back reference = 1 No options No first char No need char abc123bc 0: bc123bc 1: bc 2: bc /a[b]/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /(?=a).*/I Capturing subpattern count = 0 May match empty string No options First char = 'a' No need char /(?=abc).xyz/IiI Capturing subpattern count = 0 Options: caseless First char = 'a' (caseless) Need char = 'z' (caseless) /(?=abc)(?i).xyz/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'z' (caseless) /(?=a)(?=b)/I Capturing subpattern count = 0 May match empty string No options First char = 'a' No need char /(?=.)a/I Capturing subpattern count = 0 No options First char = 'a' No need char /((?=abcda)a)/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'a' /((?=abcda)ab)/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'b' /()a/I Capturing subpattern count = 1 No options No first char Need char = 'a' /(?(1)ab|ac)(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' No need char /(?(1)abz|acz)(.)/I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' Need char = 'z' /(?(1)abz)(.)/I Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char /(?(1)abz)(1)23/I Capturing subpattern count = 1 Max back reference = 1 No options No first char Need char = '3' /(a)+/I Capturing subpattern count = 1 No options First char = 'a' No need char /(a){2,3}/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'a' /(a)*/I Capturing subpattern count = 1 May match empty string No options No first char No need char /[a]/I Capturing subpattern count = 0 No options First char = 'a' No need char /[ab]/I Capturing subpattern count = 0 No options No first char No need char /[ab]/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: a b /[^a]/I Capturing subpattern count = 0 No options No first char No need char /\d456/I Capturing subpattern count = 0 No options No first char Need char = '6' /\d456/IS Capturing subpattern count = 0 No options No first char Need char = '6' Subject length lower bound = 4 Starting chars: 0 1 2 3 4 5 6 7 8 9 /a^b/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /^a/Im Capturing subpattern count = 0 Options: multiline First char at start or follows newline Need char = 'a' abcde 0: a xy\nabc 0: a *** Failers No match xyabc No match /c|abc/I Capturing subpattern count = 0 No options No first char Need char = 'c' /(?i)[ab]/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: A B a b /[ab](?i)cd/IS Capturing subpattern count = 0 No options No first char Need char = 'd' (caseless) Subject length lower bound = 3 Starting chars: a b /abc(?C)def/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'f' abcdef --->abcdef 0 ^ ^ d 0: abcdef 1234abcdef --->1234abcdef 0 ^ ^ d 0: abcdef *** Failers No match abcxyz No match abcxyzf --->abcxyzf 0 ^ ^ d No match /abc(?C)de(?C1)f/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'f' 123abcdef --->123abcdef 0 ^ ^ d 1 ^ ^ f 0: abcdef /(?C1)\dabc(?C2)def/IS Capturing subpattern count = 0 No options No first char Need char = 'f' Subject length lower bound = 7 Starting chars: 0 1 2 3 4 5 6 7 8 9 1234abcdef --->1234abcdef 1 ^ \d 1 ^ \d 1 ^ \d 1 ^ \d 2 ^ ^ d 0: 4abcdef *** Failers No match abcdef No match /(?C1)\dabc(?C2)def/ISS Capturing subpattern count = 0 No options No first char Need char = 'f' 1234abcdef --->1234abcdef 1 ^ \d 1 ^ \d 1 ^ \d 1 ^ \d 2 ^ ^ d 0: 4abcdef *** Failers No match abcdef --->abcdef 1 ^ \d 1 ^ \d 1 ^ \d 1 ^ \d 1 ^ \d 1 ^ \d No match /(?C255)ab/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'b' /(?C256)ab/I Failed: number after (?C is > 255 at offset 6 /(?Cab)xx/I Failed: closing ) for (?C expected at offset 3 /(?C12vr)x/I Failed: closing ) for (?C expected at offset 5 /abc(?C)def/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'f' *** Failers No match \x83\x0\x61bcdef --->\x83\x00abcdef 0 ^ ^ d 0: abcdef /(abc)(?C)de(?C1)f/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'f' 123abcdef --->123abcdef 0 ^ ^ d 1 ^ ^ f 0: abcdef 1: abc 123abcdef\C+ Callout 0: last capture = 1 0: 1: abc --->123abcdef ^ ^ d Callout 1: last capture = 1 0: 1: abc --->123abcdef ^ ^ f 0: abcdef 1: abc 123abcdef\C- 0: abcdef 1: abc *** Failers No match 123abcdef\C!1 --->123abcdef 0 ^ ^ d 1 ^ ^ f No match /(?C0)(abc(?C1))*/I Capturing subpattern count = 1 May match empty string No options No first char No need char abcabcabc --->abcabcabc 0 ^ (abc(?C1))* 1 ^ ^ ) 1 ^ ^ ) 1 ^ ^ ) 0: abcabcabc 1: abc abcabc\C!1!3 --->abcabc 0 ^ (abc(?C1))* 1 ^ ^ ) 1 ^ ^ ) 0: abcabc 1: abc *** Failers --->*** Failers 0 ^ (abc(?C1))* 0: abcabcabc\C!1!3 --->abcabcabc 0 ^ (abc(?C1))* 1 ^ ^ ) 1 ^ ^ ) 1 ^ ^ ) 0: abcabc 1: abc /(\d{3}(?C))*/I Capturing subpattern count = 1 May match empty string No options No first char No need char 123\C+ Callout 0: last capture = -1 0: --->123 ^ ^ ) 0: 123 1: 123 123456\C+ Callout 0: last capture = -1 0: --->123456 ^ ^ ) Callout 0: last capture = 1 0: 1: 123 --->123456 ^ ^ ) 0: 123456 1: 456 123456789\C+ Callout 0: last capture = -1 0: --->123456789 ^ ^ ) Callout 0: last capture = 1 0: 1: 123 --->123456789 ^ ^ ) Callout 0: last capture = 1 0: 1: 456 --->123456789 ^ ^ ) 0: 123456789 1: 789 /((xyz)(?C)p|(?C1)xyzabc)/I Capturing subpattern count = 2 No options First char = 'x' No need char xyzabc\C+ Callout 0: last capture = 2 0: 1: 2: xyz --->xyzabc ^ ^ p Callout 1: last capture = -1 0: --->xyzabc ^ x 0: xyzabc 1: xyzabc /(X)((xyz)(?C)p|(?C1)xyzabc)/I Capturing subpattern count = 3 No options First char = 'X' Need char = 'x' Xxyzabc\C+ Callout 0: last capture = 3 0: 1: X 2: 3: xyz --->Xxyzabc ^ ^ p Callout 1: last capture = 1 0: 1: X --->Xxyzabc ^^ x 0: Xxyzabc 1: X 2: xyzabc /(?=(abc))(?C)abcdef/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'f' abcdef\C+ Callout 0: last capture = 1 0: 1: abc --->abcdef ^ a 0: abcdef 1: abc /(?!(abc)(?C1)d)(?C2)abcxyz/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'z' abcxyz\C+ Callout 1: last capture = 1 0: 1: abc --->abcxyz ^ ^ d Callout 2: last capture = -1 0: --->abcxyz ^ a 0: abcxyz /(?<=(abc)(?C))xyz/I Capturing subpattern count = 1 Max lookbehind = 3 No options First char = 'x' Need char = 'z' abcxyz\C+ Callout 0: last capture = 1 0: 1: abc --->abcxyz ^ ) 0: xyz 1: abc /a(b+)(c*)(?C1)/I Capturing subpattern count = 2 No options First char = 'a' Need char = 'b' abbbbbccc\C*1 --->abbbbbccc 1 ^ ^ Callout data = 1 No match /a(b+?)(c*?)(?C1)/I Capturing subpattern count = 2 No options First char = 'a' Need char = 'b' abbbbbccc\C*1 --->abbbbbccc 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 1 ^ ^ Callout data = 1 No match /(?C)abc/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' /(?C)^abc/I Capturing subpattern count = 0 Options: anchored No first char No need char /(?C)a|b/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: a b /(?R)/I Failed: recursive call could loop indefinitely at offset 3 /(a|(?R))/I Failed: recursive call could loop indefinitely at offset 6 /(ab|(bc|(de|(?R))))/I Failed: recursive call could loop indefinitely at offset 15 /x(ab|(bc|(de|(?R))))/I Capturing subpattern count = 3 No options First char = 'x' No need char xab 0: xab 1: ab xbc 0: xbc 1: bc 2: bc xde 0: xde 1: de 2: de 3: de xxab 0: xxab 1: xab 2: xab 3: xab xxxab 0: xxxab 1: xxab 2: xxab 3: xxab *** Failers No match xyab No match /(ab|(bc|(de|(?1))))/I Failed: recursive call could loop indefinitely at offset 15 /x(ab|(bc|(de|(?1)x)x)x)/I Failed: recursive call could loop indefinitely at offset 16 /^([^()]|\((?1)*\))*$/I Capturing subpattern count = 1 May match empty string Options: anchored No first char No need char abc 0: abc 1: c a(b)c 0: a(b)c 1: c a(b(c))d 0: a(b(c))d 1: d *** Failers) No match a(b(c)d No match /^>abc>([^()]|\((?1)*\))*abc>123abc>123abc>1(2)3abc>1(2)3abc>(1(2)3)abc>(1(2)3)]*+) | (?2)) * >))/Ix Capturing subpattern count = 2 Options: extended First char = '<' Need char = '>' <> 0: <> 1: <> 2: <> 0: 1: 2: hij> 0: hij> 1: hij> 2: hij> hij> 0: 1: 2: def> 0: def> 1: def> 2: def> 0: <> 1: <> 2: <> *** Failers No match b|c)d(?Pe)/DZ ------------------------------------------------------------------ Bra a CBra 1 b Alt c Ket d CBra 2 e Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 Named capturing subpatterns: longername2 2 name1 1 No options First char = 'a' Need char = 'e' abde 0: abde 1: b 2: e acde 0: acde 1: c 2: e /(?:a(?Pc(?Pd)))(?Pa)/DZ ------------------------------------------------------------------ Bra Bra a CBra 1 c CBra 2 d Ket Ket Ket CBra 3 a Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 3 Named capturing subpatterns: a 3 c 1 d 2 No options First char = 'a' Need char = 'a' /(?Pa)...(?P=a)bbb(?P>a)d/DZ ------------------------------------------------------------------ Bra CBra 1 a Ket Any Any Any \1 bbb Recurse d Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: a 1 No options First char = 'a' Need char = 'd' /^\W*(?:(?P(?P.)\W*(?P>one)\W*(?P=two)|)|(?P(?P.)\W*(?P>three)\W*(?P=four)|\W*.\W*))\W*$/Ii Capturing subpattern count = 4 Max back reference = 4 Named capturing subpatterns: four 4 one 1 three 3 two 2 May match empty string Options: anchored caseless No first char No need char 1221 0: 1221 1: 1221 2: 1 Satan, oscillate my metallic sonatas! 0: Satan, oscillate my metallic sonatas! 1: 2: 3: Satan, oscillate my metallic sonatas 4: S A man, a plan, a canal: Panama! 0: A man, a plan, a canal: Panama! 1: 2: 3: A man, a plan, a canal: Panama 4: A Able was I ere I saw Elba. 0: Able was I ere I saw Elba. 1: 2: 3: Able was I ere I saw Elba 4: A *** Failers No match The quick brown fox No match /((?(R)a|b))\1(?1)?/I Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char bb 0: bb 1: b bbaa 0: bba 1: b /(.*)a/Is Capturing subpattern count = 1 Options: anchored dotall No first char Need char = 'a' /(.*)a\1/Is Capturing subpattern count = 1 Max back reference = 1 Options: dotall No first char Need char = 'a' /(.*)a(b)\2/Is Capturing subpattern count = 2 Max back reference = 2 Options: anchored dotall No first char Need char = 'b' /((.*)a|(.*)b)z/Is Capturing subpattern count = 3 Options: anchored dotall No first char Need char = 'z' /((.*)a|(.*)b)z\1/Is Capturing subpattern count = 3 Max back reference = 1 Options: dotall No first char Need char = 'z' /((.*)a|(.*)b)z\2/Is Capturing subpattern count = 3 Max back reference = 2 Options: dotall No first char Need char = 'z' /((.*)a|(.*)b)z\3/Is Capturing subpattern count = 3 Max back reference = 3 Options: dotall No first char Need char = 'z' /((.*)a|^(.*)b)z\3/Is Capturing subpattern count = 3 Max back reference = 3 Options: anchored dotall No first char Need char = 'z' /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a/Is Capturing subpattern count = 31 May match empty string Options: anchored dotall No first char No need char /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\31/Is Capturing subpattern count = 31 Max back reference = 31 May match empty string Options: dotall No first char No need char /(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)|(.*)a\32/Is Capturing subpattern count = 32 Max back reference = 32 May match empty string Options: dotall No first char No need char /(a)(bc)/INDZ ------------------------------------------------------------------ Bra Bra a Ket Bra bc Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: no_auto_capture First char = 'a' Need char = 'c' abc 0: abc /(?Pa)(bc)/INDZ ------------------------------------------------------------------ Bra CBra 1 a Ket Bra bc Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Named capturing subpatterns: one 1 Options: no_auto_capture First char = 'a' Need char = 'c' abc 0: abc 1: a /(a)(?Pbc)/INDZ ------------------------------------------------------------------ Bra Bra a Ket CBra 1 bc Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Named capturing subpatterns: named 1 Options: no_auto_capture First char = 'a' Need char = 'c' /(a+)*zz/I Capturing subpattern count = 1 No options No first char Need char = 'z' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazzbbbbbb\M Minimum match() limit = 8 Minimum match() recursion limit = 6 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazz 1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaz\M Minimum match() limit = 32768 Minimum match() recursion limit = 29 No match /(aaa(?C1)bbb|ab)/I Capturing subpattern count = 1 No options First char = 'a' Need char = 'b' aaabbb --->aaabbb 1 ^ ^ b 0: aaabbb 1: aaabbb aaabbb\C*0 --->aaabbb 1 ^ ^ b 0: aaabbb 1: aaabbb aaabbb\C*1 --->aaabbb 1 ^ ^ b Callout data = 1 0: ab 1: ab aaabbb\C*-1 --->aaabbb 1 ^ ^ b Callout data = -1 No match /ab(?Pcd)ef(?Pgh)/I Capturing subpattern count = 2 Named capturing subpatterns: one 1 two 2 No options First char = 'a' Need char = 'h' abcdefgh 0: abcdefgh 1: cd 2: gh abcdefgh\C1\Gtwo 0: abcdefgh 1: cd 2: gh 1C cd (2) G gh (2) two abcdefgh\Cone\Ctwo 0: abcdefgh 1: cd 2: gh C cd (2) one C gh (2) two abcdefgh\Cthree no parentheses with name "three" 0: abcdefgh 1: cd 2: gh copy substring three failed -7 /(?P)(?P)/DZ ------------------------------------------------------------------ Bra CBra 1 Ket CBra 2 Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 Named capturing subpatterns: Tes 1 Test 2 May match empty string No options No first char No need char /(?P)(?P)/DZ ------------------------------------------------------------------ Bra CBra 1 Ket CBra 2 Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 Named capturing subpatterns: Tes 2 Test 1 May match empty string No options No first char No need char /(?Pzz)(?Paa)/I Capturing subpattern count = 2 Named capturing subpatterns: A 2 Z 1 No options First char = 'z' Need char = 'a' zzaa\CZ 0: zzaa 1: zz 2: aa C zz (2) Z zzaa\CA 0: zzaa 1: zz 2: aa C aa (2) A /(?Peks)(?Peccs)/I Failed: two named subpatterns have the same name at offset 15 /(?Pabc(?Pdef)(?Pxyz))/I Failed: two named subpatterns have the same name at offset 30 "\[((?P\d+)(,(?P>elem))*)\]"I Capturing subpattern count = 3 Named capturing subpatterns: elem 2 No options First char = '[' Need char = ']' [10,20,30,5,5,4,4,2,43,23,4234] 0: [10,20,30,5,5,4,4,2,43,23,4234] 1: 10,20,30,5,5,4,4,2,43,23,4234 2: 10 3: ,4234 *** Failers No match [] No match "\[((?P\d+)(,(?P>elem))*)?\]"I Capturing subpattern count = 3 Named capturing subpatterns: elem 2 No options First char = '[' Need char = ']' [10,20,30,5,5,4,4,2,43,23,4234] 0: [10,20,30,5,5,4,4,2,43,23,4234] 1: 10,20,30,5,5,4,4,2,43,23,4234 2: 10 3: ,4234 [] 0: [] /(a(b(?2)c))?/DZ ------------------------------------------------------------------ Bra Brazero CBra 1 a CBra 2 b Recurse c Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string No options No first char No need char /(a(b(?2)c))*/DZ ------------------------------------------------------------------ Bra Brazero CBra 1 a CBra 2 b Recurse c Ket KetRmax Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string No options No first char No need char /(a(b(?2)c)){0,2}/DZ ------------------------------------------------------------------ Bra Brazero Bra CBra 1 a CBra 2 b Recurse c Ket Ket Brazero CBra 1 a CBra 2 b Recurse c Ket Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string No options No first char No need char /[ab]{1}+/DZ ------------------------------------------------------------------ Bra [ab]{1,1}+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/Ii Capturing subpattern count = 3 Options: caseless No first char Need char = 'g' (caseless) Baby Bjorn Active Carrier - With free SHIPPING!! 0: Baby Bjorn Active Carrier - With free SHIPPING!! 1: Baby Bjorn Active Carrier - With free SHIPPING!! /((w\/|-|with)*(free|immediate)*.*?shipping\s*[!.-]*)/IiS Capturing subpattern count = 3 Options: caseless No first char Need char = 'g' (caseless) Subject length lower bound = 8 No starting char list Baby Bjorn Active Carrier - With free SHIPPING!! 0: Baby Bjorn Active Carrier - With free SHIPPING!! 1: Baby Bjorn Active Carrier - With free SHIPPING!! /a*.*b/ISDZ ------------------------------------------------------------------ Bra a* Any* b Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char Need char = 'b' Subject length lower bound = 1 No starting char list /(a|b)*.?c/ISDZ ------------------------------------------------------------------ Bra Brazero CBra 1 a Alt b KetRmax Any? c Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 No options No first char Need char = 'c' Subject length lower bound = 1 No starting char list /abc(?C255)de(?C)f/DZ ------------------------------------------------------------------ Bra abc Callout 255 10 1 de Callout 0 16 1 f Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = 'a' Need char = 'f' /abcde/ICDZ ------------------------------------------------------------------ Bra Callout 255 0 1 a Callout 255 1 1 b Callout 255 2 1 c Callout 255 3 1 d Callout 255 4 1 e Callout 255 5 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: First char = 'a' Need char = 'e' abcde --->abcde +0 ^ a +1 ^^ b +2 ^ ^ c +3 ^ ^ d +4 ^ ^ e +5 ^ ^ 0: abcde abcdfe --->abcdfe +0 ^ a +1 ^^ b +2 ^ ^ c +3 ^ ^ d +4 ^ ^ e No match /a*b/ICDZS ------------------------------------------------------------------ Bra Callout 255 0 2 a*+ Callout 255 2 1 b Callout 255 3 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: No first char Need char = 'b' Subject length lower bound = 1 Starting chars: a b ab --->ab +0 ^ a* +2 ^^ b +3 ^ ^ 0: ab aaaab --->aaaab +0 ^ a* +2 ^ ^ b +3 ^ ^ 0: aaaab aaaacb --->aaaacb +0 ^ a* +2 ^ ^ b +0 ^ a* +2 ^ ^ b +0 ^ a* +2 ^ ^ b +0 ^ a* +2 ^^ b +0 ^ a* +2 ^ b +3 ^^ 0: b /a*b/ICDZSS ------------------------------------------------------------------ Bra Callout 255 0 2 a*+ Callout 255 2 1 b Callout 255 3 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: No first char Need char = 'b' ab --->ab +0 ^ a* +2 ^^ b +3 ^ ^ 0: ab aaaab --->aaaab +0 ^ a* +2 ^ ^ b +3 ^ ^ 0: aaaab aaaacb --->aaaacb +0 ^ a* +2 ^ ^ b +0 ^ a* +2 ^ ^ b +0 ^ a* +2 ^ ^ b +0 ^ a* +2 ^^ b +0 ^ a* +2 ^ b +0 ^ a* +2 ^ b +3 ^^ 0: b /a+b/ICDZ ------------------------------------------------------------------ Bra Callout 255 0 2 a++ Callout 255 2 1 b Callout 255 3 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: First char = 'a' Need char = 'b' ab --->ab +0 ^ a+ +2 ^^ b +3 ^ ^ 0: ab aaaab --->aaaab +0 ^ a+ +2 ^ ^ b +3 ^ ^ 0: aaaab aaaacb --->aaaacb +0 ^ a+ +2 ^ ^ b +0 ^ a+ +2 ^ ^ b +0 ^ a+ +2 ^ ^ b +0 ^ a+ +2 ^^ b No match /(abc|def)x/ICDZS ------------------------------------------------------------------ Bra Callout 255 0 9 CBra 1 Callout 255 1 1 a Callout 255 2 1 b Callout 255 3 1 c Callout 255 4 0 Alt Callout 255 5 1 d Callout 255 6 1 e Callout 255 7 1 f Callout 255 8 0 Ket Callout 255 9 1 x Callout 255 10 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: No first char Need char = 'x' Subject length lower bound = 4 Starting chars: a d abcx --->abcx +0 ^ (abc|def) +1 ^ a +2 ^^ b +3 ^ ^ c +4 ^ ^ | +9 ^ ^ x +10 ^ ^ 0: abcx 1: abc defx --->defx +0 ^ (abc|def) +1 ^ a +5 ^ d +6 ^^ e +7 ^ ^ f +8 ^ ^ ) +9 ^ ^ x +10 ^ ^ 0: defx 1: def ** Failers No match abcdefzx --->abcdefzx +0 ^ (abc|def) +1 ^ a +2 ^^ b +3 ^ ^ c +4 ^ ^ | +9 ^ ^ x +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d +6 ^^ e +7 ^ ^ f +8 ^ ^ ) +9 ^ ^ x No match /(abc|def)x/ICDZSS ------------------------------------------------------------------ Bra Callout 255 0 9 CBra 1 Callout 255 1 1 a Callout 255 2 1 b Callout 255 3 1 c Callout 255 4 0 Alt Callout 255 5 1 d Callout 255 6 1 e Callout 255 7 1 f Callout 255 8 0 Ket Callout 255 9 1 x Callout 255 10 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: No first char Need char = 'x' abcx --->abcx +0 ^ (abc|def) +1 ^ a +2 ^^ b +3 ^ ^ c +4 ^ ^ | +9 ^ ^ x +10 ^ ^ 0: abcx 1: abc defx --->defx +0 ^ (abc|def) +1 ^ a +5 ^ d +6 ^^ e +7 ^ ^ f +8 ^ ^ ) +9 ^ ^ x +10 ^ ^ 0: defx 1: def ** Failers No match abcdefzx --->abcdefzx +0 ^ (abc|def) +1 ^ a +2 ^^ b +3 ^ ^ c +4 ^ ^ | +9 ^ ^ x +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d +6 ^^ e +7 ^ ^ f +8 ^ ^ ) +9 ^ ^ x +0 ^ (abc|def) +1 ^ a +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d +0 ^ (abc|def) +1 ^ a +5 ^ d No match /(ab|cd){3,4}/IC Capturing subpattern count = 1 Options: No first char No need char ababab --->ababab +0 ^ (ab|cd){3,4} +1 ^ a +2 ^^ b +3 ^ ^ | +1 ^ ^ a +2 ^ ^ b +3 ^ ^ | +1 ^ ^ a +2 ^ ^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +12 ^ ^ 0: ababab 1: ab abcdabcd --->abcdabcd +0 ^ (ab|cd){3,4} +1 ^ a +2 ^^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +1 ^ ^ a +2 ^ ^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +12 ^ ^ 0: abcdabcd 1: cd abcdcdcdcdcd --->abcdcdcdcdcd +0 ^ (ab|cd){3,4} +1 ^ a +2 ^^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +12 ^ ^ 0: abcdcdcd 1: cd /([ab]{,4}c|xy)/ICDZS ------------------------------------------------------------------ Bra Callout 255 0 14 CBra 1 Callout 255 1 4 [ab] Callout 255 5 1 { Callout 255 6 1 , Callout 255 7 1 4 Callout 255 8 1 } Callout 255 9 1 c Callout 255 10 0 Alt Callout 255 11 1 x Callout 255 12 1 y Callout 255 13 0 Ket Callout 255 14 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: No first char No need char Subject length lower bound = 2 Starting chars: a b x Note: that { does NOT introduce a quantifier --->Note: that { does NOT introduce a quantifier +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +5 ^^ { +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +5 ^^ { +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +5 ^^ { +11 ^ x No match /([ab]{,4}c|xy)/ICDZSS ------------------------------------------------------------------ Bra Callout 255 0 14 CBra 1 Callout 255 1 4 [ab] Callout 255 5 1 { Callout 255 6 1 , Callout 255 7 1 4 Callout 255 8 1 } Callout 255 9 1 c Callout 255 10 0 Alt Callout 255 11 1 x Callout 255 12 1 y Callout 255 13 0 Ket Callout 255 14 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: No first char No need char Note: that { does NOT introduce a quantifier --->Note: that { does NOT introduce a quantifier +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +5 ^^ { +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +5 ^^ { +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +5 ^^ { +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x +0 ^ ([ab]{,4}c|xy) +1 ^ [ab] +11 ^ x No match /([ab]{1,4}c|xy){4,5}?123/ICDZ ------------------------------------------------------------------ Bra Callout 255 0 21 CBra 1 Callout 255 1 9 [ab]{1,4}+ Callout 255 10 1 c Callout 255 11 0 Alt Callout 255 12 1 x Callout 255 13 1 y Callout 255 14 0 Ket CBra 1 Callout 255 1 9 [ab]{1,4}+ Callout 255 10 1 c Callout 255 11 0 Alt Callout 255 12 1 x Callout 255 13 1 y Callout 255 14 0 Ket CBra 1 Callout 255 1 9 [ab]{1,4}+ Callout 255 10 1 c Callout 255 11 0 Alt Callout 255 12 1 x Callout 255 13 1 y Callout 255 14 0 Ket CBra 1 Callout 255 1 9 [ab]{1,4}+ Callout 255 10 1 c Callout 255 11 0 Alt Callout 255 12 1 x Callout 255 13 1 y Callout 255 14 0 Ket Braminzero CBra 1 Callout 255 1 9 [ab]{1,4}+ Callout 255 10 1 c Callout 255 11 0 Alt Callout 255 12 1 x Callout 255 13 1 y Callout 255 14 0 Ket Callout 255 21 1 1 Callout 255 22 1 2 Callout 255 23 1 3 Callout 255 24 0 Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: No first char Need char = '3' aacaacaacaacaac123 --->aacaacaacaacaac123 +0 ^ ([ab]{1,4}c|xy){4,5}? +1 ^ [ab]{1,4} +10 ^ ^ c +11 ^ ^ | +1 ^ ^ [ab]{1,4} +10 ^ ^ c +11 ^ ^ | +1 ^ ^ [ab]{1,4} +10 ^ ^ c +11 ^ ^ | +1 ^ ^ [ab]{1,4} +10 ^ ^ c +11 ^ ^ | +21 ^ ^ 1 +1 ^ ^ [ab]{1,4} +10 ^ ^ c +11 ^ ^ | +21 ^ ^ 1 +22 ^ ^ 2 +23 ^ ^ 3 +24 ^ ^ 0: aacaacaacaacaac123 1: aac /\b.*/I Capturing subpattern count = 0 Max lookbehind = 1 May match empty string No options No first char No need char ab cd\>1 0: cd /\b.*/Is Capturing subpattern count = 0 Max lookbehind = 1 May match empty string Options: dotall No first char No need char ab cd\>1 0: cd /(?!.bcd).*/I Capturing subpattern count = 0 May match empty string No options No first char No need char Xbcd12345 0: bcd12345 /abcde/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'e' ab\P Partial match: ab abc\P Partial match: abc abcd\P Partial match: abcd abcde\P 0: abcde the quick brown abc\P Partial match: abc ** Failers\P No match the quick brown abxyz fox\P No match "^(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/(20)?\d\d$"I Capturing subpattern count = 3 Options: anchored No first char Need char = '/' 13/05/04\P 0: 13/05/04 1: 13 2: 05 13/5/2004\P 0: 13/5/2004 1: 13 2: 5 3: 20 02/05/09\P 0: 02/05/09 1: 02 2: 05 1\P Partial match: 1 1/2\P Partial match: 1/2 1/2/0\P Partial match: 1/2/0 1/2/04\P 0: 1/2/04 1: 1 2: 2 0\P Partial match: 0 02/\P Partial match: 02/ 02/0\P Partial match: 02/0 02/1\P Partial match: 02/1 ** Failers\P No match \P No match 123\P No match 33/4/04\P No match 3/13/04\P No match 0/1/2003\P No match 0/\P No match 02/0/\P No match 02/13\P No match /0{0,2}ABC/I Capturing subpattern count = 0 No options No first char Need char = 'C' /\d{3,}ABC/I Capturing subpattern count = 0 No options No first char Need char = 'C' /\d*ABC/I Capturing subpattern count = 0 No options No first char Need char = 'C' /[abc]+DE/I Capturing subpattern count = 0 No options No first char Need char = 'E' /[abc]?123/I Capturing subpattern count = 0 No options No first char Need char = '3' 123\P 0: 123 a\P Partial match: a b\P Partial match: b c\P Partial match: c c12\P Partial match: c12 c123\P 0: c123 /^(?:\d){3,5}X/I Capturing subpattern count = 0 Options: anchored No first char Need char = 'X' 1\P Partial match: 1 123\P Partial match: 123 123X 0: 123X 1234\P Partial match: 1234 1234X 0: 1234X 12345\P Partial match: 12345 12345X 0: 12345X *** Failers No match 1X No match 123456\P No match //KF>testsavedregex Compiled pattern written to testsavedregex Study data written to testsavedregex /abc/IS>testsavedregex Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' Subject length lower bound = 3 No starting char list Compiled pattern written to testsavedregex Study data written to testsavedregex testsavedregex Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' Compiled pattern written to testsavedregex testsavedregex Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' Subject length lower bound = 3 No starting char list Compiled pattern written to testsavedregex Study data written to testsavedregex testsavedregex Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' Compiled pattern written to testsavedregex testsavedregex Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: a b Compiled pattern written to testsavedregex Study data written to testsavedregex testsavedregex Capturing subpattern count = 1 No options No first char No need char Compiled pattern written to testsavedregex testsavedregex Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: a b Compiled pattern written to testsavedregex Study data written to testsavedregex testsavedregex Capturing subpattern count = 1 No options No first char No need char Compiled pattern written to testsavedregex (.)*~smgI Capturing subpattern count = 3 Max back reference = 1 Options: multiline dotall First char = '<' Need char = '>' \J1024\n\n\nPartner der LCO\nde\nPartner der LINEAS Consulting\nGmbH\nLINEAS Consulting GmbH Hamburg\nPartnerfirmen\n30 days\nindex,follow\n\nja\n3\nPartner\n\n\nLCO\nLINEAS Consulting\n15.10.2003\n\n\n\n\nDie Partnerfirmen der LINEAS Consulting\nGmbH\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n 0: \x0a\x0aPartner der LCO\x0ade\x0aPartner der LINEAS Consulting\x0aGmbH\x0aLINEAS Consulting GmbH Hamburg\x0aPartnerfirmen\x0a30 days\x0aindex,follow\x0a\x0aja\x0a3\x0aPartner\x0a\x0a\x0aLCO\x0aLINEAS Consulting\x0a15.10.2003\x0a\x0a\x0a\x0a\x0aDie Partnerfirmen der LINEAS Consulting\x0aGmbH\x0a\x0a\x0a \x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a 1: seite 2: \x0a 3: seite /^a/IF Capturing subpattern count = 0 Options: anchored No first char No need char /line\nbreak/I Capturing subpattern count = 0 Contains explicit CR or LF match No options First char = 'l' Need char = 'k' this is a line\nbreak 0: line\x0abreak line one\nthis is a line\nbreak in the second line 0: line\x0abreak /line\nbreak/If Capturing subpattern count = 0 Contains explicit CR or LF match Options: firstline First char = 'l' Need char = 'k' this is a line\nbreak 0: line\x0abreak ** Failers No match line one\nthis is a line\nbreak in the second line No match /line\nbreak/Imf Capturing subpattern count = 0 Contains explicit CR or LF match Options: multiline firstline First char = 'l' Need char = 'k' this is a line\nbreak 0: line\x0abreak ** Failers No match line one\nthis is a line\nbreak in the second line No match /(?i)(?-i)AbCd/I Capturing subpattern count = 0 No options First char = 'A' Need char = 'd' AbCd 0: AbCd ** Failers No match abcd No match /a{11111111111111111111}/I Failed: number too big in {} quantifier at offset 8 /(){64294967295}/I Failed: number too big in {} quantifier at offset 9 /(){2,4294967295}/I Failed: number too big in {} quantifier at offset 11 "(?i:a)(?i:b)(?i:c)(?i:d)(?i:e)(?i:f)(?i:g)(?i:h)(?i:i)(?i:j)(k)(?i:l)A\1B"I Capturing subpattern count = 1 Max back reference = 1 No options First char = 'a' (caseless) Need char = 'B' abcdefghijklAkB 0: abcdefghijklAkB 1: k "(?Pa)(?Pb)(?Pc)(?Pd)(?Pe)(?Pf)(?Pg)(?Ph)(?Pi)(?Pj)(?Pk)(?Pl)A\11B"I Capturing subpattern count = 12 Max back reference = 11 Named capturing subpatterns: n0 1 n1 2 n10 11 n11 12 n2 3 n3 4 n4 5 n5 6 n6 7 n7 8 n8 9 n9 10 No options First char = 'a' Need char = 'B' abcdefghijklAkB 0: abcdefghijklAkB 1: a 2: b 3: c 4: d 5: e 6: f 7: g 8: h 9: i 10: j 11: k 12: l "(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)A\11B"I Capturing subpattern count = 12 Max back reference = 11 No options First char = 'a' Need char = 'B' abcdefghijklAkB 0: abcdefghijklAkB 1: a 2: b 3: c 4: d 5: e 6: f 7: g 8: h 9: i 10: j 11: k 12: l "(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)(?Pa)"I Capturing subpattern count = 101 Named capturing subpatterns: name0 1 name1 2 name10 11 name100 101 name11 12 name12 13 name13 14 name14 15 name15 16 name16 17 name17 18 name18 19 name19 20 name2 3 name20 21 name21 22 name22 23 name23 24 name24 25 name25 26 name26 27 name27 28 name28 29 name29 30 name3 4 name30 31 name31 32 name32 33 name33 34 name34 35 name35 36 name36 37 name37 38 name38 39 name39 40 name4 5 name40 41 name41 42 name42 43 name43 44 name44 45 name45 46 name46 47 name47 48 name48 49 name49 50 name5 6 name50 51 name51 52 name52 53 name53 54 name54 55 name55 56 name56 57 name57 58 name58 59 name59 60 name6 7 name60 61 name61 62 name62 63 name63 64 name64 65 name65 66 name66 67 name67 68 name68 69 name69 70 name7 8 name70 71 name71 72 name72 73 name73 74 name74 75 name75 76 name76 77 name77 78 name78 79 name79 80 name8 9 name80 81 name81 82 name82 83 name83 84 name84 85 name85 86 name86 87 name87 88 name88 89 name89 90 name9 10 name90 91 name91 92 name92 93 name93 94 name94 95 name95 96 name96 97 name97 98 name98 99 name99 100 No options First char = 'a' Need char = 'a' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Matched, but too many substrings 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1: a 2: a 3: a 4: a 5: a 6: a 7: a 8: a 9: a 10: a 11: a 12: a 13: a 14: a "(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)"I Capturing subpattern count = 101 No options First char = 'a' Need char = 'a' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Matched, but too many substrings 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1: a 2: a 3: a 4: a 5: a 6: a 7: a 8: a 9: a 10: a 11: a 12: a 13: a 14: a /[^()]*(?:\((?R)\)[^()]*)*/I Capturing subpattern count = 0 May match empty string No options No first char No need char (this(and)that 0: (this(and)that) 0: (this(and)that) (this(and)that)stuff 0: (this(and)that)stuff /[^()]*(?:\((?>(?R))\)[^()]*)*/I Capturing subpattern count = 0 May match empty string No options No first char No need char (this(and)that 0: (this(and)that) 0: (this(and)that) /[^()]*(?:\((?R)\))*[^()]*/I Capturing subpattern count = 0 May match empty string No options No first char No need char (this(and)that 0: (this(and)that) 0: (this(and)that) /(?:\((?R)\))*[^()]*/I Capturing subpattern count = 0 May match empty string No options No first char No need char (this(and)that 0: (this(and)that) 0: ((this)) 0: ((this)) /(?:\((?R)\))|[^()]*/I Capturing subpattern count = 0 May match empty string No options No first char No need char (this(and)that 0: (this(and)that) 0: (this) 0: (this) ((this)) 0: ((this)) /\x{0000ff}/I Capturing subpattern count = 0 No options First char = \xff No need char /^((?Pa1)|(?Pa2)b)/I Failed: two named subpatterns have the same name at offset 17 /^((?Pa1)|(?Pa2)b)/IJ Capturing subpattern count = 3 Named capturing subpatterns: A 2 A 3 Options: anchored dupnames No first char No need char a1b\CA 0: a1 1: a1 2: a1 C a1 (2) A a2b\CA 0: a2b 1: a2b 2: 3: a2 C a2 (2) A ** Failers No match a1b\CZ\CA no parentheses with name "Z" 0: a1 1: a1 2: a1 copy substring Z failed -7 C a1 (2) A /(?|(?)(?)(?)|(?)(?)(?))/IJ Capturing subpattern count = 3 Named capturing subpatterns: a 1 a 3 b 2 May match empty string Options: dupnames No first char No need char /^(?Pa)(?Pb)/IJ Capturing subpattern count = 2 Named capturing subpatterns: A 1 A 2 Options: anchored dupnames No first char No need char ab\CA 0: ab 1: a 2: b C a (1) A /^(?Pa)(?Pb)|cd/IJ Capturing subpattern count = 2 Named capturing subpatterns: A 1 A 2 Options: dupnames No first char No need char ab\CA 0: ab 1: a 2: b C a (1) A cd\CA 0: cd copy substring A failed -7 /^(?Pa)(?Pb)|cd(?Pef)(?Pgh)/IJ Capturing subpattern count = 4 Named capturing subpatterns: A 1 A 2 A 3 A 4 Options: dupnames No first char No need char cdefgh\CA 0: cdefgh 1: 2: 3: ef 4: gh C ef (2) A /^((?Pa1)|(?Pa2)b)/IJ Capturing subpattern count = 3 Named capturing subpatterns: A 2 A 3 Options: anchored dupnames No first char No need char a1b\GA 0: a1 1: a1 2: a1 G a1 (2) A a2b\GA 0: a2b 1: a2b 2: 3: a2 G a2 (2) A ** Failers No match a1b\GZ\GA no parentheses with name "Z" 0: a1 1: a1 2: a1 get substring Z failed -7 G a1 (2) A /^(?Pa)(?Pb)/IJ Capturing subpattern count = 2 Named capturing subpatterns: A 1 A 2 Options: anchored dupnames No first char No need char ab\GA 0: ab 1: a 2: b G a (1) A /^(?Pa)(?Pb)|cd/IJ Capturing subpattern count = 2 Named capturing subpatterns: A 1 A 2 Options: dupnames No first char No need char ab\GA 0: ab 1: a 2: b G a (1) A cd\GA 0: cd get substring A failed -7 /^(?Pa)(?Pb)|cd(?Pef)(?Pgh)/IJ Capturing subpattern count = 4 Named capturing subpatterns: A 1 A 2 A 3 A 4 Options: dupnames No first char No need char cdefgh\GA 0: cdefgh 1: 2: 3: ef 4: gh G ef (2) A /(?J)^((?Pa1)|(?Pa2)b)/I Capturing subpattern count = 3 Named capturing subpatterns: A 2 A 3 Options: anchored Duplicate name status changes No first char No need char a1b\CA 0: a1 1: a1 2: a1 C a1 (2) A a2b\CA 0: a2b 1: a2b 2: 3: a2 C a2 (2) A /^(?Pa) (?J:(?Pb)(?Pc)) (?Pd)/I Failed: two named subpatterns have the same name at offset 37 / In this next test, J is not set at the outer level; consequently it isn't set in the pattern's options; consequently pcre_get_named_substring() produces a random value. /Ix Capturing subpattern count = 1 Options: extended First char = 'I' Need char = 'e' /^(?Pa) (?J:(?Pb)(?Pc)) (?Pd)/I Capturing subpattern count = 4 Named capturing subpatterns: A 1 B 2 B 3 C 4 Options: anchored Duplicate name status changes No first char No need char a bc d\CA\CB\CC 0: a bc d 1: a 2: b 3: c 4: d C a (1) A C b (1) B C d (1) C /^(?Pa)?(?(A)a|b)/I Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: A 1 Options: anchored No first char No need char aabc 0: aa 1: a bc 0: b ** Failers No match abc No match /(?:(?(ZZ)a|b)(?PX))+/I Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: ZZ 1 No options No first char Need char = 'X' bXaX 0: bXaX 1: X /(?:(?(2y)a|b)(X))+/I Failed: malformed number or name after (?( at offset 7 /(?:(?(ZA)a|b)(?PX))+/I Failed: reference to non-existent subpattern at offset 9 /(?:(?(ZZ)a|b)(?(ZZ)a|b)(?PX))+/I Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: ZZ 1 No options No first char Need char = 'X' bbXaaX 0: bbXaaX 1: X /(?:(?(ZZ)a|\(b\))\\(?PX))+/I Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: ZZ 1 No options No first char Need char = 'X' (b)\\Xa\\X 0: (b)\Xa\X 1: X /(?PX|Y))+/I Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: A 1 No options No first char No need char bXXaYYaY 0: bXXaYYaY 1: Y bXYaXXaX 0: bX 1: X /()()()()()()()()()(?:(?(A)(?P=A)a|b)(?PX|Y))+/I Capturing subpattern count = 10 Max back reference = 10 Named capturing subpatterns: A 10 No options No first char No need char bXXaYYaY 0: bXXaYYaY 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: Y /\s*,\s*/IS Capturing subpattern count = 0 No options No first char Need char = ',' Subject length lower bound = 1 Starting chars: \x09 \x0a \x0b \x0c \x0d \x20 , \x0b,\x0b 0: \x0b,\x0b \x0c,\x0d 0: \x0c,\x0d /^abc/Im Capturing subpattern count = 0 Options: multiline First char at start or follows newline Need char = 'c' xyz\nabc 0: abc xyz\nabc\ 0: abc xyz\r\nabc\ 0: abc xyz\rabc\ 0: abc xyz\r\nabc\ 0: abc ** Failers No match xyz\nabc\ No match xyz\r\nabc\ No match xyz\nabc\ No match xyz\rabc\ No match xyz\rabc\ No match /abc$/Im Capturing subpattern count = 0 Options: multiline Forced newline sequence: LF First char = 'a' Need char = 'c' xyzabc 0: abc xyzabc\n 0: abc xyzabc\npqr 0: abc xyzabc\r\ 0: abc xyzabc\rpqr\ 0: abc xyzabc\r\n\ 0: abc xyzabc\r\npqr\ 0: abc ** Failers No match xyzabc\r No match xyzabc\rpqr No match xyzabc\r\n No match xyzabc\r\npqr No match /^abc/Im Capturing subpattern count = 0 Options: multiline Forced newline sequence: CR First char at start or follows newline Need char = 'c' xyz\rabcdef 0: abc xyz\nabcdef\ 0: abc ** Failers No match xyz\nabcdef No match /^abc/Im Capturing subpattern count = 0 Options: multiline Forced newline sequence: LF First char at start or follows newline Need char = 'c' xyz\nabcdef 0: abc xyz\rabcdef\ 0: abc ** Failers No match xyz\rabcdef No match /^abc/Im Capturing subpattern count = 0 Options: multiline Forced newline sequence: CRLF First char at start or follows newline Need char = 'c' xyz\r\nabcdef 0: abc xyz\rabcdef\ 0: abc ** Failers No match xyz\rabcdef No match /^abc/Im Unknown modifier at: /abc/I Capturing subpattern count = 0 No options First char = 'a' Need char = 'c' xyz\rabc\ Unknown escape sequence at: abc 0: abc /.*/I Capturing subpattern count = 0 May match empty string Options: Forced newline sequence: LF First char at start or follows newline No need char abc\ndef 0: abc abc\rdef 0: abc\x0ddef abc\r\ndef 0: abc\x0d \abc\ndef 0: abc\x0adef \abc\rdef 0: abc \abc\r\ndef 0: abc \abc\ndef 0: abc\x0adef \abc\rdef 0: abc\x0ddef \abc\r\ndef 0: abc /\w+(.)(.)?def/Is Capturing subpattern count = 2 Options: dotall No first char Need char = 'f' abc\ndef 0: abc\x0adef 1: \x0a abc\rdef 0: abc\x0ddef 1: \x0d abc\r\ndef 0: abc\x0d\x0adef 1: \x0d 2: \x0a +((?:\s|//.*\\n|/[*](?:\\n|.)*?[*]/)*)+I Capturing subpattern count = 1 May match empty string No options No first char No need char /* this is a C style comment */\M Minimum match() limit = 120 Minimum match() recursion limit = 6 0: /* this is a C style comment */ 1: /* this is a C style comment */ /(?P25[0-5]|2[0-4]\d|[01]?\d?\d)(?:\.(?P>B)){3}/I Capturing subpattern count = 1 Named capturing subpatterns: B 1 No options No first char Need char = '.' /()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() ()()()()()()()()()()()()()()()()()()()() (.(.))/Ix Capturing subpattern count = 102 Options: extended No first char No need char XY\O400 0: XY 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: XY 102: Y /(a*b|(?i:c*(?-i)d))/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: C a b c d /()[ab]xyz/IS Capturing subpattern count = 1 No options No first char Need char = 'z' Subject length lower bound = 4 Starting chars: a b /(|)[ab]xyz/IS Capturing subpattern count = 1 No options No first char Need char = 'z' Subject length lower bound = 4 Starting chars: a b /(|c)[ab]xyz/IS Capturing subpattern count = 1 No options No first char Need char = 'z' Subject length lower bound = 4 Starting chars: a b c /(|c?)[ab]xyz/IS Capturing subpattern count = 1 No options No first char Need char = 'z' Subject length lower bound = 4 Starting chars: a b c /(d?|c?)[ab]xyz/IS Capturing subpattern count = 1 No options No first char Need char = 'z' Subject length lower bound = 4 Starting chars: a b c d /(d?|c)[ab]xyz/IS Capturing subpattern count = 1 No options No first char Need char = 'z' Subject length lower bound = 4 Starting chars: a b c d /^a*b\d/DZ ------------------------------------------------------------------ Bra ^ a*+ b \d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char Need char = 'b' /^a*+b\d/DZ ------------------------------------------------------------------ Bra ^ a*+ b \d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char Need char = 'b' /^a*?b\d/DZ ------------------------------------------------------------------ Bra ^ a*+ b \d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char Need char = 'b' /^a+A\d/DZ ------------------------------------------------------------------ Bra ^ a++ A \d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored No first char Need char = 'A' aaaA5 0: aaaA5 ** Failers No match aaaa5 No match /^a*A\d/IiDZ ------------------------------------------------------------------ Bra ^ /i a* /i A \d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored caseless No first char Need char = 'A' (caseless) aaaA5 0: aaaA5 aaaa5 0: aaaa5 /(a*|b*)[cd]/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: a b c d /(a+|b*)[cd]/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: a b c d /(a*|b+)[cd]/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: a b c d /(a+|b+)[cd]/IS Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((( a )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) )))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ))) /Ix Capturing subpattern count = 203 Options: extended First char = 'a' No need char large nest Matched, but too many substrings 0: a 1: a 2: a 3: a 4: a 5: a 6: a 7: a 8: a 9: a 10: a 11: a 12: a 13: a 14: a /a*\d/BZ ------------------------------------------------------------------ Bra a*+ \d Ket End ------------------------------------------------------------------ /a*\D/BZ ------------------------------------------------------------------ Bra a* \D Ket End ------------------------------------------------------------------ /0*\d/BZ ------------------------------------------------------------------ Bra 0* \d Ket End ------------------------------------------------------------------ /0*\D/BZ ------------------------------------------------------------------ Bra 0*+ \D Ket End ------------------------------------------------------------------ /a*\s/BZ ------------------------------------------------------------------ Bra a*+ \s Ket End ------------------------------------------------------------------ /a*\S/BZ ------------------------------------------------------------------ Bra a* \S Ket End ------------------------------------------------------------------ / *\s/BZ ------------------------------------------------------------------ Bra * \s Ket End ------------------------------------------------------------------ / *\S/BZ ------------------------------------------------------------------ Bra *+ \S Ket End ------------------------------------------------------------------ /a*\w/BZ ------------------------------------------------------------------ Bra a* \w Ket End ------------------------------------------------------------------ /a*\W/BZ ------------------------------------------------------------------ Bra a*+ \W Ket End ------------------------------------------------------------------ /=*\w/BZ ------------------------------------------------------------------ Bra =*+ \w Ket End ------------------------------------------------------------------ /=*\W/BZ ------------------------------------------------------------------ Bra =* \W Ket End ------------------------------------------------------------------ /\d*a/BZ ------------------------------------------------------------------ Bra \d*+ a Ket End ------------------------------------------------------------------ /\d*2/BZ ------------------------------------------------------------------ Bra \d* 2 Ket End ------------------------------------------------------------------ /\d*\d/BZ ------------------------------------------------------------------ Bra \d* \d Ket End ------------------------------------------------------------------ /\d*\D/BZ ------------------------------------------------------------------ Bra \d*+ \D Ket End ------------------------------------------------------------------ /\d*\s/BZ ------------------------------------------------------------------ Bra \d*+ \s Ket End ------------------------------------------------------------------ /\d*\S/BZ ------------------------------------------------------------------ Bra \d* \S Ket End ------------------------------------------------------------------ /\d*\w/BZ ------------------------------------------------------------------ Bra \d* \w Ket End ------------------------------------------------------------------ /\d*\W/BZ ------------------------------------------------------------------ Bra \d*+ \W Ket End ------------------------------------------------------------------ /\D*a/BZ ------------------------------------------------------------------ Bra \D* a Ket End ------------------------------------------------------------------ /\D*2/BZ ------------------------------------------------------------------ Bra \D*+ 2 Ket End ------------------------------------------------------------------ /\D*\d/BZ ------------------------------------------------------------------ Bra \D*+ \d Ket End ------------------------------------------------------------------ /\D*\D/BZ ------------------------------------------------------------------ Bra \D* \D Ket End ------------------------------------------------------------------ /\D*\s/BZ ------------------------------------------------------------------ Bra \D* \s Ket End ------------------------------------------------------------------ /\D*\S/BZ ------------------------------------------------------------------ Bra \D* \S Ket End ------------------------------------------------------------------ /\D*\w/BZ ------------------------------------------------------------------ Bra \D* \w Ket End ------------------------------------------------------------------ /\D*\W/BZ ------------------------------------------------------------------ Bra \D* \W Ket End ------------------------------------------------------------------ /\s*a/BZ ------------------------------------------------------------------ Bra \s*+ a Ket End ------------------------------------------------------------------ /\s*2/BZ ------------------------------------------------------------------ Bra \s*+ 2 Ket End ------------------------------------------------------------------ /\s*\d/BZ ------------------------------------------------------------------ Bra \s*+ \d Ket End ------------------------------------------------------------------ /\s*\D/BZ ------------------------------------------------------------------ Bra \s* \D Ket End ------------------------------------------------------------------ /\s*\s/BZ ------------------------------------------------------------------ Bra \s* \s Ket End ------------------------------------------------------------------ /\s*\S/BZ ------------------------------------------------------------------ Bra \s*+ \S Ket End ------------------------------------------------------------------ /\s*\w/BZ ------------------------------------------------------------------ Bra \s*+ \w Ket End ------------------------------------------------------------------ /\s*\W/BZ ------------------------------------------------------------------ Bra \s* \W Ket End ------------------------------------------------------------------ /\S*a/BZ ------------------------------------------------------------------ Bra \S* a Ket End ------------------------------------------------------------------ /\S*2/BZ ------------------------------------------------------------------ Bra \S* 2 Ket End ------------------------------------------------------------------ /\S*\d/BZ ------------------------------------------------------------------ Bra \S* \d Ket End ------------------------------------------------------------------ /\S*\D/BZ ------------------------------------------------------------------ Bra \S* \D Ket End ------------------------------------------------------------------ /\S*\s/BZ ------------------------------------------------------------------ Bra \S*+ \s Ket End ------------------------------------------------------------------ /\S*\S/BZ ------------------------------------------------------------------ Bra \S* \S Ket End ------------------------------------------------------------------ /\S*\w/BZ ------------------------------------------------------------------ Bra \S* \w Ket End ------------------------------------------------------------------ /\S*\W/BZ ------------------------------------------------------------------ Bra \S* \W Ket End ------------------------------------------------------------------ /\w*a/BZ ------------------------------------------------------------------ Bra \w* a Ket End ------------------------------------------------------------------ /\w*2/BZ ------------------------------------------------------------------ Bra \w* 2 Ket End ------------------------------------------------------------------ /\w*\d/BZ ------------------------------------------------------------------ Bra \w* \d Ket End ------------------------------------------------------------------ /\w*\D/BZ ------------------------------------------------------------------ Bra \w* \D Ket End ------------------------------------------------------------------ /\w*\s/BZ ------------------------------------------------------------------ Bra \w*+ \s Ket End ------------------------------------------------------------------ /\w*\S/BZ ------------------------------------------------------------------ Bra \w* \S Ket End ------------------------------------------------------------------ /\w*\w/BZ ------------------------------------------------------------------ Bra \w* \w Ket End ------------------------------------------------------------------ /\w*\W/BZ ------------------------------------------------------------------ Bra \w*+ \W Ket End ------------------------------------------------------------------ /\W*a/BZ ------------------------------------------------------------------ Bra \W*+ a Ket End ------------------------------------------------------------------ /\W*2/BZ ------------------------------------------------------------------ Bra \W*+ 2 Ket End ------------------------------------------------------------------ /\W*\d/BZ ------------------------------------------------------------------ Bra \W*+ \d Ket End ------------------------------------------------------------------ /\W*\D/BZ ------------------------------------------------------------------ Bra \W* \D Ket End ------------------------------------------------------------------ /\W*\s/BZ ------------------------------------------------------------------ Bra \W* \s Ket End ------------------------------------------------------------------ /\W*\S/BZ ------------------------------------------------------------------ Bra \W* \S Ket End ------------------------------------------------------------------ /\W*\w/BZ ------------------------------------------------------------------ Bra \W*+ \w Ket End ------------------------------------------------------------------ /\W*\W/BZ ------------------------------------------------------------------ Bra \W* \W Ket End ------------------------------------------------------------------ /[^a]+a/BZ ------------------------------------------------------------------ Bra [^a]++ a Ket End ------------------------------------------------------------------ /[^a]+a/BZi ------------------------------------------------------------------ Bra /i [^a]++ /i a Ket End ------------------------------------------------------------------ /[^a]+A/BZi ------------------------------------------------------------------ Bra /i [^a]++ /i A Ket End ------------------------------------------------------------------ /[^a]+b/BZ ------------------------------------------------------------------ Bra [^a]+ b Ket End ------------------------------------------------------------------ /[^a]+\d/BZ ------------------------------------------------------------------ Bra [^a]+ \d Ket End ------------------------------------------------------------------ /a*[^a]/BZ ------------------------------------------------------------------ Bra a*+ [^a] Ket End ------------------------------------------------------------------ /(?Px)(?Py)/I Capturing subpattern count = 2 Named capturing subpatterns: abc 1 xyz 2 No options First char = 'x' Need char = 'y' xy\Cabc\Cxyz 0: xy 1: x 2: y C x (1) abc C y (1) xyz /(?x)(?'xyz'y)/I Capturing subpattern count = 2 Named capturing subpatterns: abc 1 xyz 2 No options First char = 'x' Need char = 'y' xy\Cabc\Cxyz 0: xy 1: x 2: y C x (1) abc C y (1) xyz /(?x)(?'xyz>y)/I Failed: syntax error in subpattern name (missing terminator) at offset 15 /(?P'abc'x)(?Py)/I Failed: unrecognized character after (?P at offset 3 /^(?:(?(ZZ)a|b)(?X))+/ bXaX 0: bXaX 1: X bXbX 0: bX 1: X ** Failers No match aXaX No match aXbX No match /^(?P>abc)(?xxx)/ Failed: reference to non-existent subpattern at offset 8 /^(?P>abc)(?x|y)/ xx 0: xx 1: x xy 0: xy 1: y yy 0: yy 1: y yx 0: yx 1: x /^(?P>abc)(?Px|y)/ xx 0: xx 1: x xy 0: xy 1: y yy 0: yy 1: y yx 0: yx 1: x /^((?(abc)a|b)(?x|y))+/ bxay 0: bxay 1: ay 2: y bxby 0: bx 1: bx 2: x ** Failers No match axby No match /^(((?P=abc)|X)(?x|y))+/ XxXxxx 0: XxXxxx 1: xx 2: x 3: x XxXyyx 0: XxXyyx 1: yx 2: y 3: x XxXyxx 0: XxXy 1: Xy 2: X 3: y ** Failers No match x No match /^(?1)(abc)/ abcabc 0: abcabc 1: abc /^(?:(?:\1|X)(a|b))+/ Xaaa 0: Xaaa 1: a Xaba 0: Xa 1: a /^[\E\Qa\E-\Qz\E]+/BZ ------------------------------------------------------------------ Bra ^ [a-z]++ Ket End ------------------------------------------------------------------ /^[a\Q]bc\E]/BZ ------------------------------------------------------------------ Bra ^ [\]a-c] Ket End ------------------------------------------------------------------ /^[a-\Q\E]/BZ ------------------------------------------------------------------ Bra ^ [\-a] Ket End ------------------------------------------------------------------ /^(?P>abc)[()](?)/BZ ------------------------------------------------------------------ Bra ^ Recurse [()] CBra 1 Ket Ket End ------------------------------------------------------------------ /^((?(abc)y)[()](?Px))+/BZ ------------------------------------------------------------------ Bra ^ CBra 1 Cond 2 Cond ref y Ket [()] CBra 2 x Ket KetRmax Ket End ------------------------------------------------------------------ (xy)x 0: (xy)x 1: y)x 2: x /^(?P>abc)\Q()\E(?)/BZ ------------------------------------------------------------------ Bra ^ Recurse () CBra 1 Ket Ket End ------------------------------------------------------------------ /^(?P>abc)[a\Q(]\E(](?)/BZ ------------------------------------------------------------------ Bra ^ Recurse [(\]a] CBra 1 Ket Ket End ------------------------------------------------------------------ /^(?P>abc) # this is (a comment) (?)/BZx ------------------------------------------------------------------ Bra ^ Recurse CBra 1 Ket Ket End ------------------------------------------------------------------ /^\W*(?:(?(?.)\W*(?&one)\W*\k|)|(?(?.)\W*(?&three)\W*\k'four'|\W*.\W*))\W*$/Ii Capturing subpattern count = 4 Max back reference = 4 Named capturing subpatterns: four 4 one 1 three 3 two 2 May match empty string Options: anchored caseless No first char No need char 1221 0: 1221 1: 1221 2: 1 Satan, oscillate my metallic sonatas! 0: Satan, oscillate my metallic sonatas! 1: 2: 3: Satan, oscillate my metallic sonatas 4: S A man, a plan, a canal: Panama! 0: A man, a plan, a canal: Panama! 1: 2: 3: A man, a plan, a canal: Panama 4: A Able was I ere I saw Elba. 0: Able was I ere I saw Elba. 1: 2: 3: Able was I ere I saw Elba 4: A *** Failers No match The quick brown fox No match /(?=(\w+))\1:/I Capturing subpattern count = 1 Max back reference = 1 No options No first char Need char = ':' abcd: 0: abcd: 1: abcd /(?=(?'abc'\w+))\k:/I Capturing subpattern count = 1 Max back reference = 1 Named capturing subpatterns: abc 1 No options No first char Need char = ':' abcd: 0: abcd: 1: abcd /(?'abc'a|b)(?d|e)\k{2}/J adaa 0: adaa 1: a 2: d ** Failers No match addd No match adbb No match /(?'abc'a|b)(?d|e)(?&abc){2}/J bdaa 0: bdaa 1: b 2: d bdab 0: bdab 1: b 2: d ** Failers No match bddd No match /(?( (?'B' abc (?(R) (?(R&A)1) (?(R&B)2) X | (?1) (?2) (?R) ))) /x abcabc1Xabc2XabcXabcabc 0: abcabc1Xabc2XabcX 1: abcabc1Xabc2XabcX 2: abcabc1Xabc2XabcX /(? (?'B' abc (?(R) (?(R&C)1) (?(R&B)2) X | (?1) (?2) (?R) ))) /x Failed: reference to non-existent subpattern at offset 29 /^(?(DEFINE) abc | xyz ) /x Failed: DEFINE group contains more than one branch at offset 22 /(?(DEFINE) abc) xyz/xI Capturing subpattern count = 0 Options: extended First char = 'x' Need char = 'z' /(a|)*\d/ \O0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match \O0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 Matched, but too many substrings /^a.b/ a\rb 0: a\x0db a\nb\ 0: a\x0ab a\x85b\ 0: a\x85b ** Failers No match a\nb No match a\nb\ No match a\rb\ No match a\rb\ No match a\x85b\ No match a\rb\ No match /^abc./mgx abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x85abc7 JUNK 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc7 /abc.$/mgx abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x85 abc7 abc9 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc9 /a/ /a/ Failed: inconsistent NEWLINE options at offset 0 /^a\Rb/ a\nb 0: a\x0ab a\rb 0: a\x0db a\r\nb 0: a\x0d\x0ab a\x0bb 0: a\x0bb a\x0cb 0: a\x0cb a\x85b 0: a\x85b ** Failers No match a\n\rb No match /^a\R*b/ ab 0: ab a\nb 0: a\x0ab a\rb 0: a\x0db a\r\nb 0: a\x0d\x0ab a\x0bb 0: a\x0bb a\x0cb 0: a\x0cb a\x85b 0: a\x85b a\n\rb 0: a\x0a\x0db a\n\r\x85\x0cb 0: a\x0a\x0d\x85\x0cb /^a\R+b/ a\nb 0: a\x0ab a\rb 0: a\x0db a\r\nb 0: a\x0d\x0ab a\x0bb 0: a\x0bb a\x0cb 0: a\x0cb a\x85b 0: a\x85b a\n\rb 0: a\x0a\x0db a\n\r\x85\x0cb 0: a\x0a\x0d\x85\x0cb ** Failers No match ab No match /^a\R{1,3}b/ a\nb 0: a\x0ab a\n\rb 0: a\x0a\x0db a\n\r\x85b 0: a\x0a\x0d\x85b a\r\n\r\nb 0: a\x0d\x0a\x0d\x0ab a\r\n\r\n\r\nb 0: a\x0d\x0a\x0d\x0a\x0d\x0ab a\n\r\n\rb 0: a\x0a\x0d\x0a\x0db a\n\n\r\nb 0: a\x0a\x0a\x0d\x0ab ** Failers No match a\n\n\n\rb No match a\r No match /^a[\R]b/ aRb 0: aRb ** Failers No match a\nb No match /(?&abc)X(?P)/I Capturing subpattern count = 1 Named capturing subpatterns: abc 1 No options No first char Need char = 'P' abcPXP123 0: PXP 1: P /(?1)X(?P)/I Capturing subpattern count = 1 Named capturing subpatterns: abc 1 No options No first char Need char = 'P' abcPXP123 0: PXP 1: P /(?:a(?&abc)b)*(?x)/ 123axbaxbaxbx456 0: axbaxbaxbx 1: x 123axbaxbaxb456 0: x 1: x /(?:a(?&abc)b){1,5}(?x)/ 123axbaxbaxbx456 0: axbaxbaxbx 1: x /(?:a(?&abc)b){2,5}(?x)/ 123axbaxbaxbx456 0: axbaxbaxbx 1: x /(?:a(?&abc)b){2,}(?x)/ 123axbaxbaxbx456 0: axbaxbaxbx 1: x /(abc)(?i:(?1))/ defabcabcxyz 0: abcabc 1: abc DEFabcABCXYZ No match /(abc)(?:(?i)(?1))/ defabcabcxyz 0: abcabc 1: abc DEFabcABCXYZ No match /^(a)\g-2/ Failed: reference to non-existent subpattern at offset 7 /^(a)\g/ Failed: a numbered reference must not be zero at offset 5 /^(a)\g{0}/ Failed: a numbered reference must not be zero at offset 8 /^(a)\g{3/ Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 8 /^(a)\g{aa}/ Failed: reference to non-existent subpattern at offset 9 /^a.b/ a\rb 0: a\x0db *** Failers No match a\nb No match /.+foo/ afoo 0: afoo ** Failers No match \r\nfoo No match \nfoo No match /.+foo/ afoo 0: afoo \nfoo 0: \x0afoo ** Failers No match \r\nfoo No match /.+foo/ afoo 0: afoo ** Failers No match \nfoo No match \r\nfoo No match /.+foo/s afoo 0: afoo \r\nfoo 0: \x0d\x0afoo \nfoo 0: \x0afoo /^$/mg abc\r\rxyz 0: abc\n\rxyz 0: ** Failers No match abc\r\nxyz No match /(?m)^$/g+ abc\r\n\r\n 0: 0+ \x0d\x0a /(?m)^$|^\r\n/g+ abc\r\n\r\n 0: 0+ \x0d\x0a 0: \x0d\x0a 0+ /(?m)$/g+ abc\r\n\r\n 0: 0+ \x0d\x0a\x0d\x0a 0: 0+ \x0d\x0a 0: 0+ /abc.$/mgx abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x85 abc9 0: abc1 0: abc4 0: abc5 0: abc9 /^X/m XABC 0: X ** Failers No match XABC\B No match /(ab|c)(?-1)/BZ ------------------------------------------------------------------ Bra CBra 1 ab Alt c Ket Recurse Ket End ------------------------------------------------------------------ abc 0: abc 1: ab /xy(?+1)(abc)/BZ ------------------------------------------------------------------ Bra xy Recurse CBra 1 abc Ket Ket End ------------------------------------------------------------------ xyabcabc 0: xyabcabc 1: abc ** Failers No match xyabc No match /x(?-0)y/ Failed: a numbered reference must not be zero at offset 5 /x(?-1)y/ Failed: reference to non-existent subpattern at offset 5 /x(?+0)y/ Failed: a numbered reference must not be zero at offset 5 /x(?+1)y/ Failed: reference to non-existent subpattern at offset 5 /^(abc)?(?(-1)X|Y)/BZ ------------------------------------------------------------------ Bra ^ Brazero CBra 1 abc Ket Cond 1 Cond ref X Alt Y Ket Ket End ------------------------------------------------------------------ abcX 0: abcX 1: abc Y 0: Y ** Failers No match abcY No match /^((?(+1)X|Y)(abc))+/BZ ------------------------------------------------------------------ Bra ^ CBra 1 Cond 2 Cond ref X Alt Y Ket CBra 2 abc Ket KetRmax Ket End ------------------------------------------------------------------ YabcXabc 0: YabcXabc 1: Xabc 2: abc YabcXabcXabc 0: YabcXabcXabc 1: Xabc 2: abc ** Failers No match XabcXabc No match /(?(-1)a)/BZ Failed: reference to non-existent subpattern at offset 6 /((?(-1)a))/BZ ------------------------------------------------------------------ Bra CBra 1 Cond 1 Cond ref a Ket Ket Ket End ------------------------------------------------------------------ /((?(-2)a))/BZ Failed: reference to non-existent subpattern at offset 7 /^(?(+1)X|Y)(.)/BZ ------------------------------------------------------------------ Bra ^ Cond 1 Cond ref X Alt Y Ket CBra 1 Any Ket Ket End ------------------------------------------------------------------ Y! 0: Y! 1: ! /(?tom|bon)-\k{A}/ tom-tom 0: tom-tom 1: tom bon-bon 0: bon-bon 1: bon ** Failers No match tom-bon No match /\g{A/ Failed: syntax error in subpattern name (missing terminator) at offset 4 /(?|(abc)|(xyz))/BZ ------------------------------------------------------------------ Bra Bra CBra 1 abc Ket Alt CBra 1 xyz Ket Ket Ket End ------------------------------------------------------------------ >abc< 0: abc 1: abc >xyz< 0: xyz 1: xyz /(x)(?|(abc)|(xyz))(x)/BZ ------------------------------------------------------------------ Bra CBra 1 x Ket Bra CBra 2 abc Ket Alt CBra 2 xyz Ket Ket CBra 3 x Ket Ket End ------------------------------------------------------------------ xabcx 0: xabcx 1: x 2: abc 3: x xxyzx 0: xxyzx 1: x 2: xyz 3: x /(x)(?|(abc)(pqr)|(xyz))(x)/BZ ------------------------------------------------------------------ Bra CBra 1 x Ket Bra CBra 2 abc Ket CBra 3 pqr Ket Alt CBra 2 xyz Ket Ket CBra 4 x Ket Ket End ------------------------------------------------------------------ xabcpqrx 0: xabcpqrx 1: x 2: abc 3: pqr 4: x xxyzx 0: xxyzx 1: x 2: xyz 3: 4: x /\H++X/BZ ------------------------------------------------------------------ Bra \H++ X Ket End ------------------------------------------------------------------ ** Failers No match XXXX No match /\H+\hY/BZ ------------------------------------------------------------------ Bra \H++ \h Y Ket End ------------------------------------------------------------------ XXXX Y 0: XXXX Y /\H+ Y/BZ ------------------------------------------------------------------ Bra \H++ Y Ket End ------------------------------------------------------------------ /\h+A/BZ ------------------------------------------------------------------ Bra \h++ A Ket End ------------------------------------------------------------------ /\v*B/BZ ------------------------------------------------------------------ Bra \v*+ B Ket End ------------------------------------------------------------------ /\V+\x0a/BZ ------------------------------------------------------------------ Bra \V++ \x0a Ket End ------------------------------------------------------------------ /A+\h/BZ ------------------------------------------------------------------ Bra A++ \h Ket End ------------------------------------------------------------------ / *\H/BZ ------------------------------------------------------------------ Bra *+ \H Ket End ------------------------------------------------------------------ /A*\v/BZ ------------------------------------------------------------------ Bra A*+ \v Ket End ------------------------------------------------------------------ /\x0b*\V/BZ ------------------------------------------------------------------ Bra \x0b*+ \V Ket End ------------------------------------------------------------------ /\d+\h/BZ ------------------------------------------------------------------ Bra \d++ \h Ket End ------------------------------------------------------------------ /\d*\v/BZ ------------------------------------------------------------------ Bra \d*+ \v Ket End ------------------------------------------------------------------ /S+\h\S+\v/BZ ------------------------------------------------------------------ Bra S++ \h \S++ \v Ket End ------------------------------------------------------------------ /\w{3,}\h\w+\v/BZ ------------------------------------------------------------------ Bra \w{3} \w*+ \h \w++ \v Ket End ------------------------------------------------------------------ /\h+\d\h+\w\h+\S\h+\H/BZ ------------------------------------------------------------------ Bra \h++ \d \h++ \w \h++ \S \h++ \H Ket End ------------------------------------------------------------------ /\v+\d\v+\w\v+\S\v+\V/BZ ------------------------------------------------------------------ Bra \v++ \d \v++ \w \v++ \S \v++ \V Ket End ------------------------------------------------------------------ /\H+\h\H+\d/BZ ------------------------------------------------------------------ Bra \H++ \h \H+ \d Ket End ------------------------------------------------------------------ /\V+\v\V+\w/BZ ------------------------------------------------------------------ Bra \V++ \v \V+ \w Ket End ------------------------------------------------------------------ /\( (?: [^()]* | (?R) )* \)/x \J1024(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(00)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0) 0: (0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(0(00)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)0) /[\E]AAA/ Failed: missing terminating ] for character class at offset 7 /[\Q\E]AAA/ Failed: missing terminating ] for character class at offset 9 /[^\E]AAA/ Failed: missing terminating ] for character class at offset 8 /[^\Q\E]AAA/ Failed: missing terminating ] for character class at offset 10 /[\E^]AAA/ Failed: missing terminating ] for character class at offset 8 /[\Q\E^]AAA/ Failed: missing terminating ] for character class at offset 10 /A(*PRUNE)B(*SKIP)C(*THEN)D(*COMMIT)E(*F)F(*FAIL)G(?!)H(*ACCEPT)I/BZ ------------------------------------------------------------------ Bra A *PRUNE B *SKIP C *THEN D *COMMIT E *FAIL F *FAIL G *FAIL H *ACCEPT I Ket End ------------------------------------------------------------------ /^a+(*FAIL)/C aaaaaa --->aaaaaa +0 ^ ^ +1 ^ a+ +3 ^ ^ (*FAIL) +3 ^ ^ (*FAIL) +3 ^ ^ (*FAIL) +3 ^ ^ (*FAIL) +3 ^ ^ (*FAIL) +3 ^^ (*FAIL) No match /a+b?c+(*FAIL)/C aaabccc --->aaabccc +0 ^ a+ +2 ^ ^ b? +4 ^ ^ c+ +6 ^ ^ (*FAIL) +6 ^ ^ (*FAIL) +6 ^ ^ (*FAIL) +0 ^ a+ +2 ^ ^ b? +4 ^ ^ c+ +6 ^ ^ (*FAIL) +6 ^ ^ (*FAIL) +6 ^ ^ (*FAIL) +0 ^ a+ +2 ^^ b? +4 ^ ^ c+ +6 ^ ^ (*FAIL) +6 ^ ^ (*FAIL) +6 ^ ^ (*FAIL) No match /a+b?(*PRUNE)c+(*FAIL)/C aaabccc --->aaabccc +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*PRUNE) +12 ^ ^ c+ +14 ^ ^ (*FAIL) +14 ^ ^ (*FAIL) +14 ^ ^ (*FAIL) +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*PRUNE) +12 ^ ^ c+ +14 ^ ^ (*FAIL) +14 ^ ^ (*FAIL) +14 ^ ^ (*FAIL) +0 ^ a+ +2 ^^ b? +4 ^ ^ (*PRUNE) +12 ^ ^ c+ +14 ^ ^ (*FAIL) +14 ^ ^ (*FAIL) +14 ^ ^ (*FAIL) No match /a+b?(*COMMIT)c+(*FAIL)/C aaabccc --->aaabccc +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*COMMIT) +13 ^ ^ c+ +15 ^ ^ (*FAIL) +15 ^ ^ (*FAIL) +15 ^ ^ (*FAIL) No match /a+b?(*SKIP)c+(*FAIL)/C aaabcccaaabccc --->aaabcccaaabccc +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*SKIP) +11 ^ ^ c+ +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*SKIP) +11 ^ ^ c+ +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) No match /a+b?(*THEN)c+(*FAIL)/C aaabccc --->aaabccc +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*THEN) +11 ^ ^ c+ +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +0 ^ a+ +2 ^ ^ b? +4 ^ ^ (*THEN) +11 ^ ^ c+ +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +0 ^ a+ +2 ^^ b? +4 ^ ^ (*THEN) +11 ^ ^ c+ +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) +13 ^ ^ (*FAIL) No match /a(*MARK)b/ Failed: (*MARK) must have an argument at offset 7 /(?i:A{1,}\6666666666)/ Failed: number is too big at offset 19 /\g6666666666/ Failed: number is too big at offset 11 /[\g6666666666]/BZ ------------------------------------------------------------------ Bra [6g] Ket End ------------------------------------------------------------------ /(?1)\c[/ Failed: reference to non-existent subpattern at offset 3 /.+A/ \r\nA No match /\nA/ \r\nA 0: \x0aA /[\r\n]A/ \r\nA 0: \x0aA /(\r|\n)A/ \r\nA 0: \x0aA 1: \x0a /a(*CR)b/ Failed: (*VERB) not recognized or malformed at offset 5 /(*CR)a.b/ a\nb 0: a\x0ab ** Failers No match a\rb No match /(*CR)a.b/ a\nb 0: a\x0ab ** Failers No match a\rb No match /(*LF)a.b/ a\rb 0: a\x0db ** Failers No match a\nb No match /(*CRLF)a.b/ a\rb 0: a\x0db a\nb 0: a\x0ab ** Failers No match a\r\nb No match /(*ANYCRLF)a.b/ ** Failers No match a\rb No match a\nb No match a\r\nb No match /(*ANY)a.b/ ** Failers No match a\rb No match a\nb No match a\r\nb No match a\x85b No match /(*ANY).*/g abc\r\ndef 0: abc 0: 0: def 0: /(*ANYCRLF).*/g abc\r\ndef 0: abc 0: 0: def 0: /(*CRLF).*/g abc\r\ndef 0: abc 0: 0: def 0: /a\Rb/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab ** Failers No match a\x85b No match a\x0bb No match /a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab a\x85b 0: a\x85b a\x0bb 0: a\x0bb ** Failers No match a\x85b\ No match a\x0bb\ No match /a\R?b/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab ** Failers No match a\x85b No match a\x0bb No match /a\R?b/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab a\x85b 0: a\x85b a\x0bb 0: a\x0bb ** Failers No match a\x85b\ No match a\x0bb\ No match /a\R{2,4}b/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\r\n\nb 0: a\x0d\x0a\x0ab a\n\r\rb 0: a\x0a\x0d\x0db a\r\n\r\n\r\n\r\nb 0: a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0ab ** Failers No match a\x85\85b No match a\x0b\0bb No match /a\R{2,4}b/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\r\rb 0: a\x0d\x0db a\n\n\nb 0: a\x0a\x0a\x0ab a\r\n\n\r\rb 0: a\x0d\x0a\x0a\x0d\x0db a\x85\85b No match a\x0b\0bb No match ** Failers No match a\r\r\r\r\rb No match a\x85\85b\ No match a\x0b\0bb\ No match /(*BSR_ANYCRLF)a\Rb/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\nb 0: a\x0ab a\rb 0: a\x0db /(*BSR_UNICODE)a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\x85b 0: a\x85b /(*BSR_ANYCRLF)(*CRLF)a\Rb/I Capturing subpattern count = 0 Options: bsr_anycrlf Forced newline sequence: CRLF First char = 'a' Need char = 'b' a\nb 0: a\x0ab a\rb 0: a\x0db /(*CRLF)(*BSR_UNICODE)a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode Forced newline sequence: CRLF First char = 'a' Need char = 'b' a\x85b 0: a\x85b /(*CRLF)(*BSR_ANYCRLF)(*CR)ab/I Capturing subpattern count = 0 Options: bsr_anycrlf Forced newline sequence: CR First char = 'a' Need char = 'b' /(?)(?&)/ Failed: subpattern name expected at offset 9 /(?)(?&a)/ Failed: reference to non-existent subpattern at offset 12 /(?)(?&aaaaaaaaaaaaaaaaaaaaaaa)/ Failed: reference to non-existent subpattern at offset 32 /(?+-a)/ Failed: digit expected after (?+ at offset 3 /(?-+a)/ Failed: unrecognized character after (? or (?- at offset 3 /(?(-1))/ Failed: reference to non-existent subpattern at offset 6 /(?(+10))/ Failed: reference to non-existent subpattern at offset 7 /(?(10))/ Failed: reference to non-existent subpattern at offset 6 /(?(+2))()()/ /(?(2))()()/ /\k''/ Failed: subpattern name expected at offset 3 /\k<>/ Failed: subpattern name expected at offset 3 /\k{}/ Failed: subpattern name expected at offset 3 /\k/ Failed: \k is not followed by a braced, angle-bracketed, or quoted name at offset 1 /\kabc/ Failed: \k is not followed by a braced, angle-bracketed, or quoted name at offset 1 /(?P=)/ Failed: subpattern name expected at offset 4 /(?P>)/ Failed: subpattern name expected at offset 4 /(?!\w)(?R)/ Failed: recursive call could loop indefinitely at offset 9 /(?=\w)(?R)/ Failed: recursive call could loop indefinitely at offset 9 /(?x|y){0}z/ xzxx 0: xz yzyy 0: yz ** Failers No match xxz No match /(\3)(\1)(a)/ cat No match /(\3)(\1)(a)/ cat 0: a 1: 2: 3: a /TA]/ The ACTA] comes 0: TA] /TA]/ Failed: ] is an invalid data character in JavaScript compatibility mode at offset 2 /(?2)[]a()b](abc)/ Failed: reference to non-existent subpattern at offset 3 /(?2)[^]a()b](abc)/ Failed: reference to non-existent subpattern at offset 3 /(?1)[]a()b](abc)/ abcbabc 0: abcbabc 1: abc ** Failers No match abcXabc No match /(?1)[^]a()b](abc)/ abcXabc 0: abcXabc 1: abc ** Failers No match abcbabc No match /(?2)[]a()b](abc)(xyz)/ xyzbabcxyz 0: xyzbabcxyz 1: abc 2: xyz /(?&N)[]a(?)](?abc)/ Failed: reference to non-existent subpattern at offset 4 /(?&N)[]a(?)](abc)/ Failed: reference to non-existent subpattern at offset 4 /a[]b/ Failed: missing terminating ] for character class at offset 4 /a[^]b/ Failed: missing terminating ] for character class at offset 5 /a[]b/ ** Failers No match ab No match /a[]+b/ ** Failers No match ab No match /a[]*+b/ ** Failers No match ab No match /a[^]b/ aXb 0: aXb a\nb 0: a\x0ab ** Failers No match ab No match /a[^]+b/ aXb 0: aXb a\nX\nXb 0: a\x0aX\x0aXb ** Failers No match ab No match /a(?!)b/BZ ------------------------------------------------------------------ Bra a *FAIL b Ket End ------------------------------------------------------------------ /(?!)?a/BZ ------------------------------------------------------------------ Bra Brazero Assert not Ket a Ket End ------------------------------------------------------------------ ab 0: a /a(*FAIL)+b/ Failed: nothing to repeat at offset 8 /(abc|pqr|123){0}[xyz]/SI Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 1 Starting chars: x y z /(?(?=.*b)b|^)/CI Capturing subpattern count = 0 May match empty string Options: No first char No need char adc --->adc +0 ^ (?(?=.*b)b|^) +2 ^ (?=.*b) +5 ^ .* +7 ^ ^ b +7 ^ ^ b +7 ^^ b +7 ^ b +11 ^ ^ +12 ^ ) +13 ^ 0: abc --->abc +0 ^ (?(?=.*b)b|^) +2 ^ (?=.*b) +5 ^ .* +7 ^ ^ b +7 ^ ^ b +7 ^^ b +8 ^ ^ ) +9 ^ b +0 ^ (?(?=.*b)b|^) +2 ^ (?=.*b) +5 ^ .* +7 ^ ^ b +7 ^^ b +7 ^ b +8 ^^ ) +9 ^ b +10 ^^ | +13 ^^ 0: b /(?(?=b).*b|^d)/I Capturing subpattern count = 0 No options No first char No need char /(?(?=.*b).*b|^d)/I Capturing subpattern count = 0 No options No first char No need char /xyz/C xyz --->xyz +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz abcxyz --->abcxyz +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz abcxyz\Y --->abcxyz +0 ^ x +0 ^ x +0 ^ x +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz ** Failers No match abc No match abc\Y --->abc +0 ^ x +0 ^ x +0 ^ x +0 ^ x No match abcxypqr No match abcxypqr\Y --->abcxypqr +0 ^ x +0 ^ x +0 ^ x +0 ^ x +1 ^^ y +2 ^ ^ z +0 ^ x +0 ^ x +0 ^ x +0 ^ x +0 ^ x No match /(*NO_START_OPT)xyz/C abcxyz --->abcxyz +15 ^ x +15 ^ x +15 ^ x +15 ^ x +16 ^^ y +17 ^ ^ z +18 ^ ^ 0: xyz /(*NO_AUTO_POSSESS)a+b/BZ ------------------------------------------------------------------ Bra a+ b Ket End ------------------------------------------------------------------ /xyz/CY abcxyz --->abcxyz +0 ^ x +0 ^ x +0 ^ x +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz /^"((?(?=[a])[^"])|b)*"$/C "ab" --->"ab" +0 ^ ^ +1 ^ " +2 ^^ ((?(?=[a])[^"])|b)* +3 ^^ (?(?=[a])[^"]) +5 ^^ (?=[a]) +8 ^^ [a] +11 ^ ^ ) +12 ^^ [^"] +16 ^ ^ ) +17 ^ ^ | +3 ^ ^ (?(?=[a])[^"]) +5 ^ ^ (?=[a]) +8 ^ ^ [a] +17 ^ ^ | +21 ^ ^ " +18 ^ ^ b +19 ^ ^ ) +3 ^ ^ (?(?=[a])[^"]) +5 ^ ^ (?=[a]) +8 ^ ^ [a] +17 ^ ^ | +21 ^ ^ " +22 ^ ^ $ +23 ^ ^ 0: "ab" 1: /^"((?(?=[a])[^"])|b)*"$/ "ab" 0: "ab" 1: /^X(?5)(a)(?|(b)|(q))(c)(d)Y/ Failed: reference to non-existent subpattern at offset 5 /^X(?&N)(a)(?|(b)|(q))(c)(d)(?Y)/ XYabcdY 0: XYabcdY 1: a 2: b 3: c 4: d 5: Y /Xa{2,4}b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /Xa{2,4}?b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /Xa{2,4}+b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\d{2,4}b/ X\P Partial match: X X3\P Partial match: X3 X33\P Partial match: X33 X333\P Partial match: X333 X3333\P Partial match: X3333 /X\d{2,4}?b/ X\P Partial match: X X3\P Partial match: X3 X33\P Partial match: X33 X333\P Partial match: X333 X3333\P Partial match: X3333 /X\d{2,4}+b/ X\P Partial match: X X3\P Partial match: X3 X33\P Partial match: X33 X333\P Partial match: X333 X3333\P Partial match: X3333 /X\D{2,4}b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\D{2,4}?b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\D{2,4}+b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[abc]{2,4}b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[abc]{2,4}?b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[abc]{2,4}+b/ X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[^a]{2,4}b/ X\P Partial match: X Xz\P Partial match: Xz Xzz\P Partial match: Xzz Xzzz\P Partial match: Xzzz Xzzzz\P Partial match: Xzzzz /X[^a]{2,4}?b/ X\P Partial match: X Xz\P Partial match: Xz Xzz\P Partial match: Xzz Xzzz\P Partial match: Xzzz Xzzzz\P Partial match: Xzzzz /X[^a]{2,4}+b/ X\P Partial match: X Xz\P Partial match: Xz Xzz\P Partial match: Xzz Xzzz\P Partial match: Xzzz Xzzzz\P Partial match: Xzzzz /(Y)X\1{2,4}b/ YX\P Partial match: YX YXY\P Partial match: YXY YXYY\P Partial match: YXYY YXYYY\P Partial match: YXYYY YXYYYY\P Partial match: YXYYYY /(Y)X\1{2,4}?b/ YX\P Partial match: YX YXY\P Partial match: YXY YXYY\P Partial match: YXYY YXYYY\P Partial match: YXYYY YXYYYY\P Partial match: YXYYYY /(Y)X\1{2,4}+b/ YX\P Partial match: YX YXY\P Partial match: YXY YXYY\P Partial match: YXYY YXYYY\P Partial match: YXYYY YXYYYY\P Partial match: YXYYYY /\++\KZ|\d+X|9+Y/ ++++123999\P Partial match: 123999 ++++123999Y\P 0: 999Y ++++Z1234\P 0: Z /Z(*F)/ Z\P No match ZA\P No match /Z(?!)/ Z\P No match ZA\P No match /dog(sbody)?/ dogs\P 0: dog dogs\P\P Partial match: dogs /dog(sbody)??/ dogs\P 0: dog dogs\P\P 0: dog /dog|dogsbody/ dogs\P 0: dog dogs\P\P 0: dog /dogsbody|dog/ dogs\P 0: dog dogs\P\P Partial match: dogs /\bthe cat\b/ the cat\P 0: the cat the cat\P\P Partial match: the cat /abc/ abc\P 0: abc abc\P\P 0: abc /abc\K123/ xyzabc123pqr 0: 123 xyzabc12\P Partial match: abc12 xyzabc12\P\P Partial match: abc12 /(?<=abc)123/ xyzabc123pqr 0: 123 xyzabc12\P Partial match at offset 6: abc12 xyzabc12\P\P Partial match at offset 6: abc12 /\babc\b/ +++abc+++ 0: abc +++ab\P Partial match at offset 3: +ab +++ab\P\P Partial match at offset 3: +ab /(?&word)(?&element)(?(DEFINE)(?<[^m][^>]>[^<])(?\w*+))/BZ ------------------------------------------------------------------ Bra Recurse Recurse Cond Cond def CBra 1 < [^m] [^>] > [^<] Ket CBra 2 \w*+ Ket Ket Ket End ------------------------------------------------------------------ /(?&word)(?&element)(?(DEFINE)(?<[^\d][^>]>[^<])(?\w*+))/BZ ------------------------------------------------------------------ Bra Recurse Recurse Cond Cond def CBra 1 < [\x00-/:-\xff] (neg) [^>] > [^<] Ket CBra 2 \w*+ Ket Ket Ket End ------------------------------------------------------------------ /(ab)(x(y)z(cd(*ACCEPT)))pq/BZ ------------------------------------------------------------------ Bra CBra 1 ab Ket CBra 2 x CBra 3 y Ket z CBra 4 cd Close 4 Close 2 *ACCEPT Ket Ket pq Ket End ------------------------------------------------------------------ /abc\K/+ abcdef 0: 0+ def abcdef\N\N 0: 0+ def xyzabcdef\N\N 0: 0+ def ** Failers No match abcdef\N No match xyzabcdef\N No match /^(?:(?=abc)|abc\K)/+ abcdef 0: 0+ abcdef abcdef\N\N 0: 0+ def ** Failers No match abcdef\N No match /a?b?/+ xyz 0: 0+ xyz xyzabc 0: 0+ xyzabc xyzabc\N 0: ab 0+ c xyzabc\N\N 0: 0+ yzabc xyz\N\N 0: 0+ yz ** Failers 0: 0+ ** Failers xyz\N No match /^a?b?/+ xyz 0: 0+ xyz xyzabc 0: 0+ xyzabc ** Failers 0: 0+ ** Failers xyzabc\N No match xyzabc\N\N No match xyz\N\N No match xyz\N No match /^(?a|b\gc)/ aaaa 0: a 1: a bacxxx 0: bac 1: bac bbaccxxx 0: bbacc 1: bbacc bbbacccxx 0: bbbaccc 1: bbbaccc /^(?a|b\g'name'c)/ aaaa 0: a 1: a bacxxx 0: bac 1: bac bbaccxxx 0: bbacc 1: bbacc bbbacccxx 0: bbbaccc 1: bbbaccc /^(a|b\g<1>c)/ aaaa 0: a 1: a bacxxx 0: bac 1: bac bbaccxxx 0: bbacc 1: bbacc bbbacccxx 0: bbbaccc 1: bbbaccc /^(a|b\g'1'c)/ aaaa 0: a 1: a bacxxx 0: bac 1: bac bbaccxxx 0: bbacc 1: bbacc bbbacccxx 0: bbbaccc 1: bbbaccc /^(a|b\g'-1'c)/ aaaa 0: a 1: a bacxxx 0: bac 1: bac bbaccxxx 0: bbacc 1: bbacc bbbacccxx 0: bbbaccc 1: bbbaccc /(^(a|b\g<-1>c))/ aaaa 0: a 1: a 2: a bacxxx 0: bac 1: bac 2: bac bbaccxxx 0: bbacc 1: bbacc 2: bbacc bbbacccxx 0: bbbaccc 1: bbbaccc 2: bbbaccc /(?-i:\g)(?i:(?a))/ XaaX 0: aa 1: a XAAX 0: AA 1: A /(?i:\g)(?-i:(?a))/ XaaX 0: aa 1: a ** Failers No match XAAX No match /(?-i:\g<+1>)(?i:(a))/ XaaX 0: aa 1: a XAAX 0: AA 1: A /(?=(?(?#simplesyntax)\$(?[a-zA-Z_\x{7f}-\x{ff}][a-zA-Z0-9_\x{7f}-\x{ff}]*)(?:\[(?[a-zA-Z0-9_\x{7f}-\x{ff}]+|\$\g)\]|->\g(\(.*?\))?)?|(?#simple syntax withbraces)\$\{(?:\g(?\[(?:\g|'(?:\\.|[^'\\])*'|"(?:\g|\\.|[^"\\])*")\])?|\g|\$\{\g\})\}|(?#complexsyntax)\{(?\$(?\g(\g*|\(.*?\))?)(?:->\g)*|\$\g|\$\{\g\})\}))\{/ /(?a|b|c)\g*/ abc 0: abc 1: a accccbbb 0: accccbbb 1: a /^X(?7)(a)(?|(b)|(q)(r)(s))(c)(d)(Y)/ XYabcdY 0: XYabcdY 1: a 2: b 3: 4: 5: c 6: d 7: Y /(?<=b(?1)|zzz)(a)/ xbaax 0: a 1: a xzzzax 0: a 1: a /(a)(?<=b\1)/ Failed: lookbehind assertion is not fixed length at offset 10 /(a)(?<=b+(?1))/ Failed: lookbehind assertion is not fixed length at offset 13 /(a+)(?<=b(?1))/ Failed: lookbehind assertion is not fixed length at offset 14 /(a(?<=b(?1)))/ Failed: lookbehind assertion is not fixed length at offset 13 /(?<=b(?1))xyz/ Failed: reference to non-existent subpattern at offset 8 /(?<=b(?1))xyz(b+)pqrstuvew/ Failed: lookbehind assertion is not fixed length at offset 26 /(a|bc)\1/SI Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /(a|bc)\1{2,3}/SI Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char Subject length lower bound = 3 Starting chars: a b /(a|bc)(?1)/SI Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /(a|b\1)(a|b\1)/SI Capturing subpattern count = 2 Max back reference = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /(a|b\1){2}/SI Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /(a|bbbb\1)(a|bbbb\1)/SI Capturing subpattern count = 2 Max back reference = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /(a|bbbb\1){2}/SI Capturing subpattern count = 1 Max back reference = 1 No options No first char No need char Subject length lower bound = 2 Starting chars: a b /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/SI Capturing subpattern count = 1 Options: anchored No first char Need char = ':' Subject length lower bound = 22 No starting char list /]{0,})>]{0,})>([\d]{0,}\.)(.*)((
    ([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/isIS Capturing subpattern count = 11 Options: caseless dotall First char = '<' Need char = '>' Subject length lower bound = 47 No starting char list "(?>.*/)foo"SI Capturing subpattern count = 0 No options No first char Need char = 'o' Subject length lower bound = 4 No starting char list /(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /xSI Capturing subpattern count = 0 Options: extended No first char Need char = '-' Subject length lower bound = 8 No starting char list /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/iSI Capturing subpattern count = 1 Options: caseless No first char No need char Subject length lower bound = 1 Starting chars: A B C a b c /(?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb)))/SI Capturing subpattern count = 0 No options No first char Need char = 'b' Subject length lower bound = 41 Starting chars: c d /A)|(?
    B))/I Capturing subpattern count = 1 Named capturing subpatterns: a 1 No options No first char No need char AB\Ca 0: A 1: A C A (1) a BA\Ca 0: B 1: B C B (1) a /(?|(?A)|(?B))/ Failed: different names for subpatterns of the same number are not allowed at offset 15 /(?:a(? (?')|(?")) | b(? (?')|(?")) ) (?('quote')[a-z]+|[0-9]+)/JIx Capturing subpattern count = 6 Max back reference = 1 Named capturing subpatterns: apostrophe 2 apostrophe 5 quote 1 quote 4 realquote 3 realquote 6 Options: extended dupnames No first char No need char a"aaaaa 0: a"aaaaa 1: " 2: 3: " b"aaaaa 0: b"aaaaa 1: 2: 3: 4: " 5: 6: " ** Failers No match b"11111 No match a"11111 No match /^(?|(a)(b)(c)(?d)|(?e)) (?('D')X|Y)/JDZx ------------------------------------------------------------------ Bra ^ Bra CBra 1 a Ket CBra 2 b Ket CBra 3 c Ket CBra 4 d Ket Alt CBra 1 e Ket Ket Cond Cond ref 2 X Alt Y Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 4 Max back reference = 4 Named capturing subpatterns: D 4 D 1 Options: anchored extended dupnames No first char No need char abcdX 0: abcdX 1: a 2: b 3: c 4: d eX 0: eX 1: e ** Failers No match abcdY No match ey No match /(?a) (b)(c) (?d (?(R&A)$ | (?4)) )/JDZx ------------------------------------------------------------------ Bra CBra 1 a Ket CBra 2 b Ket CBra 3 c Ket CBra 4 d Cond Cond recurse 2 $ Alt Recurse Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 4 Max back reference = 1 Named capturing subpatterns: A 1 A 4 Options: extended dupnames First char = 'a' Need char = 'd' abcdd 0: abcdd 1: a 2: b 3: c 4: dd ** Failers No match abcdde No match /abcd*/ xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd /abcd*/i xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd XXXXABCD\P 0: ABCD XXXXABCD\P\P Partial match: ABCD /abc\d*/ xxxxabc1\P 0: abc1 xxxxabc1\P\P Partial match: abc1 /(a)bc\1*/ xxxxabca\P 0: abca 1: a xxxxabca\P\P Partial match: abca /abc[de]*/ xxxxabcde\P 0: abcde xxxxabcde\P\P Partial match: abcde /-- This is not in the Perl-compatible test because Perl seems currently to be broken and not behaving as specified in that it *does* bumpalong after hitting (*COMMIT). --/ /(?1)(A(*COMMIT)|B)D/ ABD 0: ABD 1: B XABD 0: ABD 1: B BAD 0: BAD 1: A ABXABD 0: ABD 1: B ** Failers No match ABX No match BAXBAD No match /(\3)(\1)(a)/ cat 0: a 1: 2: 3: a /(\3)(\1)(a)/SI Capturing subpattern count = 3 Max back reference = 3 Options: No first char Need char = 'a' Subject length lower bound = 1 No starting char list cat 0: a 1: 2: 3: a /(\3)(\1)(a)/SI Capturing subpattern count = 3 Max back reference = 3 No options No first char Need char = 'a' Subject length lower bound = 3 No starting char list cat No match /i(?(DEFINE)(?a))/SI Capturing subpattern count = 1 Named capturing subpatterns: s 1 No options First char = 'i' No need char Subject length lower bound = 1 No starting char list i 0: i /()i(?(1)a)/SI Capturing subpattern count = 1 Max back reference = 1 No options No first char Need char = 'i' Subject length lower bound = 1 Starting chars: i ia 0: ia 1: /(?i)a(?-i)b|c/BZ ------------------------------------------------------------------ Bra /i a b Alt c Ket End ------------------------------------------------------------------ XabX 0: ab XAbX 0: Ab CcC 0: c ** Failers No match XABX No match /(?i)a(?s)b|c/BZ ------------------------------------------------------------------ Bra /i ab Alt /i c Ket End ------------------------------------------------------------------ /(?i)a(?s-i)b|c/BZ ------------------------------------------------------------------ Bra /i a b Alt c Ket End ------------------------------------------------------------------ /^(ab(c\1)d|x){2}$/BZ ------------------------------------------------------------------ Bra ^ Once CBra 1 ab CBra 2 c \1 Ket d Alt x Ket Ket Once CBra 1 ab CBra 2 c \1 Ket d Alt x Ket Ket $ Ket End ------------------------------------------------------------------ xabcxd 0: xabcxd 1: abcxd 2: cx /^(?&t)*+(?(DEFINE)(?.))$/BZ ------------------------------------------------------------------ Bra ^ Braposzero SBraPos Recurse KetRpos Cond Cond def CBra 1 Any Ket Ket $ Ket End ------------------------------------------------------------------ /^(?&t)*(?(DEFINE)(?.))$/BZ ------------------------------------------------------------------ Bra ^ Brazero Once Recurse KetRmax Cond Cond def CBra 1 Any Ket Ket $ Ket End ------------------------------------------------------------------ / -- This one is here because Perl gives the match as "b" rather than "ab". I believe this to be a Perl bug. --/ /(?>a\Kb)z|(ab)/ ab 0: ab 1: ab /(?P(?P0|)|(?P>L2)(?P>L1))/ Failed: recursive call could loop indefinitely at offset 31 /abc(*MARK:)pqr/ Failed: (*MARK) must have an argument at offset 10 /abc(*:)pqr/ Failed: (*MARK) must have an argument at offset 6 /abc(*FAIL:123)xyz/ Failed: an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT) at offset 13 /--- This should, and does, fail. In Perl, it does not, which I think is a bug because replacing the B in the pattern by (B|D) does make it fail. ---/ /A(*COMMIT)B/+K ACABX No match /--- These should be different, but in Perl they are not, which I think is a bug in Perl. ---/ /A(*THEN)B|A(*THEN)C/K AC 0: AC /A(*PRUNE)B|A(*PRUNE)C/K AC No match /--- Mark names can be duplicated. Perl doesn't give a mark for this one, though PCRE does. ---/ /^A(*:A)B|^X(*:A)Y/K ** Failers No match XAQQ No match, mark = A /--- COMMIT at the start of a pattern should be the same as an anchor. Perl optimizations defeat this. So does the PCRE optimization unless we disable it with \Y. ---/ /(*COMMIT)ABC/ ABCDEFG 0: ABC ** Failers No match DEFGABC\Y No match /^(ab (c+(*THEN)cd) | xyz)/x abcccd No match /^(ab (c+(*PRUNE)cd) | xyz)/x abcccd No match /^(ab (c+(*FAIL)cd) | xyz)/x abcccd No match /--- Perl gets some of these wrong ---/ /(?>.(*ACCEPT))*?5/ abcde 0: a /(.(*ACCEPT))*?5/ abcde 0: a 1: a /(.(*ACCEPT))5/ abcde 0: a 1: a /(.(*ACCEPT))*5/ abcde 0: a 1: a /A\NB./BZ ------------------------------------------------------------------ Bra A Any B Any Ket End ------------------------------------------------------------------ ACBD 0: ACBD *** Failers No match A\nB No match ACB\n No match /A\NB./sBZ ------------------------------------------------------------------ Bra A Any B AllAny Ket End ------------------------------------------------------------------ ACBD 0: ACBD ACB\n 0: ACB\x0a *** Failers No match A\nB No match /A\NB/ A\nB 0: A\x0aB A\rB 0: A\x0dB ** Failers No match A\r\nB No match /\R+b/BZ ------------------------------------------------------------------ Bra \R++ b Ket End ------------------------------------------------------------------ /\R+\n/BZ ------------------------------------------------------------------ Bra \R+ \x0a Ket End ------------------------------------------------------------------ /\R+\d/BZ ------------------------------------------------------------------ Bra \R++ \d Ket End ------------------------------------------------------------------ /\d*\R/BZ ------------------------------------------------------------------ Bra \d*+ \R Ket End ------------------------------------------------------------------ /\s*\R/BZ ------------------------------------------------------------------ Bra \s* \R Ket End ------------------------------------------------------------------ \x20\x0a 0: \x0a \x20\x0d 0: \x0d \x20\x0d\x0a 0: \x0d\x0a /\S*\R/BZ ------------------------------------------------------------------ Bra \S*+ \R Ket End ------------------------------------------------------------------ a\x0a 0: a\x0a /X\h*\R/BZ ------------------------------------------------------------------ Bra X \h*+ \R Ket End ------------------------------------------------------------------ X\x20\x0a 0: X \x0a /X\H*\R/BZ ------------------------------------------------------------------ Bra X \H* \R Ket End ------------------------------------------------------------------ X\x0d\x0a 0: X\x0d\x0a /X\H+\R/BZ ------------------------------------------------------------------ Bra X \H+ \R Ket End ------------------------------------------------------------------ X\x0d\x0a 0: X\x0d\x0a /X\H++\R/BZ ------------------------------------------------------------------ Bra X \H++ \R Ket End ------------------------------------------------------------------ X\x0d\x0a No match /(?<=abc)def/ abc\P\P Partial match at offset 3: abc /abc$/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc$/m abc 0: abc abc\n 0: abc abc\P\P Partial match: abc abc\n\P\P 0: abc abc\P 0: abc abc\n\P 0: abc /abc\z/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc\Z/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc\b/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc\B/ abc No match abc\P Partial match: abc abc\P\P Partial match: abc /.+/ abc\>0 0: abc abc\>1 0: bc abc\>2 0: c abc\>3 No match abc\>4 Error -24 (bad offset value) abc\>-4 Error -24 (bad offset value) /^\cģ/ Failed: \c must be followed by an ASCII character at offset 3 /(?P(?P=abn)xxx)/BZ ------------------------------------------------------------------ Bra Once CBra 1 \1 xxx Ket Ket Ket End ------------------------------------------------------------------ /(a\1z)/BZ ------------------------------------------------------------------ Bra Once CBra 1 a \1 z Ket Ket Ket End ------------------------------------------------------------------ /(?P(?P=abn)(?(?P=axn)xxx)/BZ Failed: reference to non-existent subpattern at offset 15 /(?P(?P=axn)xxx)(?yy)/BZ ------------------------------------------------------------------ Bra CBra 1 \2 xxx Ket CBra 2 yy Ket Ket End ------------------------------------------------------------------ /-- These tests are here because Perl gets the first one wrong. --/ /(\R*)(.)/s \r\n 0: \x0d 1: 2: \x0d \r\r\n\n\r 0: \x0d\x0d\x0a\x0a\x0d 1: \x0d\x0d\x0a\x0a 2: \x0d \r\r\n\n\r\n 0: \x0d\x0d\x0a\x0a\x0d 1: \x0d\x0d\x0a\x0a 2: \x0d /(\R)*(.)/s \r\n 0: \x0d 1: 2: \x0d \r\r\n\n\r 0: \x0d\x0d\x0a\x0a\x0d 1: \x0a 2: \x0d \r\r\n\n\r\n 0: \x0d\x0d\x0a\x0a\x0d 1: \x0a 2: \x0d /((?>\r\n|\n|\x0b|\f|\r|\x85)*)(.)/s \r\n 0: \x0d 1: 2: \x0d \r\r\n\n\r 0: \x0d\x0d\x0a\x0a\x0d 1: \x0d\x0d\x0a\x0a 2: \x0d \r\r\n\n\r\n 0: \x0d\x0d\x0a\x0a\x0d 1: \x0d\x0d\x0a\x0a 2: \x0d /-- --/ /^abc$/BZ ------------------------------------------------------------------ Bra ^ abc $ Ket End ------------------------------------------------------------------ /^abc$/BZm ------------------------------------------------------------------ Bra /m ^ abc /m $ Ket End ------------------------------------------------------------------ /^(a)*+(\w)/S aaaaX 0: aaaaX 1: a 2: X ** Failers No match aaaa No match /^(?:a)*+(\w)/S aaaaX 0: aaaaX 1: X ** Failers No match aaaa No match /(a)++1234/SDZ ------------------------------------------------------------------ Bra CBraPos 1 a KetRpos 1234 Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 No options First char = 'a' Need char = '4' Subject length lower bound = 5 No starting char list /([abc])++1234/SI Capturing subpattern count = 1 No options No first char Need char = '4' Subject length lower bound = 5 Starting chars: a b c /(?<=(abc)+)X/ Failed: lookbehind assertion is not fixed length at offset 10 /(^ab)/I Capturing subpattern count = 1 Options: anchored No first char No need char /(^ab)++/I Capturing subpattern count = 1 Options: anchored No first char No need char /(^ab|^)+/I Capturing subpattern count = 1 May match empty string Options: anchored No first char No need char /(^ab|^)++/I Capturing subpattern count = 1 May match empty string Options: anchored No first char No need char /(?:^ab)/I Capturing subpattern count = 0 Options: anchored No first char No need char /(?:^ab)++/I Capturing subpattern count = 0 Options: anchored No first char No need char /(?:^ab|^)+/I Capturing subpattern count = 0 May match empty string Options: anchored No first char No need char /(?:^ab|^)++/I Capturing subpattern count = 0 May match empty string Options: anchored No first char No need char /(.*ab)/I Capturing subpattern count = 1 No options First char at start or follows newline Need char = 'b' /(.*ab)++/I Capturing subpattern count = 1 No options First char at start or follows newline Need char = 'b' /(.*ab|.*)+/I Capturing subpattern count = 1 May match empty string No options First char at start or follows newline No need char /(.*ab|.*)++/I Capturing subpattern count = 1 May match empty string No options First char at start or follows newline No need char /(?:.*ab)/I Capturing subpattern count = 0 No options First char at start or follows newline Need char = 'b' /(?:.*ab)++/I Capturing subpattern count = 0 No options First char at start or follows newline Need char = 'b' /(?:.*ab|.*)+/I Capturing subpattern count = 0 May match empty string No options First char at start or follows newline No need char /(?:.*ab|.*)++/I Capturing subpattern count = 0 May match empty string No options First char at start or follows newline No need char /(?=a)[bcd]/I Capturing subpattern count = 0 No options First char = 'a' No need char /((?=a))[bcd]/I Capturing subpattern count = 1 No options First char = 'a' No need char /((?=a))+[bcd]/I Capturing subpattern count = 1 No options First char = 'a' No need char /((?=a))++[bcd]/I Capturing subpattern count = 1 No options First char = 'a' No need char /(?=a+)[bcd]/iI Capturing subpattern count = 0 Options: caseless First char = 'a' (caseless) No need char /(?=a+?)[bcd]/iI Capturing subpattern count = 0 Options: caseless First char = 'a' (caseless) No need char /(?=a++)[bcd]/iI Capturing subpattern count = 0 Options: caseless First char = 'a' (caseless) No need char /(?=a{3})[bcd]/iI Capturing subpattern count = 0 Options: caseless First char = 'a' (caseless) Need char = 'a' (caseless) /(abc)\1+/S /-- Perl doesn't get these right IMO (the 3rd is PCRE-specific) --/ /(?1)(?:(b(*ACCEPT))){0}/ b 0: b /(?1)(?:(b(*ACCEPT))){0}c/ bc 0: bc ** Failers No match b No match /(?1)(?:((*ACCEPT))){0}c/ c 0: c c\N 0: c /^.*?(?(?=a)a|b(*THEN)c)/ ba No match /^.*?(?(?=a)a|bc)/ ba 0: ba /^.*?(?(?=a)a(*THEN)b|c)/ ac No match /^.*?(?(?=a)a(*THEN)b)c/ ac No match /^.*?(a(*THEN)b)c/ aabc No match /^.*? (?1) c (?(DEFINE)(a(*THEN)b))/x aabc 0: aabc /^.*?(a(*THEN)b|z)c/ aabc 0: aabc 1: ab /^.*?(z|a(*THEN)b)c/ aabc 0: aabc 1: ab /-- --/ /-- These studied versions are here because they are not Perl-compatible; the studying means the mark is not seen. --/ /(*MARK:A)(*SKIP:B)(C|X)/KS C 0: C 1: C MK: A D No match, mark = A /(*:A)A+(*SKIP:A)(B|Z)/KS AAAC No match, mark = A /-- --/ "(?=a*(*ACCEPT)b)c" c 0: c c\N 0: c /(?1)c(?(DEFINE)((*ACCEPT)b))/ c 0: c c\N 0: c /(?>(*ACCEPT)b)c/ c 0: c\N No match /(?:(?>(a)))+a%/++ %aa% 0: aa% 0+ 1: a 1+ a% /(a)b|ac/++SS ac\O3 0: ac 0+ /(a)(b)x|abc/++ abc\O6 0: abc 0+ /(a)bc|(a)(b)\2/ \O3abc Matched, but too many substrings 0: abc \O4abc Matched, but too many substrings 0: abc /(?(DEFINE)(a(?2)|b)(b(?1)|a))(?:(?1)|(?2))/SI Capturing subpattern count = 2 No options No first char No need char Subject length lower bound = 1 No starting char list /(a(?2)|b)(b(?1)|a)(?:(?1)|(?2))/SI Capturing subpattern count = 2 No options No first char No need char Subject length lower bound = 3 Starting chars: a b /(a(?2)|b)(b(?1)|a)(?1)(?2)/SI Capturing subpattern count = 2 No options No first char No need char Subject length lower bound = 4 Starting chars: a b /(abc)(?1)/SI Capturing subpattern count = 1 No options First char = 'a' Need char = 'c' Subject length lower bound = 6 No starting char list /^(?>a)++/ aa\M Minimum match() limit = 5 Minimum match() recursion limit = 2 0: aa aaaaaaaaa\M Minimum match() limit = 12 Minimum match() recursion limit = 2 0: aaaaaaaaa /(a)(?1)++/ aa\M Minimum match() limit = 7 Minimum match() recursion limit = 4 0: aa 1: a aaaaaaaaa\M Minimum match() limit = 21 Minimum match() recursion limit = 4 0: aaaaaaaaa 1: a /(?:(foo)|(bar)|(baz))X/SS= bazfooX 0: fooX 1: foo 2: 3: foobazbarX 0: barX 1: 2: bar 3: barfooX 0: fooX 1: foo 2: 3: bazX 0: bazX 1: 2: 3: baz foobarbazX 0: bazX 1: 2: 3: baz bazfooX\O0 Matched, but too many substrings bazfooX\O2 Matched, but too many substrings 0: fooX bazfooX\O4 Matched, but too many substrings 0: fooX 1: bazfooX\O6 Matched, but too many substrings 0: fooX 1: foo 2: bazfooX\O8 Matched, but too many substrings 0: fooX 1: foo 2: 3: bazfooX\O10 0: fooX 1: foo 2: 3: /(?=abc){3}abc/BZ ------------------------------------------------------------------ Bra Assert abc Ket abc Ket End ------------------------------------------------------------------ /(?=abc)+abc/BZ ------------------------------------------------------------------ Bra Assert abc Ket abc Ket End ------------------------------------------------------------------ /(?=abc)++abc/BZ ------------------------------------------------------------------ Bra Assert abc Ket abc Ket End ------------------------------------------------------------------ /(?=abc){0}xyz/BZ ------------------------------------------------------------------ Bra Skip zero Assert abc Ket xyz Ket End ------------------------------------------------------------------ /(?=(a))?./BZ ------------------------------------------------------------------ Bra Brazero Assert CBra 1 a Ket Ket Any Ket End ------------------------------------------------------------------ /(?=(a))??./BZ ------------------------------------------------------------------ Bra Braminzero Assert CBra 1 a Ket Ket Any Ket End ------------------------------------------------------------------ /^(?=(a)){0}b(?1)/BZ ------------------------------------------------------------------ Bra ^ Skip zero Assert CBra 1 a Ket Ket b Recurse Ket End ------------------------------------------------------------------ /(?(DEFINE)(a))?b(?1)/BZ ------------------------------------------------------------------ Bra Cond Cond def CBra 1 a Ket Ket b Recurse Ket End ------------------------------------------------------------------ /^(?=(?1))?[az]([abc])d/BZ ------------------------------------------------------------------ Bra ^ Brazero Assert Recurse Ket [az] CBra 1 [a-c] Ket d Ket End ------------------------------------------------------------------ /^(?!a){0}\w+/BZ ------------------------------------------------------------------ Bra ^ Skip zero Assert not a Ket \w++ Ket End ------------------------------------------------------------------ /(?<=(abc))?xyz/BZ ------------------------------------------------------------------ Bra Brazero AssertB Reverse CBra 1 abc Ket Ket xyz Ket End ------------------------------------------------------------------ /[:a[:abc]b:]/BZ ------------------------------------------------------------------ Bra [:[a-c] b:] Ket End ------------------------------------------------------------------ /((?2))((?1))/SS abc Error -26 (nested recursion at the same subject position) /((?(R2)a+|(?1)b))/SS aaaabcde Error -26 (nested recursion at the same subject position) /(?(R)a*(?1)|((?R))b)/SS aaaabcde Error -26 (nested recursion at the same subject position) /(a+|(?R)b)/ Failed: recursive call could loop indefinitely at offset 7 /^(a(*:A)(d|e(*:B))z|aeq)/C adz --->adz +0 ^ ^ +1 ^ (a(*:A)(d|e(*:B))z|aeq) +2 ^ a +3 ^^ (*:A) +8 ^^ (d|e(*:B)) Latest Mark: A +9 ^^ d +10 ^ ^ | +18 ^ ^ z +19 ^ ^ | +24 ^ ^ 0: adz 1: adz 2: d aez --->aez +0 ^ ^ +1 ^ (a(*:A)(d|e(*:B))z|aeq) +2 ^ a +3 ^^ (*:A) +8 ^^ (d|e(*:B)) Latest Mark: A +9 ^^ d +11 ^^ e +12 ^ ^ (*:B) +17 ^ ^ ) Latest Mark: B +18 ^ ^ z +19 ^ ^ | +24 ^ ^ 0: aez 1: aez 2: e aeqwerty --->aeqwerty +0 ^ ^ +1 ^ (a(*:A)(d|e(*:B))z|aeq) +2 ^ a +3 ^^ (*:A) +8 ^^ (d|e(*:B)) Latest Mark: A +9 ^^ d +11 ^^ e +12 ^ ^ (*:B) +17 ^ ^ ) Latest Mark: B +18 ^ ^ z +20 ^ a +21 ^^ e +22 ^ ^ q +23 ^ ^ ) +24 ^ ^ 0: aeq 1: aeq /.(*F)/ \P\Pabc No match /\btype\b\W*?\btext\b\W*?\bjavascript\b/IS Capturing subpattern count = 0 Max lookbehind = 1 No options First char = 't' Need char = 't' Subject length lower bound = 18 No starting char list /\btype\b\W*?\btext\b\W*?\bjavascript\b|\burl\b\W*?\bshell:|a+)(?>(z+))\w/BZ ------------------------------------------------------------------ Bra ^ Once_NC a++ Ket Once CBra 1 z++ Ket Ket \w Ket End ------------------------------------------------------------------ aaaazzzzb 0: aaaazzzzb 1: zzzz ** Failers No match aazz No match /(.)(\1|a(?2))/ bab 0: bab 1: b 2: ab /\1|(.)(?R)\1/ cbbbc 0: cbbbc 1: c /(.)((?(1)c|a)|a(?2))/ baa No match /(?P(?P=abn)xxx)/BZ ------------------------------------------------------------------ Bra Once CBra 1 \1 xxx Ket Ket Ket End ------------------------------------------------------------------ /(a\1z)/BZ ------------------------------------------------------------------ Bra Once CBra 1 a \1 z Ket Ket Ket End ------------------------------------------------------------------ /^(?>a+)(?>b+)(?>c+)(?>d+)(?>e+)/ \Maabbccddee Minimum match() limit = 7 Minimum match() recursion limit = 2 0: aabbccddee /^(?>(a+))(?>(b+))(?>(c+))(?>(d+))(?>(e+))/ \Maabbccddee Minimum match() limit = 17 Minimum match() recursion limit = 16 0: aabbccddee 1: aa 2: bb 3: cc 4: dd 5: ee /^(?>(a+))(?>b+)(?>(c+))(?>d+)(?>(e+))/ \Maabbccddee Minimum match() limit = 13 Minimum match() recursion limit = 10 0: aabbccddee 1: aa 2: cc 3: ee /^a\x41z/ aAz 0: aAz *** Failers No match ax41z No match /^a[m\x41]z/ aAz 0: aAz /^a\x1z/ ax1z 0: ax1z /^a\u0041z/ aAz 0: aAz *** Failers No match au0041z No match /^a[m\u0041]z/ aAz 0: aAz /^a\u041z/ au041z 0: au041z *** Failers No match aAz No match /^a\U0041z/ aU0041z 0: aU0041z *** Failers No match aAz No match /(?(?=c)c|d)++Y/BZ ------------------------------------------------------------------ Bra BraPos Cond Assert c Ket c Alt d Ket KetRpos Y Ket End ------------------------------------------------------------------ /(?(?=c)c|d)*+Y/BZ ------------------------------------------------------------------ Bra Braposzero BraPos Cond Assert c Ket c Alt d Ket KetRpos Y Ket End ------------------------------------------------------------------ /a[\NB]c/ Failed: \N is not supported in a class at offset 3 /a[B-\Nc]/ Failed: invalid range in character class at offset 5 /a[B\Nc]/ Failed: \N is not supported in a class at offset 4 /(a)(?2){0,1999}?(b)/ /(a)(?(DEFINE)(b))(?2){0,1999}?(?2)/ /--- This test, with something more complicated than individual letters, causes different behaviour in Perl. Perhaps it disables some optimization; no tag is passed back for the failures, whereas in PCRE there is a tag. ---/ /(A|P)(*:A)(B|P) | (X|P)(X|P)(*:B)(Y|P)/xK AABC 0: AB 1: A 2: B MK: A XXYZ 0: XXY 1: 2: 3: X 4: X 5: Y MK: B ** Failers No match XAQQ No match, mark = A XAQQXZZ No match, mark = A AXQQQ No match, mark = A AXXQQQ No match, mark = B /-- Perl doesn't give marks for these, though it does if the alternatives are replaced by single letters. --/ /(b|q)(*:m)f|a(*:n)w/K aw 0: aw MK: n ** Failers No match, mark = n abc No match, mark = m /(q|b)(*:m)f|a(*:n)w/K aw 0: aw MK: n ** Failers No match, mark = n abc No match, mark = m /-- After a partial match, the behaviour is as for a failure. --/ /^a(*:X)bcde/K abc\P Partial match, mark=X: abc /-- These are here because Perl doesn't return a mark, except for the first --/ /(?=(*:x))(q|)/K+ abc 0: 0+ abc 1: MK: x /(?=(*:x))((*:y)q|)/K+ abc 0: 0+ abc 1: MK: x /(?=(*:x))(?:(*:y)q|)/K+ abc 0: 0+ abc MK: x /(?=(*:x))(?>(*:y)q|)/K+ abc 0: 0+ abc MK: x /(?=a(*:x))(?!a(*:y)c)/K+ ab 0: 0+ ab MK: x /(?=a(*:x))(?=a(*:y)c|)/K+ ab 0: 0+ ab MK: x /(..)\1/ ab\P Partial match: ab aba\P Partial match: aba abab\P 0: abab 1: ab /(..)\1/i ab\P Partial match: ab abA\P Partial match: abA aBAb\P 0: aBAb 1: aB /(..)\1{2,}/ ab\P Partial match: ab aba\P Partial match: aba abab\P Partial match: abab ababa\P Partial match: ababa ababab\P 0: ababab 1: ab ababab\P\P Partial match: ababab abababa\P 0: ababab 1: ab abababa\P\P Partial match: abababa /(..)\1{2,}/i ab\P Partial match: ab aBa\P Partial match: aBa aBAb\P Partial match: aBAb AbaBA\P Partial match: AbaBA abABAb\P 0: abABAb 1: ab aBAbaB\P\P Partial match: aBAbaB abABabA\P 0: abABab 1: ab abaBABa\P\P Partial match: abaBABa /(..)\1{2,}?x/i ab\P Partial match: ab abA\P Partial match: abA aBAb\P Partial match: aBAb abaBA\P Partial match: abaBA abAbaB\P Partial match: abAbaB abaBabA\P Partial match: abaBabA abAbABaBx\P 0: abAbABaBx 1: ab /^(..)\1/ aba\P Partial match: aba /^(..)\1{2,3}x/ aba\P Partial match: aba ababa\P Partial match: ababa ababa\P\P Partial match: ababa abababx 0: abababx 1: ab ababababx 0: ababababx 1: ab /^(..)\1{2,3}?x/ aba\P Partial match: aba ababa\P Partial match: ababa ababa\P\P Partial match: ababa abababx 0: abababx 1: ab ababababx 0: ababababx 1: ab /^(..)(\1{2,3})ab/ abababab 0: abababab 1: ab 2: abab /^\R/ \r\P 0: \x0d \r\P\P Partial match: \x0d /^\R{2,3}x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P Partial match: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P Partial match: \x0d\x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d \r\rx 0: \x0d\x0dx \r\r\rx 0: \x0d\x0d\x0dx /^\R{2,3}?x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P Partial match: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P Partial match: \x0d\x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d \r\rx 0: \x0d\x0dx \r\r\rx 0: \x0d\x0d\x0dx /^\R?x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d x 0: x \rx 0: \x0dx /^\R+x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\n\P Partial match: \x0d\x0a \r\n\P\P Partial match: \x0d\x0a \rx 0: \x0dx /^a$/ a\r\P Partial match: a\x0d a\r\P\P Partial match: a\x0d /^a$/m a\r\P Partial match: a\x0d a\r\P\P Partial match: a\x0d /^(a$|a\r)/ a\r\P 0: a\x0d 1: a\x0d a\r\P\P Partial match: a\x0d /^(a$|a\r)/m a\r\P 0: a\x0d 1: a\x0d a\r\P\P Partial match: a\x0d /./ \r\P 0: \x0d \r\P\P Partial match: \x0d /.{2,3}/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P 0: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P 0: \x0d\x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d /.{2,3}?/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P 0: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P 0: \x0d\x0d \r\r\r\P\P 0: \x0d\x0d "AB(C(D))(E(F))?(?(?=\2)(?=\4))" ABCDGHI\O03 Matched, but too many substrings 0: ABCD /-- These are all run as real matches in test 1; here we are just checking the settings of the anchored and startline bits. --/ /(?>.*?a)(?<=ba)/I Capturing subpattern count = 0 Max lookbehind = 2 No options No first char Need char = 'a' /(?:.*?a)(?<=ba)/I Capturing subpattern count = 0 Max lookbehind = 2 No options First char at start or follows newline Need char = 'a' /.*?a(*PRUNE)b/I Capturing subpattern count = 0 No options No first char Need char = 'b' /.*?a(*PRUNE)b/sI Capturing subpattern count = 0 Options: dotall No first char Need char = 'b' /^a(*PRUNE)b/sI Capturing subpattern count = 0 Options: anchored dotall No first char No need char /.*?a(*SKIP)b/I Capturing subpattern count = 0 No options No first char Need char = 'b' /(?>.*?a)b/sI Capturing subpattern count = 0 Options: dotall No first char Need char = 'b' /(?>.*?a)b/I Capturing subpattern count = 0 No options No first char Need char = 'b' /(?>^a)b/sI Capturing subpattern count = 0 Options: anchored dotall No first char No need char /(?>.*?)(?<=(abcd)|(wxyz))/I Capturing subpattern count = 2 Max lookbehind = 4 May match empty string No options No first char No need char /(?>.*)(?<=(abcd)|(wxyz))/I Capturing subpattern count = 2 Max lookbehind = 4 May match empty string No options No first char No need char "(?>.*)foo"I Capturing subpattern count = 0 No options No first char Need char = 'o' "(?>.*?)foo"I Capturing subpattern count = 0 No options No first char Need char = 'o' /(?>^abc)/mI Capturing subpattern count = 0 Options: multiline First char at start or follows newline Need char = 'c' /(?>.*abc)/mI Capturing subpattern count = 0 Options: multiline No first char Need char = 'c' /(?:.*abc)/mI Capturing subpattern count = 0 Options: multiline First char at start or follows newline Need char = 'c' /-- Check PCRE_STUDY_EXTRA_NEEDED --/ /.?/S-I Capturing subpattern count = 0 May match empty string No options No first char No need char Study returned NULL /.?/S!I Capturing subpattern count = 0 May match empty string No options No first char No need char Subject length lower bound = -1 No starting char list /(?:(a)+(?C1)bb|aa(?C2)b)/ aab\C+ Callout 1: last capture = 1 0: 1: a --->aab ^ ^ b Callout 1: last capture = 1 0: 1: a --->aab ^^ b Callout 2: last capture = -1 0: --->aab ^ ^ b 0: aab /(?:(a)++(?C1)bb|aa(?C2)b)/ aab\C+ Callout 1: last capture = 1 0: 1: a --->aab ^ ^ b Callout 2: last capture = -1 0: --->aab ^ ^ b 0: aab /(?:(?>(a))(?C1)bb|aa(?C2)b)/ aab\C+ Callout 1: last capture = 1 0: 1: a --->aab ^^ b Callout 2: last capture = -1 0: --->aab ^ ^ b 0: aab /(?:(?1)(?C1)x|ab(?C2))((a)){0}/ aab\C+ Callout 1: last capture = -1 0: --->aab ^^ x Callout 1: last capture = -1 0: --->aab ^^ x Callout 2: last capture = -1 0: --->aab ^ ^ ) 0: ab /(?1)(?C1)((a)(?C2)){0}/ aab\C+ Callout 2: last capture = 2 0: 1: 2: a --->aab ^^ ) Callout 1: last capture = -1 0: --->aab ^^ ((a)(?C2)){0} 0: a /(?:(a)+(?C1)bb|aa(?C2)b)++/ aab\C+ Callout 1: last capture = 1 0: 1: a --->aab ^ ^ b Callout 1: last capture = 1 0: 1: a --->aab ^^ b Callout 2: last capture = -1 0: --->aab ^ ^ b 0: aab aab\C+\O2 Callout 1: last capture = 1 0: --->aab ^ ^ b Callout 1: last capture = 1 0: --->aab ^^ b Callout 2: last capture = -1 0: --->aab ^ ^ b 0: aab /(ab)x|ab/ ab\O3 0: ab ab\O2 0: ab /(ab)/ ab\O3 Matched, but too many substrings 0: ab ab\O2 Matched, but too many substrings 0: ab /(?<=123)(*MARK:xx)abc/K xxxx123a\P\P Partial match at offset 7, mark=xx: 123a xxxx123a\P Partial match at offset 7, mark=xx: 123a /123\Kabc/ xxxx123a\P\P Partial match: 123a xxxx123a\P Partial match: 123a /^(?(?=a)aa|bb)/C bb --->bb +0 ^ ^ +1 ^ (?(?=a)aa|bb) +3 ^ (?=a) +6 ^ a +11 ^ b +12 ^^ b +13 ^ ^ ) +14 ^ ^ 0: bb /(?C1)^(?C2)(?(?C99)(?=(?C3)a(?C4))(?C5)a(?C6)a(?C7)|(?C8)b(?C9)b(?C10))(?C11)/ bb --->bb 1 ^ ^ 2 ^ (?(?C99)(?=(?C3)a(?C4))(?C5)a(?C6)a(?C7)|(?C8)b(?C9)b(?C10)) 99 ^ (?=(?C3)a(?C4)) 3 ^ a 8 ^ b 9 ^^ b 10 ^ ^ ) 11 ^ ^ 0: bb /-- Perl seems to have a bug with this one --/ /aaaaa(*COMMIT)(*PRUNE)b|a+c/ aaaaaac 0: aaaac /-- Here are some that Perl treats differently because of the way it handles backtracking verbs. --/ /(?!a(*COMMIT)b)ac|ad/ ac 0: ac ad 0: ad /^(?!a(*THEN)b|ac)../ ac No match ad 0: ad /^(?=a(*THEN)b|ac)/ ac 0: /\A.*?(?:a|b(*THEN)c)/ ba 0: ba /\A.*?(?:a|b(*THEN)c)++/ ba 0: ba /\A.*?(?:a|b(*THEN)c|d)/ ba 0: ba /(?:(a(*MARK:X)a+(*SKIP:X)b)){0}(?:(?1)|aac)/ aac 0: aac /\A.*?(a|b(*THEN)c)/ ba 0: ba 1: a /^(A(*THEN)B|A(*THEN)D)/ AD 0: AD 1: AD /(?!b(*THEN)a)bn|bnn/ bnn 0: bn /(?(?=b(*SKIP)a)bn|bnn)/ bnn No match /(?=b(*THEN)a|)bn|bnn/ bnn 0: bn /-------------------------/ /(*LIMIT_MATCH=12bc)abc/ Failed: (*VERB) not recognized or malformed at offset 7 /(*LIMIT_MATCH=4294967290)abc/ Failed: (*VERB) not recognized or malformed at offset 7 /(*LIMIT_RECURSION=4294967280)abc/I Capturing subpattern count = 0 Recursion limit = 4294967280 No options First char = 'a' Need char = 'c' /(a+)*zz/ aaaaaaaaaaaaaz No match aaaaaaaaaaaaaz\q3000 Error -8 (match limit exceeded) /(a+)*zz/S- aaaaaaaaaaaaaz\Q10 Error -21 (recursion limit exceeded) /(*LIMIT_MATCH=3000)(a+)*zz/I Capturing subpattern count = 1 Match limit = 3000 No options No first char Need char = 'z' aaaaaaaaaaaaaz Error -8 (match limit exceeded) aaaaaaaaaaaaaz\q60000 Error -8 (match limit exceeded) /(*LIMIT_MATCH=60000)(*LIMIT_MATCH=3000)(a+)*zz/I Capturing subpattern count = 1 Match limit = 3000 No options No first char Need char = 'z' aaaaaaaaaaaaaz Error -8 (match limit exceeded) /(*LIMIT_MATCH=60000)(a+)*zz/I Capturing subpattern count = 1 Match limit = 60000 No options No first char Need char = 'z' aaaaaaaaaaaaaz No match aaaaaaaaaaaaaz\q3000 Error -8 (match limit exceeded) /(*LIMIT_RECURSION=10)(a+)*zz/IS- Capturing subpattern count = 1 Recursion limit = 10 No options No first char Need char = 'z' Subject length lower bound = 2 Starting chars: a z aaaaaaaaaaaaaz Error -21 (recursion limit exceeded) aaaaaaaaaaaaaz\Q1000 Error -21 (recursion limit exceeded) /(*LIMIT_RECURSION=10)(*LIMIT_RECURSION=1000)(a+)*zz/IS- Capturing subpattern count = 1 Recursion limit = 10 No options No first char Need char = 'z' Subject length lower bound = 2 Starting chars: a z aaaaaaaaaaaaaz Error -21 (recursion limit exceeded) /(*LIMIT_RECURSION=1000)(a+)*zz/IS- Capturing subpattern count = 1 Recursion limit = 1000 No options No first char Need char = 'z' Subject length lower bound = 2 Starting chars: a z aaaaaaaaaaaaaz No match aaaaaaaaaaaaaz\Q10 Error -21 (recursion limit exceeded) /-- This test causes a segfault with Perl 5.18.0 --/ /^(?=(a)){0}b(?1)/ backgammon 0: ba /(?|(?f)|(?b))/JI Capturing subpattern count = 1 Named capturing subpatterns: n 1 Options: dupnames No first char No need char /(?abc)(?z)\k()/JDZS ------------------------------------------------------------------ Bra CBra 1 abc Ket CBra 2 z Ket \k2 CBra 3 Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 3 Max back reference = 2 Named capturing subpatterns: a 1 a 2 Options: dupnames First char = 'a' Need char = 'z' Subject length lower bound = 5 No starting char list /a*[bcd]/BZ ------------------------------------------------------------------ Bra a*+ [b-d] Ket End ------------------------------------------------------------------ /[bcd]*a/BZ ------------------------------------------------------------------ Bra [b-d]*+ a Ket End ------------------------------------------------------------------ /-- A complete set of tests for auto-possessification of character types --/ /\D+\D \D+\d \D+\S \D+\s \D+\W \D+\w \D+. \D+\C \D+\R \D+\H \D+\h \D+\V \D+\v \D+\Z \D+\z \D+$/BZx ------------------------------------------------------------------ Bra \D+ \D \D++ \d \D+ \S \D+ \s \D+ \W \D+ \w \D+ Any \D+ AllAny \D+ \R \D+ \H \D+ \h \D+ \V \D+ \v \D+ \Z \D++ \z \D+ $ Ket End ------------------------------------------------------------------ /\d+\D \d+\d \d+\S \d+\s \d+\W \d+\w \d+. \d+\C \d+\R \d+\H \d+\h \d+\V \d+\v \d+\Z \d+\z \d+$/BZx ------------------------------------------------------------------ Bra \d++ \D \d+ \d \d+ \S \d++ \s \d++ \W \d+ \w \d+ Any \d+ AllAny \d++ \R \d+ \H \d++ \h \d+ \V \d++ \v \d++ \Z \d++ \z \d++ $ Ket End ------------------------------------------------------------------ /\S+\D \S+\d \S+\S \S+\s \S+\W \S+\w \S+. \S+\C \S+\R \S+\H \S+\h \S+\V \S+\v \S+\Z \S+\z \S+$/BZx ------------------------------------------------------------------ Bra \S+ \D \S+ \d \S+ \S \S++ \s \S+ \W \S+ \w \S+ Any \S+ AllAny \S++ \R \S+ \H \S++ \h \S+ \V \S++ \v \S++ \Z \S++ \z \S++ $ Ket End ------------------------------------------------------------------ /\s+\D \s+\d \s+\S \s+\s \s+\W \s+\w \s+. \s+\C \s+\R \s+\H \s+\h \s+\V \s+\v \s+\Z \s+\z \s+$/BZx ------------------------------------------------------------------ Bra \s+ \D \s++ \d \s++ \S \s+ \s \s+ \W \s++ \w \s+ Any \s+ AllAny \s+ \R \s+ \H \s+ \h \s+ \V \s+ \v \s+ \Z \s++ \z \s+ $ Ket End ------------------------------------------------------------------ /\W+\D \W+\d \W+\S \W+\s \W+\W \W+\w \W+. \W+\C \W+\R \W+\H \W+\h \W+\V \W+\v \W+\Z \W+\z \W+$/BZx ------------------------------------------------------------------ Bra \W+ \D \W++ \d \W+ \S \W+ \s \W+ \W \W++ \w \W+ Any \W+ AllAny \W+ \R \W+ \H \W+ \h \W+ \V \W+ \v \W+ \Z \W++ \z \W+ $ Ket End ------------------------------------------------------------------ /\w+\D \w+\d \w+\S \w+\s \w+\W \w+\w \w+. \w+\C \w+\R \w+\H \w+\h \w+\V \w+\v \w+\Z \w+\z \w+$/BZx ------------------------------------------------------------------ Bra \w+ \D \w+ \d \w+ \S \w++ \s \w++ \W \w+ \w \w+ Any \w+ AllAny \w++ \R \w+ \H \w++ \h \w+ \V \w++ \v \w++ \Z \w++ \z \w++ $ Ket End ------------------------------------------------------------------ /\C+\D \C+\d \C+\S \C+\s \C+\W \C+\w \C+. \C+\C \C+\R \C+\H \C+\h \C+\V \C+\v \C+\Z \C+\z \C+$/BZx ------------------------------------------------------------------ Bra AllAny+ \D AllAny+ \d AllAny+ \S AllAny+ \s AllAny+ \W AllAny+ \w AllAny+ Any AllAny+ AllAny AllAny+ \R AllAny+ \H AllAny+ \h AllAny+ \V AllAny+ \v AllAny+ \Z AllAny++ \z AllAny+ $ Ket End ------------------------------------------------------------------ /\R+\D \R+\d \R+\S \R+\s \R+\W \R+\w \R+. \R+\C \R+\R \R+\H \R+\h \R+\V \R+\v \R+\Z \R+\z \R+$/BZx ------------------------------------------------------------------ Bra \R+ \D \R++ \d \R+ \S \R++ \s \R+ \W \R++ \w \R++ Any \R+ AllAny \R+ \R \R+ \H \R++ \h \R+ \V \R+ \v \R+ \Z \R++ \z \R+ $ Ket End ------------------------------------------------------------------ /\H+\D \H+\d \H+\S \H+\s \H+\W \H+\w \H+. \H+\C \H+\R \H+\H \H+\h \H+\V \H+\v \H+\Z \H+\z \H+$/BZx ------------------------------------------------------------------ Bra \H+ \D \H+ \d \H+ \S \H+ \s \H+ \W \H+ \w \H+ Any \H+ AllAny \H+ \R \H+ \H \H++ \h \H+ \V \H+ \v \H+ \Z \H++ \z \H+ $ Ket End ------------------------------------------------------------------ /\h+\D \h+\d \h+\S \h+\s \h+\W \h+\w \h+. \h+\C \h+\R \h+\H \h+\h \h+\V \h+\v \h+\Z \h+\z \h+$/BZx ------------------------------------------------------------------ Bra \h+ \D \h++ \d \h++ \S \h+ \s \h+ \W \h++ \w \h+ Any \h+ AllAny \h++ \R \h++ \H \h+ \h \h+ \V \h++ \v \h+ \Z \h++ \z \h+ $ Ket End ------------------------------------------------------------------ /\V+\D \V+\d \V+\S \V+\s \V+\W \V+\w \V+. \V+\C \V+\R \V+\H \V+\h \V+\V \V+\v \V+\Z \V+\z \V+$/BZx ------------------------------------------------------------------ Bra \V+ \D \V+ \d \V+ \S \V+ \s \V+ \W \V+ \w \V+ Any \V+ AllAny \V++ \R \V+ \H \V+ \h \V+ \V \V++ \v \V+ \Z \V++ \z \V+ $ Ket End ------------------------------------------------------------------ /\v+\D \v+\d \v+\S \v+\s \v+\W \v+\w \v+. \v+\C \v+\R \v+\H \v+\h \v+\V \v+\v \v+\Z \v+\z \v+$/BZx ------------------------------------------------------------------ Bra \v+ \D \v++ \d \v++ \S \v+ \s \v+ \W \v++ \w \v+ Any \v+ AllAny \v+ \R \v+ \H \v++ \h \v++ \V \v+ \v \v+ \Z \v++ \z \v+ $ Ket End ------------------------------------------------------------------ / a+\D a+\d a+\S a+\s a+\W a+\w a+. a+\C a+\R a+\H a+\h a+\V a+\v a+\Z a+\z a+$/BZx ------------------------------------------------------------------ Bra a+ \D a++ \d a+ \S a++ \s a++ \W a+ \w a+ Any a+ AllAny a++ \R a+ \H a++ \h a+ \V a++ \v a++ \Z a++ \z a++ $ Ket End ------------------------------------------------------------------ /\n+\D \n+\d \n+\S \n+\s \n+\W \n+\w \n+. \n+\C \n+\R \n+\H \n+\h \n+\V \n+\v \n+\Z \n+\z \n+$/BZx ------------------------------------------------------------------ Bra \x0a+ \D \x0a++ \d \x0a++ \S \x0a+ \s \x0a+ \W \x0a++ \w \x0a+ Any \x0a+ AllAny \x0a+ \R \x0a+ \H \x0a++ \h \x0a++ \V \x0a+ \v \x0a+ \Z \x0a++ \z \x0a+ $ Ket End ------------------------------------------------------------------ / .+\D .+\d .+\S .+\s .+\W .+\w .+. .+\C .+\R .+\H .+\h .+\V .+\v .+\Z .+\z .+$/BZx ------------------------------------------------------------------ Bra Any+ \D Any+ \d Any+ \S Any+ \s Any+ \W Any+ \w Any+ Any Any+ AllAny Any++ \R Any+ \H Any+ \h Any+ \V Any+ \v Any+ \Z Any++ \z Any+ $ Ket End ------------------------------------------------------------------ / .+\D .+\d .+\S .+\s .+\W .+\w .+. .+\C .+\R .+\H .+\h .+\V .+\v .+\Z .+\z .+$/BZxs ------------------------------------------------------------------ Bra AllAny+ \D AllAny+ \d AllAny+ \S AllAny+ \s AllAny+ \W AllAny+ \w AllAny+ AllAny AllAny+ AllAny AllAny+ \R AllAny+ \H AllAny+ \h AllAny+ \V AllAny+ \v AllAny+ \Z AllAny++ \z AllAny+ $ Ket End ------------------------------------------------------------------ /\D+$ \d+$ \S+$ \s+$ \W+$ \w+$ \C+$ \R+$ \H+$ \h+$ \V+$ \v+$ a+$ \n+$ .+$ .+$/BZxm ------------------------------------------------------------------ Bra \D+ /m $ \d++ /m $ \S++ /m $ \s+ /m $ \W+ /m $ \w++ /m $ AllAny+ /m $ \R+ /m $ \H+ /m $ \h+ /m $ \V+ /m $ \v+ /m $ a+ /m $ \x0a+ /m $ Any+ /m $ Any+ /m $ Ket End ------------------------------------------------------------------ /(?=a+)a(a+)++a/BZ ------------------------------------------------------------------ Bra Assert a++ Ket a CBraPos 1 a++ KetRpos a Ket End ------------------------------------------------------------------ /a+(bb|cc)a+(?:bb|cc)a+(?>bb|cc)a+(?:bb|cc)+a+(aa)a+(?:bb|aa)/BZ ------------------------------------------------------------------ Bra a++ CBra 1 bb Alt cc Ket a++ Bra bb Alt cc Ket a++ Once_NC bb Alt cc Ket a++ Bra bb Alt cc KetRmax a+ CBra 2 aa Ket a+ Bra bb Alt aa Ket Ket End ------------------------------------------------------------------ /a+(bb|cc)?#a+(?:bb|cc)??#a+(?:bb|cc)?+#a+(?:bb|cc)*#a+(bb|cc)?a#a+(?:aa)?/BZ ------------------------------------------------------------------ Bra a++ Brazero CBra 1 bb Alt cc Ket # a++ Braminzero Bra bb Alt cc Ket # a++ Once Brazero Bra bb Alt cc Ket Ket # a++ Brazero Bra bb Alt cc KetRmax # a+ Brazero CBra 2 bb Alt cc Ket a# a+ Brazero Bra aa Ket Ket End ------------------------------------------------------------------ /a+(?:bb)?a#a+(?:|||)#a+(?:|b)a#a+(?:|||)?a/BZ ------------------------------------------------------------------ Bra a+ Brazero Bra bb Ket a# a++ Bra Alt Alt Alt Ket # a+ Bra Alt b Ket a# a+ Brazero Bra Alt Alt Alt Ket a Ket End ------------------------------------------------------------------ /[ab]*/BZ ------------------------------------------------------------------ Bra [ab]*+ Ket End ------------------------------------------------------------------ aaaa 0: aaaa /[ab]*?/BZ ------------------------------------------------------------------ Bra [ab]*? Ket End ------------------------------------------------------------------ aaaa 0: /[ab]?/BZ ------------------------------------------------------------------ Bra [ab]?+ Ket End ------------------------------------------------------------------ aaaa 0: a /[ab]??/BZ ------------------------------------------------------------------ Bra [ab]?? Ket End ------------------------------------------------------------------ aaaa 0: /[ab]+/BZ ------------------------------------------------------------------ Bra [ab]++ Ket End ------------------------------------------------------------------ aaaa 0: aaaa /[ab]+?/BZ ------------------------------------------------------------------ Bra [ab]+? Ket End ------------------------------------------------------------------ aaaa 0: a /[ab]{2,3}/BZ ------------------------------------------------------------------ Bra [ab]{2,3}+ Ket End ------------------------------------------------------------------ aaaa 0: aaa /[ab]{2,3}?/BZ ------------------------------------------------------------------ Bra [ab]{2,3}? Ket End ------------------------------------------------------------------ aaaa 0: aa /[ab]{2,}/BZ ------------------------------------------------------------------ Bra [ab]{2,}+ Ket End ------------------------------------------------------------------ aaaa 0: aaaa /[ab]{2,}?/BZ ------------------------------------------------------------------ Bra [ab]{2,}? Ket End ------------------------------------------------------------------ aaaa 0: aa /\d+\s{0,5}=\s*\S?=\w{0,4}\W*/BZ ------------------------------------------------------------------ Bra \d++ \s{0,5}+ = \s*+ \S? = \w{0,4}+ \W*+ Ket End ------------------------------------------------------------------ /[a-d]{5,12}[e-z0-9]*#[^a-z]+[b-y]*a[2-7]?[^0-9a-z]+/BZ ------------------------------------------------------------------ Bra [a-d]{5,12}+ [0-9e-z]*+ # [\x00-`{-\xff] (neg)++ [b-y]*+ a [2-7]?+ [\x00-/:-`{-\xff] (neg)++ Ket End ------------------------------------------------------------------ /[a-z]*\s#[ \t]?\S#[a-c]*\S#[C-G]+?\d#[4-8]*\D#[4-9,]*\D#[!$]{0,5}\w#[M-Xf-l]+\W#[a-c,]?\W/BZ ------------------------------------------------------------------ Bra [a-z]*+ \s # [\x09 ]?+ \S # [a-c]* \S # [C-G]++ \d # [4-8]*+ \D # [,4-9]* \D # [!$]{0,5}+ \w # [M-Xf-l]++ \W # [,a-c]? \W Ket End ------------------------------------------------------------------ /a+(aa|bb)*c#a*(bb|cc)*a#a?(bb|cc)*d#[a-f]*(g|hh)*f/BZ ------------------------------------------------------------------ Bra a+ Brazero CBra 1 aa Alt bb KetRmax c# a* Brazero CBra 2 bb Alt cc KetRmax a# a?+ Brazero CBra 3 bb Alt cc KetRmax d# [a-f]* Brazero CBra 4 g Alt hh KetRmax f Ket End ------------------------------------------------------------------ /[a-f]*(g|hh|i)*i#[a-x]{4,}(y{0,6})*y#[a-k]+(ll|mm)+n/BZ ------------------------------------------------------------------ Bra [a-f]*+ Brazero CBra 1 g Alt hh Alt i KetRmax i# [a-x]{4,} Brazero SCBra 2 y{0,6} KetRmax y# [a-k]++ CBra 3 ll Alt mm KetRmax n Ket End ------------------------------------------------------------------ /[a-f]*(?>gg|hh)+#[a-f]*(?>gg|hh)?#[a-f]*(?>gg|hh)*a#[a-f]*(?>gg|hh)*h/BZ ------------------------------------------------------------------ Bra [a-f]*+ Once_NC gg Alt hh KetRmax # [a-f]*+ Brazero Once_NC gg Alt hh Ket # [a-f]* Brazero Once_NC gg Alt hh KetRmax a# [a-f]*+ Brazero Once_NC gg Alt hh KetRmax h Ket End ------------------------------------------------------------------ /[a-c]*d/DZS ------------------------------------------------------------------ Bra [a-c]*+ d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char Need char = 'd' Subject length lower bound = 1 Starting chars: a b c d /[a-c]+d/DZS ------------------------------------------------------------------ Bra [a-c]++ d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char Need char = 'd' Subject length lower bound = 2 Starting chars: a b c /[a-c]?d/DZS ------------------------------------------------------------------ Bra [a-c]?+ d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char Need char = 'd' Subject length lower bound = 1 Starting chars: a b c d /[a-c]{4,6}d/DZS ------------------------------------------------------------------ Bra [a-c]{4,6}+ d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char Need char = 'd' Subject length lower bound = 5 Starting chars: a b c /[a-c]{0,6}d/DZS ------------------------------------------------------------------ Bra [a-c]{0,6}+ d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char Need char = 'd' Subject length lower bound = 1 Starting chars: a b c d /-- End of special auto-possessive tests --/ /^A\o{1239}B/ Failed: non-octal character in \o{} (closing brace missing?) at offset 8 /^A\oB/ Failed: missing opening brace after \o at offset 3 /^A\x{zz}B/ Failed: non-hex character in \x{} (closing brace missing?) at offset 5 /^A\x{12Z/ Failed: non-hex character in \x{} (closing brace missing?) at offset 7 /^A\x{/ Failed: non-hex character in \x{} (closing brace missing?) at offset 5 /[ab]++/BZO ------------------------------------------------------------------ Bra [ab]++ Ket End ------------------------------------------------------------------ /[^ab]*+/BZO ------------------------------------------------------------------ Bra [\x00-`c-\xff] (neg)*+ Ket End ------------------------------------------------------------------ /a{4}+/BZO ------------------------------------------------------------------ Bra a{4} Ket End ------------------------------------------------------------------ /a{4}+/BZOi ------------------------------------------------------------------ Bra /i a{4} Ket End ------------------------------------------------------------------ /[a-[:digit:]]+/ Failed: invalid range in character class at offset 3 /[A-[:digit:]]+/ Failed: invalid range in character class at offset 3 /[a-[.xxx.]]+/ Failed: invalid range in character class at offset 3 /[a-[=xxx=]]+/ Failed: invalid range in character class at offset 3 /[a-[!xxx!]]+/ Failed: range out of order in character class at offset 3 /[A-[!xxx!]]+/ A]]] 0: A]]] /[a-\d]+/ Failed: invalid range in character class at offset 4 /(?<0abc>xx)/ Failed: group name must start with a non-digit at offset 3 /(?&1abc)xx(?<1abc>y)/ Failed: group name must start with a non-digit at offset 3 /(?xx)/ Failed: syntax error in subpattern name (missing terminator) at offset 5 /(?'0abc'xx)/ Failed: group name must start with a non-digit at offset 3 /(?P<0abc>xx)/ Failed: group name must start with a non-digit at offset 4 /\k<5ghj>/ Failed: group name must start with a non-digit at offset 3 /\k'5ghj'/ Failed: group name must start with a non-digit at offset 3 /\k{2fgh}/ Failed: group name must start with a non-digit at offset 3 /(?P=8yuki)/ Failed: group name must start with a non-digit at offset 4 /\g{4df}/ Failed: group name must start with a non-digit at offset 3 /(?&1abc)xx(?<1abc>y)/ Failed: group name must start with a non-digit at offset 3 /(?P>1abc)xx(?<1abc>y)/ Failed: group name must start with a non-digit at offset 4 /\g'3gh'/ Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 2 /\g<5fg>/ Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 2 /(?(<4gh>)abc)/ Failed: group name must start with a non-digit at offset 4 /(?('4gh')abc)/ Failed: group name must start with a non-digit at offset 4 /(?(4gh)abc)/ Failed: malformed number or name after (?( at offset 4 /(?(R&6yh)abc)/ Failed: group name must start with a non-digit at offset 5 /(((a\2)|(a*)\g<-1>))*a?/BZ ------------------------------------------------------------------ Bra Brazero SCBra 1 Once CBra 2 CBra 3 a \2 Ket Alt CBra 4 a* Ket Recurse Ket Ket KetRmax a?+ Ket End ------------------------------------------------------------------ /-- Test the ugly "start or end of word" compatibility syntax --/ /[[:<:]]red[[:>:]]/BZ ------------------------------------------------------------------ Bra \b Assert \w Ket red \b AssertB Reverse \w Ket Ket End ------------------------------------------------------------------ little red riding hood 0: red a /red/ thing 0: red red is a colour 0: red put it all on red 0: red ** Failers No match no reduction No match Alfred Winifred No match /[a[:<:]] should give error/ Failed: unknown POSIX class name at offset 4 /(?=ab\K)/+ abcd Start of matched string is beyond its end - displaying from end to start. 0: ab 0+ abcd /abcd/f xx\nxabcd No match / -- Test stack check external calls --/ /(((((a)))))/Q0 /(((((a)))))/Q1 Failed: parentheses are too deeply nested (stack check) at offset 0 /(((((a)))))/Q ** Missing 0 or 1 after /Q /^\w+(?>\s*)(?<=\w)/BZ ------------------------------------------------------------------ Bra ^ \w+ Once_NC \s*+ Ket AssertB Reverse \w Ket Ket End ------------------------------------------------------------------ /\othing/ Failed: missing opening brace after \o at offset 1 /\o{}/ Failed: digits missing in \x{} or \o{} at offset 1 /\o{whatever}/ Failed: non-octal character in \o{} (closing brace missing?) at offset 3 /\xthing/ /\x{}/ Failed: digits missing in \x{} or \o{} at offset 3 /\x{whatever}/ Failed: non-hex character in \x{} (closing brace missing?) at offset 3 "((?=(?(?=(?(?=(?(?=()))))))))" a 0: 1: 2: "(?(?=)==)(((((((((?=)))))))))" a No match /^(?:(a)|b)(?(1)A|B)/I Capturing subpattern count = 1 Max back reference = 1 Options: anchored No first char No need char aA123\O3 Matched, but too many substrings 0: aA aA123\O6 0: aA 1: a '^(?:(?a)|b)(?()A|B)' aA123\O3 Matched, but too many substrings 0: aA aA123\O6 0: aA 1: a '^(?)(?:(?a)|b)(?()A|B)'J aA123\O3 Matched, but too many substrings 0: aA aA123\O6 Matched, but too many substrings 0: aA 1: '^(?:(?X)|)(?:(?a)|b)\k{AA}'J aa123\O3 Matched, but too many substrings 0: aa aa123\O6 Matched, but too many substrings 0: aa 1: /(?(?J)(?1(111111)11|)1|1|)(?()1)/ /(?(?=0)?)+/ Failed: nothing to repeat at offset 7 /(?(?=0)(?=00)?00765)/ 00765 0: 00765 /(?(?=0)(?=00)?00765|(?!3).56)/ 00765 0: 00765 456 0: 456 ** Failers No match 356 No match '^(a)*+(\w)' g 0: g 1: 2: g g\O3 Matched, but too many substrings 0: g '^(?:a)*+(\w)' g 0: g 1: g g\O3 Matched, but too many substrings 0: g //C \O\C+ Callout 255: last capture = -1 ---> +0 ^ Matched, but too many substrings "((?2){0,1999}())?" /((?+1)(\1))/BZ ------------------------------------------------------------------ Bra Once CBra 1 Recurse CBra 2 \1 Ket Ket Ket Ket End ------------------------------------------------------------------ /(?(?!)a|b)/ bbb 0: b aaa No match "((?2)+)((?1))" "(?(?.*!.*)?)" Failed: assertion expected after (?( or (?(?C) at offset 3 "X((?2)()*+){2}+"BZ ------------------------------------------------------------------ Bra X Once CBra 1 Recurse Braposzero SCBraPos 2 KetRpos Ket CBra 1 Recurse Braposzero SCBraPos 2 KetRpos Ket Ket Ket End ------------------------------------------------------------------ "X((?2)()*+){2}"BZ ------------------------------------------------------------------ Bra X CBra 1 Recurse Braposzero SCBraPos 2 KetRpos Ket CBra 1 Recurse Braposzero SCBraPos 2 KetRpos Ket Ket End ------------------------------------------------------------------ "(?<=((?2))((?1)))" Failed: lookbehind assertion is not fixed length at offset 17 /(?<=\Ka)/g+ aaaaa 0: a 0+ aaaa 0: a 0+ aaaa 0: a 0+ aaa 0: a 0+ aa 0: a 0+ a 0: a 0+ /(?<=\Ka)/G+ aaaaa 0: a 0+ aaaa 0: a 0+ aaa 0: a 0+ aa 0: a 0+ a 0: a 0+ /((?2){73}(?2))((?1))/ /.((?2)(?R)\1)()/BZ ------------------------------------------------------------------ Bra Any Once CBra 1 Recurse Recurse \1 Ket Ket CBra 2 Ket Ket End ------------------------------------------------------------------ /(?1)()((((((\1++))\x85)+)|))/ /(\9*+(?2);\3++()2|)++{/ Failed: reference to non-existent subpattern at offset 22 /\V\x85\9*+((?2)\3++()2)*:2/ Failed: reference to non-existent subpattern at offset 26 /(((?(R)){0,2}) (?''((?'R')((?'R')))))/J /(((?(X)){0,2}) (?''((?'X')((?'X')))))/J /(((?(R)){0,2}) (?''((?'X')((?'R')))))/ "(?J)(?'d'(?'d'\g{d}))" ".*?\h.+.\.+\R*?\xd(?i)(?=!(?=b`b`b`\`b\xa9b!)`\a`bbbbbbbbbbbbb`bbbbbbbbbbbb*R\x85bbbbbbb\C?{((?2)(?))(( \H){8(?<=(?1){29}\xa8bbbb\x16\xd\xc6^($(?1)/ /a[[:punct:]b]/BZ ------------------------------------------------------------------ Bra a [!-/:-@[-`b{-~] Ket End ------------------------------------------------------------------ /L(?#(|++)(?J:(?)(?))(?)/ \O\CC Matched, but too many substrings copy substring C failed -7 /(?=a\K)/ ring bpattingbobnd $ 1,oern cou \rb\L Start of matched string is beyond its end - displaying from end to start. 0: a 0L /(?<=((?C)0))/ 9010 --->9010 0 ^ 0 0 ^ 0 0: 1: 0 abcd --->abcd 0 ^ 0 0 ^ 0 0 ^ 0 0 ^ 0 No match /((?J)(?'R'(?'R'(?'R'(?'R'(?'R'(?|(\k'R'))))))))/ /\N(?(?C)0?!.)*/ Failed: assertion expected after (?( or (?(?C) at offset 4 /(?abc)(?(R)xyz)/BZ ------------------------------------------------------------------ Bra CBra 1 abc Ket Cond Cond recurse any xyz Ket Ket End ------------------------------------------------------------------ /(?abc)(?(R)xyz)/BZ ------------------------------------------------------------------ Bra CBra 1 abc Ket Cond 1 Cond ref xyz Ket Ket End ------------------------------------------------------------------ /(?=.*[A-Z])/I Capturing subpattern count = 0 May match empty string No options No first char No need char "(?<=(a))\1?b" ab 0: b 1: a aaab 0: ab 1: a "(?=(a))\1?b" ab 0: ab 1: a aaab 0: ab 1: a /(?(?=^))b/ abc 0: b /-- End of testinput2 --/ ================================================ FILE: src/pcre/testdata/testoutput20 ================================================ /-- These DFA tests are for the handling of characters greater than 255 in 16- or 32-bit, non-UTF mode. --/ /^\x{ffff}+/i \x{ffff} 0: \x{ffff} /^\x{ffff}?/i \x{ffff} 0: \x{ffff} /^\x{ffff}*/i \x{ffff} 0: \x{ffff} /^\x{ffff}{3}/i \x{ffff}\x{ffff}\x{ffff} 0: \x{ffff}\x{ffff}\x{ffff} /^\x{ffff}{0,3}/i \x{ffff} 0: \x{ffff} /-- End of testinput20 --/ ================================================ FILE: src/pcre/testdata/testoutput21-16 ================================================ /-- Tests for reloading pre-compiled patterns. The first one gives an error right away, and can be any old pattern compiled in 8-bit mode ("abc" is typical). The others require the link size to be 2. */x (?:[AaLl]+)[^xX-]*?)(?P[\x{150}-\x{250}\x{300}]| [^\x{800}aAs-uS-U\x{d800}-\x{dfff}])++[^#\b\x{500}\x{1000}]{3,5}$ /x In 16-bit mode with options: S>testdata/saved16LE-1 FS>testdata/saved16BE-1 In 32-bit mode with options: S>testdata/saved32LE-1 FS>testdata/saved32BE-1 --%x (?:[AaLl]+)[^xX-]*?)(?P[\x{150}-\x{250}\x{300}]| [^\x{800}aAs-uS-U\x{d800}-\x{dfff}])++[^#\b\x{500}\x{1000}]{3,5}$ /x In 16-bit mode with options: S>testdata/saved16LE-1 FS>testdata/saved16BE-1 In 32-bit mode with options: S>testdata/saved32LE-1 FS>testdata/saved32BE-1 --%x [aZ\x{400}-\x{10ffff}]{4,} [\x{f123}\x{10039}\x{20000}-\x{21234}]?| [A-Cx-z\x{100000}-\x{1000a7}\x{101234}]) (?[^az])/x In 16-bit mode with options: S8>testdata/saved16LE-2 FS8>testdata/saved16BE-2 In 32-bit mode with options: S8>testdata/saved32LE-2 FS8>testdata/saved32BE-2 --%8x [aZ\x{400}-\x{10ffff}]{4,} [\x{f123}\x{10039}\x{20000}-\x{21234}]?| [A-Cx-z\x{100000}-\x{1000a7}\x{101234}]) (?[^az])/x In 16-bit mode with options: S8>testdata/saved16LE-2 FS8>testdata/saved16BE-2 In 32-bit mode with options: S8>testdata/saved32LE-2 FS8>testdata/saved32BE-2 --%8x ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff /[\V]/BZSI ------------------------------------------------------------------ Bra [\x00-\x09\x0e-\x84\x86-\xff\x{100}-\x{2027}\x{202a}-\x{ffff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff /-- End of testinput23 --/ ================================================ FILE: src/pcre/testdata/testoutput24 ================================================ /-- Tests for the 16-bit library with UTF-16 support only */ < forbid W /bad/8 \x{d800} Error -10 (bad UTF-16 string) offset=0 reason=1 /short/8 \P\P\x{d800} Error -25 (short UTF-16 string) offset=0 reason=1 /-- End of testinput24 --/ ================================================ FILE: src/pcre/testdata/testoutput25 ================================================ /-- Tests for the 32-bit library only */ < forbid 8W /-- Check maximum character size --/ /\x{110000}/ /\x{7fffffff}/ /\x{80000000}/ /\x{ffffffff}/ /\x{100000000}/ Failed: character value in \x{} or \o{} is too large at offset 12 /\o{17777777777}/ /\o{20000000000}/ /\o{37777777777}/ /\o{40000000000}/ Failed: character value in \x{} or \o{} is too large at offset 14 /\x{7fffffff}\x{7fffffff}/I Capturing subpattern count = 0 No options First char = \x{7fffffff} Need char = \x{7fffffff} /\x{80000000}\x{80000000}/I Capturing subpattern count = 0 No options First char = \x{80000000} Need char = \x{80000000} /\x{ffffffff}\x{ffffffff}/I Capturing subpattern count = 0 No options First char = \x{ffffffff} Need char = \x{ffffffff} /-- Non-UTF characters --/ /\C{2,3}/ \x{400000}\x{400001}\x{400002}\x{400003} 0: \x{400000}\x{400001}\x{400002} /\x{400000}\x{800000}/iDZ ------------------------------------------------------------------ Bra /i \x{400000}\x{800000} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless First char = \x{400000} Need char = \x{800000} /-- Check character ranges --/ /[\H]/BZSI ------------------------------------------------------------------ Bra [\x00-\x08\x0a-\x1f!-\x9f\xa1-\xff\x{100}-\x{167f}\x{1681}-\x{180d}\x{180f}-\x{1fff}\x{200b}-\x{202e}\x{2030}-\x{205e}\x{2060}-\x{2fff}\x{3001}-\x{ffffffff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x0a \x0b \x0c \x0d \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x85 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff /[\V]/BZSI ------------------------------------------------------------------ Bra [\x00-\x09\x0e-\x84\x86-\xff\x{100}-\x{2027}\x{202a}-\x{ffffffff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: \x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f \x20 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x7f \x80 \x81 \x82 \x83 \x84 \x86 \x87 \x88 \x89 \x8a \x8b \x8c \x8d \x8e \x8f \x90 \x91 \x92 \x93 \x94 \x95 \x96 \x97 \x98 \x99 \x9a \x9b \x9c \x9d \x9e \x9f \xa0 \xa1 \xa2 \xa3 \xa4 \xa5 \xa6 \xa7 \xa8 \xa9 \xaa \xab \xac \xad \xae \xaf \xb0 \xb1 \xb2 \xb3 \xb4 \xb5 \xb6 \xb7 \xb8 \xb9 \xba \xbb \xbc \xbd \xbe \xbf \xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf \xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef \xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff /-- End of testinput25 --/ ================================================ FILE: src/pcre/testdata/testoutput26 ================================================ /-- Tests for the 32-bit library with UTF-32 support only */ < forbid W /-- Non-UTF characters --/ /\x{110000}/8 Failed: character value in \x{} or \o{} is too large at offset 9 /\o{4200000}/8 Failed: character value in \x{} or \o{} is too large at offset 10 /\C/8 \x{110000} Error -10 (bad UTF-32 string) offset=0 reason=3 /-- End of testinput26 --/ ================================================ FILE: src/pcre/testdata/testoutput3 ================================================ /-- This set of tests checks local-specific features, using the "fr_FR" locale. It is not Perl-compatible. When run via RunTest, the locale is edited to be whichever of "fr_FR", "french", or "fr" is found to exist. There is different version of this file called wintestinput3 for use on Windows, where the locale is called "french" and the tests are run using RunTest.bat. --/ < forbid 8W /^[\w]+/ *** Failers No match cole No match /^[\w]+/Lfr_FR cole 0: cole /^[\w]+/ *** Failers No match cole No match /^[\W]+/ cole 0: \xc9 /^[\W]+/Lfr_FR *** Failers 0: *** cole No match /[\b]/ \b 0: \x08 *** Failers No match a No match /[\b]/Lfr_FR \b 0: \x08 *** Failers No match a No match /^\w+/ *** Failers No match cole No match /^\w+/Lfr_FR cole 0: cole /(.+)\b(.+)/ cole 0: \xc9cole 1: \xc9 2: cole /(.+)\b(.+)/Lfr_FR *** Failers 0: *** Failers 1: *** 2: Failers cole No match /cole/i cole 0: \xc9cole *** Failers No match cole No match /cole/iLfr_FR cole 0: cole cole 0: cole /\w/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /\w/ISLfr_FR Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /^[\xc8-\xc9]/iLfr_FR cole 0: cole 0: /^[\xc8-\xc9]/Lfr_FR cole 0: *** Failers No match cole No match /\W+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[\W]+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[^[:alpha:]]+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /\w+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[\w]+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]]+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]][[:lower:]][[:upper:]]/DZLfr_FR ------------------------------------------------------------------ Bra [A-Za-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\xff] [a-z\xb5\xdf-\xf6\xf8-\xff] [A-Z\xc0-\xd6\xd8-\xde] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /-- End of testinput3 --/ ================================================ FILE: src/pcre/testdata/testoutput3A ================================================ /-- This set of tests checks local-specific features, using the "fr_FR" locale. It is not Perl-compatible. When run via RunTest, the locale is edited to be whichever of "fr_FR", "french", or "fr" is found to exist. There is different version of this file called wintestinput3 for use on Windows, where the locale is called "french" and the tests are run using RunTest.bat. --/ < forbid 8W /^[\w]+/ *** Failers No match cole No match /^[\w]+/Lfr_FR cole 0: cole /^[\w]+/ *** Failers No match cole No match /^[\W]+/ cole 0: \xc9 /^[\W]+/Lfr_FR *** Failers 0: *** cole No match /[\b]/ \b 0: \x08 *** Failers No match a No match /[\b]/Lfr_FR \b 0: \x08 *** Failers No match a No match /^\w+/ *** Failers No match cole No match /^\w+/Lfr_FR cole 0: cole /(.+)\b(.+)/ cole 0: \xc9cole 1: \xc9 2: cole /(.+)\b(.+)/Lfr_FR *** Failers 0: *** Failers 1: *** 2: Failers cole No match /cole/i cole 0: \xc9cole *** Failers No match cole No match /cole/iLfr_FR cole 0: cole cole 0: cole /\w/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /\w/ISLfr_FR Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /^[\xc8-\xc9]/iLfr_FR cole 0: cole 0: /^[\xc8-\xc9]/Lfr_FR cole 0: *** Failers No match cole No match /\W+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[\W]+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[^[:alpha:]]+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /\w+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[\w]+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]]+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]][[:lower:]][[:upper:]]/DZLfr_FR ------------------------------------------------------------------ Bra [A-Za-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\xff] [a-z\xaa\xb5\xba\xdf-\xf6\xf8-\xff] [A-Z\xc0-\xd6\xd8-\xde] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /-- End of testinput3 --/ ================================================ FILE: src/pcre/testdata/testoutput3B ================================================ /-- This set of tests checks local-specific features, using the "fr_FR" locale. It is not Perl-compatible. When run via RunTest, the locale is edited to be whichever of "fr_FR", "french", or "fr" is found to exist. There is different version of this file called wintestinput3 for use on Windows, where the locale is called "french" and the tests are run using RunTest.bat. --/ < forbid 8W /^[\w]+/ *** Failers No match cole No match /^[\w]+/Lfr_FR cole 0: cole /^[\w]+/ *** Failers No match cole No match /^[\W]+/ cole 0: \xc9 /^[\W]+/Lfr_FR *** Failers 0: *** cole No match /[\b]/ \b 0: \x08 *** Failers No match a No match /[\b]/Lfr_FR \b 0: \x08 *** Failers No match a No match /^\w+/ *** Failers No match cole No match /^\w+/Lfr_FR cole 0: cole /(.+)\b(.+)/ cole 0: \xc9cole 1: \xc9 2: cole /(.+)\b(.+)/Lfr_FR *** Failers 0: *** Failers 1: *** 2: Failers cole No match /cole/i cole 0: \xc9cole *** Failers No match cole No match /cole/iLfr_FR cole 0: cole cole 0: cole /\w/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /\w/ISLfr_FR Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /^[\xc8-\xc9]/iLfr_FR cole 0: cole 0: /^[\xc8-\xc9]/Lfr_FR cole 0: *** Failers No match cole No match /\W+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[\W]+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[^[:alpha:]]+/Lfr_FR >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /\w+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[\w]+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]]+/Lfr_FR >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]][[:lower:]][[:upper:]]/DZLfr_FR ------------------------------------------------------------------ Bra [A-Za-z\x83\x8a\x8c\x8e\x9a\x9c\x9e\x9f\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\xff] [a-z\x83\x9a\x9c\x9e\xaa\xb5\xba\xdf-\xf6\xf8-\xff] [A-Z\x8a\x8c\x8e\x9f\xc0-\xd6\xd8-\xde] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /-- End of testinput3 --/ ================================================ FILE: src/pcre/testdata/testoutput4 ================================================ /-- This set of tests is for UTF support, excluding Unicode properties. It is compatible with all versions of Perl >= 5.10 and both the 8-bit and 16-bit PCRE libraries. --/ < forbid 9?=ABCDEFfGILMNPTUWXZ< /a.b/8 acb 0: acb a\x7fb 0: a\x{7f}b a\x{100}b 0: a\x{100}b *** Failers No match a\nb No match /a(.{3})b/8 a\x{4000}xyb 0: a\x{4000}xyb 1: \x{4000}xy a\x{4000}\x7fyb 0: a\x{4000}\x{7f}yb 1: \x{4000}\x{7f}y a\x{4000}\x{100}yb 0: a\x{4000}\x{100}yb 1: \x{4000}\x{100}y *** Failers No match a\x{4000}b No match ac\ncb No match /a(.*?)(.)/ a\xc0\x88b 0: a\xc0 1: 2: \xc0 /a(.*?)(.)/8 a\x{100}b 0: a\x{100} 1: 2: \x{100} /a(.*)(.)/ a\xc0\x88b 0: a\xc0\x88b 1: \xc0\x88 2: b /a(.*)(.)/8 a\x{100}b 0: a\x{100}b 1: \x{100} 2: b /a(.)(.)/ a\xc0\x92bcd 0: a\xc0\x92 1: \xc0 2: \x92 /a(.)(.)/8 a\x{240}bcd 0: a\x{240}b 1: \x{240} 2: b /a(.?)(.)/ a\xc0\x92bcd 0: a\xc0\x92 1: \xc0 2: \x92 /a(.?)(.)/8 a\x{240}bcd 0: a\x{240}b 1: \x{240} 2: b /a(.??)(.)/ a\xc0\x92bcd 0: a\xc0 1: 2: \xc0 /a(.??)(.)/8 a\x{240}bcd 0: a\x{240} 1: 2: \x{240} /a(.{3})b/8 a\x{1234}xyb 0: a\x{1234}xyb 1: \x{1234}xy a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb 1: \x{1234}\x{4321}y a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b 1: \x{1234}\x{4321}\x{3412} *** Failers No match a\x{1234}b No match ac\ncb No match /a(.{3,})b/8 a\x{1234}xyb 0: a\x{1234}xyb 1: \x{1234}xy a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb 1: \x{1234}\x{4321}y a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b 1: \x{1234}\x{4321}\x{3412} axxxxbcdefghijb 0: axxxxbcdefghijb 1: xxxxbcdefghij a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b 1: \x{1234}\x{4321}\x{3412}\x{3421} *** Failers No match a\x{1234}b No match /a(.{3,}?)b/8 a\x{1234}xyb 0: a\x{1234}xyb 1: \x{1234}xy a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb 1: \x{1234}\x{4321}y a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b 1: \x{1234}\x{4321}\x{3412} axxxxbcdefghijb 0: axxxxb 1: xxxx a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b 1: \x{1234}\x{4321}\x{3412}\x{3421} *** Failers No match a\x{1234}b No match /a(.{3,5})b/8 a\x{1234}xyb 0: a\x{1234}xyb 1: \x{1234}xy a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb 1: \x{1234}\x{4321}y a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b 1: \x{1234}\x{4321}\x{3412} axxxxbcdefghijb 0: axxxxb 1: xxxx a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b 1: \x{1234}\x{4321}\x{3412}\x{3421} axbxxbcdefghijb 0: axbxxb 1: xbxx axxxxxbcdefghijb 0: axxxxxb 1: xxxxx *** Failers No match a\x{1234}b No match axxxxxxbcdefghijb No match /a(.{3,5}?)b/8 a\x{1234}xyb 0: a\x{1234}xyb 1: \x{1234}xy a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb 1: \x{1234}\x{4321}y a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b 1: \x{1234}\x{4321}\x{3412} axxxxbcdefghijb 0: axxxxb 1: xxxx a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b 1: \x{1234}\x{4321}\x{3412}\x{3421} axbxxbcdefghijb 0: axbxxb 1: xbxx axxxxxbcdefghijb 0: axxxxxb 1: xxxxx *** Failers No match a\x{1234}b No match axxxxxxbcdefghijb No match /^[a\x{c0}]/8 *** Failers No match \x{100} No match /(?<=aXb)cd/8 aXbcd 0: cd /(?<=a\x{100}b)cd/8 a\x{100}bcd 0: cd /(?<=a\x{100000}b)cd/8 a\x{100000}bcd 0: cd /(?:\x{100}){3}b/8 \x{100}\x{100}\x{100}b 0: \x{100}\x{100}\x{100}b *** Failers No match \x{100}\x{100}b No match /\x{ab}/8 \x{ab} 0: \x{ab} \xc2\xab 0: \x{ab} *** Failers No match \x00{ab} No match /(?<=(.))X/8 WXYZ 0: X 1: W \x{256}XYZ 0: X 1: \x{256} *** Failers No match XYZ No match /[^a]+/8g bcd 0: bcd \x{100}aY\x{256}Z 0: \x{100} 0: Y\x{256}Z /^[^a]{2}/8 \x{100}bc 0: \x{100}b /^[^a]{2,}/8 \x{100}bcAa 0: \x{100}bcA /^[^a]{2,}?/8 \x{100}bca 0: \x{100}b /[^a]+/8ig bcd 0: bcd \x{100}aY\x{256}Z 0: \x{100} 0: Y\x{256}Z /^[^a]{2}/8i \x{100}bc 0: \x{100}b /^[^a]{2,}/8i \x{100}bcAa 0: \x{100}bc /^[^a]{2,}?/8i \x{100}bca 0: \x{100}b /\x{100}{0,0}/8 abcd 0: /\x{100}?/8 abcd 0: \x{100}\x{100} 0: \x{100} /\x{100}{0,3}/8 \x{100}\x{100} 0: \x{100}\x{100} \x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100} /\x{100}*/8 abce 0: \x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100} /\x{100}{1,1}/8 abcd\x{100}\x{100}\x{100}\x{100} 0: \x{100} /\x{100}{1,3}/8 abcd\x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100} /\x{100}+/8 abcd\x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100} /\x{100}{3}/8 abcd\x{100}\x{100}\x{100}XX 0: \x{100}\x{100}\x{100} /\x{100}{3,5}/8 abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX 0: \x{100}\x{100}\x{100}\x{100}\x{100} /\x{100}{3,}/8 abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX 0: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} /(?<=a\x{100}{2}b)X/8+ Xyyya\x{100}\x{100}bXzzz 0: X 0+ zzz /\D*/8 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /\D*/8 \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} /\D/8 1X2 0: X 1\x{100}2 0: \x{100} />\S/8 > >X Y 0: >X > >\x{100} Y 0: >\x{100} /\d/8 \x{100}3 0: 3 /\s/8 \x{100} X 0: /\D+/8 12abcd34 0: abcd *** Failers 0: *** Failers 1234 No match /\D{2,3}/8 12abcd34 0: abc 12ab34 0: ab *** Failers 0: *** 1234 No match 12a34 No match /\D{2,3}?/8 12abcd34 0: ab 12ab34 0: ab *** Failers 0: ** 1234 No match 12a34 No match /\d+/8 12abcd34 0: 12 *** Failers No match /\d{2,3}/8 12abcd34 0: 12 1234abcd 0: 123 *** Failers No match 1.4 No match /\d{2,3}?/8 12abcd34 0: 12 1234abcd 0: 12 *** Failers No match 1.4 No match /\S+/8 12abcd34 0: 12abcd34 *** Failers 0: *** \ \ No match /\S{2,3}/8 12abcd34 0: 12a 1234abcd 0: 123 *** Failers 0: *** \ \ No match /\S{2,3}?/8 12abcd34 0: 12 1234abcd 0: 12 *** Failers 0: ** \ \ No match />\s+ <34 0: > < 0+ 34 *** Failers No match />\s{2,3} < 0+ cd ab> < 0+ ce *** Failers No match ab> \s{2,3}? < 0+ cd ab> < 0+ ce *** Failers No match ab> \xff< 0: \xff /[\xff]/8 >\x{ff}< 0: \x{ff} /[^\xFF]/ XYZ 0: X /[^\xff]/8 XYZ 0: X \x{123} 0: \x{123} /^[ac]*b/8 xb No match /^[ac\x{100}]*b/8 xb No match /^[^x]*b/8i xb No match /^[^x]*b/8 xb No match /^\d*b/8 xb No match /(|a)/g8 catac 0: 1: 0: 1: 0: a 1: a 0: 1: 0: 1: 0: a 1: a 0: 1: 0: 1: a\x{256}a 0: 1: 0: a 1: a 0: 1: 0: 1: 0: a 1: a 0: 1: /^\x{85}$/8i \x{85} 0: \x{85} /^ሴ/8 ሴ 0: \x{1234} /^\ሴ/8 ሴ 0: \x{1234} "(?s)(.{1,5})"8 abcdefg 0: abcde 1: abcde ab 0: ab 1: ab /a*\x{100}*\w/8 a 0: a /\S\S/8g A\x{a3}BC 0: A\x{a3} 0: BC /\S{2}/8g A\x{a3}BC 0: A\x{a3} 0: BC /\W\W/8g +\x{a3}== 0: +\x{a3} 0: == /\W{2}/8g +\x{a3}== 0: +\x{a3} 0: == /\S/8g \x{442}\x{435}\x{441}\x{442} 0: \x{442} 0: \x{435} 0: \x{441} 0: \x{442} /[\S]/8g \x{442}\x{435}\x{441}\x{442} 0: \x{442} 0: \x{435} 0: \x{441} 0: \x{442} /\D/8g \x{442}\x{435}\x{441}\x{442} 0: \x{442} 0: \x{435} 0: \x{441} 0: \x{442} /[\D]/8g \x{442}\x{435}\x{441}\x{442} 0: \x{442} 0: \x{435} 0: \x{441} 0: \x{442} /\W/8g \x{2442}\x{2435}\x{2441}\x{2442} 0: \x{2442} 0: \x{2435} 0: \x{2441} 0: \x{2442} /[\W]/8g \x{2442}\x{2435}\x{2441}\x{2442} 0: \x{2442} 0: \x{2435} 0: \x{2441} 0: \x{2442} /[\S\s]*/8 abc\n\r\x{442}\x{435}\x{441}\x{442}xyz 0: abc\x{0a}\x{0d}\x{442}\x{435}\x{441}\x{442}xyz /[\x{41f}\S]/8g \x{442}\x{435}\x{441}\x{442} 0: \x{442} 0: \x{435} 0: \x{441} 0: \x{442} /.[^\S]./8g abc def\x{442}\x{443}xyz\npqr 0: c d 0: z\x{0a}p /.[^\S\n]./8g abc def\x{442}\x{443}xyz\npqr 0: c d /[[:^alnum:]]/8g +\x{2442} 0: + 0: \x{2442} /[[:^alpha:]]/8g +\x{2442} 0: + 0: \x{2442} /[[:^ascii:]]/8g A\x{442} 0: \x{442} /[[:^blank:]]/8g A\x{442} 0: A 0: \x{442} /[[:^cntrl:]]/8g A\x{442} 0: A 0: \x{442} /[[:^digit:]]/8g A\x{442} 0: A 0: \x{442} /[[:^graph:]]/8g \x19\x{e01ff} 0: \x{19} 0: \x{e01ff} /[[:^lower:]]/8g A\x{422} 0: A 0: \x{422} /[[:^print:]]/8g \x{19}\x{e01ff} 0: \x{19} 0: \x{e01ff} /[[:^punct:]]/8g A\x{442} 0: A 0: \x{442} /[[:^space:]]/8g A\x{442} 0: A 0: \x{442} /[[:^upper:]]/8g a\x{442} 0: a 0: \x{442} /[[:^word:]]/8g +\x{2442} 0: + 0: \x{2442} /[[:^xdigit:]]/8g M\x{442} 0: M 0: \x{442} /[^ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJĴĶĹĻĽĿŁŃŅŇŊŌŎŐŒŔŖŘŚŜŞŠŢŤŦŨŪŬŮŰŲŴŶŸŹŻŽƁƂƄƆƇƉƊƋƎƏƐƑƓƔƖƗƘƜƝƟƠƢƤƦƧƩƬƮƯƱƲƳƵƷƸƼDŽLJNJǍǏǑǓǕǗǙǛǞǠǢǤǦǨǪǬǮDZǴǶǷǸǺǼǾȀȂȄȆȈȊȌȎȐȒȔȖȘȚȜȞȠȢȤȦȨȪȬȮȰȲȺȻȽȾɁΆΈΉΊΌΎΏΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫϒϓϔϘϚϜϞϠϢϤϦϨϪϬϮϴϷϹϺϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎҐҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾӀӁӃӅӇӉӋӍӐӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӶӸԀԂԄԆԈԊԌԎԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖႠႡႢႣႤႥႦႧႨႩႪႫႬႭႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅḀḂḄḆḈḊḌḎḐḒḔḖḘḚḜḞḠḢḤḦḨḪḬḮḰḲḴḶḸḺḼḾṀṂṄṆṈṊṌṎṐṒṔṖṘṚṜṞṠṢṤṦṨṪṬṮṰṲṴṶṸṺṼṾẀẂẄẆẈẊẌẎẐẒẔẠẢẤẦẨẪẬẮẰẲẴẶẸẺẼẾỀỂỄỆỈỊỌỎỐỒỔỖỘỚỜỞỠỢỤỦỨỪỬỮỰỲỴỶỸἈἉἊἋἌἍἎἏἘἙἚἛἜἝἨἩἪἫἬἭἮἯἸἹἺἻἼἽἾἿὈὉὊὋὌὍὙὛὝὟὨὩὪὫὬὭὮὯᾸᾹᾺΆῈΈῊΉῘῙῚΊῨῩῪΎῬῸΌῺΏabcdefghijklmnopqrstuvwxyzªµºßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıijĵķĸĺļľŀłńņňʼnŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźżžſƀƃƅƈƌƍƒƕƙƚƛƞơƣƥƨƪƫƭưƴƶƹƺƽƾƿdžljnjǎǐǒǔǖǘǚǜǝǟǡǣǥǧǩǫǭǯǰdzǵǹǻǽǿȁȃȅȇȉȋȍȏȑȓȕȗșțȝȟȡȣȥȧȩȫȭȯȱȳȴȵȶȷȸȹȼȿɀɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώϐϑϕϖϗϙϛϝϟϡϣϥϧϩϫϭϯϰϱϲϳϵϸϻϼабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿҁҋҍҏґғҕҗҙқҝҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӂӄӆӈӊӌӎӑӓӕӗәӛӝӟӡӣӥӧөӫӭӯӱӳӵӷӹԁԃԅԇԉԋԍԏաբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտրցւփքօֆևᴀᴁᴂᴃᴄᴅᴆᴇᴈᴉᴊᴋᴌᴍᴎᴏᴐᴑᴒᴓᴔᴕᴖᴗᴘᴙᴚᴛᴜᴝᴞᴟᴠᴡᴢᴣᴤᴥᴦᴧᴨᴩᴪᴫᵢᵣᵤᵥᵦᵧᵨᵩᵪᵫᵬᵭᵮᵯᵰᵱᵲᵳᵴᵵᵶᵷᵹᵺᵻᵼᵽᵾᵿᶀᶁᶂᶃᶄᶅᶆᶇᶈᶉᶊᶋᶌᶍᶎᶏᶐᶑᶒᶓᶔᶕᶖᶗᶘᶙᶚḁḃḅḇḉḋḍḏḑḓḕḗḙḛḝḟḡḣḥḧḩḫḭḯḱḳḵḷḹḻḽḿṁṃṅṇṉṋṍṏṑṓṕṗṙṛṝṟṡṣṥṧṩṫṭṯṱṳṵṷṹṻṽṿẁẃẅẇẉẋẍẏẑẓẕẖẗẘẙẚẛạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹἀἁἂἃἄἅἆἇἐἑἒἓἔἕἠἡἢἣἤἥἦἧἰἱἲἳἴἵἶἷὀὁὂὃὄὅὐὑὒὓὔὕὖὗὠὡὢὣὤὥὦὧὰάὲέὴήὶίὸόὺύὼώᾀᾁᾂᾃᾄᾅᾆᾇᾐᾑᾒᾓᾔᾕᾖᾗᾠᾡᾢᾣᾤᾥᾦᾧᾰᾱᾲᾳᾴᾶᾷιῂῃῄῆῇῐῑῒΐῖῗῠῡῢΰῤῥῦῧῲῳῴῶῷⲁⲃⲅⲇⲉⲋⲍⲏⲑⲓⲕⲗⲙⲛⲝⲟⲡⲣⲥⲧⲩⲫⲭⲯⲱⲳⲵⲷⲹⲻⲽⲿⳁⳃⳅⳇⳉⳋⳍⳏⳑⳓⳕⳗⳙⳛⳝⳟⳡⳣⳤⴀⴁⴂⴃⴄⴅⴆⴇⴈⴉⴊⴋⴌⴍⴎⴏⴐⴑⴒⴓⴔⴕⴖⴗⴘⴙⴚⴛⴜⴝⴞⴟⴠⴡⴢⴣⴤⴥfffiflffifflſtstﬓﬔﬕﬖﬗ\d-_^]/8 /^[^d]*?$/ abc 0: abc /^[^d]*?$/8 abc 0: abc /^[^d]*?$/i abc 0: abc /^[^d]*?$/8i abc 0: abc /(?i)[\xc3\xa9\xc3\xbd]|[\xc3\xa9\xc3\xbdA]/8 /^[a\x{c0}]b/8 \x{c0}b 0: \x{c0}b /^([a\x{c0}]*?)aa/8 a\x{c0}aaaa/ 0: a\x{c0}aa 1: a\x{c0} /^([a\x{c0}]*?)aa/8 a\x{c0}aaaa/ 0: a\x{c0}aa 1: a\x{c0} a\x{c0}a\x{c0}aaa/ 0: a\x{c0}a\x{c0}aa 1: a\x{c0}a\x{c0} /^([a\x{c0}]*)aa/8 a\x{c0}aaaa/ 0: a\x{c0}aaaa 1: a\x{c0}aa a\x{c0}a\x{c0}aaa/ 0: a\x{c0}a\x{c0}aaa 1: a\x{c0}a\x{c0}a /^([a\x{c0}]*)a\x{c0}/8 a\x{c0}aaaa/ 0: a\x{c0} 1: a\x{c0}a\x{c0}aaa/ 0: a\x{c0}a\x{c0} 1: a\x{c0} /A*/g8 AAB\x{123}BAA 0: AA 0: 0: 0: 0: AA 0: /(abc)\1/8i abc No match /(abc)\1/8 abc No match /a(*:a\x{1234}b)/8K abc 0: a MK: a\x{1234}b /a(*:a£b)/8K abc 0: a MK: a\x{a3}b /-- Noncharacters --/ /./8 \x{fffe} 0: \x{fffe} \x{ffff} 0: \x{ffff} \x{1fffe} 0: \x{1fffe} \x{1ffff} 0: \x{1ffff} \x{2fffe} 0: \x{2fffe} \x{2ffff} 0: \x{2ffff} \x{3fffe} 0: \x{3fffe} \x{3ffff} 0: \x{3ffff} \x{4fffe} 0: \x{4fffe} \x{4ffff} 0: \x{4ffff} \x{5fffe} 0: \x{5fffe} \x{5ffff} 0: \x{5ffff} \x{6fffe} 0: \x{6fffe} \x{6ffff} 0: \x{6ffff} \x{7fffe} 0: \x{7fffe} \x{7ffff} 0: \x{7ffff} \x{8fffe} 0: \x{8fffe} \x{8ffff} 0: \x{8ffff} \x{9fffe} 0: \x{9fffe} \x{9ffff} 0: \x{9ffff} \x{afffe} 0: \x{afffe} \x{affff} 0: \x{affff} \x{bfffe} 0: \x{bfffe} \x{bffff} 0: \x{bffff} \x{cfffe} 0: \x{cfffe} \x{cffff} 0: \x{cffff} \x{dfffe} 0: \x{dfffe} \x{dffff} 0: \x{dffff} \x{efffe} 0: \x{efffe} \x{effff} 0: \x{effff} \x{ffffe} 0: \x{ffffe} \x{fffff} 0: \x{fffff} \x{10fffe} 0: \x{10fffe} \x{10ffff} 0: \x{10ffff} \x{fdd0} 0: \x{fdd0} \x{fdd1} 0: \x{fdd1} \x{fdd2} 0: \x{fdd2} \x{fdd3} 0: \x{fdd3} \x{fdd4} 0: \x{fdd4} \x{fdd5} 0: \x{fdd5} \x{fdd6} 0: \x{fdd6} \x{fdd7} 0: \x{fdd7} \x{fdd8} 0: \x{fdd8} \x{fdd9} 0: \x{fdd9} \x{fdda} 0: \x{fdda} \x{fddb} 0: \x{fddb} \x{fddc} 0: \x{fddc} \x{fddd} 0: \x{fddd} \x{fdde} 0: \x{fdde} \x{fddf} 0: \x{fddf} \x{fde0} 0: \x{fde0} \x{fde1} 0: \x{fde1} \x{fde2} 0: \x{fde2} \x{fde3} 0: \x{fde3} \x{fde4} 0: \x{fde4} \x{fde5} 0: \x{fde5} \x{fde6} 0: \x{fde6} \x{fde7} 0: \x{fde7} \x{fde8} 0: \x{fde8} \x{fde9} 0: \x{fde9} \x{fdea} 0: \x{fdea} \x{fdeb} 0: \x{fdeb} \x{fdec} 0: \x{fdec} \x{fded} 0: \x{fded} \x{fdee} 0: \x{fdee} \x{fdef} 0: \x{fdef} /^\d*\w{4}/8 1234 0: 1234 123 No match /^[^b]*\w{4}/8 aaaa 0: aaaa aaa No match /^[^b]*\w{4}/8i aaaa 0: aaaa aaa No match /^\x{100}*.{4}/8 \x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100} \x{100}\x{100}\x{100} No match /^\x{100}*.{4}/8i \x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100} \x{100}\x{100}\x{100} No match /^a+[a\x{200}]/8 aa 0: aa /^.\B.\B./8 \x{10123}\x{10124}\x{10125} 0: \x{10123}\x{10124}\x{10125} /^#[^\x{ffff}]#[^\x{ffff}]#[^\x{ffff}]#/8 #\x{10000}#\x{100}#\x{10ffff}# 0: #\x{10000}#\x{100}#\x{10ffff}# "[\S\V\H]"8 /\C(\W?ſ)'?{{/8 \\C(\\W?ſ)'?{{ No match /[^\x{100}-\x{ffff}]*[\x80-\xff]/8 \x{99}\x{99}\x{99} 0: \x{99}\x{99}\x{99} /-- End of testinput4 --/ ================================================ FILE: src/pcre/testdata/testoutput5 ================================================ /-- This set of tests checks the API, internals, and non-Perl stuff for UTF support, excluding Unicode properties. However, tests that give different results in 8-bit and 16-bit modes are excluded (see tests 16 and 17). --/ < forbid W /\x{110000}/8DZ Failed: character value in \x{} or \o{} is too large at offset 9 /\o{4200000}/8DZ Failed: character value in \x{} or \o{} is too large at offset 10 /\x{ffffffff}/8 Failed: character value in \x{} or \o{} is too large at offset 11 /\o{37777777777}/8 Failed: character value in \x{} or \o{} is too large at offset 14 /\x{100000000}/8 Failed: character value in \x{} or \o{} is too large at offset 12 /\o{77777777777}/8 Failed: character value in \x{} or \o{} is too large at offset 14 /\x{d800}/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 7 /\o{154000}/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 9 /\x{dfff}/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 7 /\o{157777}/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 9 /\x{d7ff}/8 /\o{153777}/8 /\x{e000}/8 /\o{170000}/8 /^\x{100}a\x{1234}/8 \x{100}a\x{1234}bcd 0: \x{100}a\x{1234} /\x{0041}\x{2262}\x{0391}\x{002e}/DZ8 ------------------------------------------------------------------ Bra A\x{2262}\x{391}. Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'A' Need char = '.' \x{0041}\x{2262}\x{0391}\x{002e} 0: A\x{2262}\x{391}. /.{3,5}X/DZ8 ------------------------------------------------------------------ Bra Any{3} Any{0,2} X Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char Need char = 'X' \x{212ab}\x{212ab}\x{212ab}\x{861}X 0: \x{212ab}\x{212ab}\x{212ab}\x{861}X /.{3,5}?/DZ8 ------------------------------------------------------------------ Bra Any{3} Any{0,2}? Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char \x{212ab}\x{212ab}\x{212ab}\x{861} 0: \x{212ab}\x{212ab}\x{212ab} /(?<=\C)X/8 Failed: \C not allowed in lookbehind assertion at offset 6 /^[ab]/8DZ ------------------------------------------------------------------ Bra ^ [ab] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored utf No first char No need char bar 0: b *** Failers No match c No match \x{ff} No match \x{100} No match /^[^ab]/8DZ ------------------------------------------------------------------ Bra ^ [\x00-`c-\xff] (neg) Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored utf No first char No need char c 0: c \x{ff} 0: \x{ff} \x{100} 0: \x{100} *** Failers 0: * aaa No match /\x{100}*(\d+|"(?1)")/8 1234 0: 1234 1: 1234 "1234" 0: "1234" 1: "1234" \x{100}1234 0: \x{100}1234 1: 1234 "\x{100}1234" 0: \x{100}1234 1: 1234 \x{100}\x{100}12ab 0: \x{100}\x{100}12 1: 12 \x{100}\x{100}"12" 0: \x{100}\x{100}"12" 1: "12" *** Failers No match \x{100}\x{100}abcd No match /\x{100}*/8DZ ------------------------------------------------------------------ Bra \x{100}*+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 May match empty string Options: utf No first char No need char /a\x{100}*/8DZ ------------------------------------------------------------------ Bra a \x{100}*+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' No need char /ab\x{100}*/8DZ ------------------------------------------------------------------ Bra ab \x{100}*+ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf First char = 'a' Need char = 'b' /\x{100}*A/8DZ ------------------------------------------------------------------ Bra \x{100}*+ A Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char Need char = 'A' A 0: A /\x{100}*\d(?R)/8DZ ------------------------------------------------------------------ Bra \x{100}*+ \d Recurse Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /[Z\x{100}]/8DZ ------------------------------------------------------------------ Bra [Z\x{100}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char Z\x{100} 0: Z \x{100} 0: \x{100} \x{100}Z 0: \x{100} *** Failers No match /[\x{200}-\x{100}]/8 Failed: range out of order in character class at offset 15 /[Ā-Ą]/8 \x{100} 0: \x{100} \x{104} 0: \x{104} *** Failers No match \x{105} No match \x{ff} No match /[z-\x{100}]/8DZ ------------------------------------------------------------------ Bra [z-\xff\x{100}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /[z\Qa-d]Ā\E]/8DZ ------------------------------------------------------------------ Bra [\-\]adz\x{100}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char \x{100} 0: \x{100} Ā 0: \x{100} /[\xFF]/DZ ------------------------------------------------------------------ Bra \x{ff} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options First char = \xff No need char >\xff< 0: \xff /[^\xFF]/DZ ------------------------------------------------------------------ Bra [^\x{ff}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[Ä-Ü]/8 Ö # Matches without Study 0: \x{d6} \x{d6} 0: \x{d6} /[Ä-Ü]/8S Ö <-- Same with Study 0: \x{d6} \x{d6} 0: \x{d6} /[\x{c4}-\x{dc}]/8 Ö # Matches without Study 0: \x{d6} \x{d6} 0: \x{d6} /[\x{c4}-\x{dc}]/8S Ö <-- Same with Study 0: \x{d6} \x{d6} 0: \x{d6} /[^\x{100}]abc(xyz(?1))/8DZ ------------------------------------------------------------------ Bra [^\x{100}] abc CBra 1 xyz Recurse Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char Need char = 'z' /[ab\x{100}]abc(xyz(?1))/8DZ ------------------------------------------------------------------ Bra [ab\x{100}] abc CBra 1 xyz Recurse Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char Need char = 'z' /(\x{100}(b(?2)c))?/DZ8 ------------------------------------------------------------------ Bra Brazero CBra 1 \x{100} CBra 2 b Recurse c Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string Options: utf No first char No need char /(\x{100}(b(?2)c)){0,2}/DZ8 ------------------------------------------------------------------ Bra Brazero Bra CBra 1 \x{100} CBra 2 b Recurse c Ket Ket Brazero CBra 1 \x{100} CBra 2 b Recurse c Ket Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string Options: utf No first char No need char /(\x{100}(b(?1)c))?/DZ8 ------------------------------------------------------------------ Bra Brazero CBra 1 \x{100} CBra 2 b Recurse c Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string Options: utf No first char No need char /(\x{100}(b(?1)c)){0,2}/DZ8 ------------------------------------------------------------------ Bra Brazero Bra CBra 1 \x{100} CBra 2 b Recurse c Ket Ket Brazero CBra 1 \x{100} CBra 2 b Recurse c Ket Ket Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 2 May match empty string Options: utf No first char No need char /\W/8 A.B 0: . A\x{100}B 0: \x{100} /\w/8 \x{100}X 0: X /^\ሴ/8DZ ------------------------------------------------------------------ Bra ^ \x{1234} Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: anchored utf No first char No need char /\x{100}*\d/8DZ ------------------------------------------------------------------ Bra \x{100}*+ \d Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}*\s/8DZ ------------------------------------------------------------------ Bra \x{100}*+ \s Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}*\w/8DZ ------------------------------------------------------------------ Bra \x{100}*+ \w Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}*\D/8DZ ------------------------------------------------------------------ Bra \x{100}* \D Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}*\S/8DZ ------------------------------------------------------------------ Bra \x{100}* \S Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /\x{100}*\W/8DZ ------------------------------------------------------------------ Bra \x{100}* \W Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /()()()()()()()()()() ()()()()()()()()()() ()()()()()()()()()() ()()()()()()()()()() A (x) (?41) B/8x AxxB Matched, but too many substrings 0: AxxB 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: /^[\x{100}\E-\Q\E\x{150}]/BZ8 ------------------------------------------------------------------ Bra ^ [\x{100}-\x{150}] Ket End ------------------------------------------------------------------ /^[\QĀ\E-\QŐ\E]/BZ8 ------------------------------------------------------------------ Bra ^ [\x{100}-\x{150}] Ket End ------------------------------------------------------------------ /^abc./mgx8 abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x{0085}abc7 \x{2028}abc8 \x{2029}abc9 JUNK 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc7 0: abc8 0: abc9 /abc.$/mgx8 abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x{0085} abc7\x{2028} abc8\x{2029} abc9 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc7 0: abc8 0: abc9 /^a\Rb/8 a\nb 0: a\x{0a}b a\rb 0: a\x{0d}b a\r\nb 0: a\x{0d}\x{0a}b a\x0bb 0: a\x{0b}b a\x0cb 0: a\x{0c}b a\x{85}b 0: a\x{85}b a\x{2028}b 0: a\x{2028}b a\x{2029}b 0: a\x{2029}b ** Failers No match a\n\rb No match /^a\R*b/8 ab 0: ab a\nb 0: a\x{0a}b a\rb 0: a\x{0d}b a\r\nb 0: a\x{0d}\x{0a}b a\x0bb 0: a\x{0b}b a\x0c\x{2028}\x{2029}b 0: a\x{0c}\x{2028}\x{2029}b a\x{85}b 0: a\x{85}b a\n\rb 0: a\x{0a}\x{0d}b a\n\r\x{85}\x0cb 0: a\x{0a}\x{0d}\x{85}\x{0c}b /^a\R+b/8 a\nb 0: a\x{0a}b a\rb 0: a\x{0d}b a\r\nb 0: a\x{0d}\x{0a}b a\x0bb 0: a\x{0b}b a\x0c\x{2028}\x{2029}b 0: a\x{0c}\x{2028}\x{2029}b a\x{85}b 0: a\x{85}b a\n\rb 0: a\x{0a}\x{0d}b a\n\r\x{85}\x0cb 0: a\x{0a}\x{0d}\x{85}\x{0c}b ** Failers No match ab No match /^a\R{1,3}b/8 a\nb 0: a\x{0a}b a\n\rb 0: a\x{0a}\x{0d}b a\n\r\x{85}b 0: a\x{0a}\x{0d}\x{85}b a\r\n\r\nb 0: a\x{0d}\x{0a}\x{0d}\x{0a}b a\r\n\r\n\r\nb 0: a\x{0d}\x{0a}\x{0d}\x{0a}\x{0d}\x{0a}b a\n\r\n\rb 0: a\x{0a}\x{0d}\x{0a}\x{0d}b a\n\n\r\nb 0: a\x{0a}\x{0a}\x{0d}\x{0a}b ** Failers No match a\n\n\n\rb No match a\r No match /\H\h\V\v/8 X X\x0a 0: X X\x{0a} X\x09X\x0b 0: X\x{09}X\x{0b} ** Failers No match \x{a0} X\x0a No match /\H*\h+\V?\v{3,4}/8 \x09\x20\x{a0}X\x0a\x0b\x0c\x0d\x0a 0: \x{09} \x{a0}X\x{0a}\x{0b}\x{0c}\x{0d} \x09\x20\x{a0}\x0a\x0b\x0c\x0d\x0a 0: \x{09} \x{a0}\x{0a}\x{0b}\x{0c}\x{0d} \x09\x20\x{a0}\x0a\x0b\x0c 0: \x{09} \x{a0}\x{0a}\x{0b}\x{0c} ** Failers No match \x09\x20\x{a0}\x0a\x0b No match /\H\h\V\v/8 \x{3001}\x{3000}\x{2030}\x{2028} 0: \x{3001}\x{3000}\x{2030}\x{2028} X\x{180e}X\x{85} 0: X\x{180e}X\x{85} ** Failers No match \x{2009} X\x0a No match /\H*\h+\V?\v{3,4}/8 \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x0c\x0d\x0a 0: \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x{0c}\x{0d} \x09\x{205f}\x{a0}\x0a\x{2029}\x0c\x{2028}\x0a 0: \x{09}\x{205f}\x{a0}\x{0a}\x{2029}\x{0c}\x{2028} \x09\x20\x{202f}\x0a\x0b\x0c 0: \x{09} \x{202f}\x{0a}\x{0b}\x{0c} ** Failers No match \x09\x{200a}\x{a0}\x{2028}\x0b No match /[\h]/8BZ ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}] Ket End ------------------------------------------------------------------ >\x{1680} 0: \x{1680} /[\h]{3,}/8BZ ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}]{3,}+ Ket End ------------------------------------------------------------------ >\x{1680}\x{180e}\x{2000}\x{2003}\x{200a}\x{202f}\x{205f}\x{3000}< 0: \x{1680}\x{180e}\x{2000}\x{2003}\x{200a}\x{202f}\x{205f}\x{3000} /[\v]/8BZ ------------------------------------------------------------------ Bra [\x0a-\x0d\x85\x{2028}-\x{2029}] Ket End ------------------------------------------------------------------ /[\H]/8BZ ------------------------------------------------------------------ Bra [\x00-\x08\x0a-\x1f!-\x9f\xa1-\xff\x{100}-\x{167f}\x{1681}-\x{180d}\x{180f}-\x{1fff}\x{200b}-\x{202e}\x{2030}-\x{205e}\x{2060}-\x{2fff}\x{3001}-\x{10ffff}] Ket End ------------------------------------------------------------------ /[\V]/8BZ ------------------------------------------------------------------ Bra [\x00-\x09\x0e-\x84\x86-\xff\x{100}-\x{2027}\x{202a}-\x{10ffff}] Ket End ------------------------------------------------------------------ /.*$/8 \x{1ec5} 0: \x{1ec5} /a\Rb/I8 Capturing subpattern count = 0 Options: bsr_anycrlf utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b ** Failers No match a\x{85}b No match a\x0bb No match /a\Rb/I8 Capturing subpattern count = 0 Options: bsr_unicode utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b a\x{85}b 0: a\x{85}b a\x0bb 0: a\x{0b}b ** Failers No match a\x{85}b\ No match a\x0bb\ No match /a\R?b/I8 Capturing subpattern count = 0 Options: bsr_anycrlf utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b ** Failers No match a\x{85}b No match a\x0bb No match /a\R?b/I8 Capturing subpattern count = 0 Options: bsr_unicode utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b a\x{85}b 0: a\x{85}b a\x0bb 0: a\x{0b}b ** Failers No match a\x{85}b\ No match a\x0bb\ No match /.*a.*=.b.*/8 QQQ\x{2029}ABCaXYZ=!bPQR 0: ABCaXYZ=!bPQR ** Failers No match a\x{2029}b No match \x61\xe2\x80\xa9\x62 No match /[[:a\x{100}b:]]/8 Failed: unknown POSIX class name at offset 3 /a[^]b/8 a\x{1234}b 0: a\x{1234}b a\nb 0: a\x{0a}b ** Failers No match ab No match /a[^]+b/8 aXb 0: aXb a\nX\nX\x{1234}b 0: a\x{0a}X\x{0a}X\x{1234}b ** Failers No match ab No match /(\x{de})\1/ \x{de}\x{de} 0: \xde\xde 1: \xde /X/8f A\x{1ec5}ABCXYZ 0: X /Xa{2,4}b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /Xa{2,4}?b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /Xa{2,4}+b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\x{123}{2,4}b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X\x{123}{2,4}?b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X\x{123}{2,4}+b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X\x{123}{2,4}b/8 Xx\P No match X\x{123}x\P No match X\x{123}\x{123}x\P No match X\x{123}\x{123}\x{123}x\P No match X\x{123}\x{123}\x{123}\x{123}x\P No match /X\x{123}{2,4}?b/8 Xx\P No match X\x{123}x\P No match X\x{123}\x{123}x\P No match X\x{123}\x{123}\x{123}x\P No match X\x{123}\x{123}\x{123}\x{123}x\P No match /X\x{123}{2,4}+b/8 Xx\P No match X\x{123}x\P No match X\x{123}\x{123}x\P No match X\x{123}\x{123}\x{123}x\P No match X\x{123}\x{123}\x{123}\x{123}x\P No match /X\d{2,4}b/8 X\P Partial match: X X3\P Partial match: X3 X33\P Partial match: X33 X333\P Partial match: X333 X3333\P Partial match: X3333 /X\d{2,4}?b/8 X\P Partial match: X X3\P Partial match: X3 X33\P Partial match: X33 X333\P Partial match: X333 X3333\P Partial match: X3333 /X\d{2,4}+b/8 X\P Partial match: X X3\P Partial match: X3 X33\P Partial match: X33 X333\P Partial match: X333 X3333\P Partial match: X3333 /X\D{2,4}b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\D{2,4}?b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\D{2,4}+b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X\D{2,4}b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X\D{2,4}?b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X\D{2,4}+b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X[abc]{2,4}b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[abc]{2,4}?b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[abc]{2,4}+b/8 X\P Partial match: X Xa\P Partial match: Xa Xaa\P Partial match: Xaa Xaaa\P Partial match: Xaaa Xaaaa\P Partial match: Xaaaa /X[abc\x{123}]{2,4}b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X[abc\x{123}]{2,4}?b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X[abc\x{123}]{2,4}+b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X[^a]{2,4}b/8 X\P Partial match: X Xz\P Partial match: Xz Xzz\P Partial match: Xzz Xzzz\P Partial match: Xzzz Xzzzz\P Partial match: Xzzzz /X[^a]{2,4}?b/8 X\P Partial match: X Xz\P Partial match: Xz Xzz\P Partial match: Xzz Xzzz\P Partial match: Xzzz Xzzzz\P Partial match: Xzzzz /X[^a]{2,4}+b/8 X\P Partial match: X Xz\P Partial match: Xz Xzz\P Partial match: Xzz Xzzz\P Partial match: Xzzz Xzzzz\P Partial match: Xzzzz /X[^a]{2,4}b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X[^a]{2,4}?b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /X[^a]{2,4}+b/8 X\P Partial match: X X\x{123}\P Partial match: X\x{123} X\x{123}\x{123}\P Partial match: X\x{123}\x{123} X\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123} X\x{123}\x{123}\x{123}\x{123}\P Partial match: X\x{123}\x{123}\x{123}\x{123} /(Y)X\1{2,4}b/8 YX\P Partial match: YX YXY\P Partial match: YXY YXYY\P Partial match: YXYY YXYYY\P Partial match: YXYYY YXYYYY\P Partial match: YXYYYY /(Y)X\1{2,4}?b/8 YX\P Partial match: YX YXY\P Partial match: YXY YXYY\P Partial match: YXYY YXYYY\P Partial match: YXYYY YXYYYY\P Partial match: YXYYYY /(Y)X\1{2,4}+b/8 YX\P Partial match: YX YXY\P Partial match: YXY YXYY\P Partial match: YXYY YXYYY\P Partial match: YXYYY YXYYYY\P Partial match: YXYYYY /(\x{123})X\1{2,4}b/8 \x{123}X\P Partial match: \x{123}X \x{123}X\x{123}\P Partial match: \x{123}X\x{123} \x{123}X\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123} \x{123}X\x{123}\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123}\x{123} \x{123}X\x{123}\x{123}\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123}\x{123}\x{123} /(\x{123})X\1{2,4}?b/8 \x{123}X\P Partial match: \x{123}X \x{123}X\x{123}\P Partial match: \x{123}X\x{123} \x{123}X\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123} \x{123}X\x{123}\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123}\x{123} \x{123}X\x{123}\x{123}\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123}\x{123}\x{123} /(\x{123})X\1{2,4}+b/8 \x{123}X\P Partial match: \x{123}X \x{123}X\x{123}\P Partial match: \x{123}X\x{123} \x{123}X\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123} \x{123}X\x{123}\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123}\x{123} \x{123}X\x{123}\x{123}\x{123}\x{123}\P Partial match: \x{123}X\x{123}\x{123}\x{123}\x{123} /\bthe cat\b/8 the cat\P 0: the cat the cat\P\P Partial match: the cat /abcd*/8 xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd /abcd*/i8 xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd XXXXABCD\P 0: ABCD XXXXABCD\P\P Partial match: ABCD /abc\d*/8 xxxxabc1\P 0: abc1 xxxxabc1\P\P Partial match: abc1 /(a)bc\1*/8 xxxxabca\P 0: abca 1: a xxxxabca\P\P Partial match: abca /abc[de]*/8 xxxxabcde\P 0: abcde xxxxabcde\P\P Partial match: abcde /X\W{3}X/8 \PX Partial match: X /\sxxx\s/8T1 AB\x{85}xxx\x{a0}XYZ 0: \x{85}xxx\x{a0} AB\x{a0}xxx\x{85}XYZ 0: \x{a0}xxx\x{85} /\S \S/8T1 \x{a2} \x{84} 0: \x{a2} \x{84} 'A#хц'8xBZ ------------------------------------------------------------------ Bra A Ket End ------------------------------------------------------------------ 'A#хц PQ'8xBZ ------------------------------------------------------------------ Bra APQ Ket End ------------------------------------------------------------------ /a+#хaa z#XX?/8xBZ ------------------------------------------------------------------ Bra a++ z Ket End ------------------------------------------------------------------ /a+#хaa z#х?/8xBZ ------------------------------------------------------------------ Bra a++ z Ket End ------------------------------------------------------------------ /\g{A}xxx#bXX(?'A'123) (?'A'456)/8xBZ ------------------------------------------------------------------ Bra \1 xxx CBra 1 456 Ket Ket End ------------------------------------------------------------------ /\g{A}xxx#bх(?'A'123) (?'A'456)/8xBZ ------------------------------------------------------------------ Bra \1 xxx CBra 1 456 Ket Ket End ------------------------------------------------------------------ /^\cģ/8 Failed: \c must be followed by an ASCII character at offset 3 /(\R*)(.)/s8 \r\n 0: \x{0d} 1: 2: \x{0d} \r\r\n\n\r 0: \x{0d}\x{0d}\x{0a}\x{0a}\x{0d} 1: \x{0d}\x{0d}\x{0a}\x{0a} 2: \x{0d} \r\r\n\n\r\n 0: \x{0d}\x{0d}\x{0a}\x{0a}\x{0d} 1: \x{0d}\x{0d}\x{0a}\x{0a} 2: \x{0d} /(\R)*(.)/s8 \r\n 0: \x{0d} 1: 2: \x{0d} \r\r\n\n\r 0: \x{0d}\x{0d}\x{0a}\x{0a}\x{0d} 1: \x{0a} 2: \x{0d} \r\r\n\n\r\n 0: \x{0d}\x{0d}\x{0a}\x{0a}\x{0d} 1: \x{0a} 2: \x{0d} /[^\x{1234}]+/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 No starting char list /[^\x{1234}]+?/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 No starting char list /[^\x{1234}]++/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 1 No starting char list /[^\x{1234}]{2}/iS8I Capturing subpattern count = 0 Options: caseless utf No first char No need char Subject length lower bound = 2 No starting char list // Failed: inconsistent NEWLINE options at offset 0 /f.*/ \P\Pfor Partial match: for /f.*/s \P\Pfor Partial match: for /f.*/8 \P\Pfor Partial match: for /f.*/8s \P\Pfor Partial match: for /\x{d7ff}\x{e000}/8 /\x{d800}/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 7 /\x{dfff}/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 7 /\h+/8 \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} 0: \x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\x{a0}\x{2000} 0: \x{200a}\x{a0}\x{2000} /[\h\x{e000}]+/8BZ ------------------------------------------------------------------ Bra [\x09 \xa0\x{1680}\x{180e}\x{2000}-\x{200a}\x{202f}\x{205f}\x{3000}\x{e000}]++ Ket End ------------------------------------------------------------------ \x{1681}\x{200b}\x{1680}\x{2000}\x{202f}\x{3000} 0: \x{1680}\x{2000}\x{202f}\x{3000} \x{3001}\x{2fff}\x{200a}\x{a0}\x{2000} 0: \x{200a}\x{a0}\x{2000} /\H+/8 \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} 0: \x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} 0: \x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} 0: \x{202e}\x{2030}\x{205e}\x{2060} \x{a0}\x{3000}\x{9f}\x{a1}\x{2fff}\x{3001} 0: \x{9f}\x{a1}\x{2fff}\x{3001} /[\H\x{d7ff}]+/8BZ ------------------------------------------------------------------ Bra [\x00-\x08\x0a-\x1f!-\x9f\xa1-\xff\x{100}-\x{167f}\x{1681}-\x{180d}\x{180f}-\x{1fff}\x{200b}-\x{202e}\x{2030}-\x{205e}\x{2060}-\x{2fff}\x{3001}-\x{10ffff}\x{d7ff}]++ Ket End ------------------------------------------------------------------ \x{1680}\x{180e}\x{167f}\x{1681}\x{180d}\x{180f} 0: \x{167f}\x{1681}\x{180d}\x{180f} \x{2000}\x{200a}\x{1fff}\x{200b} 0: \x{1fff}\x{200b} \x{202f}\x{205f}\x{202e}\x{2030}\x{205e}\x{2060} 0: \x{202e}\x{2030}\x{205e}\x{2060} \x{a0}\x{3000}\x{9f}\x{a1}\x{2fff}\x{3001} 0: \x{9f}\x{a1}\x{2fff}\x{3001} /\v+/8 \x{2027}\x{2030}\x{2028}\x{2029} 0: \x{2028}\x{2029} \x09\x0e\x{84}\x{86}\x{85}\x0a\x0b\x0c\x0d 0: \x{85}\x{0a}\x{0b}\x{0c}\x{0d} /[\v\x{e000}]+/8BZ ------------------------------------------------------------------ Bra [\x0a-\x0d\x85\x{2028}-\x{2029}\x{e000}]++ Ket End ------------------------------------------------------------------ \x{2027}\x{2030}\x{2028}\x{2029} 0: \x{2028}\x{2029} \x09\x0e\x{84}\x{86}\x{85}\x0a\x0b\x0c\x0d 0: \x{85}\x{0a}\x{0b}\x{0c}\x{0d} /\V+/8 \x{2028}\x{2029}\x{2027}\x{2030} 0: \x{2027}\x{2030} \x{85}\x0a\x0b\x0c\x0d\x09\x0e\x{84}\x{86} 0: \x{09}\x{0e}\x{84}\x{86} /[\V\x{d7ff}]+/8BZ ------------------------------------------------------------------ Bra [\x00-\x09\x0e-\x84\x86-\xff\x{100}-\x{2027}\x{202a}-\x{10ffff}\x{d7ff}]++ Ket End ------------------------------------------------------------------ \x{2028}\x{2029}\x{2027}\x{2030} 0: \x{2027}\x{2030} \x{85}\x0a\x0b\x0c\x0d\x09\x0e\x{84}\x{86} 0: \x{09}\x{0e}\x{84}\x{86} /\R+/8 \x{2027}\x{2030}\x{2028}\x{2029} 0: \x{2028}\x{2029} \x09\x0e\x{84}\x{86}\x{85}\x0a\x0b\x0c\x0d 0: \x{85}\x{0a}\x{0b}\x{0c}\x{0d} /(..)\1/8 ab\P Partial match: ab aba\P Partial match: aba abab\P 0: abab 1: ab /(..)\1/8i ab\P Partial match: ab abA\P Partial match: abA aBAb\P 0: aBAb 1: aB /(..)\1{2,}/8 ab\P Partial match: ab aba\P Partial match: aba abab\P Partial match: abab ababa\P Partial match: ababa ababab\P 0: ababab 1: ab ababab\P\P Partial match: ababab abababa\P 0: ababab 1: ab abababa\P\P Partial match: abababa /(..)\1{2,}/8i ab\P Partial match: ab aBa\P Partial match: aBa aBAb\P Partial match: aBAb AbaBA\P Partial match: AbaBA abABAb\P 0: abABAb 1: ab aBAbaB\P\P Partial match: aBAbaB abABabA\P 0: abABab 1: ab abaBABa\P\P Partial match: abaBABa /(..)\1{2,}?x/8i ab\P Partial match: ab abA\P Partial match: abA aBAb\P Partial match: aBAb abaBA\P Partial match: abaBA abAbaB\P Partial match: abAbaB abaBabA\P Partial match: abaBabA abAbABaBx\P 0: abAbABaBx 1: ab /./8 \r\P 0: \x{0d} \r\P\P Partial match: \x{0d} /.{2,3}/8 \r\P Partial match: \x{0d} \r\P\P Partial match: \x{0d} \r\r\P 0: \x{0d}\x{0d} \r\r\P\P Partial match: \x{0d}\x{0d} \r\r\r\P 0: \x{0d}\x{0d}\x{0d} \r\r\r\P\P Partial match: \x{0d}\x{0d}\x{0d} /.{2,3}?/8 \r\P Partial match: \x{0d} \r\P\P Partial match: \x{0d} \r\r\P 0: \x{0d}\x{0d} \r\r\P\P Partial match: \x{0d}\x{0d} \r\r\r\P 0: \x{0d}\x{0d} \r\r\r\P\P 0: \x{0d}\x{0d} /[^\x{100}][^\x{1234}][^\x{ffff}][^\x{10000}][^\x{10ffff}]/8BZ ------------------------------------------------------------------ Bra [^\x{100}] [^\x{1234}] [^\x{ffff}] [^\x{10000}] [^\x{10ffff}] Ket End ------------------------------------------------------------------ /[^\x{100}][^\x{1234}][^\x{ffff}][^\x{10000}][^\x{10ffff}]/8BZi ------------------------------------------------------------------ Bra /i [^\x{100}] /i [^\x{1234}] /i [^\x{ffff}] /i [^\x{10000}] /i [^\x{10ffff}] Ket End ------------------------------------------------------------------ /[^\x{100}]*[^\x{10000}]+[^\x{10ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{fffff}]{5,6}+/8BZ ------------------------------------------------------------------ Bra [^\x{100}]* [^\x{10000}]+ [^\x{10ffff}]?? [^\x{8000}]{4} [^\x{8000}]* [^\x{7fff}]{2} [^\x{7fff}]{0,7}? [^\x{fffff}]{5} [^\x{fffff}]?+ Ket End ------------------------------------------------------------------ /[^\x{100}]*[^\x{10000}]+[^\x{10ffff}]??[^\x{8000}]{4,}[^\x{7fff}]{2,9}?[^\x{fffff}]{5,6}+/8BZi ------------------------------------------------------------------ Bra /i [^\x{100}]* /i [^\x{10000}]+ /i [^\x{10ffff}]?? /i [^\x{8000}]{4} /i [^\x{8000}]* /i [^\x{7fff}]{2} /i [^\x{7fff}]{0,7}? /i [^\x{fffff}]{5} /i [^\x{fffff}]?+ Ket End ------------------------------------------------------------------ /(?<=\x{1234}\x{1234})\bxy/I8 Capturing subpattern count = 0 Max lookbehind = 2 Options: utf First char = 'x' Need char = 'y' /(?8BZ ------------------------------------------------------------------ Bra \x{100} Ket End ------------------------------------------------------------------ /[\u0100-\u0200]/8BZ ------------------------------------------------------------------ Bra [\x{100}-\x{200}] Ket End ------------------------------------------------------------------ /\ud800/8 Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 5 /^a+[a\x{200}]/8BZ ------------------------------------------------------------------ Bra ^ a+ [a\x{200}] Ket End ------------------------------------------------------------------ aa 0: aa /[b-d\x{200}-\x{250}]*[ae-h]?#[\x{200}-\x{250}]{0,8}[\x00-\xff]*#[\x{200}-\x{250}]+[a-z]/8BZ ------------------------------------------------------------------ Bra [b-d\x{200}-\x{250}]*+ [ae-h]?+ # [\x{200}-\x{250}]{0,8}+ [\x00-\xff]* # [\x{200}-\x{250}]++ [a-z] Ket End ------------------------------------------------------------------ /[^\xff]*PRUNE:\x{100}abc(xyz(?1))/8DZ ------------------------------------------------------------------ Bra [^\x{ff}]* PRUNE:\x{100}abc CBra 1 xyz Recurse Ket Ket End ------------------------------------------------------------------ Capturing subpattern count = 1 Options: utf No first char Need char = 'z' /(?<=\K\x{17f})/8g+ \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f} 0: \x{17f} 0+ \x{17f} 0: \x{17f} 0+ /(?<=\K\x{17f})/8G+ \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f}\x{17f} 0: \x{17f} 0+ \x{17f}\x{17f} 0: \x{17f} 0+ \x{17f} 0: \x{17f} 0+ /\C[^\v]+\x80/8 [AΏBŀC] No match /\C[^\d]+\x80/8 [AΏBŀC] No match /-- End of testinput5 --/ ================================================ FILE: src/pcre/testdata/testoutput6 ================================================ /-- This set of tests is for Unicode property support. It is compatible with Perl >= 5.15. --/ < forbid 9?=ABCDEFfGILMNPTUXZ< /^\pC\pL\pM\pN\pP\pS\pZ\s+/8W >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 0: > \x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{09}\x{0b} /^>\pZ+/8W >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 0: > \x{a0}\x{1680}\x{2028}\x{2029}\x{202f} /^>[[:space:]]*/8W >\x{20}\x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{9}\x{b} 0: > \x{a0}\x{1680}\x{2028}\x{2029}\x{202f}\x{09}\x{0b} /^>[[:blank:]]*/8W >\x{20}\x{a0}\x{1680}\x{180e}\x{2000}\x{202f}\x{9}\x{b}\x{2028} 0: > \x{a0}\x{1680}\x{180e}\x{2000}\x{202f}\x{09} /^[[:alpha:]]*/8W Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d} 0: Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d} /^[[:alnum:]]*/8W Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee} 0: Az\x{aa}\x{c0}\x{1c5}\x{2b0}\x{3b6}\x{1d7c9}\x{2fa1d}1\x{660}\x{bef}\x{16ee} /^[[:cntrl:]]*/8W \x{0}\x{09}\x{1f}\x{7f}\x{9f} 0: \x{00}\x{09}\x{1f}\x{7f} /^[[:graph:]]*/8W A\x{a1}\x{a0} 0: A\x{a1} /^[[:print:]]*/8W A z\x{a0}\x{a1} 0: A z\x{a0}\x{a1} /^[[:punct:]]*/8W .+\x{a1}\x{a0} 0: .+\x{a1} /\p{Zs}*?\R/ ** Failers No match a\xFCb No match /\p{Zs}*\R/ ** Failers No match a\xFCb No match /ⱥ/8i ⱥ 0: \x{2c65} Ⱥx 0: \x{23a} Ⱥ 0: \x{23a} /[ⱥ]/8i ⱥ 0: \x{2c65} Ⱥx 0: \x{23a} Ⱥ 0: \x{23a} /Ⱥ/8i Ⱥ 0: \x{23a} ⱥ 0: \x{2c65} /-- These are tests for extended grapheme clusters --/ /^\X/8+ G\x{34e}\x{34e}X 0: G\x{34e}\x{34e} 0+ X \x{34e}\x{34e}X 0: \x{34e}\x{34e} 0+ X \x04X 0: \x{04} 0+ X \x{1100}X 0: \x{1100} 0+ X \x{1100}\x{34e}X 0: \x{1100}\x{34e} 0+ X \x{1b04}\x{1b04}X 0: \x{1b04}\x{1b04} 0+ X *These match up to the roman letters 0: * 0+ These match up to the roman letters \x{1111}\x{1111}L,L 0: \x{1111}\x{1111} 0+ L,L \x{1111}\x{1111}\x{1169}L,L,V 0: \x{1111}\x{1111}\x{1169} 0+ L,L,V \x{1111}\x{ae4c}L, LV 0: \x{1111}\x{ae4c} 0+ L, LV \x{1111}\x{ad89}L, LVT 0: \x{1111}\x{ad89} 0+ L, LVT \x{1111}\x{ae4c}\x{1169}L, LV, V 0: \x{1111}\x{ae4c}\x{1169} 0+ L, LV, V \x{1111}\x{ae4c}\x{1169}\x{1169}L, LV, V, V 0: \x{1111}\x{ae4c}\x{1169}\x{1169} 0+ L, LV, V, V \x{1111}\x{ae4c}\x{1169}\x{11fe}L, LV, V, T 0: \x{1111}\x{ae4c}\x{1169}\x{11fe} 0+ L, LV, V, T \x{1111}\x{ad89}\x{11fe}L, LVT, T 0: \x{1111}\x{ad89}\x{11fe} 0+ L, LVT, T \x{1111}\x{ad89}\x{11fe}\x{11fe}L, LVT, T, T 0: \x{1111}\x{ad89}\x{11fe}\x{11fe} 0+ L, LVT, T, T \x{ad89}\x{11fe}\x{11fe}LVT, T, T 0: \x{ad89}\x{11fe}\x{11fe} 0+ LVT, T, T *These match just the first codepoint (invalid sequence) 0: * 0+ These match just the first codepoint (invalid sequence) \x{1111}\x{11fe}L, T 0: \x{1111} 0+ \x{11fe}L, T \x{ae4c}\x{1111}LV, L 0: \x{ae4c} 0+ \x{1111}LV, L \x{ae4c}\x{ae4c}LV, LV 0: \x{ae4c} 0+ \x{ae4c}LV, LV \x{ae4c}\x{ad89}LV, LVT 0: \x{ae4c} 0+ \x{ad89}LV, LVT \x{1169}\x{1111}V, L 0: \x{1169} 0+ \x{1111}V, L \x{1169}\x{ae4c}V, LV 0: \x{1169} 0+ \x{ae4c}V, LV \x{1169}\x{ad89}V, LVT 0: \x{1169} 0+ \x{ad89}V, LVT \x{ad89}\x{1111}LVT, L 0: \x{ad89} 0+ \x{1111}LVT, L \x{ad89}\x{1169}LVT, V 0: \x{ad89} 0+ \x{1169}LVT, V \x{ad89}\x{ae4c}LVT, LV 0: \x{ad89} 0+ \x{ae4c}LVT, LV \x{ad89}\x{ad89}LVT, LVT 0: \x{ad89} 0+ \x{ad89}LVT, LVT \x{11fe}\x{1111}T, L 0: \x{11fe} 0+ \x{1111}T, L \x{11fe}\x{1169}T, V 0: \x{11fe} 0+ \x{1169}T, V \x{11fe}\x{ae4c}T, LV 0: \x{11fe} 0+ \x{ae4c}T, LV \x{11fe}\x{ad89}T, LVT 0: \x{11fe} 0+ \x{ad89}T, LVT *Test extend and spacing mark 0: * 0+ Test extend and spacing mark \x{1111}\x{ae4c}\x{0711}L, LV, extend 0: \x{1111}\x{ae4c}\x{711} 0+ L, LV, extend \x{1111}\x{ae4c}\x{1b04}L, LV, spacing mark 0: \x{1111}\x{ae4c}\x{1b04} 0+ L, LV, spacing mark \x{1111}\x{ae4c}\x{1b04}\x{0711}\x{1b04}L, LV, spacing mark, extend, spacing mark 0: \x{1111}\x{ae4c}\x{1b04}\x{711}\x{1b04} 0+ L, LV, spacing mark, extend, spacing mark *Test CR, LF, and control 0: * 0+ Test CR, LF, and control \x0d\x{0711}CR, extend 0: \x{0d} 0+ \x{711}CR, extend \x0d\x{1b04}CR, spacingmark 0: \x{0d} 0+ \x{1b04}CR, spacingmark \x0a\x{0711}LF, extend 0: \x{0a} 0+ \x{711}LF, extend \x0a\x{1b04}LF, spacingmark 0: \x{0a} 0+ \x{1b04}LF, spacingmark \x0b\x{0711}Control, extend 0: \x{0b} 0+ \x{711}Control, extend \x09\x{1b04}Control, spacingmark 0: \x{09} 0+ \x{1b04}Control, spacingmark *There are no Prepend characters, so we can't test Prepend, CR 0: * 0+ There are no Prepend characters, so we can't test Prepend, CR /^(?>\X{2})X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ /^\X{2,4}X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ /^\X{2,4}?X/8+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0: \x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}\x{1111}\x{ae4c}X 0+ /\X*Z/8Y A\x{300} No match /\X*(.)/8Y A\x{1111}\x{ae4c}\x{1169} 0: A\x{1111} 1: \x{1111} /\X?abc/8Y \xff\x7f\x00\x00\x03\x00\x41\xcc\x80\x41\x{300}\x61\x62\x63\x00\>06\? 0: A\x{300}abc /-- --/ /\x{1e9e}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /[z\x{1e9e}]+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{00df}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /[z\x{00df}]+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{1f88}+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /[z\x{1f88}]+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /-- Characters with more than one other case; test in classes --/ /[z\x{00b5}]+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /[z\x{039c}]+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /[z\x{03bc}]+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /[z\x{00c5}]+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /[z\x{00e5}]+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /[z\x{212b}]+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /[z\x{01c4}]+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /[z\x{01c5}]+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /[z\x{01c6}]+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /[z\x{01c7}]+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /[z\x{01c8}]+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /[z\x{01c9}]+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /[z\x{01ca}]+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /[z\x{01cb}]+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /[z\x{01cc}]+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /[z\x{01f1}]+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /[z\x{01f2}]+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /[z\x{01f3}]+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /[z\x{0345}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /[z\x{0399}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /[z\x{03b9}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /[z\x{1fbe}]+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /[z\x{0392}]+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /[z\x{03b2}]+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /[z\x{03d0}]+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /[z\x{0395}]+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /[z\x{03b5}]+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /[z\x{03f5}]+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /[z\x{0398}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /[z\x{03b8}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /[z\x{03d1}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /[z\x{03f4}]+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /[z\x{039a}]+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /[z\x{03ba}]+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /[z\x{03f0}]+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /[z\x{03a0}]+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /[z\x{03c0}]+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /[z\x{03d6}]+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /[z\x{03a1}]+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /[z\x{03c1}]+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /[z\x{03f1}]+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /[z\x{03a3}]+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /[z\x{03c2}]+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /[z\x{03c3}]+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /[z\x{03a6}]+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /[z\x{03c6}]+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /[z\x{03d5}]+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /[z\x{03c9}]+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /[z\x{03a9}]+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /[z\x{2126}]+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /[z\x{1e60}]+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /[z\x{1e61}]+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /[z\x{1e9b}]+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /-- Perl 5.12.4 gets these wrong, but 5.15.3 is OK --/ /[z\x{004b}]+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /[z\x{006b}]+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /[z\x{212a}]+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /[z\x{0053}]+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /[z\x{0073}]+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /[z\x{017f}]+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /-- --/ /(ΣΆΜΟΣ) \1/8i ΣΆΜΟΣ ΣΆΜΟΣ 0: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} 1: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} ΣΆΜΟΣ σάμος 0: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} 1: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} σάμος σάμος 0: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} 1: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} σάμος σάμοσ 0: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c3} 1: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} σάμος ΣΆΜΟΣ 0: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} 1: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} /(σάμος) \1/8i ΣΆΜΟΣ ΣΆΜΟΣ 0: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} 1: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} ΣΆΜΟΣ σάμος 0: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} 1: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} σάμος σάμος 0: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} 1: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} σάμος σάμοσ 0: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c3} 1: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} σάμος ΣΆΜΟΣ 0: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} 1: \x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} /(ΣΆΜΟΣ) \1*/8i ΣΆΜΟΣ\x20 0: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} 1: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} ΣΆΜΟΣ ΣΆΜΟΣσάμοςσάμος 0: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3}\x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2}\x{3c3}\x{3ac}\x{3bc}\x{3bf}\x{3c2} 1: \x{3a3}\x{386}\x{39c}\x{39f}\x{3a3} /-- Perl matches these --/ /\x{00b5}+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /\x{039c}+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /\x{03bc}+/8i \x{00b5}\x{039c}\x{03bc} 0: \x{b5}\x{39c}\x{3bc} /\x{00c5}+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /\x{00e5}+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /\x{212b}+/8i \x{00c5}\x{00e5}\x{212b} 0: \x{c5}\x{e5}\x{212b} /\x{01c4}+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /\x{01c5}+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /\x{01c6}+/8i \x{01c4}\x{01c5}\x{01c6} 0: \x{1c4}\x{1c5}\x{1c6} /\x{01c7}+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /\x{01c8}+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /\x{01c9}+/8i \x{01c7}\x{01c8}\x{01c9} 0: \x{1c7}\x{1c8}\x{1c9} /\x{01ca}+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /\x{01cb}+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /\x{01cc}+/8i \x{01ca}\x{01cb}\x{01cc} 0: \x{1ca}\x{1cb}\x{1cc} /\x{01f1}+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /\x{01f2}+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /\x{01f3}+/8i \x{01f1}\x{01f2}\x{01f3} 0: \x{1f1}\x{1f2}\x{1f3} /\x{0345}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{0399}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{03b9}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{1fbe}+/8i \x{0345}\x{0399}\x{03b9}\x{1fbe} 0: \x{345}\x{399}\x{3b9}\x{1fbe} /\x{0392}+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /\x{03b2}+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /\x{03d0}+/8i \x{0392}\x{03b2}\x{03d0} 0: \x{392}\x{3b2}\x{3d0} /\x{0395}+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /\x{03b5}+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /\x{03f5}+/8i \x{0395}\x{03b5}\x{03f5} 0: \x{395}\x{3b5}\x{3f5} /\x{0398}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{03b8}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{03d1}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{03f4}+/8i \x{0398}\x{03b8}\x{03d1}\x{03f4} 0: \x{398}\x{3b8}\x{3d1}\x{3f4} /\x{039a}+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /\x{03ba}+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /\x{03f0}+/8i \x{039a}\x{03ba}\x{03f0} 0: \x{39a}\x{3ba}\x{3f0} /\x{03a0}+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /\x{03c0}+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /\x{03d6}+/8i \x{03a0}\x{03c0}\x{03d6} 0: \x{3a0}\x{3c0}\x{3d6} /\x{03a1}+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /\x{03c1}+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /\x{03f1}+/8i \x{03a1}\x{03c1}\x{03f1} 0: \x{3a1}\x{3c1}\x{3f1} /\x{03a3}+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /\x{03c2}+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /\x{03c3}+/8i \x{03A3}\x{03C2}\x{03C3} 0: \x{3a3}\x{3c2}\x{3c3} /\x{03a6}+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /\x{03c6}+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /\x{03d5}+/8i \x{03a6}\x{03c6}\x{03d5} 0: \x{3a6}\x{3c6}\x{3d5} /\x{03c9}+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /\x{03a9}+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /\x{2126}+/8i \x{03c9}\x{03a9}\x{2126} 0: \x{3c9}\x{3a9}\x{2126} /\x{1e60}+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /\x{1e61}+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /\x{1e9b}+/8i \x{1e60}\x{1e61}\x{1e9b} 0: \x{1e60}\x{1e61}\x{1e9b} /\x{1e9e}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{00df}+/8i \x{1e9e}\x{00df} 0: \x{1e9e}\x{df} /\x{1f88}+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /\x{1f80}+/8i \x{1f88}\x{1f80} 0: \x{1f88}\x{1f80} /-- Perl 5.12.4 gets these wrong, but 5.15.3 is OK --/ /\x{004b}+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /\x{006b}+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /\x{212a}+/8i \x{004b}\x{006b}\x{212a} 0: Kk\x{212a} /\x{0053}+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /\x{0073}+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /\x{017f}+/8i \x{0053}\x{0073}\x{017f} 0: Ss\x{17f} /^\p{Any}*\d{4}/8 1234 0: 1234 123 No match /^\X*\w{4}/8 1234 0: 1234 123 No match /^A\s+Z/8W A\x{2005}Z 0: A\x{2005}Z A\x{85}\x{180e}\x{2005}Z 0: A\x{85}\x{180e}\x{2005}Z /^A[\s]+Z/8W A\x{2005}Z 0: A\x{2005}Z A\x{85}\x{180e}\x{2005}Z 0: A\x{85}\x{180e}\x{2005}Z /^[[:graph:]]+$/8W Letter:ABC 0: Letter:ABC Mark:\x{300}\x{1d172}\x{1d17b} 0: Mark:\x{300}\x{1d172}\x{1d17b} Number:9\x{660} 0: Number:9\x{660} Punctuation:\x{66a},; 0: Punctuation:\x{66a},; Symbol:\x{6de}<>\x{fffc} 0: Symbol:\x{6de}<>\x{fffc} Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} 0: Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} 0: \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} 0: \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} 0: \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} 0: \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} \x{feff} 0: \x{feff} \x{fff9}\x{fffa}\x{fffb} 0: \x{fff9}\x{fffa}\x{fffb} \x{110bd} 0: \x{110bd} \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} 0: \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} \x{e0001} 0: \x{e0001} \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} 0: \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} ** Failers No match \x{09} No match \x{0a} No match \x{1D} No match \x{20} No match \x{85} No match \x{a0} No match \x{61c} No match \x{1680} No match \x{180e} No match \x{2028} No match \x{2029} No match \x{202f} No match \x{2065} No match \x{2066} No match \x{2067} No match \x{2068} No match \x{2069} No match \x{3000} No match \x{e0002} No match \x{e001f} No match \x{e0080} No match /^[[:print:]]+$/8W Space: \x{a0} 0: Space: \x{a0} \x{1680}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005} 0: \x{1680}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005} \x{2006}\x{2007}\x{2008}\x{2009}\x{200a} 0: \x{2006}\x{2007}\x{2008}\x{2009}\x{200a} \x{202f}\x{205f} 0: \x{202f}\x{205f} \x{3000} 0: \x{3000} Letter:ABC 0: Letter:ABC Mark:\x{300}\x{1d172}\x{1d17b} 0: Mark:\x{300}\x{1d172}\x{1d17b} Number:9\x{660} 0: Number:9\x{660} Punctuation:\x{66a},; 0: Punctuation:\x{66a},; Symbol:\x{6de}<>\x{fffc} 0: Symbol:\x{6de}<>\x{fffc} Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} 0: Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} \x{180e} 0: \x{180e} \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} 0: \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} 0: \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} \x{202f} 0: \x{202f} \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} 0: \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} 0: \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} \x{feff} 0: \x{feff} \x{fff9}\x{fffa}\x{fffb} 0: \x{fff9}\x{fffa}\x{fffb} \x{110bd} 0: \x{110bd} \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} 0: \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} \x{e0001} 0: \x{e0001} \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} 0: \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} ** Failers 0: ** Failers \x{09} No match \x{1D} No match \x{85} No match \x{61c} No match \x{2028} No match \x{2029} No match \x{2065} No match \x{2066} No match \x{2067} No match \x{2068} No match \x{2069} No match \x{e0002} No match \x{e001f} No match \x{e0080} No match /^[[:punct:]]+$/8W \$+<=>^`|~ 0: $+<=>^`|~ !\"#%&'()*,-./:;?@[\\]_{} 0: !"#%&'()*,-./:;?@[\]_{} \x{a1}\x{a7} 0: \x{a1}\x{a7} \x{37e} 0: \x{37e} ** Failers No match abcde No match /^[[:^graph:]]+$/8W \x{09}\x{0a}\x{1D}\x{20}\x{85}\x{a0}\x{61c}\x{1680}\x{180e} 0: \x{09}\x{0a}\x{1d} \x{85}\x{a0}\x{61c}\x{1680}\x{180e} \x{2028}\x{2029}\x{202f}\x{2065}\x{2066}\x{2067}\x{2068}\x{2069} 0: \x{2028}\x{2029}\x{202f}\x{2065}\x{2066}\x{2067}\x{2068}\x{2069} \x{3000}\x{e0002}\x{e001f}\x{e0080} 0: \x{3000}\x{e0002}\x{e001f}\x{e0080} ** Failers No match Letter:ABC No match Mark:\x{300}\x{1d172}\x{1d17b} No match Number:9\x{660} No match Punctuation:\x{66a},; No match Symbol:\x{6de}<>\x{fffc} No match Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} No match \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} No match \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} No match \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} No match \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} No match \x{feff} No match \x{fff9}\x{fffa}\x{fffb} No match \x{110bd} No match \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} No match \x{e0001} No match \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} No match /^[[:^print:]]+$/8W \x{09}\x{1D}\x{85}\x{61c}\x{2028}\x{2029}\x{2065}\x{2066}\x{2067} 0: \x{09}\x{1d}\x{85}\x{61c}\x{2028}\x{2029}\x{2065}\x{2066}\x{2067} \x{2068}\x{2069}\x{e0002}\x{e001f}\x{e0080} 0: \x{2068}\x{2069}\x{e0002}\x{e001f}\x{e0080} ** Failers No match Space: \x{a0} No match \x{1680}\x{2000}\x{2001}\x{2002}\x{2003}\x{2004}\x{2005} No match \x{2006}\x{2007}\x{2008}\x{2009}\x{200a} No match \x{202f}\x{205f} No match \x{3000} No match Letter:ABC No match Mark:\x{300}\x{1d172}\x{1d17b} No match Number:9\x{660} No match Punctuation:\x{66a},; No match Symbol:\x{6de}<>\x{fffc} No match Cf-property:\x{ad}\x{600}\x{601}\x{602}\x{603}\x{604}\x{6dd}\x{70f} No match \x{180e} No match \x{200b}\x{200c}\x{200d}\x{200e}\x{200f} No match \x{202a}\x{202b}\x{202c}\x{202d}\x{202e} No match \x{202f} No match \x{2060}\x{2061}\x{2062}\x{2063}\x{2064} No match \x{206a}\x{206b}\x{206c}\x{206d}\x{206e}\x{206f} No match \x{feff} No match \x{fff9}\x{fffa}\x{fffb} No match \x{110bd} No match \x{1d173}\x{1d174}\x{1d175}\x{1d176}\x{1d177}\x{1d178}\x{1d179}\x{1d17a} No match \x{e0001} No match \x{e0020}\x{e0030}\x{e0040}\x{e0050}\x{e0060}\x{e0070}\x{e007f} No match /^[[:^punct:]]+$/8W abcde 0: abcde ** Failers No match \$+<=>^`|~ No match !\"#%&'()*,-./:;?@[\\]_{} No match \x{a1}\x{a7} No match \x{37e} No match /[RST]+/8iW Ss\x{17f} 0: Ss\x{17f} /[R-T]+/8iW Ss\x{17f} 0: Ss\x{17f} /[q-u]+/8iW Ss\x{17f} 0: Ss\x{17f} /^s?c/mi8 scat 0: sc /[A-`]/i8 abcdefghijklmno 0: a /\C\X*QT/8 Ӆ\x0aT No match /[\pS#moq]/ = 0: = /[[:punct:]]/8W \xc2\xb4 No match \x{b4} No match /[[:^ascii:]]/8W \x{100} 0: \x{100} \x{200} 0: \x{200} \x{300} 0: \x{300} \x{37e} 0: \x{37e} a No match 9 No match g No match /[[:^ascii:]\w]/8W a 0: a 9 0: 9 g 0: g \x{100} 0: \x{100} \x{200} 0: \x{200} \x{300} 0: \x{300} \x{37e} 0: \x{37e} /[\w[:^ascii:]]/8W a 0: a 9 0: 9 g 0: g \x{100} 0: \x{100} \x{200} 0: \x{200} \x{300} 0: \x{300} \x{37e} 0: \x{37e} /[^[:ascii:]\W]/8W a No match 9 No match g No match \x{100} 0: \x{100} \x{200} 0: \x{200} \x{300} No match \x{37e} No match /[[:^ascii:]a]/8W a 0: a 9 No match g No match \x{100} 0: \x{100} \x{200} 0: \x{200} \x{37e} 0: \x{37e} /[^[:^ascii:]\d]/8W a 0: a ~ 0: ~ 0 No match \a 0: \x{07} \x{7f} 0: \x{7f} \x{389} No match \x{20ac} No match /(?=.*b)\pL/ 11bb 0: b /(?(?=.*b)(?=.*b)\pL|.*c)/ 11bb 0: b /-- End of testinput6 --/ ================================================ FILE: src/pcre/testdata/testoutput7 ================================================ /-- These tests for Unicode property support test PCRE's API and show some of the compiled code. They are not Perl-compatible. --/ /[\p{L}]/DZ ------------------------------------------------------------------ Bra [\p{L}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\p{^L}]/DZ ------------------------------------------------------------------ Bra [\P{L}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\P{L}]/DZ ------------------------------------------------------------------ Bra [\P{L}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[\P{^L}]/DZ ------------------------------------------------------------------ Bra [\p{L}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char /[abc\p{L}\x{0660}]/8DZ ------------------------------------------------------------------ Bra [a-c\p{L}\x{660}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char /[\p{Nd}]/8DZ ------------------------------------------------------------------ Bra [\p{Nd}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char 1234 0: 1 /[\p{Nd}+-]+/8DZ ------------------------------------------------------------------ Bra [+\-\p{Nd}]++ Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: utf No first char No need char 1234 0: 1234 12-34 0: 12-34 12+\x{661}-34 0: 12+\x{661}-34 ** Failers No match abcd No match /[\x{105}-\x{109}]/8iDZ ------------------------------------------------------------------ Bra [\x{104}-\x{109}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf No first char No need char \x{104} 0: \x{104} \x{105} 0: \x{105} \x{109} 0: \x{109} ** Failers No match \x{100} No match \x{10a} No match /[z-\x{100}]/8iDZ ------------------------------------------------------------------ Bra [Zz-\xff\x{39c}\x{3bc}\x{212b}\x{1e9e}\x{212b}\x{178}\x{100}-\x{101}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf No first char No need char Z 0: Z z 0: z \x{39c} 0: \x{39c} \x{178} 0: \x{178} | 0: | \x{80} 0: \x{80} \x{ff} 0: \x{ff} \x{100} 0: \x{100} \x{101} 0: \x{101} ** Failers No match \x{102} No match Y No match y No match /[z-\x{100}]/8DZi ------------------------------------------------------------------ Bra [Zz-\xff\x{39c}\x{3bc}\x{212b}\x{1e9e}\x{212b}\x{178}\x{100}-\x{101}] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf No first char No need char /(?:[\PPa*]*){8,}/ /[\P{Any}]/BZ ------------------------------------------------------------------ Bra [\P{Any}] Ket End ------------------------------------------------------------------ /[\P{Any}\E]/BZ ------------------------------------------------------------------ Bra [\P{Any}] Ket End ------------------------------------------------------------------ /(\P{Yi}+\277)/ /(\P{Yi}+\277)?/ /(?<=\P{Yi}{3}A)X/ /\p{Yi}+(\P{Yi}+)(?1)/ /(\P{Yi}{2}\277)?/ /[\P{Yi}A]/ /[\P{Yi}\P{Yi}\P{Yi}A]/ /[^\P{Yi}A]/ /[^\P{Yi}\P{Yi}\P{Yi}A]/ /(\P{Yi}*\277)*/ /(\P{Yi}*?\277)*/ /(\p{Yi}*+\277)*/ /(\P{Yi}?\277)*/ /(\P{Yi}??\277)*/ /(\p{Yi}?+\277)*/ /(\P{Yi}{0,3}\277)*/ /(\P{Yi}{0,3}?\277)*/ /(\p{Yi}{0,3}+\277)*/ /\p{Zl}{2,3}+/8BZ ------------------------------------------------------------------ Bra prop Zl {2} prop Zl ?+ Ket End ------------------------------------------------------------------ 

 0: \x{2028}\x{2028} \x{2028}\x{2028}\x{2028} 0: \x{2028}\x{2028}\x{2028} /\p{Zl}/8BZ ------------------------------------------------------------------ Bra prop Zl Ket End ------------------------------------------------------------------ /\p{Lu}{3}+/8BZ ------------------------------------------------------------------ Bra prop Lu {3} Ket End ------------------------------------------------------------------ /\pL{2}+/8BZ ------------------------------------------------------------------ Bra prop L {2} Ket End ------------------------------------------------------------------ /\p{Cc}{2}+/8BZ ------------------------------------------------------------------ Bra prop Cc {2} Ket End ------------------------------------------------------------------ /^\p{Cf}/8 \x{180e} 0: \x{180e} \x{061c} 0: \x{61c} \x{2066} 0: \x{2066} \x{2067} 0: \x{2067} \x{2068} 0: \x{2068} \x{2069} 0: \x{2069} /^\p{Cs}/8 \?\x{dfff} 0: \x{dfff} ** Failers No match \x{09f} No match /^\p{Mn}/8 \x{1a1b} 0: \x{1a1b} /^\p{Pe}/8 \x{2309} 0: \x{2309} \x{230b} 0: \x{230b} /^\p{Ps}/8 \x{2308} 0: \x{2308} \x{230a} 0: \x{230a} /^\p{Sc}+/8 $\x{a2}\x{a3}\x{a4}\x{a5}\x{a6} 0: $\x{a2}\x{a3}\x{a4}\x{a5} \x{9f2} 0: \x{9f2} ** Failers No match X No match \x{2c2} No match /^\p{Zs}/8 \ \ 0: \x{a0} 0: \x{a0} \x{1680} 0: \x{1680} \x{2000} 0: \x{2000} \x{2001} 0: \x{2001} ** Failers No match \x{2028} No match \x{200d} No match /-- These are here rather than in test 6 because Perl has problems with the negative versions of the properties and behaves has changed how it behaves for caseless matching. --/ /\p{^Lu}/8i 1234 0: 1 ** Failers 0: * ABC No match /\P{Lu}/8i 1234 0: 1 ** Failers 0: * ABC No match /\p{Ll}/8i a 0: a Az 0: z ** Failers 0: a ABC No match /\p{Lu}/8i A 0: A a\x{10a0}B 0: \x{10a0} ** Failers 0: F a No match \x{1d00} No match /\p{Lu}/8i A 0: A aZ 0: Z ** Failers 0: F abc No match /[\x{c0}\x{391}]/8i \x{c0} 0: \x{c0} \x{e0} 0: \x{e0} /-- The next two are special cases where the lengths of the different cases of the same character differ. The first went wrong with heap frame storage; the second was broken in all cases. --/ /^\x{023a}+?(\x{0130}+)/8i \x{023a}\x{2c65}\x{0130} 0: \x{23a}\x{2c65}\x{130} 1: \x{130} /^\x{023a}+([^X])/8i \x{023a}\x{2c65}X 0: \x{23a}\x{2c65} 1: \x{2c65} /\x{c0}+\x{116}+/8i \x{c0}\x{e0}\x{116}\x{117} 0: \x{c0}\x{e0}\x{116}\x{117} /[\x{c0}\x{116}]+/8i \x{c0}\x{e0}\x{116}\x{117} 0: \x{c0}\x{e0}\x{116}\x{117} /(\x{de})\1/8i \x{de}\x{de} 0: \x{de}\x{de} 1: \x{de} \x{de}\x{fe} 0: \x{de}\x{fe} 1: \x{de} \x{fe}\x{fe} 0: \x{fe}\x{fe} 1: \x{fe} \x{fe}\x{de} 0: \x{fe}\x{de} 1: \x{fe} /^\x{c0}$/8i \x{c0} 0: \x{c0} \x{e0} 0: \x{e0} /^\x{e0}$/8i \x{c0} 0: \x{c0} \x{e0} 0: \x{e0} /-- The next two should be Perl-compatible, but it fails to match \x{e0}. PCRE will match it only with UCP support, because without that it has no notion of case for anything other than the ASCII letters. --/ /((?i)[\x{c0}])/8 \x{c0} 0: \x{c0} 1: \x{c0} \x{e0} 0: \x{e0} 1: \x{e0} /(?i:[\x{c0}])/8 \x{c0} 0: \x{c0} \x{e0} 0: \x{e0} /-- These are PCRE's extra properties to help with Unicodizing \d etc. --/ /^\p{Xan}/8 ABCD 0: A 1234 0: 1 \x{6ca} 0: \x{6ca} \x{a6c} 0: \x{a6c} \x{10a7} 0: \x{10a7} ** Failers No match _ABC No match /^\p{Xan}+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7} ** Failers No match _ABC No match /^\p{Xan}+?/8 \x{6ca}\x{a6c}\x{10a7}_ 0: \x{6ca} /^\p{Xan}*/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7} /^\p{Xan}{2,9}/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca} /^\p{Xan}{2,9}?/8 \x{6ca}\x{a6c}\x{10a7}_ 0: \x{6ca}\x{a6c} /^[\p{Xan}]/8 ABCD1234_ 0: A 1234abcd_ 0: 1 \x{6ca} 0: \x{6ca} \x{a6c} 0: \x{a6c} \x{10a7} 0: \x{10a7} ** Failers No match _ABC No match /^[\p{Xan}]+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7} ** Failers No match _ABC No match /^>\p{Xsp}/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680} >\x{a0} 0: >\x{a0} ** Failers No match \x{0b} No match /^>\p{Xsp}+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}+?/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680} /^>\p{Xsp}*/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}{2,9}/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xsp}{2,9}?/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09} /^>[\p{Xsp}]/8 >\x{2028}\x{0b} 0: >\x{2028} /^>[\p{Xsp}]+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680} >\x{a0} 0: >\x{a0} ** Failers No match \x{0b} No match /^>\p{Xps}+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}+?/8 >\x{1680}\x{2028}\x{0b} 0: >\x{1680} /^>\p{Xps}*/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^>\p{Xps}{2,9}?/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09} /^>[\p{Xps}]/8 >\x{2028}\x{0b} 0: >\x{2028} /^>[\p{Xps}]+/8 > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} 0: > \x{09}\x{0a}\x{0c}\x{0d}\x{a0}\x{1680}\x{2028}\x{0b} /^\p{Xwd}/8 ABCD 0: A 1234 0: 1 \x{6ca} 0: \x{6ca} \x{a6c} 0: \x{a6c} \x{10a7} 0: \x{10a7} _ABC 0: _ ** Failers No match [] No match /^\p{Xwd}+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}+?/8 \x{6ca}\x{a6c}\x{10a7}_ 0: \x{6ca} /^\p{Xwd}*/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /^\p{Xwd}{2,9}/8 A_B12\x{6ca}\x{a6c}\x{10a7} 0: A_B12\x{6ca}\x{a6c}\x{10a7} /^\p{Xwd}{2,9}?/8 \x{6ca}\x{a6c}\x{10a7}_ 0: \x{6ca}\x{a6c} /^[\p{Xwd}]/8 ABCD1234_ 0: A 1234abcd_ 0: 1 \x{6ca} 0: \x{6ca} \x{a6c} 0: \x{a6c} \x{10a7} 0: \x{10a7} _ABC 0: _ ** Failers No match [] No match /^[\p{Xwd}]+/8 ABCD1234\x{6ca}\x{a6c}\x{10a7}_ 0: ABCD1234\x{6ca}\x{a6c}\x{10a7}_ /-- A check not in UTF-8 mode --/ /^[\p{Xwd}]+/ ABCD1234_ 0: ABCD1234_ /-- Some negative checks --/ /^[\P{Xwd}]+/8 !.+\x{019}\x{35a}AB 0: !.+\x{19}\x{35a} /^[\p{^Xwd}]+/8 !.+\x{019}\x{35a}AB 0: !.+\x{19}\x{35a} /[\D]/WBZ8 ------------------------------------------------------------------ Bra [\P{Nd}] Ket End ------------------------------------------------------------------ 1\x{3c8}2 0: \x{3c8} /[\d]/WBZ8 ------------------------------------------------------------------ Bra [\p{Nd}] Ket End ------------------------------------------------------------------ >\x{6f4}< 0: \x{6f4} /[\S]/WBZ8 ------------------------------------------------------------------ Bra [\P{Xsp}] Ket End ------------------------------------------------------------------ \x{1680}\x{6f4}\x{1680} 0: \x{6f4} /[\s]/WBZ8 ------------------------------------------------------------------ Bra [\p{Xsp}] Ket End ------------------------------------------------------------------ >\x{1680}< 0: \x{1680} /[\W]/WBZ8 ------------------------------------------------------------------ Bra [\P{Xwd}] Ket End ------------------------------------------------------------------ A\x{1712}B 0: \x{1712} /[\w]/WBZ8 ------------------------------------------------------------------ Bra [\p{Xwd}] Ket End ------------------------------------------------------------------ >\x{1723}< 0: \x{1723} /\D/WBZ8 ------------------------------------------------------------------ Bra notprop Nd Ket End ------------------------------------------------------------------ 1\x{3c8}2 0: \x{3c8} /\d/WBZ8 ------------------------------------------------------------------ Bra prop Nd Ket End ------------------------------------------------------------------ >\x{6f4}< 0: \x{6f4} /\S/WBZ8 ------------------------------------------------------------------ Bra notprop Xsp Ket End ------------------------------------------------------------------ \x{1680}\x{6f4}\x{1680} 0: \x{6f4} /\s/WBZ8 ------------------------------------------------------------------ Bra prop Xsp Ket End ------------------------------------------------------------------ >\x{1680}> 0: \x{1680} /\W/WBZ8 ------------------------------------------------------------------ Bra notprop Xwd Ket End ------------------------------------------------------------------ A\x{1712}B 0: \x{1712} /\w/WBZ8 ------------------------------------------------------------------ Bra prop Xwd Ket End ------------------------------------------------------------------ >\x{1723}< 0: \x{1723} /[[:alpha:]]/WBZ ------------------------------------------------------------------ Bra [\p{L}] Ket End ------------------------------------------------------------------ /[[:lower:]]/WBZ ------------------------------------------------------------------ Bra [\p{Ll}] Ket End ------------------------------------------------------------------ /[[:upper:]]/WBZ ------------------------------------------------------------------ Bra [\p{Lu}] Ket End ------------------------------------------------------------------ /[[:alnum:]]/WBZ ------------------------------------------------------------------ Bra [\p{Xan}] Ket End ------------------------------------------------------------------ /[[:ascii:]]/WBZ ------------------------------------------------------------------ Bra [\x00-\x7f] Ket End ------------------------------------------------------------------ /[[:cntrl:]]/WBZ ------------------------------------------------------------------ Bra [\x00-\x1f\x7f] Ket End ------------------------------------------------------------------ /[[:digit:]]/WBZ ------------------------------------------------------------------ Bra [\p{Nd}] Ket End ------------------------------------------------------------------ /[[:graph:]]/WBZ ------------------------------------------------------------------ Bra [[:graph:]] Ket End ------------------------------------------------------------------ /[[:print:]]/WBZ ------------------------------------------------------------------ Bra [[:print:]] Ket End ------------------------------------------------------------------ /[[:punct:]]/WBZ ------------------------------------------------------------------ Bra [[:punct:]] Ket End ------------------------------------------------------------------ /[[:space:]]/WBZ ------------------------------------------------------------------ Bra [\p{Xps}] Ket End ------------------------------------------------------------------ /[[:word:]]/WBZ ------------------------------------------------------------------ Bra [\p{Xwd}] Ket End ------------------------------------------------------------------ /[[:xdigit:]]/WBZ ------------------------------------------------------------------ Bra [0-9A-Fa-f] Ket End ------------------------------------------------------------------ /-- Unicode properties for \b abd \B --/ /\b...\B/8W abc_ 0: abc \x{37e}abc\x{376} 0: abc \x{37e}\x{376}\x{371}\x{393}\x{394} 0: \x{376}\x{371}\x{393} !\x{c0}++\x{c1}\x{c2} 0: ++\x{c1} !\x{c0}+++++ 0: \x{c0}++ /-- Without PCRE_UCP, non-ASCII always fail, even if < 256 --/ /\b...\B/8 abc_ 0: abc ** Failers 0: Fai \x{37e}abc\x{376} No match \x{37e}\x{376}\x{371}\x{393}\x{394} No match !\x{c0}++\x{c1}\x{c2} No match !\x{c0}+++++ No match /-- With PCRE_UCP, non-UTF8 chars that are < 256 still check properties --/ /\b...\B/W abc_ 0: abc !\x{c0}++\x{c1}\x{c2} 0: ++\xc1 !\x{c0}+++++ 0: \xc0++ /-- Some of these are silly, but they check various combinations --/ /[[:^alpha:][:^cntrl:]]+/8WBZ ------------------------------------------------------------------ Bra [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ Ket End ------------------------------------------------------------------ 123 0: 123 abc 0: abc /[[:^cntrl:][:^alpha:]]+/8WBZ ------------------------------------------------------------------ Bra [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ Ket End ------------------------------------------------------------------ 123 0: 123 abc 0: abc /[[:alpha:]]+/8WBZ ------------------------------------------------------------------ Bra [\p{L}]++ Ket End ------------------------------------------------------------------ abc 0: abc /[[:^alpha:]\S]+/8WBZ ------------------------------------------------------------------ Bra [\P{L}\P{Xsp}]++ Ket End ------------------------------------------------------------------ 123 0: 123 abc 0: abc /[^\d]+/8WBZ ------------------------------------------------------------------ Bra [^\p{Nd}]++ Ket End ------------------------------------------------------------------ abc123 0: abc abc\x{123} 0: abc\x{123} \x{660}abc 0: abc /\p{Lu}+9\p{Lu}+B\p{Lu}+b/BZ ------------------------------------------------------------------ Bra prop Lu ++ 9 prop Lu + B prop Lu ++ b Ket End ------------------------------------------------------------------ /\p{^Lu}+9\p{^Lu}+B\p{^Lu}+b/BZ ------------------------------------------------------------------ Bra notprop Lu + 9 notprop Lu ++ B notprop Lu + b Ket End ------------------------------------------------------------------ /\P{Lu}+9\P{Lu}+B\P{Lu}+b/BZ ------------------------------------------------------------------ Bra notprop Lu + 9 notprop Lu ++ B notprop Lu + b Ket End ------------------------------------------------------------------ /\p{Han}+X\p{Greek}+\x{370}/BZ8 ------------------------------------------------------------------ Bra prop Han ++ X prop Greek + \x{370} Ket End ------------------------------------------------------------------ /\p{Xan}+!\p{Xan}+A/BZ ------------------------------------------------------------------ Bra prop Xan ++ ! prop Xan + A Ket End ------------------------------------------------------------------ /\p{Xsp}+!\p{Xsp}\t/BZ ------------------------------------------------------------------ Bra prop Xsp ++ ! prop Xsp \x09 Ket End ------------------------------------------------------------------ /\p{Xps}+!\p{Xps}\t/BZ ------------------------------------------------------------------ Bra prop Xps ++ ! prop Xps \x09 Ket End ------------------------------------------------------------------ /\p{Xwd}+!\p{Xwd}_/BZ ------------------------------------------------------------------ Bra prop Xwd ++ ! prop Xwd _ Ket End ------------------------------------------------------------------ /A+\p{N}A+\dB+\p{N}*B+\d*/WBZ ------------------------------------------------------------------ Bra A++ prop N A++ prop Nd B+ prop N *+ B++ prop Nd *+ Ket End ------------------------------------------------------------------ /-- These behaved oddly in Perl, so they are kept in this test --/ /(\x{23a}\x{23a}\x{23a})?\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65} No match /(ȺȺȺ)?\1/8i ȺȺȺⱥⱥ No match /(\x{23a}\x{23a}\x{23a})?\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} 0: \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} 1: \x{23a}\x{23a}\x{23a} /(ȺȺȺ)?\1/8i ȺȺȺⱥⱥⱥ 0: \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} 1: \x{23a}\x{23a}\x{23a} /(\x{23a}\x{23a}\x{23a})\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65} No match /(ȺȺȺ)\1/8i ȺȺȺⱥⱥ No match /(\x{23a}\x{23a}\x{23a})\1/8i \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} 0: \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} 1: \x{23a}\x{23a}\x{23a} /(ȺȺȺ)\1/8i ȺȺȺⱥⱥⱥ 0: \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65} 1: \x{23a}\x{23a}\x{23a} /(\x{2c65}\x{2c65})\1/8i \x{2c65}\x{2c65}\x{23a}\x{23a} 0: \x{2c65}\x{2c65}\x{23a}\x{23a} 1: \x{2c65}\x{2c65} /(ⱥⱥ)\1/8i ⱥⱥȺȺ 0: \x{2c65}\x{2c65}\x{23a}\x{23a} 1: \x{2c65}\x{2c65} /(\x{23a}\x{23a}\x{23a})\1Y/8i X\x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65}YZ 0: \x{23a}\x{23a}\x{23a}\x{2c65}\x{2c65}\x{2c65}Y 1: \x{23a}\x{23a}\x{23a} /(\x{2c65}\x{2c65})\1Y/8i X\x{2c65}\x{2c65}\x{23a}\x{23a}YZ 0: \x{2c65}\x{2c65}\x{23a}\x{23a}Y 1: \x{2c65}\x{2c65} /-- --/ /-- These scripts weren't yet in Perl when I added Unicode 6.0.0 to PCRE --/ /^[\p{Batak}]/8 \x{1bc0} 0: \x{1bc0} \x{1bff} 0: \x{1bff} ** Failers No match \x{1bf4} No match /^[\p{Brahmi}]/8 \x{11000} 0: \x{11000} \x{1106f} 0: \x{1106f} ** Failers No match \x{1104e} No match /^[\p{Mandaic}]/8 \x{840} 0: \x{840} \x{85e} 0: \x{85e} ** Failers No match \x{85c} No match \x{85d} No match /-- --/ /(\X*)(.)/s8 A\x{300} 0: A 1: 2: A /^S(\X*)e(\X*)$/8 Stéréo 0: Ste\x{301}re\x{301}o 1: te\x{301}r 2: \x{301}o /^\X/8 ́réo 0: \x{301} /^a\X41z/ aX41z 0: aX41z *** Failers No match aAz No match /(?<=ab\Cde)X/8 Failed: \C not allowed in lookbehind assertion at offset 10 /\X/ a\P 0: a a\P\P Partial match: a /\Xa/ aa\P 0: aa aa\P\P 0: aa /\X{2}/ aa\P 0: aa aa\P\P Partial match: aa /\X+a/ a\P Partial match: a aa\P 0: aa aa\P\P Partial match: aa /\X+?a/ a\P Partial match: a ab\P Partial match: ab aa\P 0: aa aa\P\P 0: aa aba\P 0: aba /-- These Unicode 6.1.0 scripts are not known to Perl. --/ /\p{Chakma}\d/8W \x{11100}\x{1113c} 0: \x{11100}\x{1113c} /\p{Takri}\d/8W \x{11680}\x{116c0} 0: \x{11680}\x{116c0} /^\X/8 A\P 0: A A\P\P Partial match: A A\x{300}\x{301}\P 0: A\x{300}\x{301} A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301} A\x{301}\P 0: A\x{301} A\x{301}\P\P Partial match: A\x{301} /^\X{2,3}/8 A\P Partial match: A A\P\P Partial match: A AA\P 0: AA AA\P\P Partial match: AA A\x{300}\x{301}\P Partial match: A\x{300}\x{301} A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301} A\x{300}\x{301}A\x{300}\x{301}\P 0: A\x{300}\x{301}A\x{300}\x{301} A\x{300}\x{301}A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301}A\x{300}\x{301} /^\X{2}/8 AA\P 0: AA AA\P\P Partial match: AA A\x{300}\x{301}A\x{300}\x{301}\P 0: A\x{300}\x{301}A\x{300}\x{301} A\x{300}\x{301}A\x{300}\x{301}\P\P Partial match: A\x{300}\x{301}A\x{300}\x{301} /^\X+/8 AA\P 0: AA AA\P\P Partial match: AA /^\X+?Z/8 AA\P Partial match: AA AA\P\P Partial match: AA /A\x{3a3}B/8iDZ ------------------------------------------------------------------ Bra /i A clist 03a3 03c2 03c3 /i B Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf First char = 'A' (caseless) Need char = 'B' (caseless) /\x{3a3}B/8iDZ ------------------------------------------------------------------ Bra clist 03a3 03c2 03c3 /i B Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 Options: caseless utf No first char Need char = 'B' (caseless) /[\x{3a3}]/8iBZ ------------------------------------------------------------------ Bra clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /[^\x{3a3}]/8iBZ ------------------------------------------------------------------ Bra not clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /[\x{3a3}]+/8iBZ ------------------------------------------------------------------ Bra clist 03a3 03c2 03c3 ++ Ket End ------------------------------------------------------------------ /[^\x{3a3}]+/8iBZ ------------------------------------------------------------------ Bra not clist 03a3 03c2 03c3 ++ Ket End ------------------------------------------------------------------ /a*\x{3a3}/8iBZ ------------------------------------------------------------------ Bra /i a*+ clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /\x{3a3}+a/8iBZ ------------------------------------------------------------------ Bra clist 03a3 03c2 03c3 ++ /i a Ket End ------------------------------------------------------------------ /\x{3a3}*\x{3c2}/8iBZ ------------------------------------------------------------------ Bra clist 03a3 03c2 03c3 * clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /\x{3a3}{3}/8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} 0: \x{3a3}\x{3c3}\x{3c2} 0+ \x{3a3}\x{3c3}\x{3c2} /\x{3a3}{2,4}/8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} 0: \x{3a3}\x{3c3}\x{3c2}\x{3a3} 0+ \x{3c3}\x{3c2} /\x{3a3}{2,4}?/8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} 0: \x{3a3}\x{3c3} 0+ \x{3c2}\x{3a3}\x{3c3}\x{3c2} /\x{3a3}+./8i+ \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} 0: \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} 0+ /\x{3a3}++./8i+ ** Failers No match \x{3a3}\x{3c3}\x{3c2}\x{3a3}\x{3c3}\x{3c2} No match /\x{3a3}*\x{3c2}/8iBZ ------------------------------------------------------------------ Bra clist 03a3 03c2 03c3 * clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /[^\x{3a3}]*\x{3c2}/8iBZ ------------------------------------------------------------------ Bra not clist 03a3 03c2 03c3 *+ clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /[^a]*\x{3c2}/8iBZ ------------------------------------------------------------------ Bra /i [^a]* clist 03a3 03c2 03c3 Ket End ------------------------------------------------------------------ /ist/8iBZ ------------------------------------------------------------------ Bra /i i clist 0053 0073 017f /i t Ket End ------------------------------------------------------------------ ikt No match /is+t/8i iSs\x{17f}t 0: iSs\x{17f}t ikt No match /is+?t/8i ikt No match /is?t/8i ikt No match /is{2}t/8i iskt No match /-- This property is a PCRE special --/ /^\p{Xuc}/8 $abc 0: $ @abc 0: @ `abc 0: ` \x{1234}abc 0: \x{1234} ** Failers No match abc No match /^\p{Xuc}+/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} ** Failers No match \x{9f} No match /^\p{Xuc}+?/8 $@`\x{a0}\x{1234}\x{e000}** 0: $ ** Failers No match \x{9f} No match /^\p{Xuc}+?\*/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000}* ** Failers No match \x{9f} No match /^\p{Xuc}++/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} ** Failers No match \x{9f} No match /^\p{Xuc}{3,5}/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234} ** Failers No match \x{9f} No match /^\p{Xuc}{3,5}?/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@` ** Failers No match \x{9f} No match /^[\p{Xuc}]/8 $@`\x{a0}\x{1234}\x{e000}** 0: $ ** Failers No match \x{9f} No match /^[\p{Xuc}]+/8 $@`\x{a0}\x{1234}\x{e000}** 0: $@`\x{a0}\x{1234}\x{e000} ** Failers No match \x{9f} No match /^\P{Xuc}/8 abc 0: a ** Failers 0: * $abc No match @abc No match `abc No match \x{1234}abc No match /^[\P{Xuc}]/8 abc 0: a ** Failers 0: * $abc No match @abc No match `abc No match \x{1234}abc No match /-- Some auto-possessification tests --/ /\pN+\z/BZ ------------------------------------------------------------------ Bra prop N ++ \z Ket End ------------------------------------------------------------------ /\PN+\z/BZ ------------------------------------------------------------------ Bra notprop N ++ \z Ket End ------------------------------------------------------------------ /\pN+/BZ ------------------------------------------------------------------ Bra prop N ++ Ket End ------------------------------------------------------------------ /\PN+/BZ ------------------------------------------------------------------ Bra notprop N ++ Ket End ------------------------------------------------------------------ /\p{Any}+\p{Any} \p{Any}+\P{Any} \p{Any}+\p{L&} \p{Any}+\p{L} \p{Any}+\p{Lu} \p{Any}+\p{Han} \p{Any}+\p{Xan} \p{Any}+\p{Xsp} \p{Any}+\p{Xps} \p{Xwd}+\p{Any} \p{Any}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Any + prop Any prop Any + notprop Any prop Any + prop L& prop Any + prop L prop Any + prop Lu prop Any + prop Han prop Any + prop Xan prop Any + prop Xsp prop Any + prop Xps prop Xwd + prop Any prop Any + prop Xuc Ket End ------------------------------------------------------------------ /\p{L&}+\p{Any} \p{L&}+\p{L&} \P{L&}+\p{L&} \p{L&}+\p{L} \p{L&}+\p{Lu} \p{L&}+\p{Han} \p{L&}+\p{Xan} \p{L&}+\P{Xan} \p{L&}+\p{Xsp} \p{L&}+\p{Xps} \p{Xwd}+\p{L&} \p{L&}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop L& + prop Any prop L& + prop L& notprop L& ++ prop L& prop L& + prop L prop L& + prop Lu prop L& + prop Han prop L& + prop Xan prop L& ++ notprop Xan prop L& ++ prop Xsp prop L& ++ prop Xps prop Xwd + prop L& prop L& + prop Xuc Ket End ------------------------------------------------------------------ /\p{N}+\p{Any} \p{N}+\p{L&} \p{N}+\p{L} \p{N}+\P{L} \p{N}+\P{N} \p{N}+\p{Lu} \p{N}+\p{Han} \p{N}+\p{Xan} \p{N}+\p{Xsp} \p{N}+\p{Xps} \p{Xwd}+\p{N} \p{N}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop N + prop Any prop N + prop L& prop N ++ prop L prop N + notprop L prop N ++ notprop N prop N ++ prop Lu prop N + prop Han prop N + prop Xan prop N ++ prop Xsp prop N ++ prop Xps prop Xwd + prop N prop N + prop Xuc Ket End ------------------------------------------------------------------ /\p{Lu}+\p{Any} \p{Lu}+\p{L&} \p{Lu}+\p{L} \p{Lu}+\p{Lu} \P{Lu}+\p{Lu} \p{Lu}+\p{Nd} \p{Lu}+\P{Nd} \p{Lu}+\p{Han} \p{Lu}+\p{Xan} \p{Lu}+\p{Xsp} \p{Lu}+\p{Xps} \p{Xwd}+\p{Lu} \p{Lu}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Lu + prop Any prop Lu + prop L& prop Lu + prop L prop Lu + prop Lu notprop Lu ++ prop Lu prop Lu ++ prop Nd prop Lu + notprop Nd prop Lu + prop Han prop Lu + prop Xan prop Lu ++ prop Xsp prop Lu ++ prop Xps prop Xwd + prop Lu prop Lu + prop Xuc Ket End ------------------------------------------------------------------ /\p{Han}+\p{Lu} \p{Han}+\p{L&} \p{Han}+\p{L} \p{Han}+\p{Lu} \p{Han}+\p{Arabic} \p{Arabic}+\p{Arabic} \p{Han}+\p{Xan} \p{Han}+\p{Xsp} \p{Han}+\p{Xps} \p{Xwd}+\p{Han} \p{Han}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Han + prop Lu prop Han + prop L& prop Han + prop L prop Han + prop Lu prop Han ++ prop Arabic prop Arabic + prop Arabic prop Han + prop Xan prop Han + prop Xsp prop Han + prop Xps prop Xwd + prop Han prop Han + prop Xuc Ket End ------------------------------------------------------------------ /\p{Xan}+\p{Any} \p{Xan}+\p{L&} \P{Xan}+\p{L&} \p{Xan}+\p{L} \p{Xan}+\p{Lu} \p{Xan}+\p{Han} \p{Xan}+\p{Xan} \p{Xan}+\P{Xan} \p{Xan}+\p{Xsp} \p{Xan}+\p{Xps} \p{Xwd}+\p{Xan} \p{Xan}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Xan + prop Any prop Xan + prop L& notprop Xan ++ prop L& prop Xan + prop L prop Xan + prop Lu prop Xan + prop Han prop Xan + prop Xan prop Xan ++ notprop Xan prop Xan ++ prop Xsp prop Xan ++ prop Xps prop Xwd + prop Xan prop Xan + prop Xuc Ket End ------------------------------------------------------------------ /\p{Xsp}+\p{Any} \p{Xsp}+\p{L&} \p{Xsp}+\p{L} \p{Xsp}+\p{Lu} \p{Xsp}+\p{Han} \p{Xsp}+\p{Xan} \p{Xsp}+\p{Xsp} \P{Xsp}+\p{Xsp} \p{Xsp}+\p{Xps} \p{Xwd}+\p{Xsp} \p{Xsp}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Xsp + prop Any prop Xsp ++ prop L& prop Xsp ++ prop L prop Xsp ++ prop Lu prop Xsp + prop Han prop Xsp ++ prop Xan prop Xsp + prop Xsp notprop Xsp ++ prop Xsp prop Xsp + prop Xps prop Xwd ++ prop Xsp prop Xsp + prop Xuc Ket End ------------------------------------------------------------------ /\p{Xwd}+\p{Any} \p{Xwd}+\p{L&} \p{Xwd}+\p{L} \p{Xwd}+\p{Lu} \p{Xwd}+\p{Han} \p{Xwd}+\p{Xan} \p{Xwd}+\p{Xsp} \p{Xwd}+\p{Xps} \p{Xwd}+\p{Xwd} \p{Xwd}+\P{Xwd} \p{Xwd}+\p{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Xwd + prop Any prop Xwd + prop L& prop Xwd + prop L prop Xwd + prop Lu prop Xwd + prop Han prop Xwd + prop Xan prop Xwd ++ prop Xsp prop Xwd ++ prop Xps prop Xwd + prop Xwd prop Xwd ++ notprop Xwd prop Xwd + prop Xuc Ket End ------------------------------------------------------------------ /\p{Xuc}+\p{Any} \p{Xuc}+\p{L&} \p{Xuc}+\p{L} \p{Xuc}+\p{Lu} \p{Xuc}+\p{Han} \p{Xuc}+\p{Xan} \p{Xuc}+\p{Xsp} \p{Xuc}+\p{Xps} \p{Xwd}+\p{Xuc} \p{Xuc}+\p{Xuc} \p{Xuc}+\P{Xuc}/BWZx ------------------------------------------------------------------ Bra prop Xuc + prop Any prop Xuc + prop L& prop Xuc + prop L prop Xuc + prop Lu prop Xuc + prop Han prop Xuc + prop Xan prop Xuc + prop Xsp prop Xuc + prop Xps prop Xwd + prop Xuc prop Xuc + prop Xuc prop Xuc ++ notprop Xuc Ket End ------------------------------------------------------------------ /\p{N}+\p{Ll} \p{N}+\p{Nd} \p{N}+\P{Nd}/BWZx ------------------------------------------------------------------ Bra prop N ++ prop Ll prop N + prop Nd prop N + notprop Nd Ket End ------------------------------------------------------------------ /\p{Xan}+\p{L} \p{Xan}+\p{N} \p{Xan}+\p{C} \p{Xan}+\P{L} \P{Xan}+\p{N} \p{Xan}+\P{C}/BWZx ------------------------------------------------------------------ Bra prop Xan + prop L prop Xan + prop N prop Xan ++ prop C prop Xan + notprop L notprop Xan ++ prop N prop Xan + notprop C Ket End ------------------------------------------------------------------ /\p{L}+\p{Xan} \p{N}+\p{Xan} \p{C}+\p{Xan} \P{L}+\p{Xan} \p{N}+\p{Xan} \P{C}+\p{Xan} \p{L}+\P{Xan}/BWZx ------------------------------------------------------------------ Bra prop L + prop Xan prop N + prop Xan prop C ++ prop Xan notprop L + prop Xan prop N + prop Xan notprop C + prop Xan prop L ++ notprop Xan Ket End ------------------------------------------------------------------ /\p{Xan}+\p{Lu} \p{Xan}+\p{Nd} \p{Xan}+\p{Cc} \p{Xan}+\P{Ll} \P{Xan}+\p{No} \p{Xan}+\P{Cf}/BWZx ------------------------------------------------------------------ Bra prop Xan + prop Lu prop Xan + prop Nd prop Xan ++ prop Cc prop Xan + notprop Ll notprop Xan ++ prop No prop Xan + notprop Cf Ket End ------------------------------------------------------------------ /\p{Lu}+\p{Xan} \p{Nd}+\p{Xan} \p{Cs}+\p{Xan} \P{Lt}+\p{Xan} \p{Nl}+\p{Xan} \P{Cc}+\p{Xan} \p{Lt}+\P{Xan}/BWZx ------------------------------------------------------------------ Bra prop Lu + prop Xan prop Nd + prop Xan prop Cs ++ prop Xan notprop Lt + prop Xan prop Nl + prop Xan notprop Cc + prop Xan prop Lt ++ notprop Xan Ket End ------------------------------------------------------------------ /\w+\p{P} \w+\p{Po} \w+\s \p{Xan}+\s \s+\p{Xan} \s+\w/BWZx ------------------------------------------------------------------ Bra prop Xwd + prop P prop Xwd + prop Po prop Xwd ++ prop Xsp prop Xan ++ prop Xsp prop Xsp ++ prop Xan prop Xsp ++ prop Xwd Ket End ------------------------------------------------------------------ /\w+\P{P} \W+\p{Po} \w+\S \P{Xan}+\s \s+\P{Xan} \s+\W/BWZx ------------------------------------------------------------------ Bra prop Xwd + notprop P notprop Xwd + prop Po prop Xwd + notprop Xsp notprop Xan + prop Xsp prop Xsp + notprop Xan prop Xsp + notprop Xwd Ket End ------------------------------------------------------------------ /\w+\p{Po} \w+\p{Pc} \W+\p{Po} \W+\p{Pc} \w+\P{Po} \w+\P{Pc}/BWZx ------------------------------------------------------------------ Bra prop Xwd + prop Po prop Xwd ++ prop Pc notprop Xwd + prop Po notprop Xwd + prop Pc prop Xwd + notprop Po prop Xwd + notprop Pc Ket End ------------------------------------------------------------------ /\p{Nl}+\p{Xan} \P{Nl}+\p{Xan} \p{Nl}+\P{Xan} \P{Nl}+\P{Xan}/BWZx ------------------------------------------------------------------ Bra prop Nl + prop Xan notprop Nl + prop Xan prop Nl ++ notprop Xan notprop Nl + notprop Xan Ket End ------------------------------------------------------------------ /\p{Xan}+\p{Nl} \P{Xan}+\p{Nl} \p{Xan}+\P{Nl} \P{Xan}+\P{Nl}/BWZx ------------------------------------------------------------------ Bra prop Xan + prop Nl notprop Xan ++ prop Nl prop Xan + notprop Nl notprop Xan + notprop Nl Ket End ------------------------------------------------------------------ /\p{Xan}+\p{Nd} \P{Xan}+\p{Nd} \p{Xan}+\P{Nd} \P{Xan}+\P{Nd}/BWZx ------------------------------------------------------------------ Bra prop Xan + prop Nd notprop Xan ++ prop Nd prop Xan + notprop Nd notprop Xan + notprop Nd Ket End ------------------------------------------------------------------ /-- End auto-possessification tests --/ /\w+/8CWBZ ------------------------------------------------------------------ Bra Callout 255 0 3 prop Xwd ++ Callout 255 3 0 Ket End ------------------------------------------------------------------ abcd --->abcd +0 ^ \w+ +3 ^ ^ 0: abcd /[\p{N}]?+/BZO ------------------------------------------------------------------ Bra [\p{N}]?+ Ket End ------------------------------------------------------------------ /[\p{L}ab]{2,3}+/BZO ------------------------------------------------------------------ Bra [ab\p{L}]{2,3}+ Ket End ------------------------------------------------------------------ /\D+\X \d+\X \S+\X \s+\X \W+\X \w+\X \C+\X \R+\X \H+\X \h+\X \V+\X \v+\X a+\X \n+\X .+\X/BZx ------------------------------------------------------------------ Bra \D+ extuni \d+ extuni \S+ extuni \s+ extuni \W+ extuni \w+ extuni AllAny+ extuni \R+ extuni \H+ extuni \h+ extuni \V+ extuni \v+ extuni a+ extuni \x0a+ extuni Any+ extuni Ket End ------------------------------------------------------------------ /.+\X/BZxs ------------------------------------------------------------------ Bra AllAny+ extuni Ket End ------------------------------------------------------------------ /\X+$/BZxm ------------------------------------------------------------------ Bra extuni+ /m $ Ket End ------------------------------------------------------------------ /\X+\D \X+\d \X+\S \X+\s \X+\W \X+\w \X+. \X+\C \X+\R \X+\H \X+\h \X+\V \X+\v \X+\X \X+\Z \X+\z \X+$/BZx ------------------------------------------------------------------ Bra extuni+ \D extuni+ \d extuni+ \S extuni+ \s extuni+ \W extuni+ \w extuni+ Any extuni+ AllAny extuni+ \R extuni+ \H extuni+ \h extuni+ \V extuni+ \v extuni+ extuni extuni+ \Z extuni++ \z extuni+ $ Ket End ------------------------------------------------------------------ /\d+\s{0,5}=\s*\S?=\w{0,4}\W*/8WBZ ------------------------------------------------------------------ Bra prop Nd ++ prop Xsp {0,5}+ = prop Xsp *+ notprop Xsp ? = prop Xwd {0,4}+ notprop Xwd *+ Ket End ------------------------------------------------------------------ /[RST]+/8iWBZ ------------------------------------------------------------------ Bra [R-Tr-t\x{17f}]++ Ket End ------------------------------------------------------------------ /[R-T]+/8iWBZ ------------------------------------------------------------------ Bra [R-Tr-t\x{17f}]++ Ket End ------------------------------------------------------------------ /[Q-U]+/8iWBZ ------------------------------------------------------------------ Bra [Q-Uq-u\x{17f}]++ Ket End ------------------------------------------------------------------ /^s?c/mi8I Capturing subpattern count = 0 Options: caseless multiline utf First char at start or follows newline Need char = 'c' (caseless) scat 0: sc /a[[:punct:]b]/WBZ ------------------------------------------------------------------ Bra a [b[:punct:]] Ket End ------------------------------------------------------------------ /a[[:punct:]b]/8WBZ ------------------------------------------------------------------ Bra a [b[:punct:]] Ket End ------------------------------------------------------------------ /a[b[:punct:]]/8WBZ ------------------------------------------------------------------ Bra a [b[:punct:]] Ket End ------------------------------------------------------------------ /L(?#(|++3 0: abc *** Failers No match xyzabc No match xyzabc\>2 No match /x\dy\Dz/ x9yzz 0: x9yzz x0y+z 0: x0y+z *** Failers No match xyz No match xxy0z No match /x\sy\Sz/ x yzz 0: x yzz x y+z 0: x y+z *** Failers No match xyz No match xxyyz No match /x\wy\Wz/ xxy+z 0: xxy+z *** Failers No match xxy0z No match x+y+z No match /x.y/ x+y 0: x+y x-y 0: x-y *** Failers No match x\ny No match /x.y/s x+y 0: x+y x-y 0: x-y x\ny 0: x\x0ay /(a.b(?s)c.d|x.y)p.q/ a+bc+dp+q 0: a+bc+dp+q a+bc\ndp+q 0: a+bc\x0adp+q x\nyp+q 0: x\x0ayp+q *** Failers No match a\nbc\ndp+q No match a+bc\ndp\nq No match x\nyp\nq No match /a\d\z/ ba0 0: a0 *** Failers No match ba0\n No match ba0\ncd No match /a\d\z/m ba0 0: a0 *** Failers No match ba0\n No match ba0\ncd No match /a\d\Z/ ba0 0: a0 ba0\n 0: a0 *** Failers No match ba0\ncd No match /a\d\Z/m ba0 0: a0 ba0\n 0: a0 *** Failers No match ba0\ncd No match /a\d$/ ba0 0: a0 ba0\n 0: a0 *** Failers No match ba0\ncd No match /a\d$/m ba0 0: a0 ba0\n 0: a0 ba0\ncd 0: a0 *** Failers No match /abc/i abc 0: abc aBc 0: aBc ABC 0: ABC /[^a]/ abcd 0: b /ab?\w/ abz 0: abz 1: ab abbz 0: abb 1: ab azz 0: az /x{0,3}yz/ ayzq 0: yz axyzq 0: xyz axxyz 0: xxyz axxxyzq 0: xxxyz axxxxyzq 0: xxxyz *** Failers No match ax No match axx No match /x{3}yz/ axxxyzq 0: xxxyz axxxxyzq 0: xxxyz *** Failers No match ax No match axx No match ayzq No match axyzq No match axxyz No match /x{2,3}yz/ axxyz 0: xxyz axxxyzq 0: xxxyz axxxxyzq 0: xxxyz *** Failers No match ax No match axx No match ayzq No match axyzq No match /[^a]+/O bac 0: b bcdefax 0: bcdef 1: bcde 2: bcd 3: bc 4: b *** Failers 0: *** F 1: *** 2: *** 3: ** 4: * aaaaa No match /[^a]*/O bac 0: b 1: bcdefax 0: bcdef 1: bcde 2: bcd 3: bc 4: b 5: *** Failers 0: *** F 1: *** 2: *** 3: ** 4: * 5: aaaaa 0: /[^a]{3,5}/O xyz 0: xyz awxyza 0: wxyz 1: wxy abcdefa 0: bcdef 1: bcde 2: bcd abcdefghijk 0: bcdef 1: bcde 2: bcd *** Failers 0: *** F 1: *** 2: *** axya No match axa No match aaaaa No match /\d*/ 1234b567 0: 1234 xyz 0: /\D*/ a1234b567 0: a xyz 0: xyz /\d+/ ab1234c56 0: 1234 *** Failers No match xyz No match /\D+/ ab123c56 0: ab *** Failers 0: *** Failers 789 No match /\d?A/ 045ABC 0: 5A ABC 0: A *** Failers No match XYZ No match /\D?A/ ABC 0: A BAC 0: BA 9ABC 0: A *** Failers No match /a+/ aaaa 0: aaaa /^.*xyz/ xyz 0: xyz ggggggggxyz 0: ggggggggxyz /^.+xyz/ abcdxyz 0: abcdxyz axyz 0: axyz *** Failers No match xyz No match /^.?xyz/ xyz 0: xyz cxyz 0: cxyz /^\d{2,3}X/ 12X 0: 12X 123X 0: 123X *** Failers No match X No match 1X No match 1234X No match /^[abcd]\d/ a45 0: a4 b93 0: b9 c99z 0: c9 d04 0: d0 *** Failers No match e45 No match abcd No match abcd1234 No match 1234 No match /^[abcd]*\d/ a45 0: a4 b93 0: b9 c99z 0: c9 d04 0: d0 abcd1234 0: abcd1 1234 0: 1 *** Failers No match e45 No match abcd No match /^[abcd]+\d/ a45 0: a4 b93 0: b9 c99z 0: c9 d04 0: d0 abcd1234 0: abcd1 *** Failers No match 1234 No match e45 No match abcd No match /^a+X/ aX 0: aX aaX 0: aaX /^[abcd]?\d/ a45 0: a4 b93 0: b9 c99z 0: c9 d04 0: d0 1234 0: 1 *** Failers No match abcd1234 No match e45 No match /^[abcd]{2,3}\d/ ab45 0: ab4 bcd93 0: bcd9 *** Failers No match 1234 No match a36 No match abcd1234 No match ee45 No match /^(abc)*\d/ abc45 0: abc4 abcabcabc45 0: abcabcabc4 42xyz 0: 4 *** Failers No match /^(abc)+\d/ abc45 0: abc4 abcabcabc45 0: abcabcabc4 *** Failers No match 42xyz No match /^(abc)?\d/ abc45 0: abc4 42xyz 0: 4 *** Failers No match abcabcabc45 No match /^(abc){2,3}\d/ abcabc45 0: abcabc4 abcabcabc45 0: abcabcabc4 *** Failers No match abcabcabcabc45 No match abc45 No match 42xyz No match /1(abc|xyz)2(?1)3/ 1abc2abc3456 0: 1abc2abc3 1abc2xyz3456 0: 1abc2xyz3 /^(a*\w|ab)=(a*\w|ab)/ ab=ab 0: ab=ab 1: ab=a /^(a*\w|ab)=(?1)/ ab=ab 0: ab=ab 1: ab=a /^([^()]|\((?1)*\))*$/ abc 0: abc a(b)c 0: a(b)c a(b(c))d 0: a(b(c))d *** Failers) No match a(b(c)d No match /^>abc>([^()]|\((?1)*\))*abc>123abc>123abc>1(2)3abc>1(2)3abc>(1(2)3)abc>(1(2)3)a*)\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9876 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9 *** Failers No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /< (?: (?(R) \d++ | [^<>]*+) | (?R)) * >/x <> 0: <> 0: hij> 0: hij> hij> 0: def> 0: def> 0: <> *** Failers No match abcxyz 1 ^ ^ x 0: abcxyz 123abcxyz999 --->123abcxyz999 1 ^ ^ x 0: abcxyz /(ab|cd){3,4}/C ababab --->ababab +0 ^ (ab|cd){3,4} +1 ^ a +4 ^ c +2 ^^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +2 ^ ^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +2 ^ ^ b +3 ^ ^ | +12 ^ ^ +1 ^ ^ a +4 ^ ^ c 0: ababab abcdabcd --->abcdabcd +0 ^ (ab|cd){3,4} +1 ^ a +4 ^ c +2 ^^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +1 ^ ^ a +4 ^ ^ c +2 ^ ^ b +3 ^ ^ | +12 ^ ^ +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +12 ^ ^ 0: abcdabcd 1: abcdab abcdcdcdcdcd --->abcdcdcdcdcd +0 ^ (ab|cd){3,4} +1 ^ a +4 ^ c +2 ^^ b +3 ^ ^ | +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +12 ^ ^ +1 ^ ^ a +4 ^ ^ c +5 ^ ^ d +6 ^ ^ ) +12 ^ ^ 0: abcdcdcd 1: abcdcd /^abc/ abcdef 0: abc *** Failers No match abcdef\B No match /^(a*|xyz)/ bcd 0: aaabcd 0: aaa xyz 0: xyz 1: xyz\N 0: xyz *** Failers 0: bcd\N No match /xyz$/ xyz 0: xyz xyz\n 0: xyz *** Failers No match xyz\Z No match xyz\n\Z No match /xyz$/m xyz 0: xyz xyz\n 0: xyz abcxyz\npqr 0: xyz abcxyz\npqr\Z 0: xyz xyz\n\Z 0: xyz *** Failers No match xyz\Z No match /\Gabc/ abcdef 0: abc defabcxyz\>3 0: abc *** Failers No match defabcxyz No match /^abcdef/ ab\P Partial match: ab abcde\P Partial match: abcde abcdef\P 0: abcdef *** Failers No match abx\P No match /^a{2,4}\d+z/ a\P Partial match: a aa\P Partial match: aa aa2\P Partial match: aa2 aaa\P Partial match: aaa aaa23\P Partial match: aaa23 aaaa12345\P Partial match: aaaa12345 aa0z\P 0: aa0z aaaa4444444444444z\P 0: aaaa4444444444444z *** Failers No match az\P No match aaaaa\P No match a56\P No match /^abcdef/ abc\P Partial match: abc def\R 0: def /(?<=foo)bar/ xyzfo\P No match foob\P\>2 Partial match at offset 3: foob foobar...\R\P\>4 0: ar xyzfo\P No match foobar\>2 0: bar *** Failers No match xyzfo\P No match obar\R No match /(ab*(cd|ef))+X/ adfadadaklhlkalkajhlkjahdfasdfasdfladsfjkj\P\Z No match lkjhlkjhlkjhlkjhabbbbbbcdaefabbbbbbbefa\P\B\Z Partial match: abbbbbbcdaefabbbbbbbefa cdabbbbbbbb\P\R\B\Z Partial match: cdabbbbbbbb efabbbbbbbbbbbbbbbb\P\R\B\Z Partial match: efabbbbbbbbbbbbbbbb bbbbbbbbbbbbcdXyasdfadf\P\R\B\Z 0: bbbbbbbbbbbbcdX /(a|b)/SF>testsavedregex Compiled pattern written to testsavedregex Study data written to testsavedregex >>aaabxyzpqrrrabbxyyyypqAzz 0: aaabxyzpqrrrabbxyyyypqAzz >aaaabxyzpqrrrabbxyyyypqAzz 0: aaaabxyzpqrrrabbxyyyypqAzz >>>>abcxyzpqrrrabbxyyyypqAzz 0: abcxyzpqrrrabbxyyyypqAzz *** Failers No match abxyzpqrrabbxyyyypqAzz No match abxyzpqrrrrabbxyyyypqAzz No match abxyzpqrrrabxyyyypqAzz No match aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz No match aaaabcxyzzzzpqrrrabbbxyyypqAzz No match aaabcxyzpqrrrabbxyyyypqqqqqqqAzz No match /^(abc){1,2}zz/ abczz 0: abczz abcabczz 0: abcabczz *** Failers No match zz No match abcabcabczz No match >>abczz No match /^(b+?|a){1,2}?c/ bc 0: bc bbc 0: bbc bbbc 0: bbbc bac 0: bac bbac 0: bbac aac 0: aac abbbbbbbbbbbc 0: abbbbbbbbbbbc bbbbbbbbbbbac 0: bbbbbbbbbbbac *** Failers No match aaac No match abbbbbbbbbbbac No match /^(b+|a){1,2}c/ bc 0: bc bbc 0: bbc bbbc 0: bbbc bac 0: bac bbac 0: bbac aac 0: aac abbbbbbbbbbbc 0: abbbbbbbbbbbc bbbbbbbbbbbac 0: bbbbbbbbbbbac *** Failers No match aaac No match abbbbbbbbbbbac No match /^(b+|a){1,2}?bc/ bbc 0: bbc /^(b*|ba){1,2}?bc/ babc 0: babc bbabc 0: bbabc bababc 0: bababc *** Failers No match bababbc No match babababc No match /^(ba|b*){1,2}?bc/ babc 0: babc bbabc 0: bbabc bababc 0: bababc *** Failers No match bababbc No match babababc No match /^\ca\cA\c[\c{\c:/ \x01\x01\e;z 0: \x01\x01\x1b;z /^[ab\]cde]/ athing 0: a bthing 0: b ]thing 0: ] cthing 0: c dthing 0: d ething 0: e *** Failers No match fthing No match [thing No match \\thing No match /^[]cde]/ ]thing 0: ] cthing 0: c dthing 0: d ething 0: e *** Failers No match athing No match fthing No match /^[^ab\]cde]/ fthing 0: f [thing 0: [ \\thing 0: \ *** Failers 0: * athing No match bthing No match ]thing No match cthing No match dthing No match ething No match /^[^]cde]/ athing 0: a fthing 0: f *** Failers 0: * ]thing No match cthing No match dthing No match ething No match /^\/ 0: \x81 /^/ 0: \xff /^[0-9]+$/ 0 0: 0 1 0: 1 2 0: 2 3 0: 3 4 0: 4 5 0: 5 6 0: 6 7 0: 7 8 0: 8 9 0: 9 10 0: 10 100 0: 100 *** Failers No match abc No match /^.*nter/ enter 0: enter inter 0: inter uponter 0: uponter /^xxx[0-9]+$/ xxx0 0: xxx0 xxx1234 0: xxx1234 *** Failers No match xxx No match /^.+[0-9][0-9][0-9]$/ x123 0: x123 xx123 0: xx123 123456 0: 123456 *** Failers No match 123 No match x1234 0: x1234 /^.+?[0-9][0-9][0-9]$/ x123 0: x123 xx123 0: xx123 123456 0: 123456 *** Failers No match 123 No match x1234 0: x1234 /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/ abc!pqr=apquxz.ixr.zzz.ac.uk 0: abc!pqr=apquxz.ixr.zzz.ac.uk *** Failers No match !pqr=apquxz.ixr.zzz.ac.uk No match abc!=apquxz.ixr.zzz.ac.uk No match abc!pqr=apquxz:ixr.zzz.ac.uk No match abc!pqr=apquxz.ixr.zzz.ac.ukk No match /:/ Well, we need a colon: somewhere 0: : *** Fail if we don't No match /([\da-f:]+)$/i 0abc 0: 0abc abc 0: abc fed 0: fed E 0: E :: 0: :: 5f03:12C0::932e 0: 5f03:12C0::932e fed def 0: def Any old stuff 0: ff *** Failers No match 0zzz No match gzzz No match fed\x20 No match Any old rubbish No match /^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ .1.2.3 0: .1.2.3 A.12.123.0 0: A.12.123.0 *** Failers No match .1.2.3333 No match 1.2.3 No match 1234.2.3 No match /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/ 1 IN SOA non-sp1 non-sp2( 0: 1 IN SOA non-sp1 non-sp2( 1 IN SOA non-sp1 non-sp2 ( 0: 1 IN SOA non-sp1 non-sp2 ( *** Failers No match 1IN SOA non-sp1 non-sp2( No match /^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/ a. 0: a. Z. 0: Z. 2. 0: 2. ab-c.pq-r. 0: ab-c.pq-r. sxk.zzz.ac.uk. 0: sxk.zzz.ac.uk. x-.y-. 0: x-.y-. *** Failers No match -abc.peq. No match /^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/ *.a 0: *.a *.b0-a 0: *.b0-a *.c3-b.c 0: *.c3-b.c *.c-a.b-c 0: *.c-a.b-c *** Failers No match *.0 No match *.a- No match *.a-b.c- No match *.c-a.0-c No match /^(?=ab(de))(abd)(e)/ abde 0: abde /^(?!(ab)de|x)(abd)(f)/ abdf 0: abdf /^(?=(ab(cd)))(ab)/ abcd 0: ab /^[\da-f](\.[\da-f])*$/i a.b.c.d 0: a.b.c.d A.B.C.D 0: A.B.C.D a.b.c.1.2.3.C 0: a.b.c.1.2.3.C /^\".*\"\s*(;.*)?$/ \"1234\" 0: "1234" \"abcd\" ; 0: "abcd" ; \"\" ; rhubarb 0: "" ; rhubarb *** Failers No match \"1234\" : things No match /^$/ \ 0: *** Failers No match / ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/x ab c 0: ab c *** Failers No match abc No match ab cde No match /(?x) ^ a (?# begins with a) b\sc (?# then b c) $ (?# then end)/ ab c 0: ab c *** Failers No match abc No match ab cde No match /^ a\ b[c ]d $/x a bcd 0: a bcd a b d 0: a b d *** Failers No match abcd No match ab d No match /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/ abcdefhijklm 0: abcdefhijklm /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/ abcdefhijklm 0: abcdefhijklm /^[\w][\W][\s][\S][\d][\D][\b][\n][\c]][\022]/ a+ Z0+\x08\n\x1d\x12 0: a+ Z0+\x08\x0a\x1d\x12 /^[.^$|()*+?{,}]+/ .^\$(*+)|{?,?} 0: .^$(*+)|{?,?} /^a*\w/ z 0: z az 0: az 1: a aaaz 0: aaaz 1: aaa 2: aa 3: a a 0: a aa 0: aa 1: a aaaa 0: aaaa 1: aaa 2: aa 3: a a+ 0: a aa+ 0: aa 1: a /^a*?\w/ z 0: z az 0: az 1: a aaaz 0: aaaz 1: aaa 2: aa 3: a a 0: a aa 0: aa 1: a aaaa 0: aaaa 1: aaa 2: aa 3: a a+ 0: a aa+ 0: aa 1: a /^a+\w/ az 0: az aaaz 0: aaaz 1: aaa 2: aa aa 0: aa aaaa 0: aaaa 1: aaa 2: aa aa+ 0: aa /^a+?\w/ az 0: az aaaz 0: aaaz 1: aaa 2: aa aa 0: aa aaaa 0: aaaa 1: aaa 2: aa aa+ 0: aa /^\d{8}\w{2,}/ 1234567890 0: 1234567890 12345678ab 0: 12345678ab 12345678__ 0: 12345678__ *** Failers No match 1234567 No match /^[aeiou\d]{4,5}$/ uoie 0: uoie 1234 0: 1234 12345 0: 12345 aaaaa 0: aaaaa *** Failers No match 123456 No match /^[aeiou\d]{4,5}?/ uoie 0: uoie 1234 0: 1234 12345 0: 12345 1: 1234 aaaaa 0: aaaaa 1: aaaa 123456 0: 12345 1: 1234 /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/ From abcd Mon Sep 01 12:33:02 1997 0: From abcd Mon Sep 01 12:33 /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/ From abcd Mon Sep 01 12:33:02 1997 0: From abcd Mon Sep 01 12:33 From abcd Mon Sep 1 12:33:02 1997 0: From abcd Mon Sep 1 12:33 *** Failers No match From abcd Sep 01 12:33:02 1997 No match /^12.34/s 12\n34 0: 12\x0a34 12\r34 0: 12\x0d34 /\w+(?=\t)/ the quick brown\t fox 0: brown /foo(?!bar)(.*)/ foobar is foolish see? 0: foolish see? /(?:(?!foo)...|^.{0,2})bar(.*)/ foobar crowbar etc 0: rowbar etc barrel 0: barrel 2barrel 0: 2barrel A barrel 0: A barrel /^(\D*)(?=\d)(?!123)/ abc456 0: abc *** Failers No match abc123 No match /^1234(?# test newlines inside)/ 1234 0: 1234 /^1234 #comment in extended re /x 1234 0: 1234 /#rhubarb abcd/x abcd 0: abcd /^abcd#rhubarb/x abcd 0: abcd /(?!^)abc/ the abc 0: abc *** Failers No match abc No match /(?=^)abc/ abc 0: abc *** Failers No match the abc No match /^[ab]{1,3}(ab*|b)/O aabbbbb 0: aabbbbb 1: aabbbb 2: aabbb 3: aabb 4: aab 5: aa /^[ab]{1,3}?(ab*|b)/O aabbbbb 0: aabbbbb 1: aabbbb 2: aabbb 3: aabb 4: aab 5: aa /^[ab]{1,3}?(ab*?|b)/O aabbbbb 0: aabbbbb 1: aabbbb 2: aabbb 3: aabb 4: aab 5: aa /^[ab]{1,3}(ab*?|b)/O aabbbbb 0: aabbbbb 1: aabbbb 2: aabbb 3: aabb 4: aab 5: aa / (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional leading comment (?: (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # one word, optionally followed by.... (?: [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] | # atom and space parts, or... \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) | # comments, or... " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote # quoted strings )* < (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # leading < (?: @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* , (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* )* # further okay, if led by comma : # closing colon (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) # initial word (?: (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | " (?: # opening quote... [^\\\x80-\xff\n\015"] # Anything except backslash and quote | # or \\ [^\x80-\xff] # Escaped something (something != CR) )* " # closing quote ) )* # further okay, if led by a period (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* @ (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # initial subdomain (?: # (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* \. # if led by a period... (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) # ...further okay )* # address spec (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* > # trailing > # name and address ) (?: [\040\t] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] | \( (?: [^\\\x80-\xff\n\015()] | \\ [^\x80-\xff] )* \) )* \) )* # optional trailing comment /x Alan Other 0: Alan Other 0: user@dom.ain 1: user@dom user\@dom.ain 0: user@dom.ain 1: user@dom \"A. Other\" (a comment) 0: "A. Other" (a comment) 1: "A. Other" 2: "A. Other" A. Other (a comment) 0: Other (a comment) 1: Other 2: Other \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay 1: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re A missing angle @,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address | # or (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) # leading word [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # "normal" atoms and or spaces (?: (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) | " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " ) # "special" comment or quoted string [^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037] * # more "normal" )* < [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # < (?: @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* (?: , [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* )* # additional domains : [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )? # optional route (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom # Atom | # or " # " [^\\\x80-\xff\n\015"] * # normal (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015"] * )* # ( special normal* )* " # " # Quoted string ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # additional words )* @ [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments (?: \. [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. (?: [^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+ # some number of atom characters... (?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]) # ..not followed by something that could be part of an atom | \[ # [ (?: [^\\\x80-\xff\n\015\[\]] | \\ [^\x80-\xff] )* # stuff \] # ] ) [\040\t]* # Nab whitespace. (?: \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: # ( (?: \\ [^\x80-\xff] | \( # ( [^\\\x80-\xff\n\015()] * # normal* (?: \\ [^\x80-\xff] [^\\\x80-\xff\n\015()] * )* # (special normal*)* \) # ) ) # special [^\\\x80-\xff\n\015()] * # normal* )* # )* \) # ) [\040\t]* )* # If comment found, allow more spaces. # optional trailing comments )* # address spec > # > # name and address ) /x Alan Other 0: Alan Other 0: user@dom.ain 1: user@dom user\@dom.ain 0: user@dom.ain 1: user@dom \"A. Other\" (a comment) 0: "A. Other" A. Other (a comment) 0: Other \"/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/\"\@x400-re.lay 0: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re.lay 1: "/s=user/ou=host/o=place/prmd=uu.yy/admd= /c=gb/"@x400-re A missing angle a\rb 0: a\x0db *** Failers No match a\nb No match /abc$/ abc 0: abc abc\n 0: abc *** Failers No match abc\ndef No match /(abc)\123/ abc\x53 0: abcS /(abc)\223/ abc\x93 0: abc\x93 /(abc)\323/ abc\xd3 0: abc\xd3 /(abc)\100/ abc\x40 0: abc@ abc\100 0: abc@ /(abc)\1000/ abc\x400 0: abc@0 abc\x40\x30 0: abc@0 abc\1000 0: abc@0 abc\100\x30 0: abc@0 abc\100\060 0: abc@0 abc\100\60 0: abc@0 /^A\8B\9C$/ A8B9C 0: A8B9C *** Failers No match A\08B\09C No match /^[A\8B\9C]+$/ A8B9C 0: A8B9C *** Failers No match A8B9C\x00 No match /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12\123/ abcdefghijk\12S 0: abcdefghijk\x0aS /ab\idef/ abidef 0: abidef /a{0}bc/ bc 0: bc /(a|(bc)){0,0}?xyz/ xyz 0: xyz /abc[\10]de/ abc\010de 0: abc\x08de /abc[\1]de/ abc\1de 0: abc\x01de /(abc)[\1]de/ abc\1de 0: abc\x01de /(?s)a.b/ a\nb 0: a\x0ab /^([^a])([^\b])([^c]*)([^d]{3,4})/ baNOTccccd 0: baNOTcccc 1: baNOTccc 2: baNOTcc 3: baNOTc baNOTcccd 0: baNOTccc 1: baNOTcc 2: baNOTc baNOTccd 0: baNOTcc 1: baNOTc bacccd 0: baccc *** Failers 0: *** Failers 1: *** Failer 2: *** Faile 3: *** Fail 4: *** Fai 5: *** Fa anything No match b\bc No match baccd No match /[^a]/ Abc 0: A /[^a]/i Abc 0: b /[^a]+/ AAAaAbc 0: AAA /[^a]+/i AAAaAbc 0: bc /[^a]+/ bbb\nccc 0: bbb\x0accc /[^k]$/ abc 0: c *** Failers 0: s abk No match /[^k]{2,3}$/ abc 0: abc kbc 0: bc kabc 0: abc *** Failers 0: ers abk No match akb No match akk No match /^\d{8,}\@.+[^k]$/ 12345678\@a.b.c.d 0: 12345678@a.b.c.d 123456789\@x.y.z 0: 123456789@x.y.z *** Failers No match 12345678\@x.y.uk No match 1234567\@a.b.c.d No match /[^a]/ aaaabcd 0: b aaAabcd 0: A /[^a]/i aaaabcd 0: b aaAabcd 0: b /[^az]/ aaaabcd 0: b aaAabcd 0: A /[^az]/i aaaabcd 0: b aaAabcd 0: b /\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377/ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377 0: \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff /P[^*]TAIRE[^*]{1,6}?LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx 0: PSTAIREISLL /P[^*]TAIRE[^*]{1,}?LL/ xxxxxxxxxxxPSTAIREISLLxxxxxxxxx 0: PSTAIREISLL /(\.\d\d[1-9]?)\d+/ 1.230003938 0: .230003938 1.875000282 0: .875000282 1.235 0: .235 /(\.\d\d((?=0)|\d(?=\d)))/ 1.230003938 0: .230 1: .23 1.875000282 0: .875 *** Failers No match 1.235 No match /a(?)b/ ab 0: ab /\b(foo)\s+(\w+)/i Food is on the foo table 0: foo table /foo(.*)bar/ The food is under the bar in the barn. 0: food is under the bar in the bar 1: food is under the bar /foo(.*?)bar/ The food is under the bar in the barn. 0: food is under the bar in the bar 1: food is under the bar /(.*)(\d*)/O I have 2 numbers: 53147 Matched, but offsets vector is too small to show all matches 0: I have 2 numbers: 53147 1: I have 2 numbers: 5314 2: I have 2 numbers: 531 3: I have 2 numbers: 53 4: I have 2 numbers: 5 5: I have 2 numbers: 6: I have 2 numbers: 7: I have 2 numbers 8: I have 2 number 9: I have 2 numbe 10: I have 2 numb 11: I have 2 num 12: I have 2 nu 13: I have 2 n 14: I have 2 15: I have 2 16: I have 17: I have 18: I hav 19: I ha 20: I h 21: I /(.*)(\d+)/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 /(.*?)(\d*)/O I have 2 numbers: 53147 Matched, but offsets vector is too small to show all matches 0: I have 2 numbers: 53147 1: I have 2 numbers: 5314 2: I have 2 numbers: 531 3: I have 2 numbers: 53 4: I have 2 numbers: 5 5: I have 2 numbers: 6: I have 2 numbers: 7: I have 2 numbers 8: I have 2 number 9: I have 2 numbe 10: I have 2 numb 11: I have 2 num 12: I have 2 nu 13: I have 2 n 14: I have 2 15: I have 2 16: I have 17: I have 18: I hav 19: I ha 20: I h 21: I /(.*?)(\d+)/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 1: I have 2 /(.*)(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 /(.*?)(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 /(.*)\b(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 /(.*\D)(\d+)$/ I have 2 numbers: 53147 0: I have 2 numbers: 53147 /^\D*(?!123)/ ABC123 0: AB 1: A 2: /^(\D*)(?=\d)(?!123)/ ABC445 0: ABC *** Failers No match ABC123 No match /^[W-]46]/ W46]789 0: W46] -46]789 0: -46] *** Failers No match Wall No match Zebra No match 42 No match [abcd] No match ]abcd[ No match /^[W-\]46]/ W46]789 0: W Wall 0: W Zebra 0: Z Xylophone 0: X 42 0: 4 [abcd] 0: [ ]abcd[ 0: ] \\backslash 0: \ *** Failers No match -46]789 No match well No match /\d\d\/\d\d\/\d\d\d\d/ 01/01/2000 0: 01/01/2000 /word (?:[a-zA-Z0-9]+ ){0,10}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark No match /word (?:[a-zA-Z0-9]+ ){0,300}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope No match /^(a){0,0}/ bcd 0: abc 0: aab 0: /^(a){0,1}/ bcd 0: abc 0: a 1: aab 0: a 1: /^(a){0,2}/ bcd 0: abc 0: a 1: aab 0: aa 1: a 2: /^(a){0,3}/ bcd 0: abc 0: a 1: aab 0: aa 1: a 2: aaa 0: aaa 1: aa 2: a 3: /^(a){0,}/ bcd 0: abc 0: a 1: aab 0: aa 1: a 2: aaa 0: aaa 1: aa 2: a 3: aaaaaaaa 0: aaaaaaaa 1: aaaaaaa 2: aaaaaa 3: aaaaa 4: aaaa 5: aaa 6: aa 7: a 8: /^(a){1,1}/ bcd No match abc 0: a aab 0: a /^(a){1,2}/ bcd No match abc 0: a aab 0: aa 1: a /^(a){1,3}/ bcd No match abc 0: a aab 0: aa 1: a aaa 0: aaa 1: aa 2: a /^(a){1,}/ bcd No match abc 0: a aab 0: aa 1: a aaa 0: aaa 1: aa 2: a aaaaaaaa 0: aaaaaaaa 1: aaaaaaa 2: aaaaaa 3: aaaaa 4: aaaa 5: aaa 6: aa 7: a /.*\.gif/ borfle\nbib.gif\nno 0: bib.gif /.{0,}\.gif/ borfle\nbib.gif\nno 0: bib.gif /.*\.gif/m borfle\nbib.gif\nno 0: bib.gif /.*\.gif/s borfle\nbib.gif\nno 0: borfle\x0abib.gif /.*\.gif/ms borfle\nbib.gif\nno 0: borfle\x0abib.gif /.*$/ borfle\nbib.gif\nno 0: no /.*$/m borfle\nbib.gif\nno 0: borfle /.*$/s borfle\nbib.gif\nno 0: borfle\x0abib.gif\x0ano /.*$/ms borfle\nbib.gif\nno 0: borfle\x0abib.gif\x0ano 1: borfle\x0abib.gif 2: borfle /.*$/ borfle\nbib.gif\nno\n 0: no /.*$/m borfle\nbib.gif\nno\n 0: borfle /.*$/s borfle\nbib.gif\nno\n 0: borfle\x0abib.gif\x0ano\x0a 1: borfle\x0abib.gif\x0ano /.*$/ms borfle\nbib.gif\nno\n 0: borfle\x0abib.gif\x0ano\x0a 1: borfle\x0abib.gif\x0ano 2: borfle\x0abib.gif 3: borfle /(.*X|^B)/ abcde\n1234Xyz 0: 1234X BarFoo 0: B *** Failers No match abcde\nBar No match /(.*X|^B)/m abcde\n1234Xyz 0: 1234X BarFoo 0: B abcde\nBar 0: B /(.*X|^B)/s abcde\n1234Xyz 0: abcde\x0a1234X BarFoo 0: B *** Failers No match abcde\nBar No match /(.*X|^B)/ms abcde\n1234Xyz 0: abcde\x0a1234X BarFoo 0: B abcde\nBar 0: B /(?s)(.*X|^B)/ abcde\n1234Xyz 0: abcde\x0a1234X BarFoo 0: B *** Failers No match abcde\nBar No match /(?s:.*X|^B)/ abcde\n1234Xyz 0: abcde\x0a1234X BarFoo 0: B *** Failers No match abcde\nBar No match /^.*B/ **** Failers No match abc\nB No match /(?s)^.*B/ abc\nB 0: abc\x0aB /(?m)^.*B/ abc\nB 0: B /(?ms)^.*B/ abc\nB 0: abc\x0aB /(?ms)^B/ abc\nB 0: B /(?s)B$/ B\n 0: B /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ 123456654321 0: 123456654321 /^\d\d\d\d\d\d\d\d\d\d\d\d/ 123456654321 0: 123456654321 /^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/ 123456654321 0: 123456654321 /^[abc]{12}/ abcabcabcabc 0: abcabcabcabc /^[a-c]{12}/ abcabcabcabc 0: abcabcabcabc /^(a|b|c){12}/ abcabcabcabc 0: abcabcabcabc /^[abcdefghijklmnopqrstuvwxy0123456789]/ n 0: n *** Failers No match z No match /abcde{0,0}/ abcd 0: abcd *** Failers No match abce No match /ab[cd]{0,0}e/ abe 0: abe *** Failers No match abcde No match /ab(c){0,0}d/ abd 0: abd *** Failers No match abcd No match /a(b*)/ a 0: a ab 0: ab abbbb 0: abbbb *** Failers 0: a bbbbb No match /ab\d{0}e/ abe 0: abe *** Failers No match ab1e No match /"([^\\"]+|\\.)*"/ the \"quick\" brown fox 0: "quick" \"the \\\"quick\\\" brown fox\" 0: "the \"quick\" brown fox" /.*?/g+ abc 0: abc 0+ 1: ab 2: a 3: 0: 0+ /\b/g+ abc 0: 0+ abc 0: 0+ /\b/+g abc 0: 0+ abc 0: 0+ //g abc 0: 0: 0: 0: /]{0,})>]{0,})>([\d]{0,}\.)(.*)((
    ([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/is 43.
    Word Processor
    (N-1286)
    Lega lstaff.comCA - Statewide 0: 43.Word Processor
    (N-1286)
    Lega lstaff.comCA - Statewide /a[^a]b/ acb 0: acb a\nb 0: a\x0ab /a.b/ acb 0: acb *** Failers No match a\nb No match /a[^a]b/s acb 0: acb a\nb 0: a\x0ab /a.b/s acb 0: acb a\nb 0: a\x0ab /^(b+?|a){1,2}?c/ bac 0: bac bbac 0: bbac bbbac 0: bbbac bbbbac 0: bbbbac bbbbbac 0: bbbbbac /^(b+|a){1,2}?c/ bac 0: bac bbac 0: bbac bbbac 0: bbbac bbbbac 0: bbbbac bbbbbac 0: bbbbbac /(?!\A)x/m x\nb\n No match a\bx\n 0: x /\x0{ab}/ \0{ab} 0: \x00{ab} /(A|B)*?CD/ CD 0: CD /(A|B)*CD/ CD 0: CD /(?.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/ No match "(?>.*/)foo" /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo 0: /this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo /(?>(\.\d\d[1-9]?))\d+/ 1.230003938 0: .230003938 1.875000282 0: .875000282 *** Failers No match 1.235 No match /^((?>\w+)|(?>\s+))*$/ now is the time for all good men to come to the aid of the party 0: now is the time for all good men to come to the aid of the party *** Failers No match this is not a line with only words and spaces! No match /(\d+)(\w)/ 12345a 0: 12345a 1: 12345 2: 1234 3: 123 4: 12 12345+ 0: 12345 1: 1234 2: 123 3: 12 /((?>\d+))(\w)/ 12345a 0: 12345a *** Failers No match 12345+ No match /(?>a+)b/ aaab 0: aaab /((?>a+)b)/ aaab 0: aaab /(?>(a+))b/ aaab 0: aaab /(?>b)+/ aaabbbccc 0: bbb 1: bb 2: b /(?>a+|b+|c+)*c/ aaabbbbccccd 0: aaabbbbcccc 1: aaabbbbc /(a+|b+|c+)*c/ aaabbbbccccd 0: aaabbbbcccc 1: aaabbbbccc 2: aaabbbbcc 3: aaabbbbc /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x 0: abc(ade)ufh()()x 1: abc(ade)ufh()() 2: abc(ade)ufh() 3: abc(ade)ufh 4: abc(ade) 5: abc /\(((?>[^()]+)|\([^()]+\))+\)/ (abc) 0: (abc) (abc(def)xyz) 0: (abc(def)xyz) *** Failers No match ((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /a(?-i)b/i ab 0: ab Ab 0: Ab *** Failers No match aB No match AB No match /(a (?x)b c)d e/ a bcd e 0: a bcd e *** Failers No match a b cd e No match abcd e No match a bcde No match /(a b(?x)c d (?-x)e f)/ a bcde f 0: a bcde f *** Failers No match abcdef No match /(a(?i)b)c/ abc 0: abc aBc 0: aBc *** Failers No match abC No match aBC No match Abc No match ABc No match ABC No match AbC No match /a(?i:b)c/ abc 0: abc aBc 0: aBc *** Failers No match ABC No match abC No match aBC No match /a(?i:b)*c/ aBc 0: aBc aBBc 0: aBBc *** Failers No match aBC No match aBBC No match /a(?=b(?i)c)\w\wd/ abcd 0: abcd abCd 0: abCd *** Failers No match aBCd No match abcD No match /(?s-i:more.*than).*million/i more than million 0: more than million more than MILLION 0: more than MILLION more \n than Million 0: more \x0a than Million *** Failers No match MORE THAN MILLION No match more \n than \n million No match /(?:(?s-i)more.*than).*million/i more than million 0: more than million more than MILLION 0: more than MILLION more \n than Million 0: more \x0a than Million *** Failers No match MORE THAN MILLION No match more \n than \n million No match /(?>a(?i)b+)+c/ abc 0: abc aBbc 0: aBbc aBBc 0: aBBc *** Failers No match Abc No match abAb No match abbC No match /(?=a(?i)b)\w\wc/ abc 0: abc aBc 0: aBc *** Failers No match Ab No match abC No match aBC No match /(?<=a(?i)b)(\w\w)c/ abxxc 0: xxc aBxxc 0: xxc *** Failers No match Abxxc No match ABxxc No match abxxC No match /^(?(?=abc)\w{3}:|\d\d)$/ abc: 0: abc: 12 0: 12 *** Failers No match 123 No match xyz No match /^(?(?!abc)\d\d|\w{3}:)$/ abc: 0: abc: 12 0: 12 *** Failers No match 123 No match xyz No match /(?(?<=foo)bar|cat)/ foobar 0: bar cat 0: cat fcat 0: cat focat 0: cat *** Failers No match foocat No match /(?(?a*)*/ a 0: a 1: aa 0: aa 1: aaaa 0: aaaa 1: /(abc|)+/ abc 0: abc 1: abcabc 0: abcabc 1: abc 2: abcabcabc 0: abcabcabc 1: abcabc 2: abc 3: xyz 0: /([a]*)*/ a 0: a 1: aaaaa 0: aaaaa 1: aaaa 2: aaa 3: aa 4: a 5: /([ab]*)*/ a 0: a 1: b 0: b 1: ababab 0: ababab 1: ababa 2: abab 3: aba 4: ab 5: a 6: aaaabcde 0: aaaab 1: aaaa 2: aaa 3: aa 4: a 5: bbbb 0: bbbb 1: bbb 2: bb 3: b 4: /([^a]*)*/ b 0: b 1: bbbb 0: bbbb 1: bbb 2: bb 3: b 4: aaa 0: /([^ab]*)*/ cccc 0: cccc 1: ccc 2: cc 3: c 4: abab 0: /([a]*?)*/ a 0: a 1: aaaa 0: aaaa 1: aaa 2: aa 3: a 4: /([ab]*?)*/ a 0: a 1: b 0: b 1: abab 0: abab 1: aba 2: ab 3: a 4: baba 0: baba 1: bab 2: ba 3: b 4: /([^a]*?)*/ b 0: b 1: bbbb 0: bbbb 1: bbb 2: bb 3: b 4: aaa 0: /([^ab]*?)*/ c 0: c 1: cccc 0: cccc 1: ccc 2: cc 3: c 4: baba 0: /(?>a*)*/ a 0: a 1: aaabcde 0: aaa 1: /((?>a*))*/ aaaaa 0: aaaaa 1: aabbaa 0: aa 1: /((?>a*?))*/ aaaaa 0: aaaaa 1: aabbaa 0: aa 1: /(?(?=[^a-z]+[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) /x 12-sep-98 0: 12-sep-98 12-09-98 0: 12-09-98 *** Failers No match sep-12-98 No match /(?i:saturday|sunday)/ saturday 0: saturday sunday 0: sunday Saturday 0: Saturday Sunday 0: Sunday SATURDAY 0: SATURDAY SUNDAY 0: SUNDAY SunDay 0: SunDay /(a(?i)bc|BB)x/ abcx 0: abcx aBCx 0: aBCx bbx 0: bbx BBx 0: BBx *** Failers No match abcX No match aBCX No match bbX No match BBX No match /^([ab](?i)[cd]|[ef])/ ac 0: ac aC 0: aC bD 0: bD elephant 0: e Europe 0: E frog 0: f France 0: F *** Failers No match Africa No match /^(ab|a(?i)[b-c](?m-i)d|x(?i)y|z)/ ab 0: ab aBd 0: aBd xy 0: xy xY 0: xY zebra 0: z Zambesi 0: Z *** Failers No match aCD No match XY No match /(?<=foo\n)^bar/m foo\nbar 0: bar *** Failers No match bar No match baz\nbar No match /(?<=(?]&/ <&OUT 0: <& /(?:(f)(o)(o)|(b)(a)(r))*/ foobar 0: foobar 1: foo 2: /(?<=a)b/ ab 0: b *** Failers No match cb No match b No match /(?a+)ab/ /(?>a+)b/ aaab 0: aaab /([[:]+)/ a:[b]: 0: :[ /([[=]+)/ a=[b]= 0: =[ /([[.]+)/ a.[b]. 0: .[ /((?>a+)b)/ aaab 0: aaab /(?>(a+))b/ aaab 0: aaab /((?>[^()]+)|\([^()]*\))+/ ((abc(ade)ufh()()x 0: abc(ade)ufh()()x 1: abc(ade)ufh()() 2: abc(ade)ufh() 3: abc(ade)ufh 4: abc(ade) 5: abc /a\Z/ *** Failers No match aaab No match a\nb\n No match /b\Z/ a\nb\n 0: b /b\z/ /b\Z/ a\nb 0: b /b\z/ a\nb 0: b *** Failers No match /(?>.*)(?<=(abcd|wxyz))/ alphabetabcd 0: alphabetabcd endingwxyz 0: endingwxyz *** Failers No match a rather long string that doesn't end with one of them No match /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/ word cat dog elephant mussel cow horse canary baboon snake shark otherword 0: word cat dog elephant mussel cow horse canary baboon snake shark otherword word cat dog elephant mussel cow horse canary baboon snake shark No match /word (?>[a-zA-Z0-9]+ ){0,30}otherword/ word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope No match /(?<=\d{3}(?!999))foo/ 999foo 0: foo 123999foo 0: foo *** Failers No match 123abcfoo No match /(?<=(?!...999)\d{3})foo/ 999foo 0: foo 123999foo 0: foo *** Failers No match 123abcfoo No match /(?<=\d{3}(?!999)...)foo/ 123abcfoo 0: foo 123456foo 0: foo *** Failers No match 123999foo No match /(?<=\d{3}...)(?Z)+|A)*/ ZABCDEFG 0: ZA 1: Z 2: /((?>)+|A)*/ ZABCDEFG 0: /a*/g abbab 0: a 0: 0: 0: a 0: 0: /^[\d-a]/ abcde 0: a -things 0: - 0digit 0: 0 *** Failers No match bcdef No match /[[:space:]]+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09\x0a\x0c\x0d\x0b /[[:blank:]]+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09 /[\s]+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09\x0a\x0c\x0d\x0b /\s+/ > \x09\x0a\x0c\x0d\x0b< 0: \x09\x0a\x0c\x0d\x0b /a b/x ab 0: ab /(?!\A)x/m a\nxb\n 0: x /(?!^)x/m a\nxb\n No match /abc\Qabc\Eabc/ abcabcabc 0: abcabcabc /abc\Q(*+|\Eabc/ abc(*+|abc 0: abc(*+|abc / abc\Q abc\Eabc/x abc abcabc 0: abc abcabc *** Failers No match abcabcabc No match /abc#comment \Q#not comment literal\E/x abc#not comment\n literal 0: abc#not comment\x0a literal /abc#comment \Q#not comment literal/x abc#not comment\n literal 0: abc#not comment\x0a literal /abc#comment \Q#not comment literal\E #more comment /x abc#not comment\n literal 0: abc#not comment\x0a literal /abc#comment \Q#not comment literal\E #more comment/x abc#not comment\n literal 0: abc#not comment\x0a literal /\Qabc\$xyz\E/ abc\\\$xyz 0: abc\$xyz /\Qabc\E\$\Qxyz\E/ abc\$xyz 0: abc$xyz /\Gabc/ abc 0: abc *** Failers No match xyzabc No match /\Gabc./g abc1abc2xyzabc3 0: abc1 0: abc2 /abc./g abc1abc2xyzabc3 0: abc1 0: abc2 0: abc3 /a(?x: b c )d/ XabcdY 0: abcd *** Failers No match Xa b c d Y No match /((?x)x y z | a b c)/ XabcY 0: abc AxyzB 0: xyz /(?i)AB(?-i)C/ XabCY 0: abC *** Failers No match XabcY No match /((?i)AB(?-i)C|D)E/ abCE 0: abCE DE 0: DE *** Failers No match abcE No match abCe No match dE No match De No match /[z\Qa-d]\E]/ z 0: z a 0: a - 0: - d 0: d ] 0: ] *** Failers 0: a b No match /[\z\C]/ z 0: z C 0: C /\M/ M 0: M /(a+)*b/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match /(?i)reg(?:ul(?:[a]|ae)r|ex)/ REGular 0: REGular regulaer 0: regulaer Regex 0: Regex regulr 0: regul\xe4r /[--]+/ 0: \xc5\xe6\xe5\xe4\xe0 0: \xc5\xe6\xe5\xe4\xff 0: \xc5\xe6\xe5\xe4\xc0 0: \xc5\xe6\xe5\xe4\xdf /(?<=Z)X./ \x84XAZXB 0: XB /^(?(2)a|(1)(2))+$/ 123a Error -17 (backreference condition or recursion test not supported for DFA matching) /(?<=a|bbbb)c/ ac 0: c bbbbc 0: c /abc/SS>testsavedregex Compiled pattern written to testsavedregex testsavedregex Compiled pattern written to testsavedregex testsavedregex Compiled pattern written to testsavedregex Study data written to testsavedregex testsavedregex Compiled pattern written to testsavedregex Study data written to testsavedregex 0: abc xyz\r\nabc\ 0: abc xyz\rabc\ 0: abc xyz\r\nabc\ 0: abc ** Failers No match xyz\nabc\ No match xyz\r\nabc\ No match xyz\nabc\ No match xyz\rabc\ No match xyz\rabc\ No match /abc$/m xyzabc 0: abc xyzabc\n 0: abc xyzabc\npqr 0: abc xyzabc\r\ 0: abc xyzabc\rpqr\ 0: abc xyzabc\r\n\ 0: abc xyzabc\r\npqr\ 0: abc ** Failers No match xyzabc\r No match xyzabc\rpqr No match xyzabc\r\n No match xyzabc\r\npqr No match /^abc/m xyz\rabcdef 0: abc xyz\nabcdef\ 0: abc ** Failers No match xyz\nabcdef No match /^abc/m xyz\nabcdef 0: abc xyz\rabcdef\ 0: abc ** Failers No match xyz\rabcdef No match /^abc/m xyz\r\nabcdef 0: abc xyz\rabcdef\ 0: abc ** Failers No match xyz\rabcdef No match /.*/ abc\ndef 0: abc abc\rdef 0: abc\x0ddef abc\r\ndef 0: abc\x0d \abc\ndef 0: abc\x0adef \abc\rdef 0: abc \abc\r\ndef 0: abc \abc\ndef 0: abc\x0adef \abc\rdef 0: abc\x0ddef \abc\r\ndef 0: abc /\w+(.)(.)?def/s abc\ndef 0: abc\x0adef abc\rdef 0: abc\x0ddef abc\r\ndef 0: abc\x0d\x0adef /^\w+=.*(\\\n.*)*/ abc=xyz\\\npqr 0: abc=xyz\\x0apqr 1: abc=xyz\\x0apq 2: abc=xyz\\x0ap 3: abc=xyz\\x0a 4: abc=xyz\ 5: abc=xyz 6: abc=xy 7: abc=x 8: abc= /^(a()*)*/ aaaa 0: aaaa 1: aaa 2: aa 3: a 4: /^(?:a(?:(?:))*)*/ aaaa 0: aaaa 1: aaa 2: aa 3: a 4: /^(a()+)+/ aaaa 0: aaaa 1: aaa 2: aa 3: a /^(?:a(?:(?:))+)+/ aaaa 0: aaaa 1: aaa 2: aa 3: a /(a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /(?>a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /(?:a|)*\d/ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa No match aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4 /^a.b/ a\rb 0: a\x0db a\nb\ 0: a\x0ab ** Failers No match a\nb No match a\nb\ No match a\rb\ No match a\rb\ No match /^abc./mgx abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x85abc7 JUNK 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc7 /abc.$/mgx abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x85 abc9 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc9 /^a\Rb/ a\nb 0: a\x0ab a\rb 0: a\x0db a\r\nb 0: a\x0d\x0ab a\x0bb 0: a\x0bb a\x0cb 0: a\x0cb a\x85b 0: a\x85b ** Failers No match a\n\rb No match /^a\R*b/ ab 0: ab a\nb 0: a\x0ab a\rb 0: a\x0db a\r\nb 0: a\x0d\x0ab a\x0bb 0: a\x0bb a\x0cb 0: a\x0cb a\x85b 0: a\x85b a\n\rb 0: a\x0a\x0db a\n\r\x85\x0cb 0: a\x0a\x0d\x85\x0cb /^a\R+b/ a\nb 0: a\x0ab a\rb 0: a\x0db a\r\nb 0: a\x0d\x0ab a\x0bb 0: a\x0bb a\x0cb 0: a\x0cb a\x85b 0: a\x85b a\n\rb 0: a\x0a\x0db a\n\r\x85\x0cb 0: a\x0a\x0d\x85\x0cb ** Failers No match ab No match /^a\R{1,3}b/ a\nb 0: a\x0ab a\n\rb 0: a\x0a\x0db a\n\r\x85b 0: a\x0a\x0d\x85b a\r\n\r\nb 0: a\x0d\x0a\x0d\x0ab a\r\n\r\n\r\nb 0: a\x0d\x0a\x0d\x0a\x0d\x0ab a\n\r\n\rb 0: a\x0a\x0d\x0a\x0db a\n\n\r\nb 0: a\x0a\x0a\x0d\x0ab ** Failers No match a\n\n\n\rb No match a\r No match /^a[\R]b/ aRb 0: aRb ** Failers No match a\nb No match /.+foo/ afoo 0: afoo ** Failers No match \r\nfoo No match \nfoo No match /.+foo/ afoo 0: afoo \nfoo 0: \x0afoo ** Failers No match \r\nfoo No match /.+foo/ afoo 0: afoo ** Failers No match \nfoo No match \r\nfoo No match /.+foo/s afoo 0: afoo \r\nfoo 0: \x0d\x0afoo \nfoo 0: \x0afoo /^$/mg abc\r\rxyz 0: abc\n\rxyz 0: ** Failers No match abc\r\nxyz No match /^X/m XABC 0: X ** Failers No match XABC\B No match /(?m)^$/g+ abc\r\n\r\n 0: 0+ \x0d\x0a /(?m)^$|^\r\n/g+ abc\r\n\r\n 0: \x0d\x0a 0+ 1: /(?m)$/g+ abc\r\n\r\n 0: 0+ \x0d\x0a\x0d\x0a 0: 0+ \x0d\x0a 0: 0+ /(?|(abc)|(xyz))/ >abc< 0: abc >xyz< 0: xyz /(x)(?|(abc)|(xyz))(x)/ xabcx 0: xabcx xxyzx 0: xxyzx /(x)(?|(abc)(pqr)|(xyz))(x)/ xabcpqrx 0: xabcpqrx xxyzx 0: xxyzx /(?|(abc)|(xyz))(?1)/ abcabc 0: abcabc xyzabc 0: xyzabc ** Failers No match xyzxyz No match /\H\h\V\v/ X X\x0a 0: X X\x0a X\x09X\x0b 0: X\x09X\x0b ** Failers No match \xa0 X\x0a No match /\H*\h+\V?\v{3,4}/ \x09\x20\xa0X\x0a\x0b\x0c\x0d\x0a 0: \x09 \xa0X\x0a\x0b\x0c\x0d \x09\x20\xa0\x0a\x0b\x0c\x0d\x0a 0: \x09 \xa0\x0a\x0b\x0c\x0d \x09\x20\xa0\x0a\x0b\x0c 0: \x09 \xa0\x0a\x0b\x0c ** Failers No match \x09\x20\xa0\x0a\x0b No match /\H{3,4}/ XY ABCDE 0: ABCD XY PQR ST 0: PQR /.\h{3,4}./ XY AB PQRS 0: B P 1: B /\h*X\h?\H+Y\H?Z/ >XNNNYZ 0: XNNNYZ > X NYQZ 0: X NYQZ ** Failers No match >XYZ No match > X NY Z No match /\v*X\v?Y\v+Z\V*\x0a\V+\x0b\V{2,3}\x0c/ >XY\x0aZ\x0aA\x0bNN\x0c 0: XY\x0aZ\x0aA\x0bNN\x0c >\x0a\x0dX\x0aY\x0a\x0bZZZ\x0aAAA\x0bNNN\x0c 0: \x0a\x0dX\x0aY\x0a\x0bZZZ\x0aAAA\x0bNNN\x0c /.+A/ \r\nA No match /\nA/ \r\nA 0: \x0aA /[\r\n]A/ \r\nA 0: \x0aA /(\r|\n)A/ \r\nA 0: \x0aA /a\Rb/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab ** Failers No match a\x85b No match a\x0bb No match /a\Rb/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab a\x85b 0: a\x85b a\x0bb 0: a\x0bb ** Failers No match a\x85b\ No match a\x0bb\ No match /a\R?b/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab ** Failers No match a\x85b No match a\x0bb No match /a\R?b/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\rb 0: a\x0db a\nb 0: a\x0ab a\r\nb 0: a\x0d\x0ab a\x85b 0: a\x85b a\x0bb 0: a\x0bb ** Failers No match a\x85b\ No match a\x0bb\ No match /a\R{2,4}b/I Capturing subpattern count = 0 Options: bsr_anycrlf First char = 'a' Need char = 'b' a\r\n\nb 0: a\x0d\x0a\x0ab a\n\r\rb 0: a\x0a\x0d\x0db a\r\n\r\n\r\n\r\nb 0: a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0ab ** Failers No match a\x85\85b No match a\x0b\0bb No match /a\R{2,4}b/I Capturing subpattern count = 0 Options: bsr_unicode First char = 'a' Need char = 'b' a\r\rb 0: a\x0d\x0db a\n\n\nb 0: a\x0a\x0a\x0ab a\r\n\n\r\rb 0: a\x0d\x0a\x0a\x0d\x0db a\x85\85b No match a\x0b\0bb No match ** Failers No match a\r\r\r\r\rb No match a\x85\85b\ No match a\x0b\0bb\ No match /a(?!)|\wbc/ abc 0: abc /a[]b/ ** Failers No match ab No match /a[]+b/ ** Failers No match ab No match /a[]*+b/ ** Failers No match ab No match /a[^]b/ aXb 0: aXb a\nb 0: a\x0ab ** Failers No match ab No match /a[^]+b/ aXb 0: aXb a\nX\nXb 0: a\x0aX\x0aXb ** Failers No match ab No match /X$/E X 0: X ** Failers No match X\n No match /X$/ X 0: X X\n 0: X /xyz/C xyz --->xyz +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz abcxyz --->abcxyz +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz abcxyz\Y --->abcxyz +0 ^ x +0 ^ x +0 ^ x +0 ^ x +1 ^^ y +2 ^ ^ z +3 ^ ^ 0: xyz ** Failers No match abc No match abc\Y --->abc +0 ^ x +0 ^ x +0 ^ x +0 ^ x No match abcxypqr No match abcxypqr\Y --->abcxypqr +0 ^ x +0 ^ x +0 ^ x +0 ^ x +1 ^^ y +2 ^ ^ z +0 ^ x +0 ^ x +0 ^ x +0 ^ x +0 ^ x No match /(*NO_START_OPT)xyz/C abcxyz --->abcxyz +15 ^ x +15 ^ x +15 ^ x +15 ^ x +16 ^^ y +17 ^ ^ z +18 ^ ^ 0: xyz /(?C)ab/ ab --->ab 0 ^ a 0: ab \C-ab 0: ab /ab/C ab --->ab +0 ^ a +1 ^^ b +2 ^ ^ 0: ab \C-ab 0: ab /^"((?(?=[a])[^"])|b)*"$/C "ab" --->"ab" +0 ^ ^ +1 ^ " +2 ^^ ((?(?=[a])[^"])|b)* +21 ^^ " +3 ^^ (?(?=[a])[^"]) +18 ^^ b +5 ^^ (?=[a]) +8 ^ [a] +11 ^^ ) +12 ^^ [^"] +16 ^ ^ ) +17 ^ ^ | +21 ^ ^ " +3 ^ ^ (?(?=[a])[^"]) +18 ^ ^ b +5 ^ ^ (?=[a]) +8 ^ [a] +19 ^ ^ ) +21 ^ ^ " +3 ^ ^ (?(?=[a])[^"]) +18 ^ ^ b +5 ^ ^ (?=[a]) +8 ^ [a] +17 ^ ^ | +22 ^ ^ $ +23 ^ ^ 0: "ab" \C-"ab" 0: "ab" /\d+X|9+Y/ ++++123999\P Partial match: 123999 ++++123999Y\P 0: 999Y /Z(*F)/ Z\P No match ZA\P No match /Z(?!)/ Z\P No match ZA\P No match /dog(sbody)?/ dogs\P 0: dog dogs\P\P Partial match: dogs /dog(sbody)??/ dogs\P 0: dog dogs\P\P Partial match: dogs /dog|dogsbody/ dogs\P 0: dog dogs\P\P Partial match: dogs /dogsbody|dog/ dogs\P 0: dog dogs\P\P Partial match: dogs /Z(*F)Q|ZXY/ Z\P Partial match: Z ZA\P No match X\P No match /\bthe cat\b/ the cat\P 0: the cat the cat\P\P Partial match: the cat /dog(sbody)?/ dogs\D\P 0: dog body\D\R 0: body /dog(sbody)?/ dogs\D\P\P Partial match: dogs body\D\R 0: body /abc/ abc\P 0: abc abc\P\P 0: abc /abc\K123/ xyzabc123pqr Error -16 (item unsupported for DFA matching) /(?<=abc)123/ xyzabc123pqr 0: 123 xyzabc12\P Partial match at offset 6: abc12 xyzabc12\P\P Partial match at offset 6: abc12 /\babc\b/ +++abc+++ 0: abc +++ab\P Partial match at offset 3: +ab +++ab\P\P Partial match at offset 3: +ab /(?=C)/g+ ABCDECBA 0: 0+ CDECBA 0: 0+ CBA /(abc|def|xyz)/I Capturing subpattern count = 1 No options No first char No need char terhjk;abcdaadsfe 0: abc the quick xyz brown fox 0: xyz \Yterhjk;abcdaadsfe 0: abc \Ythe quick xyz brown fox 0: xyz ** Failers No match thejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd No match \Ythejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd No match /(abc|def|xyz)/SI Capturing subpattern count = 1 No options No first char No need char Subject length lower bound = 3 Starting chars: a d x terhjk;abcdaadsfe 0: abc the quick xyz brown fox 0: xyz \Yterhjk;abcdaadsfe 0: abc \Ythe quick xyz brown fox 0: xyz ** Failers No match thejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd No match \Ythejk;adlfj aenjl;fda asdfasd ehj;kjxyasiupd No match /abcd*/+ xxxxabcd\P 0: abcd 0+ xxxxabcd\P\P Partial match: abcd dddxxx\R 0: ddd 0+ xxx xxxxabcd\P\P Partial match: abcd xxx\R 0: 0+ xxx /abcd*/i xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd XXXXABCD\P 0: ABCD XXXXABCD\P\P Partial match: ABCD /abc\d*/ xxxxabc1\P 0: abc1 xxxxabc1\P\P Partial match: abc1 /abc[de]*/ xxxxabcde\P 0: abcde xxxxabcde\P\P Partial match: abcde /(?:(?1)|B)(A(*F)|C)/ ABCD 0: BC CCD 0: CC ** Failers No match CAD No match /^(?:(?1)|B)(A(*F)|C)/ CCD 0: CC BCD 0: BC ** Failers No match ABCD No match CAD No match BAD No match /^(?!a(*SKIP)b)/ ac Error -16 (item unsupported for DFA matching) /^(?=a(*SKIP)b|ac)/ ** Failers No match ac Error -16 (item unsupported for DFA matching) /^(?=a(*THEN)b|ac)/ ac Error -16 (item unsupported for DFA matching) /^(?=a(*PRUNE)b)/ ab Error -16 (item unsupported for DFA matching) ** Failers No match ac Error -16 (item unsupported for DFA matching) /^(?(?!a(*SKIP)b))/ ac Error -16 (item unsupported for DFA matching) /(?<=abc)def/ abc\P\P Partial match at offset 3: abc /abc$/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc$/m abc 0: abc abc\n 0: abc abc\P\P Partial match: abc abc\n\P\P 0: abc abc\P 0: abc abc\n\P 0: abc /abc\z/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc\Z/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc\b/ abc 0: abc abc\P 0: abc abc\P\P Partial match: abc /abc\B/ abc No match abc\P Partial match: abc abc\P\P Partial match: abc /.+/ abc\>0 0: abc abc\>1 0: bc abc\>2 0: c abc\>3 No match abc\>4 Error -24 (bad offset value) abc\>-4 Error -24 (bad offset value) /^(?:a)++\w/ aaaab 0: aaaab ** Failers No match aaaa No match bbb No match /^(?:aa|(?:a)++\w)/ aaaab 0: aaaab 1: aa aaaa 0: aa ** Failers No match bbb No match /^(?:a)*+\w/ aaaab 0: aaaab bbb 0: b ** Failers No match aaaa No match /^(a)++\w/ aaaab 0: aaaab ** Failers No match aaaa No match bbb No match /^(a|)++\w/ aaaab 0: aaaab ** Failers No match aaaa No match bbb No match /(?=abc){3}abc/+ abcabcabc 0: abc 0+ abcabc ** Failers No match xyz No match /(?=abc)+abc/+ abcabcabc 0: abc 0+ abcabc ** Failers No match xyz No match /(?=abc)++abc/+ abcabcabc 0: abc 0+ abcabc ** Failers No match xyz No match /(?=abc){0}xyz/ xyz 0: xyz /(?=abc){1}xyz/ ** Failers No match xyz No match /(?=(a))?./ ab 0: a bc 0: b /(?=(a))??./ ab 0: a bc 0: b /^(?=(a)){0}b(?1)/ backgammon 0: ba /^(?=(?1))?[az]([abc])d/ abd 0: abd zcdxx 0: zcd /^(?!a){0}\w+/ aaaaa 0: aaaaa /(?<=(abc))?xyz/ abcxyz 0: xyz pqrxyz 0: xyz /((?2))((?1))/ abc Error -26 (nested recursion at the same subject position) /(?(R)a+|(?R)b)/ aaaabcde 0: aaaab /(?(R)a+|((?R))b)/ aaaabcde 0: aaaab /((?(R)a+|(?1)b))/ aaaabcde 0: aaaab /((?(R2)a+|(?1)b))/ aaaabcde Error -17 (backreference condition or recursion test not supported for DFA matching) /(?(R)a*(?1)|((?R))b)/ aaaabcde Error -26 (nested recursion at the same subject position) /(a+)/O \O6aaaa Matched, but offsets vector is too small to show all matches 0: aaaa 1: aaa 2: aa \O8aaaa 0: aaaa 1: aaa 2: aa 3: a /ab\Cde/ abXde 0: abXde /(?<=ab\Cde)X/ abZdeX 0: X /^\R/ \r\P 0: \x0d \r\P\P Partial match: \x0d /^\R{2,3}x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P Partial match: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P Partial match: \x0d\x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d \r\rx 0: \x0d\x0dx \r\r\rx 0: \x0d\x0d\x0dx /^\R{2,3}?x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P Partial match: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P Partial match: \x0d\x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d \r\rx 0: \x0d\x0dx \r\r\rx 0: \x0d\x0d\x0dx /^\R?x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d x 0: x \rx 0: \x0dx /^\R+x/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\n\P Partial match: \x0d\x0a \r\n\P\P Partial match: \x0d\x0a \rx 0: \x0dx /^a$/ a\r\P Partial match: a\x0d a\r\P\P Partial match: a\x0d /^a$/m a\r\P Partial match: a\x0d a\r\P\P Partial match: a\x0d /^(a$|a\r)/ a\r\P 0: a\x0d a\r\P\P Partial match: a\x0d /^(a$|a\r)/m a\r\P 0: a\x0d a\r\P\P Partial match: a\x0d /./ \r\P 0: \x0d \r\P\P Partial match: \x0d /.{2,3}/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P 0: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P 0: \x0d\x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d /.{2,3}?/ \r\P Partial match: \x0d \r\P\P Partial match: \x0d \r\r\P 0: \x0d\x0d \r\r\P\P Partial match: \x0d\x0d \r\r\r\P 0: \x0d\x0d\x0d 1: \x0d\x0d \r\r\r\P\P Partial match: \x0d\x0d\x0d /-- Test simple validity check for restarts --/ /abcdef/ abc\R Error -30 (invalid data in workspace for DFA restart) /)(.)|(?R))++)*F>/ text text xxxxx text F> text2 more text. 0: text xxxxx text F> /^(?>.{4})abc|^\w\w.xabcd/ xxxxabcd 0: xxxxabcd 1: xxxxabc xx\xa0xabcd 0: xx\xa0xabcd 1: xx\xa0xabc /^(.{4}){2}+abc|^\w\w.x\w\w\w\wabcd/ xxxxxxxxabcd 0: xxxxxxxxabcd 1: xxxxxxxxabc xx\xa0xxxxxabcd 0: xx\xa0xxxxxabcd 1: xx\xa0xxxxxabc /abcd/ abcd\O0 Matched, but offsets vector is too small to show all matches /-- These tests show up auto-possessification --/ /[ab]*/ aaaa 0: aaaa /[ab]*?/ aaaa 0: aaaa 1: aaa 2: aa 3: a 4: /[ab]?/ aaaa 0: a /[ab]??/ aaaa 0: a 1: /[ab]+/ aaaa 0: aaaa /[ab]+?/ aaaa 0: aaaa 1: aaa 2: aa 3: a /[ab]{2,3}/ aaaa 0: aaa /[ab]{2,3}?/ aaaa 0: aaa 1: aa /[ab]{2,}/ aaaa 0: aaaa /[ab]{2,}?/ aaaa 0: aaaa 1: aaa 2: aa '\A(?:[^\"]++|\"(?:[^\"]*+|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER '\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER /(?(?!)a|b)/ bbb 0: b aaa No match /()()a+/O= aaa\D ** Show all captures ignored after DFA matching 0: aaa 1: aa 2: a a\D ** Show all captures ignored after DFA matching 0: a /(02-)?[0-9]{3}-[0-9]{3}/ 02-123-123 0: 02-123-123 /-- End of testinput8 --/ ================================================ FILE: src/pcre/testdata/testoutput9 ================================================ /-- This set of tests checks UTF-8 support with the DFA matching functionality of pcre_dfa_exec(), excluding Unicode property support. The -dfa flag must be used with pcretest when running it. --/ < forbid W /\x{100}ab/8 \x{100}ab 0: \x{100}ab /a\x{100}*b/8 ab 0: ab a\x{100}b 0: a\x{100}b a\x{100}\x{100}b 0: a\x{100}\x{100}b /a\x{100}+b/8 a\x{100}b 0: a\x{100}b a\x{100}\x{100}b 0: a\x{100}\x{100}b *** Failers No match ab No match /\bX/8 Xoanon 0: X +Xoanon 0: X \x{300}Xoanon 0: X *** Failers No match YXoanon No match /\BX/8 YXoanon 0: X *** Failers No match Xoanon No match +Xoanon No match \x{300}Xoanon No match /X\b/8 X+oanon 0: X ZX\x{300}oanon 0: X FAX 0: X *** Failers No match Xoanon No match /X\B/8 Xoanon 0: X *** Failers No match X+oanon No match ZX\x{300}oanon No match FAX No match /[^a]/8 abcd 0: b a\x{100} 0: \x{100} /^[abc\x{123}\x{400}-\x{402}]{2,3}\d/8 ab99 0: ab9 \x{123}\x{123}45 0: \x{123}\x{123}4 \x{400}\x{401}\x{402}6 0: \x{400}\x{401}\x{402}6 *** Failers No match d99 No match \x{123}\x{122}4 No match \x{400}\x{403}6 No match \x{400}\x{401}\x{402}\x{402}6 No match /a.b/8 acb 0: acb a\x7fb 0: a\x{7f}b a\x{100}b 0: a\x{100}b *** Failers No match a\nb No match /a(.{3})b/8 a\x{4000}xyb 0: a\x{4000}xyb a\x{4000}\x7fyb 0: a\x{4000}\x{7f}yb a\x{4000}\x{100}yb 0: a\x{4000}\x{100}yb *** Failers No match a\x{4000}b No match ac\ncb No match /a(.*?)(.)/ a\xc0\x88b 0: a\xc0\x88b 1: a\xc0\x88 2: a\xc0 /a(.*?)(.)/8 a\x{100}b 0: a\x{100}b 1: a\x{100} /a(.*)(.)/ a\xc0\x88b 0: a\xc0\x88b 1: a\xc0\x88 2: a\xc0 /a(.*)(.)/8 a\x{100}b 0: a\x{100}b 1: a\x{100} /a(.)(.)/ a\xc0\x92bcd 0: a\xc0\x92 /a(.)(.)/8 a\x{240}bcd 0: a\x{240}b /a(.?)(.)/ a\xc0\x92bcd 0: a\xc0\x92 1: a\xc0 /a(.?)(.)/8 a\x{240}bcd 0: a\x{240}b 1: a\x{240} /a(.??)(.)/ a\xc0\x92bcd 0: a\xc0\x92 1: a\xc0 /a(.??)(.)/8 a\x{240}bcd 0: a\x{240}b 1: a\x{240} /a(.{3})b/8 a\x{1234}xyb 0: a\x{1234}xyb a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b *** Failers No match a\x{1234}b No match ac\ncb No match /a(.{3,})b/8 a\x{1234}xyb 0: a\x{1234}xyb a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb 0: axxxxbcdefghijb 1: axxxxb a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b *** Failers No match a\x{1234}b No match /a(.{3,}?)b/8 a\x{1234}xyb 0: a\x{1234}xyb a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb 0: axxxxbcdefghijb 1: axxxxb a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b *** Failers No match a\x{1234}b No match /a(.{3,5})b/8 a\x{1234}xyb 0: a\x{1234}xyb a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb 0: axxxxb a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b axbxxbcdefghijb 0: axbxxb axxxxxbcdefghijb 0: axxxxxb *** Failers No match a\x{1234}b No match axxxxxxbcdefghijb No match /a(.{3,5}?)b/8 a\x{1234}xyb 0: a\x{1234}xyb a\x{1234}\x{4321}yb 0: a\x{1234}\x{4321}yb a\x{1234}\x{4321}\x{3412}b 0: a\x{1234}\x{4321}\x{3412}b axxxxbcdefghijb 0: axxxxb a\x{1234}\x{4321}\x{3412}\x{3421}b 0: a\x{1234}\x{4321}\x{3412}\x{3421}b axbxxbcdefghijb 0: axbxxb axxxxxbcdefghijb 0: axxxxxb *** Failers No match a\x{1234}b No match axxxxxxbcdefghijb No match /^[a\x{c0}]/8 *** Failers No match \x{100} No match /(?<=aXb)cd/8 aXbcd 0: cd /(?<=a\x{100}b)cd/8 a\x{100}bcd 0: cd /(?<=a\x{100000}b)cd/8 a\x{100000}bcd 0: cd /(?:\x{100}){3}b/8 \x{100}\x{100}\x{100}b 0: \x{100}\x{100}\x{100}b *** Failers No match \x{100}\x{100}b No match /\x{ab}/8 \x{ab} 0: \x{ab} \xc2\xab 0: \x{ab} *** Failers No match \x00{ab} No match /(?<=(.))X/8 WXYZ 0: X \x{256}XYZ 0: X *** Failers No match XYZ No match /[^a]+/8g bcd 0: bcd \x{100}aY\x{256}Z 0: \x{100} 0: Y\x{256}Z /^[^a]{2}/8 \x{100}bc 0: \x{100}b /^[^a]{2,}/8 \x{100}bcAa 0: \x{100}bcA /^[^a]{2,}?/8 \x{100}bca 0: \x{100}bc 1: \x{100}b /[^a]+/8ig bcd 0: bcd \x{100}aY\x{256}Z 0: \x{100} 0: Y\x{256}Z /^[^a]{2}/8i \x{100}bc 0: \x{100}b /^[^a]{2,}/8i \x{100}bcAa 0: \x{100}bc /^[^a]{2,}?/8i \x{100}bca 0: \x{100}bc 1: \x{100}b /\x{100}{0,0}/8 abcd 0: /\x{100}?/8 abcd 0: \x{100}\x{100} 0: \x{100} /\x{100}{0,3}/8 \x{100}\x{100} 0: \x{100}\x{100} \x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100} /\x{100}*/8 abce 0: \x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100} /\x{100}{1,1}/8 abcd\x{100}\x{100}\x{100}\x{100} 0: \x{100} /\x{100}{1,3}/8 abcd\x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100} /\x{100}+/8 abcd\x{100}\x{100}\x{100}\x{100} 0: \x{100}\x{100}\x{100}\x{100} /\x{100}{3}/8 abcd\x{100}\x{100}\x{100}XX 0: \x{100}\x{100}\x{100} /\x{100}{3,5}/8 abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX 0: \x{100}\x{100}\x{100}\x{100}\x{100} /\x{100}{3,}/8O abcd\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}XX 0: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 1: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 2: \x{100}\x{100}\x{100}\x{100}\x{100} 3: \x{100}\x{100}\x{100}\x{100} 4: \x{100}\x{100}\x{100} /(?<=a\x{100}{2}b)X/8 Xyyya\x{100}\x{100}bXzzz 0: X /\D*/8O aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Matched, but offsets vector is too small to show all matches 0: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 4: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 6: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 7: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 8: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 9: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 10: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 11: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 12: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 13: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 14: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 15: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 16: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 17: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 18: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 19: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 20: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 21: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /\D*/8O \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} Matched, but offsets vector is too small to show all matches 0: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 1: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 2: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 3: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 4: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 5: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 6: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 7: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 8: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 9: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 10: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 11: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 12: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 13: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 14: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 15: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 16: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 17: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 18: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 19: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 20: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} 21: \x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} /\D/8 1X2 0: X 1\x{100}2 0: \x{100} />\S/8 > >X Y 0: >X > >\x{100} Y 0: >\x{100} /\d/8 \x{100}3 0: 3 /\s/8 \x{100} X 0: /\D+/8 12abcd34 0: abcd *** Failers 0: *** Failers 1234 No match /\D{2,3}/8 12abcd34 0: abc 12ab34 0: ab *** Failers 0: *** 1234 No match 12a34 No match /\D{2,3}?/8 12abcd34 0: abc 1: ab 12ab34 0: ab *** Failers 0: *** 1: ** 1234 No match 12a34 No match /\d+/8 12abcd34 0: 12 *** Failers No match /\d{2,3}/8 12abcd34 0: 12 1234abcd 0: 123 *** Failers No match 1.4 No match /\d{2,3}?/8 12abcd34 0: 12 1234abcd 0: 123 1: 12 *** Failers No match 1.4 No match /\S+/8 12abcd34 0: 12abcd34 *** Failers 0: *** \ \ No match /\S{2,3}/8 12abcd34 0: 12a 1234abcd 0: 123 *** Failers 0: *** \ \ No match /\S{2,3}?/8 12abcd34 0: 12a 1: 12 1234abcd 0: 123 1: 12 *** Failers 0: *** 1: ** \ \ No match />\s+ <34 0: > < *** Failers No match />\s{2,3} < ab> < *** Failers No match ab> \s{2,3}? < ab> < *** Failers No match ab> \xff< 0: \xff /[\xff]/8 >\x{ff}< 0: \x{ff} /[^\xFF]/ XYZ 0: X /[^\xff]/8 XYZ 0: X \x{123} 0: \x{123} /^[ac]*b/8 xb No match /^[ac\x{100}]*b/8 xb No match /^[^x]*b/8i xb No match /^[^x]*b/8 xb No match /^\d*b/8 xb No match /(|a)/g8 catac 0: 0: a 1: 0: 0: a 1: 0: 0: a\x{256}a 0: a 1: 0: 0: a 1: 0: /^\x{85}$/8i \x{85} 0: \x{85} /^abc./mgx8 abc1 \x0aabc2 \x0babc3xx \x0cabc4 \x0dabc5xx \x0d\x0aabc6 \x{0085}abc7 \x{2028}abc8 \x{2029}abc9 JUNK 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc7 0: abc8 0: abc9 /abc.$/mgx8 abc1\x0a abc2\x0b abc3\x0c abc4\x0d abc5\x0d\x0a abc6\x{0085} abc7\x{2028} abc8\x{2029} abc9 0: abc1 0: abc2 0: abc3 0: abc4 0: abc5 0: abc6 0: abc7 0: abc8 0: abc9 /^a\Rb/8 a\nb 0: a\x{0a}b a\rb 0: a\x{0d}b a\r\nb 0: a\x{0d}\x{0a}b a\x0bb 0: a\x{0b}b a\x0cb 0: a\x{0c}b a\x{85}b 0: a\x{85}b a\x{2028}b 0: a\x{2028}b a\x{2029}b 0: a\x{2029}b ** Failers No match a\n\rb No match /^a\R*b/8 ab 0: ab a\nb 0: a\x{0a}b a\rb 0: a\x{0d}b a\r\nb 0: a\x{0d}\x{0a}b a\x0bb 0: a\x{0b}b a\x0c\x{2028}\x{2029}b 0: a\x{0c}\x{2028}\x{2029}b a\x{85}b 0: a\x{85}b a\n\rb 0: a\x{0a}\x{0d}b a\n\r\x{85}\x0cb 0: a\x{0a}\x{0d}\x{85}\x{0c}b /^a\R+b/8 a\nb 0: a\x{0a}b a\rb 0: a\x{0d}b a\r\nb 0: a\x{0d}\x{0a}b a\x0bb 0: a\x{0b}b a\x0c\x{2028}\x{2029}b 0: a\x{0c}\x{2028}\x{2029}b a\x{85}b 0: a\x{85}b a\n\rb 0: a\x{0a}\x{0d}b a\n\r\x{85}\x0cb 0: a\x{0a}\x{0d}\x{85}\x{0c}b ** Failers No match ab No match /^a\R{1,3}b/8 a\nb 0: a\x{0a}b a\n\rb 0: a\x{0a}\x{0d}b a\n\r\x{85}b 0: a\x{0a}\x{0d}\x{85}b a\r\n\r\nb 0: a\x{0d}\x{0a}\x{0d}\x{0a}b a\r\n\r\n\r\nb 0: a\x{0d}\x{0a}\x{0d}\x{0a}\x{0d}\x{0a}b a\n\r\n\rb 0: a\x{0a}\x{0d}\x{0a}\x{0d}b a\n\n\r\nb 0: a\x{0a}\x{0a}\x{0d}\x{0a}b ** Failers No match a\n\n\n\rb No match a\r No match /\h+\V?\v{3,4}/8O \x09\x20\x{a0}X\x0a\x0b\x0c\x0d\x0a 0: \x{09} \x{a0}X\x{0a}\x{0b}\x{0c}\x{0d} 1: \x{09} \x{a0}X\x{0a}\x{0b}\x{0c} /\V?\v{3,4}/8O \x20\x{a0}X\x0a\x0b\x0c\x0d\x0a 0: X\x{0a}\x{0b}\x{0c}\x{0d} 1: X\x{0a}\x{0b}\x{0c} /\h+\V?\v{3,4}/8O >\x09\x20\x{a0}X\x0a\x0a\x0a< 0: \x{09} \x{a0}X\x{0a}\x{0a}\x{0a} /\V?\v{3,4}/8O >\x09\x20\x{a0}X\x0a\x0a\x0a< 0: X\x{0a}\x{0a}\x{0a} /\H\h\V\v/8 X X\x0a 0: X X\x{0a} X\x09X\x0b 0: X\x{09}X\x{0b} ** Failers No match \x{a0} X\x0a No match /\H*\h+\V?\v{3,4}/8O \x09\x20\x{a0}X\x0a\x0b\x0c\x0d\x0a 0: \x{09} \x{a0}X\x{0a}\x{0b}\x{0c}\x{0d} 1: \x{09} \x{a0}X\x{0a}\x{0b}\x{0c} \x09\x20\x{a0}\x0a\x0b\x0c\x0d\x0a 0: \x{09} \x{a0}\x{0a}\x{0b}\x{0c}\x{0d} 1: \x{09} \x{a0}\x{0a}\x{0b}\x{0c} \x09\x20\x{a0}\x0a\x0b\x0c 0: \x{09} \x{a0}\x{0a}\x{0b}\x{0c} ** Failers No match \x09\x20\x{a0}\x0a\x0b No match /\H\h\V\v/8 \x{3001}\x{3000}\x{2030}\x{2028} 0: \x{3001}\x{3000}\x{2030}\x{2028} X\x{180e}X\x{85} 0: X\x{180e}X\x{85} ** Failers No match \x{2009} X\x0a No match /\H*\h+\V?\v{3,4}/8O \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x0c\x0d\x0a 0: \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x{0c}\x{0d} 1: \x{1680}\x{180e}\x{2007}X\x{2028}\x{2029}\x{0c} \x09\x{205f}\x{a0}\x0a\x{2029}\x0c\x{2028}\x0a 0: \x{09}\x{205f}\x{a0}\x{0a}\x{2029}\x{0c}\x{2028} 1: \x{09}\x{205f}\x{a0}\x{0a}\x{2029}\x{0c} \x09\x20\x{202f}\x0a\x0b\x0c 0: \x{09} \x{202f}\x{0a}\x{0b}\x{0c} ** Failers No match \x09\x{200a}\x{a0}\x{2028}\x0b No match /a\Rb/I8 Capturing subpattern count = 0 Options: bsr_anycrlf utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b ** Failers No match a\x{85}b No match a\x0bb No match /a\Rb/I8 Capturing subpattern count = 0 Options: bsr_unicode utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b a\x{85}b 0: a\x{85}b a\x0bb 0: a\x{0b}b ** Failers No match a\x{85}b\ No match a\x0bb\ No match /a\R?b/I8 Capturing subpattern count = 0 Options: bsr_anycrlf utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b ** Failers No match a\x{85}b No match a\x0bb No match /a\R?b/I8 Capturing subpattern count = 0 Options: bsr_unicode utf First char = 'a' Need char = 'b' a\rb 0: a\x{0d}b a\nb 0: a\x{0a}b a\r\nb 0: a\x{0d}\x{0a}b a\x{85}b 0: a\x{85}b a\x0bb 0: a\x{0b}b ** Failers No match a\x{85}b\ No match a\x0bb\ No match /X/8f A\x{1ec5}ABCXYZ 0: X /abcd*/8 xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd /abcd*/i8 xxxxabcd\P 0: abcd xxxxabcd\P\P Partial match: abcd XXXXABCD\P 0: ABCD XXXXABCD\P\P Partial match: ABCD /abc\d*/8 xxxxabc1\P 0: abc1 xxxxabc1\P\P Partial match: abc1 /abc[de]*/8 xxxxabcde\P 0: abcde xxxxabcde\P\P Partial match: abcde /\bthe cat\b/8 the cat\P 0: the cat the cat\P\P Partial match: the cat /ab\Cde/8 abXde Error -16 (item unsupported for DFA matching) /(?<=ab\Cde)X/8 Failed: \C not allowed in lookbehind assertion at offset 10 /./8 \r\P 0: \x{0d} \r\P\P Partial match: \x{0d} /.{2,3}/8 \r\P Partial match: \x{0d} \r\P\P Partial match: \x{0d} \r\r\P 0: \x{0d}\x{0d} \r\r\P\P Partial match: \x{0d}\x{0d} \r\r\r\P 0: \x{0d}\x{0d}\x{0d} \r\r\r\P\P Partial match: \x{0d}\x{0d}\x{0d} /.{2,3}?/8 \r\P Partial match: \x{0d} \r\P\P Partial match: \x{0d} \r\r\P 0: \x{0d}\x{0d} \r\r\P\P Partial match: \x{0d}\x{0d} \r\r\r\P 0: \x{0d}\x{0d}\x{0d} 1: \x{0d}\x{0d} \r\r\r\P\P Partial match: \x{0d}\x{0d}\x{0d} /[^\x{100}]/8 \x{100}\x{101}X 0: \x{101} /[^\x{100}]+/8 \x{100}\x{101}X 0: \x{101}X /-- End of testinput9 --/ ================================================ FILE: src/pcre/testdata/testoutputEBC ================================================ /-- This is a specialized test for checking, when PCRE is compiled with the EBCDIC option but in an ASCII environment, that newline and white space functionality is working. It catches cases where explicit values such as 0x0a have been used instead of names like CHAR_LF. Needless to say, it is not a genuine EBCDIC test! In patterns, alphabetic characters that follow a backslash must be in EBCDIC code. In data, newlines and other spacing characters must be in EBCDIC, but can be specified as escapes. --/ /-- Test default newline and variations --/ /^A/m ABC 0: A 12\x15ABC 0: A /^A/m 12\x15ABC 0: A 12\x0dABC 0: A 12\x0d\x15ABC 0: A 12\x25ABC 0: A /^A/m 12\x15ABC 0: A 12\x0dABC 0: A 12\x0d\x15ABC 0: A ** Fail No match 12\x25ABC No match /-- Test \h --/ /^A\/ A B 0: A\x20 A\x41B 0: AA /-- Test \H --/ /^A\/ AB 0: AB A\x42B 0: AB ** Fail No match A B No match A\x41B No match /-- Test \R --/ /^A\/ A\x15B 0: A\x15 A\x0dB 0: A\x0d A\x25B 0: A\x25 A\x0bB 0: A\x0b A\x0cB 0: A\x0c ** Fail No match A B No match /-- Test \v --/ /^A\/ A\x15B 0: A\x15 A\x0dB 0: A\x0d A\x25B 0: A\x25 A\x0bB 0: A\x0b A\x0cB 0: A\x0c ** Fail No match A B No match /-- Test \V --/ /^A\/ A B 0: A\x20 ** Fail No match A\x15B No match A\x0dB No match A\x25B No match A\x0bB No match A\x0cB No match /-- For repeated items, use an atomic group so that the output is the same for DFA matching (otherwise it may show multiple matches). --/ /-- Test \h+ --/ /^A(?>\+)/ A B 0: A\x20 /-- Test \H+ --/ /^A(?>\+)/ AB 0: AB ** Fail No match A B No match /-- Test \R+ --/ /^A(?>\+)/ A\x15B 0: A\x15 A\x0dB 0: A\x0d A\x25B 0: A\x25 A\x0bB 0: A\x0b A\x0cB 0: A\x0c ** Fail No match A B No match /-- Test \v+ --/ /^A(?>\+)/ A\x15B 0: A\x15 A\x0dB 0: A\x0d A\x25B 0: A\x25 A\x0bB 0: A\x0b A\x0cB 0: A\x0c ** Fail No match A B No match /-- Test \V+ --/ /^A(?>\+)/ A B 0: A\x20B ** Fail No match A\x15B No match A\x0dB No match A\x25B No match A\x0bB No match A\x0cB No match /-- End --/ ================================================ FILE: src/pcre/testdata/valgrind-jit.supp ================================================ { name Memcheck:Addr16 obj:??? obj:??? obj:??? } { name Memcheck:Cond obj:??? obj:??? obj:??? } ================================================ FILE: src/pcre/testdata/wintestinput3 ================================================ /^[\w]+/ *** Failers cole /^[\w]+/Lfrench cole /^[\w]+/ *** Failers cole /^[\W]+/ cole /^[\W]+/Lfrench *** Failers cole /[\b]/ \b *** Failers a /[\b]/Lfrench \b *** Failers a /^\w+/ *** Failers cole /^\w+/Lfrench cole /(.+)\b(.+)/ cole /(.+)\b(.+)/Lfrench *** Failers cole /cole/i cole *** Failers cole /cole/iLfrench cole cole /\w/IS /\w/ISLfrench /^[\xc8-\xc9]/iLfrench cole cole /^[\xc8-\xc9]/Lfrench cole *** Failers cole /\W+/Lfrench >>>\xaa<<< >>>\xba<<< /[\W]+/Lfrench >>>\xaa<<< >>>\xba<<< /[^[:alpha:]]+/Lfrench >>>\xaa<<< >>>\xba<<< /\w+/Lfrench >>>\xaa<<< >>>\xba<<< /[\w]+/Lfrench >>>\xaa<<< >>>\xba<<< /[[:alpha:]]+/Lfrench >>>\xaa<<< >>>\xba<<< /[[:alpha:]][[:lower:]][[:upper:]]/DZLfrench / End of testinput3 / ================================================ FILE: src/pcre/testdata/wintestoutput3 ================================================ /^[\w]+/ *** Failers No match cole No match /^[\w]+/Lfrench cole 0: cole /^[\w]+/ *** Failers No match cole No match /^[\W]+/ cole 0: \xc9 /^[\W]+/Lfrench *** Failers 0: *** cole No match /[\b]/ \b 0: \x08 *** Failers No match a No match /[\b]/Lfrench \b 0: \x08 *** Failers No match a No match /^\w+/ *** Failers No match cole No match /^\w+/Lfrench cole 0: cole /(.+)\b(.+)/ cole 0: \xc9cole 1: \xc9 2: cole /(.+)\b(.+)/Lfrench *** Failers 0: *** Failers 1: *** 2: Failers cole No match /cole/i cole 0: \xc9cole *** Failers No match cole No match /cole/iLfrench cole 0: cole cole 0: cole /\w/IS Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /\w/ISLfrench Capturing subpattern count = 0 No options No first char No need char Subject length lower bound = 1 Starting chars: 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z /^[\xc8-\xc9]/iLfrench cole 0: cole 0: /^[\xc8-\xc9]/Lfrench cole 0: *** Failers No match cole No match /\W+/Lfrench >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[\W]+/Lfrench >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /[^[:alpha:]]+/Lfrench >>>\xaa<<< 0: >>> >>>\xba<<< 0: >>> /\w+/Lfrench >>>\xaa<<< 0: >>>\xba<<< 0: /[\w]+/Lfrench >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]]+/Lfrench >>>\xaa<<< 0: >>>\xba<<< 0: /[[:alpha:]][[:lower:]][[:upper:]]/DZLfrench ------------------------------------------------------------------ Bra [A-Za-z\x83\x8a\x8c\x8e\x9a\x9c\x9e\x9f\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\xff] [a-z\x83\x9a\x9c\x9e\xaa\xb5\xba\xdf-\xf6\xf8-\xff] [A-Z\x8a\x8c\x8e\x9f\xc0-\xd6\xd8-\xde] Ket End ------------------------------------------------------------------ Capturing subpattern count = 0 No options No first char No need char / End of testinput3 / ================================================ FILE: src/pcre/ucp.h ================================================ /************************************************* * Unicode Property Table handler * *************************************************/ #ifndef _UCP_H #define _UCP_H /* This file contains definitions of the property values that are returned by the UCD access macros. New values that are added for new releases of Unicode should always be at the end of each enum, for backwards compatibility. IMPORTANT: Note also that the specific numeric values of the enums have to be the same as the values that are generated by the maint/MultiStage2.py script, where the equivalent property descriptive names are listed in vectors. ALSO: The specific values of the first two enums are assumed for the table called catposstab in pcre_compile.c. */ /* These are the general character categories. */ enum { ucp_C, /* Other */ ucp_L, /* Letter */ ucp_M, /* Mark */ ucp_N, /* Number */ ucp_P, /* Punctuation */ ucp_S, /* Symbol */ ucp_Z /* Separator */ }; /* These are the particular character categories. */ enum { ucp_Cc, /* Control */ ucp_Cf, /* Format */ ucp_Cn, /* Unassigned */ ucp_Co, /* Private use */ ucp_Cs, /* Surrogate */ ucp_Ll, /* Lower case letter */ ucp_Lm, /* Modifier letter */ ucp_Lo, /* Other letter */ ucp_Lt, /* Title case letter */ ucp_Lu, /* Upper case letter */ ucp_Mc, /* Spacing mark */ ucp_Me, /* Enclosing mark */ ucp_Mn, /* Non-spacing mark */ ucp_Nd, /* Decimal number */ ucp_Nl, /* Letter number */ ucp_No, /* Other number */ ucp_Pc, /* Connector punctuation */ ucp_Pd, /* Dash punctuation */ ucp_Pe, /* Close punctuation */ ucp_Pf, /* Final punctuation */ ucp_Pi, /* Initial punctuation */ ucp_Po, /* Other punctuation */ ucp_Ps, /* Open punctuation */ ucp_Sc, /* Currency symbol */ ucp_Sk, /* Modifier symbol */ ucp_Sm, /* Mathematical symbol */ ucp_So, /* Other symbol */ ucp_Zl, /* Line separator */ ucp_Zp, /* Paragraph separator */ ucp_Zs /* Space separator */ }; /* These are grapheme break properties. Note that the code for processing them assumes that the values are less than 16. If more values are added that take the number to 16 or more, the code will have to be rewritten. */ enum { ucp_gbCR, /* 0 */ ucp_gbLF, /* 1 */ ucp_gbControl, /* 2 */ ucp_gbExtend, /* 3 */ ucp_gbPrepend, /* 4 */ ucp_gbSpacingMark, /* 5 */ ucp_gbL, /* 6 Hangul syllable type L */ ucp_gbV, /* 7 Hangul syllable type V */ ucp_gbT, /* 8 Hangul syllable type T */ ucp_gbLV, /* 9 Hangul syllable type LV */ ucp_gbLVT, /* 10 Hangul syllable type LVT */ ucp_gbRegionalIndicator, /* 11 */ ucp_gbOther /* 12 */ }; /* These are the script identifications. */ enum { ucp_Arabic, ucp_Armenian, ucp_Bengali, ucp_Bopomofo, ucp_Braille, ucp_Buginese, ucp_Buhid, ucp_Canadian_Aboriginal, ucp_Cherokee, ucp_Common, ucp_Coptic, ucp_Cypriot, ucp_Cyrillic, ucp_Deseret, ucp_Devanagari, ucp_Ethiopic, ucp_Georgian, ucp_Glagolitic, ucp_Gothic, ucp_Greek, ucp_Gujarati, ucp_Gurmukhi, ucp_Han, ucp_Hangul, ucp_Hanunoo, ucp_Hebrew, ucp_Hiragana, ucp_Inherited, ucp_Kannada, ucp_Katakana, ucp_Kharoshthi, ucp_Khmer, ucp_Lao, ucp_Latin, ucp_Limbu, ucp_Linear_B, ucp_Malayalam, ucp_Mongolian, ucp_Myanmar, ucp_New_Tai_Lue, ucp_Ogham, ucp_Old_Italic, ucp_Old_Persian, ucp_Oriya, ucp_Osmanya, ucp_Runic, ucp_Shavian, ucp_Sinhala, ucp_Syloti_Nagri, ucp_Syriac, ucp_Tagalog, ucp_Tagbanwa, ucp_Tai_Le, ucp_Tamil, ucp_Telugu, ucp_Thaana, ucp_Thai, ucp_Tibetan, ucp_Tifinagh, ucp_Ugaritic, ucp_Yi, /* New for Unicode 5.0: */ ucp_Balinese, ucp_Cuneiform, ucp_Nko, ucp_Phags_Pa, ucp_Phoenician, /* New for Unicode 5.1: */ ucp_Carian, ucp_Cham, ucp_Kayah_Li, ucp_Lepcha, ucp_Lycian, ucp_Lydian, ucp_Ol_Chiki, ucp_Rejang, ucp_Saurashtra, ucp_Sundanese, ucp_Vai, /* New for Unicode 5.2: */ ucp_Avestan, ucp_Bamum, ucp_Egyptian_Hieroglyphs, ucp_Imperial_Aramaic, ucp_Inscriptional_Pahlavi, ucp_Inscriptional_Parthian, ucp_Javanese, ucp_Kaithi, ucp_Lisu, ucp_Meetei_Mayek, ucp_Old_South_Arabian, ucp_Old_Turkic, ucp_Samaritan, ucp_Tai_Tham, ucp_Tai_Viet, /* New for Unicode 6.0.0: */ ucp_Batak, ucp_Brahmi, ucp_Mandaic, /* New for Unicode 6.1.0: */ ucp_Chakma, ucp_Meroitic_Cursive, ucp_Meroitic_Hieroglyphs, ucp_Miao, ucp_Sharada, ucp_Sora_Sompeng, ucp_Takri, /* New for Unicode 7.0.0: */ ucp_Bassa_Vah, ucp_Caucasian_Albanian, ucp_Duployan, ucp_Elbasan, ucp_Grantha, ucp_Khojki, ucp_Khudawadi, ucp_Linear_A, ucp_Mahajani, ucp_Manichaean, ucp_Mende_Kikakui, ucp_Modi, ucp_Mro, ucp_Nabataean, ucp_Old_North_Arabian, ucp_Old_Permic, ucp_Pahawh_Hmong, ucp_Palmyrene, ucp_Psalter_Pahlavi, ucp_Pau_Cin_Hau, ucp_Siddham, ucp_Tirhuta, ucp_Warang_Citi }; #endif /* End of ucp.h */ ================================================ FILE: src/print.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include "hypermail.h" #include "setup.h" #include "struct.h" #include "printfile.h" #include "print.h" #include "parse.h" #include "txt2html.h" #include "finelink.h" #include "threadprint.h" #include "proto.h" #ifdef HAVE_DIRENT_H #ifdef __LCC__ #include "../lcc/dirent.h" #else #include #endif #else #ifdef __LCC__ #include #else #include #endif #endif #ifdef HAVE_STRING_H #include #endif /* conditions that say when a message's body may be removed */ #define REMOVE_MESSAGE(email) (email->is_deleted && set_delete_level != DELETE_LEAVES_TEXT \ && !(email->is_deleted == 2 && set_delete_level == DELETE_LEAVES_EXPIRED_TEXT)) static char *indextypename[NO_INDEX]; #ifdef GDBM #include "gdbm.h" /* ** store a single message summary to an already open-for-write GDBM index **/ int togdbm(void *gp, struct emailinfo *ep) { datum key; datum content; char *buf; char *dp; int rval; int num = ep->msgnum; char *name = ep->name; char *email = ep->emailaddr; char *date = ep->datestr; char *msgid = ep->msgid; char *subject = ep->subject; char *inreply = ep->inreplyto; char *fromdate = ep->fromdatestr; char *charset = ep->charset; char *isodate = strsav(secs_to_iso(ep->date)); char *isofromdate = strsav(secs_to_iso(ep->fromdate)); char *exp_time_str = strsav(ep->exp_time == -1 ? "" : secs_to_iso(ep->exp_time)); char is_deleted_str[32]; trio_snprintf(is_deleted_str, sizeof(is_deleted_str), "%d", ep->is_deleted); key.dsize = sizeof(num); /* the key is the message number */ key.dptr = (char *)# /* malloc() a string long enough for our data */ /* AUDIT biege: trailing \0 missing */ if (!(buf = (char *)calloc((name ? strlen(name) : 0) + (email ? strlen(email) : 0) + (date ? strlen(date) : 0) + (msgid ? strlen(msgid) : 0) + (subject ? strlen(subject) : 0) + (inreply ? strlen(inreply) : 0) + (fromdate ? strlen(fromdate) : 0) + (charset ? strlen(charset) : 0) + (isodate ? strlen(isodate) : 0) + (isofromdate ? strlen(isofromdate) : 0) + strlen(exp_time_str) + strlen(is_deleted_str) + 13, sizeof(char)))) { return -1; } strcpy(dp = buf, fromdate ? fromdate : ""); dp += strlen(dp) + 1; strcpy(dp, date ? date : ""); dp += strlen(dp) + 1; strcpy(dp, name ? name : ""); dp += strlen(dp) + 1; strcpy(dp, email ? email : ""); dp += strlen(dp) + 1; strcpy(dp, subject ? subject : ""); dp += strlen(dp) + 1; strcpy(dp, msgid ? msgid : ""); dp += strlen(dp) + 1; strcpy(dp, inreply ? inreply : ""); dp += strlen(dp) + 1; strcpy(dp, charset ? charset : ""); dp += strlen(dp) + 1; strcpy(dp, isofromdate ? isofromdate : ""); dp += strlen(dp) + 1; strcpy(dp, isodate ? isodate : ""); dp += strlen(dp) + 1; strcpy(dp, exp_time_str); dp += strlen(dp) + 1; strcpy(dp, is_deleted_str); dp += strlen(dp) + 1; content.dsize = dp - buf; content.dptr = buf; /* the value is in this string */ rval = gdbm_store((GDBM_FILE) gp, key, content, GDBM_REPLACE); free(buf); free(exp_time_str); free(isodate); free(isofromdate); return !rval; } /* end togdbm() */ #endif /* Uses threadlist to find the next message after * msgnum in the thread containing msgnum. * Returns NULL if there are no more messages in * the thread. */ struct emailinfo *nextinthread(int msgnum) { struct reply *rp = threadlist; #ifdef FASTREPLYCODE for (rp = threadlist_by_msgnum[msgnum]; (rp != NULL) && (rp->msgnum != msgnum); rp = rp->next) { ; } #else for (rp = threadlist; (rp != NULL) && (rp->msgnum != msgnum); rp = rp->next) { ; } #endif if (rp == NULL) { /* msgnum not found in threadlist */ return NULL; } rp = rp->next; if ((rp == NULL) || (rp->frommsgnum == -1)) { /*end of thread - no next msg */ return NULL; } return rp->data; } #if 0 /* ** Output a menu line with hyperlinks for table display ** ** All parameters are inputs only. Parameters: ** fp : HTML output file pointer ** idx : Type of page this menu is for. ** archives : "" or else the URL of more hypermail archives. ** currentid: "" or else the id of the "current" message. ** cursub : "" or else the subject of the "current" message. ** pos : Called at the top or bottom of the page. */ void fprint_menu(FILE *fp, mindex_t idx, char *archives, char *currentid, char *cursub, int pos, struct emailsubdir *subdir) { char *ptr; int dlev = (subdir != NULL); int i; int count_l = 0; #if DEBUG_HTML printcomment(fp, "fprint_menu", "begin"); #endif fprintf(fp, "

    \n\n\n"); if (set_mailcommand) { if (set_hmail) { ptr = makemailcommand(set_newmsg_command, set_hmail, currentid, cursub); if (strcmp(ptr, "NONE") != 0) fprintf(fp, "\n", ptr ? ptr : "", lang[MSG_NEW_MESSAGE]); if (ptr) free(ptr); if ((currentid != NULL && currentid[0] != '\0') || (cursub != NULL && cursub[0] != '\0')) { ptr = makemailcommand(set_replymsg_command, set_hmail, currentid, cursub); if (strcmp(ptr, "NONE") != 0) fprintf(fp, "\n", ptr ? ptr : "", lang[MSG_REPLY]); if (ptr) free(ptr); } } } if (set_about && *set_about) fprintf(fp, "\n", set_about, lang[MSG_ABOUT_THIS_LIST]); if (set_show_index_links && set_show_index_links != (pos == PAGE_TOP ? 4 : 3)) { if (idx != NO_INDEX && !set_reverse) { if (pos == PAGE_TOP) fprintf(fp, "\n", lang[MSG_END_OF_MESSAGES]); else fprintf(fp, "\n", lang[MSG_START_OF_MESSAGES]); } for (i = 0; i <= AUTHOR_INDEX; ++i) { if (idx != i && show_index[dlev][i]) { fprintf(fp, "\n", index_name[dlev][i], lang[MSG_DATE_VIEW + i]); ++count_l; } } if (show_index[dlev][ATTACHMENT_INDEX]) { if (idx != ATTACHMENT_INDEX) { fprintf(fp, "\n", index_name[dlev][ATTACHMENT_INDEX], lang[MSG_ATTACHMENT_VIEW]); ++count_l; } } if (subdir && idx != NO_INDEX) { int f_cols = (subdir->prior_subdir != NULL) + (subdir->next_subdir != NULL); const char *colspan = 2 * f_cols <= count_l ? " colspan=\"2\"" : ""; fprintf(fp, ""); if (subdir->prior_subdir) fprintf(fp, "%s, %s", colspan, subdir->rel_path_to_top, subdir->prior_subdir->subdir, index_name[dlev][idx], lang[MSG_PREV_DIRECTORY], lang[MSG_DATE_VIEW + idx]); if (subdir->next_subdir) fprintf(fp, "%s, %s", colspan, subdir->rel_path_to_top, subdir->next_subdir->subdir, index_name[dlev][idx], lang[MSG_NEXT_DIRECTORY], lang[MSG_DATE_VIEW + idx]); if (show_index[0][FOLDERS_INDEX]) fprintf(fp, "", subdir->rel_path_to_top, index_name[0][FOLDERS_INDEX], lang[MSG_FOLDERS_INDEX]); } } if (archives && *archives) fprintf(fp, "\n", archives, lang[MSG_OTHER_MAIL_ARCHIVES]); fprintf(fp, "\n
    %s%s%s%s%s%s%s
    %s%s
    \n
    \n"); #if DEBUG_HTML printcomment(fp, "fprint_menu", "end"); #endif } #endif /* non-tables version of fprint_menu */ void fprint_menu0(FILE *fp, struct emailinfo *email, int pos) { int dlev = (email->subdir != NULL); int num = email->msgnum; int loc_cmp = (pos == PAGE_BOTTOM ? 3 : 4); char *ptr; char *id= (pos == PAGE_TOP) ? "options2" : "options3"; #ifdef HAVE_ICONV size_t tmplen; char *tmpptr=i18n_convstring(email->subject,"UTF-8",email->charset,&tmplen); #endif if (!(set_show_msg_links && set_show_msg_links != loc_cmp) || (set_show_index_links && set_show_index_links != loc_cmp)) { fprintf(fp, "
      \n"); } if (set_mailcommand && set_hmail) { fprintf(fp, "
    • %s:", id,id,lang[MSG_MAIL_ACTIONS]); if ((email->msgid && email->msgid[0]) || (email->subject && email->subject[0])) { #ifdef HAVE_ICONV ptr = makemailcommand(set_replymsg_command, set_hmail, email->msgid, tmpptr); #else ptr = makemailcommand(set_replymsg_command, set_hmail, email->msgid, email->subject); #endif fprintf(fp, " [ %s ]", ptr ? ptr : "", lang[MSG_MA_REPLY]); if (ptr) free(ptr); } #ifdef HAVE_ICONV ptr = makemailcommand(set_newmsg_command, set_hmail, email->msgid, tmpptr); #else ptr = makemailcommand(set_newmsg_command, set_hmail, email->msgid, email->subject); #endif fprintf(fp, " [ %s ]", ptr ? ptr : "", lang[MSG_MA_NEW_MESSAGE]); if (ptr) free(ptr); fprintf (fp, "
    • \n"); } if (set_show_index_links && set_show_index_links != loc_cmp) { fprintf (fp, "
    • "); /* add the anchor if we didn't do so in the above block */ if (!(set_mailcommand && set_hmail)) fprintf (fp, "",id,id); fprintf(fp, "%s:", lang[MSG_CONTEMPORARY_MSGS_SORTED]); if (show_index[dlev][DATE_INDEX]) fprintf(fp, " [ %s ]", index_name[dlev][DATE_INDEX], set_fragment_prefix, num, lang[MSG_LTITLE_BY_DATE], lang[MSG_BY_DATE]); if (show_index[dlev][THREAD_INDEX]) fprintf(fp, " [ %s ]", index_name[dlev][THREAD_INDEX], set_fragment_prefix, num, lang[MSG_LTITLE_BY_THREAD], lang[MSG_BY_THREAD]); if (show_index[dlev][SUBJECT_INDEX]) fprintf(fp, " [ %s ]", index_name[dlev][SUBJECT_INDEX], set_fragment_prefix, num, lang[MSG_LTITLE_BY_SUBJECT], lang[MSG_BY_SUBJECT]); if (show_index[dlev][AUTHOR_INDEX]) fprintf(fp, " [ %s ]", index_name[dlev][AUTHOR_INDEX], set_fragment_prefix, num, lang[MSG_LTITLE_BY_AUTHOR], lang[MSG_BY_AUTHOR]); if (show_index[dlev][ATTACHMENT_INDEX]) fprintf(fp, " [ %s ]", index_name[dlev][ATTACHMENT_INDEX], lang[MSG_LTITLE_BY_ATTACHMENT], lang[MSG_BY_ATTACHMENT]); fprintf (fp, "
    • \n"); if (ihtmlhelpupfile) fprintf(fp, "
    • %s: %s
    • ", lang[MSG_HELP], ihtmlhelpupfile); } if (set_custom_archives && *set_custom_archives) fprintf(fp, "
    • %s: %s
    • \n", lang[MSG_OTHER_MAIL_ARCHIVES], set_custom_archives); if (!(set_show_msg_links && set_show_msg_links != loc_cmp) || (set_show_index_links && set_show_index_links != loc_cmp)) { fprintf (fp,"
    \n"); } #ifdef HAVE_ICONV if(tmpptr) free(tmpptr); #endif } /*----------------------------------------------------------------------------*/ #if 0 void fprint_summary(FILE *fp, int pos, long first_d, long last_d, int num) { #if DEBUG_HTML printcomment(fp, "fprint_summary", "begin"); #endif fprintf(fp, "
    \n"); fprintf(fp, "\n"); if (pos == PAGE_TOP) { fprintf(fp, "\n\n\n", num, lang[MSG_MESSAGES]); fprintf(fp, "\n \n", lang[MSG_STARTING], getdatestr(first_d)); fprintf(fp, " \n\n", lang[MSG_ENDING], getdatestr(last_d)); } else { /* bottom of page */ fprintf(fp, "\n", lang[MSG_LAST_MESSAGE_DATE], getdatestr(last_d)); fprintf(fp, "\n", lang[MSG_ARCHIVED_ON], getlocaltime()); } fprintf(fp, "
    %d %s
    %s:%s%s:%s
    %s: %s%s: %s
    \n
    \n"); #if DEBUG_HTML printcomment(fp, "fprint_summary", "end"); #endif } #endif /*----------------------------------------------------------------------------*/ void print_index_header_links (FILE *fp, mindex_t called_from, long startdatenum, long enddatenum, int amountmsgs, struct emailsubdir *subdir) { /* * Print out the links for * * About this archive * Other mail archives * Most recent messages * Messages sorted by: [ date ][ subject ][ author ] * * as appropriate. */ char *ptr; int dlev = (subdir != NULL); #if DEBUG_HTML printcomment(fp, "index_header_links", "begin"); #endif fprintf(fp, "\n", lang[MSG_NAVBAR]); fprintf(fp, "
      \n"); /* * Printout the Dates for the Starting and Ending messages * in the archive, along with a count of the messages. */ if ((called_from != AUTHOR_INDEX && show_index[dlev][AUTHOR_INDEX]) || (called_from != DATE_INDEX && show_index[dlev][DATE_INDEX]) || (called_from != THREAD_INDEX && show_index[dlev][THREAD_INDEX]) || (called_from != SUBJECT_INDEX && show_index[dlev][SUBJECT_INDEX])) { fprintf(fp, "
    • %d %s:" " %s %s,", amountmsgs, lang[MSG_ARTICLES], lang[MSG_STARTING], getdatestr(startdatenum)); fprintf(fp, " %s %s
    • \n", lang[MSG_ENDING], getdatestr(enddatenum)); if (!set_reverse && (called_from != AUTHOR_INDEX && called_from != SUBJECT_INDEX)) fprintf (fp, "
    • %s: %s
    • \n", lang[MSG_THIS_PERIOD], lang[MSG_MOST_RECENT_MESSAGES]); fprintf (fp, "
    • %s:", lang[MSG_SORT_BY]); } /* print the links to the other indexes */ if (show_index[dlev][THREAD_INDEX]) { if (called_from != THREAD_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][THREAD_INDEX], lang[MSG_LTITLE_BY_THREAD], lang[MSG_THREAD]); else fprintf(fp, " [ %s ]\n", lang[MSG_THREAD]); } if (show_index[dlev][AUTHOR_INDEX]) { if (called_from != AUTHOR_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][AUTHOR_INDEX], lang[MSG_LTITLE_BY_AUTHOR], lang[MSG_AUTHOR]); else fprintf(fp, " [ %s ]\n", lang[MSG_AUTHOR]); } if (show_index[dlev][DATE_INDEX]) { if (called_from != DATE_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][DATE_INDEX], lang[MSG_LTITLE_BY_DATE], lang[MSG_DATE]); else fprintf(fp, " [ %s ]\n", lang[MSG_DATE]); } if (show_index[dlev][SUBJECT_INDEX]) { if (called_from != SUBJECT_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][SUBJECT_INDEX], lang[MSG_LTITLE_BY_SUBJECT], lang[MSG_SUBJECT]); else fprintf(fp, " [ %s ]\n", lang[MSG_SUBJECT]); } if (set_attachmentsindex) { if (called_from != ATTACHMENT_INDEX) { fprintf(fp, " [ %s ]\n", index_name[dlev][ATTACHMENT_INDEX], lang[MSG_LTITLE_BY_ATTACHMENT], lang[MSG_ATTACHMENT]); } else fprintf(fp, " [ %s ]\n", lang[MSG_ATTACHMENT]); } fprintf (fp, "
    • \n"); /* print the mail actions */ if (set_mailcommand && set_hmail) { ptr = makemailcommand("mailto:$TO", set_hmail, "", ""); fprintf (fp, "
    • %s: [ %s ]
    • \n", lang[MSG_MAIL_ACTIONS], ptr ? ptr : "", lang[MSG_MA_NEW_MESSAGE]); if (ptr) free (ptr); } if (subdir) { fprintf(fp, "
    • %s:", lang[MSG_OTHER_PERIODS]); if (subdir->prior_subdir) fprintf(fp, "[ %s, %s ] ", subdir->rel_path_to_top, subdir->prior_subdir->subdir, index_name[dlev][called_from], lang[MSG_LTITLE_PREVPERIOD], lang[MSG_PREVPERIOD], lang[MSG_DATE_VIEW + called_from]); if (subdir->next_subdir) fprintf(fp, "[ %s, %s ] ", subdir->rel_path_to_top, subdir->next_subdir->subdir, index_name[dlev][called_from], lang[MSG_LTITLE_NEXTPERIOD], lang[MSG_NEXTPERIOD], lang[MSG_DATE_VIEW + called_from]); if (show_index[0][FOLDERS_INDEX]) fprintf(fp, "[ %s ]", subdir->rel_path_to_top, index_name[0][FOLDERS_INDEX], lang[MSG_LTITLE_FOLDERS_INDEX], lang[MSG_FOLDERS_INDEX]); fprintf (fp, "
    • \n"); } /* the following are the custom options */ if (ihtmlhelpupfile) fprintf(fp, "
    • %s: %s
    • ", lang[MSG_HELP], ihtmlhelpupfile); if ((set_about && *set_about) || (set_archives && *set_archives)) { fprintf (fp, "
    • %s:", lang[MSG_NEARBY]); if (set_about && *set_about) fprintf(fp, " [ %s ]", set_about, lang[MSG_ABOUT_THIS_ARCHIVE]); if (set_archives && *set_archives) fprintf(fp, " [ %s ]", set_archives, lang[MSG_OTHER_MAIL_ARCHIVES]); fprintf (fp, "
    • \n"); } if (set_custom_archives && *set_custom_archives) fprintf(fp, "
    • %s: %s
    • \n", lang[MSG_OTHER_MAIL_ARCHIVES], set_custom_archives); fprintf (fp, "
    \n
    \n"); /* * Printout the Dates for the Starting and Ending messages * in the archive, along with a count of the messages. */ #if DEBUG_HTML printcomment(fp, "index_header_links", "end"); #endif } void print_index_footer_links(FILE *fp, mindex_t called_from, long enddatenum, int amountmsgs, struct emailsubdir *subdir) { /* * Print out the links for * * Messages sorted by: [ date ][ subject ][ author ] * Other mail archives * * as appropriate. */ char *ptr; int dlev = (subdir != NULL); #if DEBUG_HTML printcomment(fp, "index_footer_links", "begin"); #endif fprintf (fp, "
    \n"); fprintf (fp, "\n", lang[MSG_NAVBAR]); fprintf (fp, "
      \n"); if ((called_from != AUTHOR_INDEX && show_index[dlev][AUTHOR_INDEX]) || (called_from != DATE_INDEX && show_index[dlev][DATE_INDEX]) || (called_from != THREAD_INDEX && show_index[dlev][THREAD_INDEX]) || (called_from != SUBJECT_INDEX && show_index[dlev][SUBJECT_INDEX])) fprintf(fp, "
    • %d %s " "%s:\n", amountmsgs, lang[MSG_ARTICLES], lang[MSG_SORT_BY]); /* print the links to the other indexes */ if (show_index[dlev][THREAD_INDEX]) { if (called_from != THREAD_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][THREAD_INDEX], lang[MSG_LTITLE_BY_THREAD], lang[MSG_THREAD]); else fprintf(fp, " [ %s ]\n", lang[MSG_THREAD]); } if (show_index[dlev][AUTHOR_INDEX]) { if (called_from != AUTHOR_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][AUTHOR_INDEX], lang[MSG_LTITLE_BY_AUTHOR], lang[MSG_AUTHOR]); else fprintf(fp, " [ %s ]\n", lang[MSG_AUTHOR]); } if (show_index[dlev][DATE_INDEX]) { if (called_from != DATE_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][DATE_INDEX], lang[MSG_LTITLE_BY_DATE], lang[MSG_DATE]); else fprintf(fp, " [ %s ]\n", lang[MSG_DATE]); } if (show_index[dlev][SUBJECT_INDEX]) { if (called_from != SUBJECT_INDEX) fprintf(fp, " [ %s ]\n", index_name[dlev][SUBJECT_INDEX], lang[MSG_LTITLE_BY_SUBJECT], lang[MSG_SUBJECT]); else fprintf(fp, " [ %s ]\n", lang[MSG_SUBJECT]); } if (set_attachmentsindex) { if (called_from != ATTACHMENT_INDEX) { fprintf(fp, " [ %s ]\n", index_name[dlev][ATTACHMENT_INDEX], lang[MSG_LTITLE_BY_ATTACHMENT], lang[MSG_ATTACHMENT]); } else fprintf(fp, " [ %s ]\n", lang[MSG_ATTACHMENT]); } fprintf (fp, "
    • \n"); /* print the mail actions */ if (set_mailcommand && set_hmail) { ptr = makemailcommand("mailto:$TO", set_hmail, "", ""); fprintf (fp, "
    • %s: [ %s ]
    • \n", lang[MSG_MAIL_ACTIONS], ptr ? ptr : "", lang[MSG_MA_NEW_MESSAGE]); if (ptr) free (ptr); } if (subdir) { fprintf(fp, "
    • %s:", lang[MSG_OTHER_PERIODS]); if (subdir->prior_subdir) fprintf(fp, "[ %s, %s ] ", subdir->rel_path_to_top, subdir->prior_subdir->subdir, index_name[dlev][called_from], lang[MSG_LTITLE_PREVPERIOD], lang[MSG_PREVPERIOD], lang[MSG_DATE_VIEW + called_from]); if (subdir->next_subdir) fprintf(fp, "[ %s, %s ] ", subdir->rel_path_to_top, subdir->next_subdir->subdir, index_name[dlev][called_from], lang[MSG_LTITLE_NEXTPERIOD], lang[MSG_NEXTPERIOD], lang[MSG_DATE_VIEW + called_from]); if (show_index[0][FOLDERS_INDEX]) fprintf(fp, "[ %s ]", subdir->rel_path_to_top, index_name[0][FOLDERS_INDEX], lang[MSG_LTITLE_FOLDERS_INDEX], lang[MSG_FOLDERS_INDEX]); fprintf (fp, "
    • \n"); } if (ihtmlhelplowfile) fprintf(fp, "
    • %s: %s
    • ", lang[MSG_HELP], ihtmlhelplowfile); if ((set_about && *set_about) || (set_archives && *set_archives)) { fprintf (fp, "
    • %s:", lang[MSG_NEARBY]); if (set_about && *set_about) fprintf(fp, " [ %s ]", set_about, lang[MSG_ABOUT_THIS_ARCHIVE]); if (set_archives && *set_archives) fprintf(fp, " [ %s ]", set_archives, lang[MSG_OTHER_MAIL_ARCHIVES]); fprintf (fp, "
    • \n"); } if (set_custom_archives && *set_custom_archives) fprintf(fp, "
    • %s: %s
    • \n", lang[MSG_OTHER_MAIL_ARCHIVES], set_custom_archives); fprintf (fp, "
    \n
    \n"); #if DEBUG_HTML printcomment(fp, "index_footer_links", "end"); #endif } /*----------------------------------------------------------------------------*/ void print_haof_indices(FILE *fp, struct emailsubdir *subdir) { int dlev = (subdir != NULL); fprintf(fp, " \n"); if (show_index[dlev][DATE_INDEX]) fprintf(fp, " %s\n", index_name[dlev][DATE_INDEX]); if (show_index[dlev][SUBJECT_INDEX]) fprintf(fp, " %s\n", index_name[dlev][SUBJECT_INDEX]); if (show_index[dlev][THREAD_INDEX]) fprintf(fp, " %s\n", index_name[dlev][THREAD_INDEX]); if (show_index[dlev][AUTHOR_INDEX]) fprintf(fp, " %s\n", index_name[dlev][AUTHOR_INDEX]); if (show_index[dlev][ATTACHMENT_INDEX]) fprintf(fp, " %s\n", index_name[dlev][ATTACHMENT_INDEX]); fprintf(fp, " \n\n"); } /* ** Prints a comment in the file. */ void printcomment(FILE *fp, char *label, char *value) { if (label && *label && value && *value) { /* we only save the non-NULL ones */ char *ext_label; char *ext_value; char *ptr; /* It's illegal in a comment to have a value which has a -- sequence */ if (strstr (label, "--")) ext_label = convdash (label); else ext_label = label; if (strstr (value, "--")) ext_value = convdash (value); else ext_value = value; ptr = strchr(ext_value, '@'); if (set_spamprotect_id && ptr && (!strcmp(label, "id") || !strcmp(label, "inreplyto"))) { struct Push retbuf; INIT_PUSH(retbuf); PushNString(&retbuf, ext_value, ptr - ext_value); PushNString(&retbuf, set_antispam_at, strlen(set_antispam_at)); PushString(&retbuf, ptr + 1); if (ext_value != value) free (ext_value); ext_value = PUSH_STRING(retbuf); } fprintf(fp, "\n", ext_label, ext_value); if (ext_label != label) free(ext_label); if (ext_value != value) free(ext_value); } } /* ** Prints a line of HTML. Used to filter off unwanted tags from the output. */ void printhtml(FILE *fp, char *line) { /* the banned tags ignore all of them that begin exactly like "" }; /* ending >-letter must be included */ unsigned int i; int lindex; while (*line) { if ('<' != *line) fputc(*line++, fp); else { if ('/' == line[1]) lindex = 2; else lindex = 1; for (i = 0; i < sizeof(banned_tags) / sizeof(banned_tags[0]); i++) { if (!strncasecmp(&line[lindex], banned_tags[i], strlen(banned_tags[i]))) { line += strlen(banned_tags[i]) + lindex; break; } } if (sizeof(banned_tags) / sizeof(banned_tags[0]) == i) { fputc(*line++, fp); if (2 == lindex) fputc(*line++, fp); } } } } /* ** Pretty-prints the dates in the index files. */ void printdates(FILE *fp, struct header *hp, int year, int month, struct emailinfo *subdir_email, char *prev_date_str) { char *subject=NULL,*name=NULL; const char *startline; const char *break_str; const char *endline; const char *subj_tag; const char *subj_end_tag; static char date_str[DATESTRLEN+40]; /* made static for smaller stack */ static char *first_attributes = ""; if (hp != NULL) { struct emailinfo *em=hp->data; printdates(fp, hp->left, year, month, subdir_email, prev_date_str); if ((year == -1 || year_of_datenum(em->date) == year) && (month == -1 || month_of_datenum(em->date) == month) && !em->is_deleted && (!subdir_email || subdir_email->subdir == em->subdir)) { #ifdef HAVE_ICONV subject = convchars(em->subject, "utf-8"); name = convchars(em->name, "utf-8"); #else subject = convchars(em->subject, em->charset); name = convchars(em->name, em->charset); #endif if(set_indextable) { startline = ""; break_str = ""; strcpy(date_str, getdateindexdatestr(hp->data->date)); endline = ""; subj_tag = ""; subj_end_tag = ""; } else { char *tmp; bool is_first; tmp = getdateindexdatestr(hp->data->date); if (strcmp (prev_date_str, tmp)) { if (*prev_date_str) { /* close the previous date item */ fprintf (fp, "
  • \n"); is_first = FALSE; } else is_first = TRUE; snprintf(date_str, sizeof(date_str), "
  • %s%s
      \n", (is_first) ? first_attributes : "", tmp); fprintf (fp, "%s", date_str); strcpy (prev_date_str, tmp); } date_str[0] = 0; startline = "
    • "; break_str = " "; endline = "
    • "; subj_tag = ""; subj_end_tag = ""; } fprintf(fp,"%s%s%s%s%s%s%s%s%s\n", startline, msg_href(em, subdir_email, FALSE), subj_tag, subject, subj_end_tag, break_str, set_fragment_prefix, em->msgnum, set_fragment_prefix, em->msgnum, name, break_str, date_str, endline); free(subject); free(name); } printdates(fp, hp->right, year, month, subdir_email, prev_date_str); } } /* ** Pretty-prints the files with attachments in the index files. ** Returns the number of attachments that were printed. */ int printattachments(FILE *fp, struct header *hp, struct emailinfo *subdir_email, bool *is_first) { char *subject=NULL,*name=NULL; char *attdir; char *msgnum; int nb_attach = 0; static char *first_attributes = ""; const char *rel_path_to_top = (subdir_email ? subdir_email->subdir->rel_path_to_top : ""); if (hp != NULL) { struct emailinfo *em = hp->data; nb_attach = printattachments(fp, hp->left, subdir_email, is_first); if ((!subdir_email || subdir_email->subdir == em->subdir) && !em->is_deleted) { subject = (set_i18n) ? em->subject : convchars(em->subject, em->charset); name = (set_i18n) ? em->name : convchars(em->name,em->charset); /* See if there's a directory corresponding to this message */ msgnum = message_name(em); trio_asprintf(&attdir, "%s%c" DIR_PREFIXER "%s", set_dir, PATH_SEPARATOR, msgnum); if (isdir(attdir)) { DIR *dir = opendir(attdir); /* consider that if there's an attachment directory, there are attachments */ nb_attach++; if (set_indextable) { fprintf(fp, "%s%s%s" "%s\n", msg_href(em, subdir_email, TRUE), subject, set_fragment_prefix, em->msgnum, set_fragment_prefix, em->msgnum, name, getindexdatestr(em->date)); } else { fprintf(fp, "
    • %s%s%s " "%s (%s)\n", (*is_first) ? first_attributes : "", msg_href(em, subdir_email, TRUE), subject, set_fragment_prefix, em->msgnum, set_fragment_prefix, em->msgnum, name, getindexdatestr(em->date)); if (*is_first) *is_first = FALSE; } if (dir) { #ifdef HAVE_DIRENT_H struct dirent *entry; #else struct direct *entry; #endif struct stat fileinfo; char *filename, *stripped_filename; const char *fmt2 = (set_indextable ? "    %s" "(%d %s)\n" : "
    • %s (%d %s)
    • \n"); int first_time = 1; while ((entry = readdir(dir))) { int file_size = -1; if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name)) continue; nb_attach++; if (first_time && !set_indextable) { first_time = 0; fprintf(fp, "
        \n"); } trio_asprintf(&filename, "%s%c%s", attdir, PATH_SEPARATOR, entry->d_name); if (!stat(filename, &fileinfo)) file_size = (int)fileinfo.st_size; free(filename); trio_asprintf(&filename, DIR_PREFIXER "%s%c%s", message_name(em), PATH_SEPARATOR, entry->d_name); stripped_filename = strchr(entry->d_name, '-'); if (stripped_filename) fprintf(fp, fmt2, rel_path_to_top, filename, stripped_filename + 1, file_size, lang[MSG_BYTES]); else if(strcmp(entry->d_name, ".meta")) fprintf(fp, fmt2, rel_path_to_top, filename, entry->d_name, file_size, lang[MSG_BYTES]); free(filename); } if (!first_time && !set_indextable) { fprintf(fp, "
      \n"); } closedir(dir); } } free(attdir); if (!set_i18n) { free(subject); free(name); } } nb_attach += printattachments(fp, hp->right, subdir_email, is_first); } return nb_attach; } int showheader(char *header) { return (!inlist (set_skip_headers, header) && (inlist(set_show_headers, header) || inlist(set_show_headers, "*"))); } /* * ConvURLsWithHrefs handles lines with URLs that are already written as * href's, to avoid having ConvURLsString add a second href to those URLs. */ static char *ConvURLsWithHrefs(const char *line, char *mailid, char *mailsubject, char *c, char *charset) { char *p; struct Push retbuf; char *tmpline5; char *tmpline6; char *tmpline1; /* only do the convertion if a complete href is found */ p = strcasestr(c, ""); if (!p) return NULL; tmpline1 = (char *)emalloc(strlen(line) + 1); strncpy(tmpline1, line, c - line); /* AUDIT biege: who gurantees that c-line doesnt become smaller 0? IOF? */ tmpline1[c - line] = 0; INIT_PUSH(retbuf); /* complete href found; run ConvURLsString on text outside it */ tmpline5 = ConvURLsString(tmpline1, mailid, mailsubject, charset); if (!tmpline5) return NULL; PushString(&retbuf, tmpline5); free(tmpline5); p += 4; tmpline6 = NULL; /* pcm 2007-10-01 disabled the following ConvURLsString call to have */ /* it escape urls in mid line the same as it did for urls at start of */ /* line. I'm still puzzled why the change works. */ /* tmpline6 = ConvURLsString(p, mailid, mailsubject, charset); */ if (!tmpline6) { free(PUSH_STRING(retbuf)); return NULL; } strncpy(tmpline1, c, p - c); /* AUDIT biege: who gurantees that p-c doesnt become smaller 0? IOF? */ tmpline1[p - c] = 0; /* convert markup to lower case for XHTML compatiblity */ p = tmpline1 + 1; while (*p != '=') { *p = tolower (*p); p++; } p = strstr (tmpline1, ""); if (p) *(p+2) = 'a'; PushString(&retbuf, tmpline1); PushString(&retbuf, tmpline6); free(tmpline1); free(tmpline6); RETURN_PUSH(retbuf); } /* * ConvMsgid converts a msgid into a link to the message it refers to if that * message is in the archive, and call ConvURLsString on the rest of the line. */ static char *ConvMsgid(char *line, char *inreply, char *mailid, char *mailsubject, char *charset) { char *tmpline4; int subjmatch; char *tmpline1; char *c; struct Push buff; struct emailinfo *ep = hashreplylookup(-1, inreply, mailsubject, &subjmatch); if (ep == NULL || subjmatch) return NULL; /* not a known msgid - maybe an email addr? */ c = strstr(line, inreply); if (!c) return NULL; /* should never happen */ INIT_PUSH(buff); tmpline1 = (char *)emalloc(c - line + 1); strncpy(tmpline1, line, c - line); /* AUDIT biege: who gurantees that c-line doesnt become smaller 0? IOF? */ tmpline1[c - line] = 0; tmpline4 = ConvURLsString(tmpline1, mailid, mailsubject, charset); free(tmpline1); PushString(&buff, tmpline4); free(tmpline4); PushString(&buff, msg_href(ep, ep, TRUE)); PushString(&buff, inreply); PushString(&buff, ""); tmpline4 = ConvURLsString(c + strlen(inreply), mailid, mailsubject, charset); if (tmpline4) { PushString(&buff, tmpline4); free(tmpline4); } else if (0) printf("cant ConvURLsString %s | %s.\n", c, inreply); RETURN_PUSH(buff); } /* ** Converts URLs, email addresses, and message IDs in a line to links, ** mail commands, and articles respectively. Write everything to the ** file pointed to by 'fp'. */ void ConvURLs(FILE *fp, char *line, char *mailid, char *mailsubject, char *charset) { char *parsed = ConvURLsString(line, mailid, mailsubject, charset); if (parsed) { /* write it to the file! */ /* add a call to convchars with charset */ fwrite(parsed, strlen(parsed), 1, fp); free(parsed); } } char *ConvURLsString(char *line, char *mailid, char *mailsubject, char *charset) { char *parsed; char *newparse; char *c; #ifdef HAVE_ICONV size_t tmplen; char *tmpptr=i18n_convstring(mailsubject,"UTF-8",charset,&tmplen); mailsubject=tmpptr; #endif if (set_href_detection) { if ((c = strcasestr(line, "")) return parsed; /* we didn't find any previous href convertion, we try to do a mailto: convertion */ if (use_mailcommand) { /* Exclude headers that are not mail type headers */ if (parsed && *parsed) { newparse = parseemail(parsed, /* source */ mailid, /* mail's Message-Id: */ mailsubject, /* mail's Subject: */ MAKEMAILCOMMAND); /* make a mailto: */ free(parsed); parsed = newparse; } } #ifdef HAVE_ICONV if(tmpptr) free(tmpptr); #endif return parsed; } void printheaders (FILE *fp, struct emailinfo *email) { struct body *bp = email->bodylist; char *id = email->msgid; char *subject = email->subject; char head[128]; char head_lower[128]; char *header_content; if (REMOVE_MESSAGE(email)) { int d_index = MSG_DELETED; if (email->is_deleted == 2) d_index = MSG_EXPIRED; if (email->is_deleted == 4 || email->is_deleted == 8) d_index = MSG_FILTERED_OUT; fprintf(fp, ""); fprintf(fp, "(%s)\n", lang[d_index]); return; } if (set_show_headers) { while (bp != NULL && bp->header) { if ((bp->line)[0] == '\n') { /* don't try to convert newline */ break; } if (sscanf(bp->line, "%127[^:]", head) == 1 && showheader(head)) { /* this is a header we want to show */ strcpy (head_lower, head); strtolower (head_lower); /* we print the header, escaping it as needed */ header_content = bp->line + strlen (head) + 2; fprintf (fp, "%s: ", head_lower, head); /* JK: avoid converting Message-Id: headers */ if (!strcmp(head_lower, "message-id") && use_mailcommand) { /* we desactivate it just during this conversion */ use_mailcommand = 0; ConvURLs(fp, header_content, id, subject, email->charset); use_mailcommand = 1; } else{ #ifdef HAVE_ICONV size_t tmplen; char *tmpptr=i18n_convstring(header_content,"UTF-8",email->charset,&tmplen); ConvURLs(fp, tmpptr, id, subject, email->charset); if (tmpptr) free(tmpptr); #else ConvURLs(fp, header_content, id, subject, email->charset); #endif } fprintf (fp, "
      \n"); } /* go to the next header or stop if we reached the end of the headers (signaled thru the \n char). */ if ((bp->line)[0] != '\n') { bp = bp->next; continue; } else break; } } } /* printheaders */ /* ** The heuristics for displaying an otherwise ordinary line (a non-quote, ** non-sig, non-inhtml, non-blank line) if 'showhtml' is 1 (which really means ** we're *not* doing
       or txt2html to format the text) have changed so
      ** that indented text shows up correctly.  First, leading spaces become HTML
      ** non-breaking spaces ( ).  In order for this to work, those lines
      ** must have been preceded by a 
      or

      . We accomplish this by checking ** ahead when we print each line... if we determine that the next line ** should be broken before, we do so. */ void printbody(FILE *fp, struct emailinfo *email, int maybe_reply, int is_reply) { int insig, inblank; struct body *bp = email->bodylist; char *id = email->msgid; char *subject = email->subject; int msgnum = email->msgnum; char inheader = FALSE; /* we always start in a mail header */ int pre = FALSE; int inquote; int quote_num; int quoted_percent; bool replace_quoted; if (set_linkquotes || set_showhtml == 2) /* should be changed to unconditional after tested for a while? - pcm@rahul.net 1999-09-09 */ find_quote_prefix(email->bodylist, is_reply); if (set_quote_hide_threshold <= 100) quoted_percent = compute_quoted_percent(bp); else quoted_percent = 100; replace_quoted = (quoted_percent > set_quote_hide_threshold); if (set_showprogress && replace_quoted) printf("\nMessage %d quoted text (%d %%) replaced by links\n", msgnum, quoted_percent); if (email->is_deleted && set_delete_level != DELETE_LEAVES_TEXT && !(email->is_deleted == 2 && set_delete_level == DELETE_LEAVES_EXPIRED_TEXT)) { int d_index = MSG_DELETED; if (email->is_deleted == 2) d_index = MSG_EXPIRED; if (email->is_deleted == 4 || email->is_deleted == 8) d_index = MSG_FILTERED_OUT; if (email->is_deleted == 64) d_index = MSG_DELETED_OTHER; switch(d_index) { case MSG_DELETED: if(set_htmlmessage_deleted_spam){ fprintf(fp,"%s\n",set_htmlmessage_deleted_spam); break; } case MSG_DELETED_OTHER: if(set_htmlmessage_deleted_other){ fprintf(fp,"%s\n",set_htmlmessage_deleted_other); break; } default: fprintf(fp, ""); fprintf(fp, "

      %s

      \n", lang[d_index]); } return; } if (email->annotation_content == ANNOTATION_CONTENT_EDITED) { if (set_htmlmessage_edited) fprintf(fp,"%s\n",set_htmlmessage_edited); else fprintf(fp, "

      %s

      \n", lang[MSG_EDITED]); } if (!set_showhtml) { fprintf(fp, "
      \n");
      	pre = TRUE;
          }
      
          /* tag the start of the message body */
          fprintf(fp, "");
      
          if (set_showhtml == 2)
            init_txt2html();
          inquote = 0;
          quote_num = 0;
      
          inblank = 1;
          insig = 0;
      
          while (bp != NULL) {
      	if (bp->html) {
      	  /* already in HTML, don't touch */
        	  if (pre) {
      	    fprintf(fp, "
      \n"); pre = FALSE; } printhtml(fp, bp->line); inheader = FALSE; /* this can't be a header if already in HTML */ bp = bp->next; continue; } if (bp->header) { char head[128]; if (!inheader) { /* JK: I'm not sure why, but I had a !set_showhtml here */ if (!set_showhtml && !pre && set_showheaders) { fprintf(fp, "
      \n");
      		pre = TRUE;
      	      }
      	      inheader = TRUE;
      	    }
      	    if (sscanf(bp->line, "%127[^:]", head) == 1 && set_show_headers && !showheader(head)) {
      	      /* the show header keyword has been used, then we skip all those
      		 that aren't mentioned! */
      	      if (isalnum(*head) || !set_showheaders) {
      		/* this check is only to make sure that the last line among 
      		   the headers (the "\n" one) won't be filtered off */
      		bp = bp->next;
      		continue;
      	      }
      	    }
      	}
      	else {
      	  if (inheader) {
      	    insig = 0;
      	    if (set_showhtml) {
      	      if (pre) {
      		fprintf(fp, "
      \n"); pre = FALSE; } fprintf(fp, "
      \n"); } else { if (!pre) { fprintf(fp, "
      \n");
      		pre = TRUE;
      	      }
      	    }
      	    inheader = FALSE;
      	  }
      	}
      
      	if (((bp->line)[0] != '\n') && (bp->header && !set_showheaders)) {
      	    bp = bp->next;
      	    continue;
      	}
      
      	if (set_showhtml == 2 && !inheader) {
      	    txt2html(fp, email, bp, replace_quoted, maybe_reply);
      	    bp = bp->next;
      	    continue;
      	}
      
              if (bp->header && set_showheaders && !pre) {
      	  fprintf(fp, "
      \n");
      	  pre = TRUE;
      	}
       
      	if ((bp->line)[0] == '\n' && inblank) {
      	  bp = bp->next;
      	  continue;
      	}
      	else
      	  inblank = 0;
      	
      	if (set_showhtml) {
      	  if (is_sig_start(bp->line)) {
      	    insig = 1;
      	    if (!pre) {
      	      fprintf(fp, "
      \n");
      	      pre = TRUE;
      	    }
      	  }
      	  
      	  if (!inheader && (bp->line)[0] == '\n')
      	    /* within the 
       statements you do not need to
      	       insert 

      statements since text is already preformated. the W3C HTML validation script fails for such pages Akis Karnouskos */ { if (!pre) fprintf(fp, "
      "); } else { if (insig) { ConvURLs(fp, bp->line, id, subject, email->charset); } else if (isquote(bp->line)) { if (set_linkquotes) { if (handle_quoted_text(fp, email, bp, bp->line, inquote, quote_num, replace_quoted, maybe_reply)) { ++quote_num; inquote = 1; } } else { fprintf(fp, "<%s class=\"%s\">", set_iquotes ? "em" : "span", find_quote_class(bp->line)); ConvURLs(fp, bp->line, id, subject, email->charset); fprintf(fp, "%s
      \n", (set_iquotes) ? "" : ""); } } else if ((bp->line)[0] != '\0' && !bp->header) { char *sp; sp = print_leading_whitespace(fp, bp->line); /* JK: avoid converting Message-Id: headers */ if (bp->header && bp->parsedheader && !strncasecmp(bp->line, "Message-Id:", 11) && use_mailcommand) { /* we desactivate it just during this conversion */ use_mailcommand = 0; ConvURLs(fp, sp, id, subject, email->charset); use_mailcommand = 1; } else ConvURLs(fp, sp, id, subject, email->charset); /* * Determine whether we should break. * We could check for leading spaces * or quote lines, but in general, * non-alphanumeric lines should be * broken before. */ if ((set_showbr && !bp->header) || ((bp->next != NULL) && !isalnum(bp->next->line[0]))) fprintf(fp, "
      "); if (!bp->header) { fprintf(fp, "\n"); } } } } else if ((bp->line)[0] != '\0' && !bp->header) { /* JK: avoid converting Message-Id: headers */ if (bp->header && bp->parsedheader && !strncasecmp(bp->line, "Message-Id:", 11) && use_mailcommand) { /* we desactivate it just during this conversion */ use_mailcommand = 0; ConvURLs(fp, bp->line, id, subject, email->charset); use_mailcommand = 1; } else ConvURLs(fp, bp->line, id, subject, email->charset); } if (!isquote(bp->line)) inquote = 0; bp = bp->next; } if (pre) fprintf(fp, "

      \n"); else if (set_showhtml == 2) end_txt2html(fp); } char *print_leading_whitespace(FILE *fp, char *sp) { while (*sp && (*sp == ' ' || *sp == '\t')) { if (*sp == '\t') fprintf(fp, "        "); else fprintf(fp, " "); sp++; } return sp; } void print_headers(FILE *fp, struct emailinfo *email, int in_thread_file) { /* * Print the message's author info and date. * General form: from:: name
      */ fprintf(fp, "
      \n"); #ifdef HAVE_ICONV size_t tmplen; char *tmpsubject=i18n_convstring(email->subject,"UTF-8",email->charset,&tmplen); char *tmptmpname=i18n_convstring(email->name,"UTF-8",email->charset,&tmplen); char *tmpname=convchars(tmptmpname,"utf-8"); free(tmptmpname); #else char *tmpsubject=0; char *tmpname=convchars(email->name, email->charset); #endif /* the from header */ fprintf (fp, "\n"); fprintf (fp, "%s: ", lang[MSG_FROM]); if (REMOVE_MESSAGE(email)) { /* don't show the email address and name if we have deleted the message */ fprintf(fp, "<%s>", lang[MSG_SENDER_DELETED]); } else if (!strcmp(email->name, email->emailaddr)) { if (use_mailcommand) { char *ptr = makemailcommand(set_mailcommand, email->emailaddr, #ifdef HAVE_ICONV email->msgid, tmpsubject); #else email->msgid, email->subject); #endif fprintf(fp, "<%s>", ptr ? ptr : "", obfuscate_email_address(email->emailaddr)); if (ptr) free(ptr); } else fprintf(fp, "%s", tmpname); } else { if (use_mailcommand && strcmp(email->emailaddr, "(no email)") != 0) { char *ptr = makemailcommand(set_mailcommand, email->emailaddr, #ifdef HAVE_ICONV email->msgid, tmpsubject); #else email->msgid, email->subject); #endif fprintf(fp, "%s <%s>", tmpname, ptr ? ptr : "", obfuscate_email_address(email->emailaddr)); if (ptr) free(ptr); } else { fprintf(fp, "%s <%s>", tmpname, (strcmp(email->emailaddr, "(no email)") != 0) ? email->emailaddr : "no email"); } } fprintf (fp, "\n
      \n"); /* subject */ if (in_thread_file) #ifdef HAVE_ICONV fprintf(fp, "%s: %s
      \n", lang[MSG_SUBJECT], tmpsubject); #else fprintf(fp, "%s: %s
      \n", lang[MSG_SUBJECT], tmpsubject=convchars(email->subject,email->charset)); #endif /* date */ fprintf(fp, "%s: %s
      \n", lang[MSG_CDATE], email->datestr); printheaders (fp, email); fprintf(fp, "
      \n"); if(tmpsubject) free(tmpsubject); if(tmpname) free(tmpname); } static char *href01(struct emailinfo *email, struct emailinfo *email2, int in_thread_file, bool generate_markup) { static char buffer[256]; if (in_thread_file) { if (generate_markup) sprintf(buffer, "", email2->msgnum); else sprintf(buffer, "#%.4d", email2->msgnum); return buffer; } else return msg_href(email2, email, generate_markup); } static void print_replies(FILE *fp, struct emailinfo *email, int num, int in_thread_file) { struct reply *rp; struct emailinfo *email2; char *ptr; bool list_started = FALSE; #ifdef FASTREPLYCODE for (rp = email->replylist; rp != NULL; rp = rp->next) { if (hashnumlookup(rp->msgnum, &email2)) { #else for (rp = replylist; rp != NULL; rp = rp->next) { if (rp->frommsgnum == num && hashnumlookup(rp->msgnum, &email2)) { #endif char *del_msg = (email2->is_deleted ? lang[MSG_DEL_SHORT] : ""); if (!list_started) { list_started = TRUE; fprintf (fp, "
    • \n"); } else fprintf (fp, "
    • "); if (rp->maybereply) fprintf(fp, "%s:", lang[MSG_MAYBE_REPLY]); else fprintf(fp, "%s:", lang[MSG_REPLY]); fprintf(fp, "%s ", del_msg, href01(email, email2, in_thread_file, FALSE), lang[MSG_LTITLE_REPLIES]); #ifdef HAVE_ICONV char *tmpptr; ptr = i18n_utf2numref(email2->subject,1); tmpptr = i18n_utf2numref(email2->name,1); fprintf(fp, "%s: \"%s\"
    • \n", tmpptr, ptr); if (tmpptr) free(tmpptr); #else ptr = convchars(email2->subject, email2->charset); fprintf(fp, "%s: \"%s\"\n", email2->name, ptr); #endif if (ptr) free(ptr); } } printcomment(fp, "lreply", "end"); } int print_links_up(FILE *fp, struct emailinfo *email, int pos, int in_thread_file) { int num = email->msgnum; int subjmatch; struct emailinfo *email2; struct emailinfo *email_next_in_thread = nextinthread(email->msgnum); char *ptr; struct reply *rp; int is_reply = 0; int loc_cmp = (pos == PAGE_BOTTOM ? 3 : 4); /* * Should we print message links ? */ if (set_show_msg_links && set_show_msg_links != loc_cmp) { if (pos == PAGE_TOP) ptr = "navbar"; else ptr = "navbarfoot"; fprintf(fp, "\n", ptr, ptr); if (pos == PAGE_TOP) fprintf(fp, "
        \n"); fprintf(fp, "
      • \n"); fprintf(fp, "%s:\n", lang[MSG_THIS_MESSAGE]); fprintf(fp, "[ " "%s ]\n", lang[MSG_MSG_BODY]); if (set_mailcommand && set_hmail) { if ((email->msgid && email->msgid[0]) || (email->subject && email->subject[0])) { #ifdef HAVE_ICONV size_t tmplen; char *tmpptr=i18n_convstring(email->subject,"UTF-8",email->charset,&tmplen); ptr = makemailcommand(set_replymsg_command, set_hmail, email->msgid, tmpptr); if (tmpptr) free(tmpptr); #else ptr = makemailcommand(set_replymsg_command, set_hmail, email->msgid, email->subject); #endif fprintf(fp, " [ %s ]\n", ptr, lang[MSG_MA_REPLY], lang[MSG_RESPOND]); if (ptr) free(ptr); } } switch(set_show_index_links){ case 0: break; case 1: fprintf(fp, " [ %s (top, bottom) ]\n", lang[MSG_MORE_OPTIONS]); break; case 3: fprintf(fp, " [ %s ]\n", lang[MSG_MORE_OPTIONS]); break; case 4: fprintf(fp, " [ %s ]\n", lang[MSG_MORE_OPTIONS]); break; } fprintf(fp, "
      • \n"); fprintf(fp, "
      • \n"); fprintf(fp, "%s:\n", lang[MSG_RELATED_MESSAGES]); /* * Is there a next message? */ printcomment(fp, "unext", "start"); email2 = neighborlookup(num, 1); if (email2) { char *tmpptr; #ifdef HAVE_ICONV ptr=i18n_utf2numref(email2->subject,1); tmpptr=i18n_utf2numref(email2->name,1); #else ptr = convchars(email2->subject, email2->charset); tmpptr= convchars(email2->name,email2->charset); #endif fprintf(fp, "[ %s ]\n", msg_href (email2, email, FALSE), tmpptr, ptr ? ptr : "", lang[MSG_NEXT_MESSAGE]); if (tmpptr) free(tmpptr); if (ptr) free(ptr); } /* * Is there a previous message? */ email2 = neighborlookup(num, -1); #if 0 /* pcm removed 2002-08-30, old_reply_to is always NULL */ if (set_linkquotes && old_reply_to && pos == PAGE_BOTTOM && num - 1 == (get_new_reply_to() == -1 ? old_reply_to->msgnum : get_new_reply_to())) email2 = NULL; #endif if (email2) { char *tmpptr; #ifdef HAVE_ICONV ptr = i18n_utf2numref(email2->subject,1); tmpptr=i18n_utf2numref(email2->name,1); #else ptr = convchars(email2->subject, email2->charset); tmpptr=convchars(email2->name,email2->charset); #endif fprintf(fp, "[ %s ]\n", msg_relpath(email2, email), tmpptr, ptr ? ptr : "", lang[MSG_PREVIOUS_MESSAGE]); if (ptr) free(ptr); if (tmpptr) free(tmpptr); } /* * Is this message a reply to another? */ if (email->inreplyto[0]) { email2 = hashreplylookup(email->msgnum, email->inreplyto, email->subject, &subjmatch); if (email2) { char *del_msg = (email2->is_deleted ? lang[MSG_DEL_SHORT] : ""); is_reply = 1; char *tmpptr; #ifdef HAVE_ICONV ptr = i18n_utf2numref(email2->subject,1); tmpptr=i18n_utf2numref(email2->name,1); #else ptr = convchars(email2->subject, email2->charset); tmpptr=convchars(email2->name,email2->charset); #endif fprintf(fp, "[ %s ]\n", href01(email, email2, in_thread_file, FALSE), del_msg, tmpptr, ptr ? ptr : "", (subjmatch) ? lang[MSG_MAYBE_IN_REPLY_TO] : lang[MSG_IN_REPLY_TO]); if (ptr) free (ptr); if (tmpptr) free (tmpptr); } else if (set_inreplyto_command) { char *tmpptr; tmpptr = makeinreplytocommand(set_inreplyto_command, email->subject, email->inreplyto); if (tmpptr) { /* use an msgid resolver */ fprintf(fp, "[ %s ]\n", tmpptr, lang[MSG_UNKNOWN_IN_REPLY_TO], lang[MSG_IN_REPLY_TO]); free (tmpptr); } } } /* * Is there a message next in the thread? */ printcomment(fp, "unextthread", "start"); if (email_next_in_thread) { char *tmpptr; #ifdef HAVE_ICONV ptr = i18n_utf2numref(email_next_in_thread->subject,1); tmpptr=i18n_utf2numref(email_next_in_thread->name,1); #else ptr = convchars(email_next_in_thread->subject, email_next_in_thread->charset); tmpptr=convchars(email_next_in_thread->name,email_next_in_thread->charset); #endif fprintf(fp, "[ %s ]\n", href01(email, email_next_in_thread, in_thread_file, FALSE), tmpptr, ptr, lang[MSG_NEXT_IN_THREAD]); if (ptr) free(ptr); if (tmpptr) free(tmpptr); email->initial_next_in_thread = email_next_in_thread->msgnum; } /* * Does this message have replies? If so, just add one link to the bottom reply section. */ if (set_show_msg_links == 3) { /* print_replies(fp, email, num, in_thread_file); */ is_reply = print_links(fp, email, pos, in_thread_file); } else if (set_showreplies) { #ifdef FASTREPLYCODE for (rp = email->replylist; rp != NULL; rp = rp->next) { if (hashnumlookup(rp->msgnum, &email2)) { #else for (rp = replylist; rp != NULL; rp = rp->next) { if (rp->frommsgnum == num && hashnumlookup(rp->msgnum, &email2)) { #endif fprintf (fp, " [ %s ]\n", lang[MSG_REPLIES]); break; } } printcomment(fp, "ureply", "end"); } /* close the list */ fprintf (fp,"
      • \n
      \n
      \n"); } return is_reply; } int print_links(FILE *fp, struct emailinfo *email, int pos, int in_thread_file) { int num = email->msgnum; int subjmatch; struct emailinfo *email2; struct emailinfo *email_next_in_thread = nextinthread(email->msgnum); char *ptr,*ptr2,*ptr3; int is_reply = 0; int loc_cmp = (pos == PAGE_BOTTOM ? 3 : 4); /* * Should we print message links ? */ if (set_show_msg_links && set_show_msg_links != loc_cmp) { fprintf(fp, "
        \n"); /* ** format for items:
      • Next: subject of message
      • \n */ fprintf (fp, "
      • %s: [ %s ]
      • \n", lang[MSG_THIS_MESSAGE], lang[MSG_MSG_BODY]); printcomment(fp, "lnext", "start"); /* * Is there a next message? */ email2 = neighborlookup(num, 1); if (email2) { #ifdef HAVE_ICONV ptr = i18n_utf2numref(email2->subject,1); ptr2 = i18n_utf2numref(email2->name,1); #else ptr = convchars(email2->subject, email2->charset); ptr2 = convchars(email2->name, email2->charset); #endif fprintf(fp, "
      • %s: ", lang[MSG_NEXT_MESSAGE]); fprintf(fp, "%s: \"%s\"
      • \n", msg_href(email2, email, FALSE), lang[MSG_LTITLE_NEXT], ptr2 ? ptr2 : "", ptr ? ptr : ""); if (ptr) free(ptr); if (ptr2) free(ptr2); } /* * Is there a previous message? */ email2 = neighborlookup(num, -1); #if 0 /* pcm removed 2002-08-30, old_reply_to is always NULL */ if (set_linkquotes && old_reply_to && pos == PAGE_BOTTOM && num - 1 == (get_new_reply_to() == -1 ? old_reply_to->msgnum : get_new_reply_to())) email2 = NULL; #endif if (email2) { #ifdef HAVE_ICONV ptr = i18n_utf2numref(email2->subject,1); ptr2 = i18n_utf2numref(email2->name,1); #else ptr = convchars(email2->subject, email2->charset); ptr2 = convchars(email2->name, email2->charset); #endif fprintf(fp, "
      • %s: ", lang[MSG_PREVIOUS_MESSAGE]); fprintf(fp, "%s: \"%s\"
      • \n", msg_href(email2, email, FALSE), lang[MSG_LTITLE_PREVIOUS], ptr2 ? ptr2 : "", ptr); if (ptr) free(ptr); if (ptr2) free(ptr2); } /* * Is this message a reply to another? */ if (email->inreplyto[0]) { email2 = hashreplylookup(email->msgnum, email->inreplyto, email->subject, &subjmatch); if (email2) { char *del_msg = (email2->is_deleted ? lang[MSG_DEL_SHORT] : ""); is_reply = 1; #ifdef HAVE_ICONV ptr = i18n_utf2numref(email2->subject,1); ptr2 = i18n_utf2numref(email2->name,1); #else ptr = convchars(email2->subject, email2->charset); ptr2 = convchars(email2->name, email2->charset); #endif if (subjmatch) fprintf(fp, "
      • %s:", lang[MSG_MAYBE_IN_REPLY_TO]); else fprintf(fp, "
      • %s:", lang[MSG_IN_REPLY_TO]); fprintf(fp, "%s %s: \"%s\"
      • \n", del_msg, href01(email, email2, in_thread_file, FALSE), lang[MSG_LTITLE_IN_REPLY_TO], ptr2, ptr); if (ptr) free(ptr); if (ptr2) free(ptr2); } else if (set_inreplyto_command) { char *tmpptr; tmpptr = makeinreplytocommand(set_inreplyto_command, email->subject, email->inreplyto); if (tmpptr) { /* use an msgid resolver */ fprintf(fp, "
      • %s:", lang[MSG_IN_REPLY_TO]); fprintf(fp, " [ %s ]
      • \n", tmpptr, lang[MSG_LTITLE_IN_REPLY_TO], lang[MSG_UNKNOWN_IN_REPLY_TO], lang[MSG_UNKNOWN_IN_REPLY_TO]); free (tmpptr); } } } /* * Is there a message next in the thread? */ printcomment(fp, "lnextthread", "start"); if (email_next_in_thread) { #ifdef HAVE_ICONV ptr = i18n_utf2numref(email_next_in_thread->subject, 1); ptr2 = i18n_utf2numref(email_next_in_thread->name,1); #else ptr = convchars(email_next_in_thread->subject, email_next_in_thread->charset); ptr2 = convchars(email_next_in_thread->name, email_next_in_thread->charset); #endif fprintf(fp, "
      • %s: ", lang[MSG_NEXT_IN_THREAD]); fprintf(fp, "%s: \"%s\"
      • \n", href01(email, email_next_in_thread, in_thread_file, FALSE), lang[MSG_LTITLE_NEXT_IN_THREAD], ptr2, ptr); if (ptr) free(ptr); if (ptr2) free(ptr2); email->initial_next_in_thread = email_next_in_thread->msgnum; } /* * Does this message have replies? If so, print them all! */ if (set_showreplies) { print_replies(fp, email, num, in_thread_file); /* close the list */ fprintf(fp, "
      \n"); } } return is_reply; } static int has_new_replies(struct emailinfo *email) { struct reply *rp; static int max_old_msgnum = -2; if (max_old_msgnum == -2) { if (set_nonsequential) max_old_msgnum = find_max_msgnum_id(); else max_old_msgnum = find_max_msgnum(); } if (email->msgnum == max_old_msgnum) return 1; /* next msg needs to be linked, even if no new reply */ #ifdef FASTREPLYCODE for (rp = email->replylist; rp != NULL; rp = rp->next) { if (rp->frommsgnum == email->msgnum && rp->msgnum > max_old_msgnum) return 1; } #endif return 0; } #ifdef GDBM static GDBM_FILE gdbm_init(void); static GDBM_FILE gdbm_init() { char indexname[MAXFILELEN]; static GDBM_FILE gp = NULL; if (set_usegdbm) { snprintf(indexname, sizeof(indexname), (set_dir[strlen(set_dir) - 1] == '/') ? "%s%s" : "%s/%s", set_dir, GDBM_INDEX_NAME); /* open the database, creating it if necessary */ if (!(gp = gdbm_open(indexname, 0, GDBM_WRCREAT, 0664, 0))) { if (set_folder_by_date && set_increment && !is_empty_archive()) { snprintf(errmsg, sizeof(errmsg), "Cannot open or create file \"%s\". Unable to " "do\nincremental updates with the folder_by_date " "option without using that file.", indexname); progerr(errmsg); } /* couldn't open; unlink it rather than risk running * with an inconsistent version; it will be recreated if * necessary */ unlink(indexname); } else { datum key; datum content; char buf[512]; key.dptr = "delete_level"; key.dsize = strlen(key.dptr); sprintf(buf, "%d", set_delete_level); content.dsize = strlen(buf) + 1; content.dptr = buf; /* the value is in this string */ gdbm_store(gp, key, content, GDBM_REPLACE); } } return gp; } #endif /* * Perform deletions on old messages when run in incremental mode. */ void update_deletions(int num_old) { struct hashemail *hlist; struct reply *rp; int save_ov = set_overwrite; set_overwrite = TRUE; for (hlist = deletedlist; hlist != NULL; hlist = hlist->next) { struct emailinfo *ep; int num = hlist->data->msgnum; if (num >= num_old) continue; /* new message - already done */ if (hashnumlookup(num, &ep)) { char *filename; if (ep->deletion_completed == set_delete_level) /* done already? */ continue; if (set_delete_level != DELETE_LEAVES_TEXT) { filename = articlehtmlfilename(ep); if (set_delete_level != DELETE_REMOVES_FILES) { struct body *bp = ep->bodylist; if (bp == NULL) parse_old_html(num, ep, 1, 0, NULL, 0); writearticles(num, num + 1); } else if (isfile(filename)) { unlink(filename); } free(filename); } #ifdef FASTREPLYCODE for (rp = ep->replylist; rp != NULL; rp = rp->next) { #else for (rp = replylist; rp != NULL; rp = rp->next) { #endif int rnum = rp->data->msgnum; if (rnum < num_old) { if (!rp->data->bodylist || !rp->data->bodylist->line[0]) parse_old_html(rnum, rp->data, TRUE, FALSE, NULL, 0); writearticles(rnum, rnum + 1); /* update MSG_IN_REPLY_TO line */ } } } } #ifdef GDBM if (set_usegdbm) { GDBM_FILE gp = gdbm_init(); for (hlist = deletedlist; hlist != NULL; hlist = hlist->next) { if (gp) { struct emailinfo *ep; int num = hlist->data->msgnum; if (num >= num_old) continue; /* new message - already done */ if (hashnumlookup(num, &ep)) { togdbm((void *)gp, ep); } } } } #endif set_overwrite = save_ov; } /* ** Printing...the other main part of this program! ** This writes out the articles, beginning with the number startnum. */ void writearticles(int startnum, int maxnum) { int num, skip, newfile; int is_reply = 0; int maybe_reply = 0; /* const, why is this here? pcm 2002-08-30 */ struct emailinfo *email; struct emailinfo *email_next_in_thread; struct body *bp; struct reply *rp; FILE *fp; char *ptr = NULL; #ifdef HAVE_ICONV char *localsubject=NULL,*localname=NULL; size_t convlen=0; #endif #ifdef GDBM /* A gdbm hack for avoiding opening all the message files to * get the header comments; see parse.c for details thereof. */ GDBM_FILE gp = gdbm_init(); #endif num = startnum; if (set_showprogress) printf("%s \"%s\"... ", lang[MSG_WRITING_ARTICLES], set_dir); while (num < maxnum) { char *filename; if ((bp = hashnumlookup(num, &email)) == NULL) { ++num; continue; } filename = articlehtmlfilename(email); #ifdef HAVE_ICONV if(email->subject) localsubject= i18n_convstring(email->subject,"UTF-8",email->charset,&convlen); if(email->name) localname= i18n_convstring(email->name,"UTF-8",email->charset,&convlen); #endif /* * Determine to overwrite files or not */ if (isfile(filename)) newfile = 0; else newfile = 1; is_reply = 0; set_new_reply_to(-1, -1); skip = 0; if (email->is_deleted && set_delete_level == DELETE_REMOVES_FILES) { if (!newfile) { unlink(filename); } #ifdef GDBM else if (gp) { togdbm((void *)gp, email); } #endif ++num; free(filename); continue; } else if (!newfile && !set_overwrite && !has_new_replies(email) && !(email->is_deleted && set_delete_msgnum)) { skip = 1; /* is this really necessary with continue ??? */ num++; free(filename); continue; } else { if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege:where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_report_new_file) { printf("%s\n", filename); } } email_next_in_thread = nextinthread(email->msgnum); /* * Create the comment fields necessary for incremental updating */ #ifdef HAVE_ICONV print_msg_header(fp, set_label, localsubject, set_dir, localname, email->emailaddr, email->msgid, email->charset, email->date, filename, REMOVE_MESSAGE(email), email->annotation_robot); #else print_msg_header(fp, set_label, email->subject, set_dir, email->name, email->emailaddr, email->msgid, email->charset, email->date, filename, REMOVE_MESSAGE(email), email->annotation_robot); #endif fprintf (fp, "
      \n"); /* print the navigation bar to upper levels */ if (ihtmlnavbar2upfile) fprintf(fp, "\n%s\n", lang[MSG_NAVBAR2UPPERLEVELS], ihtmlnavbar2upfile); /* reset the value of ptr before we actually start using it, just in case one of the ternary operations here below doesn't allocate any memory */ ptr = NULL; /* write the title */ #ifdef HAVE_ICONV fprintf(fp, "

      %s

      \n", (REMOVE_MESSAGE(email)) ? lang[MSG_SUBJECT_DELETED] : (ptr = convchars(localsubject, email->charset))); #else fprintf(fp, "

      %s

      \n", (REMOVE_MESSAGE(email)) ? lang[MSG_SUBJECT_DELETED] : (ptr = convchars(email->subject, email->charset))); #endif if (ptr) free(ptr); printcomment(fp, "received", email->fromdatestr); printcomment(fp, "isoreceived", secs_to_iso(email->fromdate)); printcomment(fp, "sent", email->datestr); printcomment(fp, "isosent", secs_to_iso(email->date)); #ifdef HAVE_ICONV printcomment(fp, "name", localname); #else printcomment(fp, "name", email->name); #endif printcomment(fp, "email", obfuscate_email_address(email->emailaddr)); #ifdef HAVE_ICONV ptr = convcharsnospamprotect(localsubject, email->charset); #else ptr = convcharsnospamprotect(email->subject, email->charset); #endif printcomment(fp, "subject", ptr); if (ptr) free(ptr); printcomment(fp, "id", email->msgid); printcomment(fp, "charset", email->charset); printcomment(fp, "inreplyto", ptr = convcharsnospamprotect(email->inreplyto, email->charset)); if (ptr) free(ptr); if (email->is_deleted) { char num_buf[32]; sprintf(num_buf, "%d", email->is_deleted); printcomment(fp, "isdeleted", num_buf); } printcomment(fp, "expires", email->exp_time == -1 ? "-1" : secs_to_iso(email->exp_time)); #ifdef GDBM if (gp) { togdbm((void *)gp, email); } #endif /* * This is here because it looks better here. The table looks * better before the Author info. This stuff should be in * printfile() so it could be laid out as the user wants... */ is_reply = print_links_up(fp, email, PAGE_TOP, FALSE); if ((set_show_index_links == 1 || set_show_index_links == 3) && !set_usetable) fprint_menu0(fp, email, PAGE_TOP); if ((set_show_msg_links && set_show_msg_links != 4) || !set_usetable) { fprintf(fp, "
      \n"); } /* * Finally...print the body! */ printcomment(fp, "body", "start"); fprintf (fp, "
      \n"); print_headers(fp, email, FALSE); printbody(fp, email, maybe_reply, is_reply); fprintf (fp, "%s %s\n", lang[MSG_RECEIVED_ON], getdatestr(email->fromdate)); fprintf (fp, "
      \n"); printcomment(fp, "body", "end"); /* * Should we print out the message links ? */ fprintf (fp, "
      \n"); fprintf (fp, "\n", lang[MSG_RELATED_MESSAGES]); print_links(fp, email, PAGE_BOTTOM, FALSE); fprint_menu0(fp, email, PAGE_BOTTOM); fprintf(fp, "\n"); fprintf(fp, "
      \n"); if (set_txtsuffix) { fprintf(fp, "

      %s", email->msgnum, set_txtsuffix, lang[MSG_TXT_VERSION]); } printfooter(fp, mhtmlfooterfile, set_label, set_dir, email->subject, filename, FALSE); fclose(fp); if (get_new_reply_to() != -1) { /* will only be true if set_linkquotes is */ struct emailinfo *e3, *e4; int was_correct = 0; replace_maybe_replies(filename, email, get_new_reply_to()); for (rp = replylist; rp != NULL; rp = rp->next) { /* get rid of old guesses for where this links */ if (rp->msgnum == num) { #ifdef FASTREPLYCODE struct reply *rp3; was_correct = (rp->frommsgnum == get_new_reply_to()); if (was_correct) break; hashnumlookup(get_new_reply_to(), &e4); hashnumlookup(rp->frommsgnum, &e3); for (rp3 = e3->replylist; rp3 != NULL && rp3->next != NULL; rp3 = rp3->next) { if (rp3->next->msgnum == num) { rp3->next = rp3->next->next; /* remove */ } } e4->replylist = addreply(e4->replylist, e4->msgnum, email, 0, NULL); #endif rp->frommsgnum = get_new_reply_to(); rp->maybereply = 0; break; /* revisit me */ } } if (!rp) { if (hashnumlookup(num, &e3)) { #ifdef FASTREPLYCODE hashnumlookup(get_new_reply_to(), &e4); if(0) fprintf(stderr, "update reply %2d %2d \n", get_new_reply_to(), num); replylist = addreply2(replylist, e4, e3, 0, &replylist_end); #else replylist = addreply(replylist, get_new_reply_to(), e3, 0, &replylist_end); #endif } } if (!was_correct) fixreplyheader(set_dir, num, TRUE, num); } if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } if (maxnum && !(num % 5) && set_showprogress) { printf("\b\b\b\b%03.0f%c", ((float)num / (float)maxnum) * 100, '%'); fflush(stdout); } free(filename); num++; #ifdef HAVE_ICONV if (localsubject) free(localsubject); if (localname) free(localname); #endif } #ifdef GDBM if (gp) { datum key; datum content; int nkey = -1; char num_buf[32]; key.dsize = sizeof(nkey); /* the key -1 is for the last msgnum */ key.dptr = (char *)&nkey; sprintf(num_buf, "%d", max_msgnum); content.dsize = strlen(num_buf) + 1; content.dptr = num_buf; gdbm_store((GDBM_FILE) gp, key, content, GDBM_REPLACE); gdbm_close(gp); } #endif if (set_showprogress) printf("\b\b\b\b \n"); } /* end writearticles() */ /* ** Write the date index... ** If email != NULL, write index for the subdir in which that email is. */ void writedates(int amountmsgs, struct emailinfo *email) { int newfile; char *filename; FILE *fp; char prev_date_str[DATESTRLEN + 40]; char *datename = index_name[email && email->subdir != NULL][DATE_INDEX]; time_t start_date_num = email && email->subdir ? email->subdir->first_email->date : firstdatenum; time_t end_date_num = email && email->subdir ? email->subdir->last_email->date : lastdatenum; filename = htmlfilename(datename, email, ""); if (isfile(filename)) newfile = 0; else newfile = 1; if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege: where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_showprogress) printf("%s \"%s\"...", lang[MSG_WRITING_DATE_INDEX], filename); /* * Print out the index file header */ print_index_header(fp, set_label, set_dir, lang[MSG_BY_DATE], datename); /* * Print out archive information links at the top of the index */ print_index_header_links(fp, DATE_INDEX, start_date_num, end_date_num, amountmsgs, email ? email->subdir : NULL); fprintf (fp, "\n"); /* * Print out the actual message index lists. Here's the beef. */ if (set_indextable) fprintf(fp, "

      \n\n\n", lang[MSG_CSUBJECT], lang[MSG_CAUTHOR], lang[MSG_CDATE]); else { fprintf (fp, "
      \n"); fprintf(fp, "
        \n"); } prev_date_str[0] = '\0'; printdates(fp, datelist, -1, -1, email, prev_date_str); if (set_indextable) fprintf(fp, "
      %s%s%s
      \n
      \n"); else { if (*prev_date_str) /* close the previous date item */ fprintf (fp, "
  • \n"); fprintf(fp, "\n"); printlaststats (fp, end_date_num); fprintf (fp, "\n"); } /* * Print out archive information links at the bottom of the index */ print_index_footer_links(fp, DATE_INDEX, end_date_num, amountmsgs, email ? email->subdir : NULL); /* * Print the index page footer. */ printfooter(fp, ihtmlfooterfile, set_label, set_dir, lang[MSG_BY_DATE], datename, TRUE); fclose(fp); /* AUDIT biege: depending on the direc. it better to use fchmod(). */ if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } free(filename); if (set_showprogress) putchar('\n'); } /* ** Write the attachments index... */ void writeattachments(int amountmsgs, struct emailinfo *email) { int newfile; char *filename; FILE *fp; char *attname = index_name[email && email->subdir != NULL][ATTACHMENT_INDEX]; time_t start_date_num = email && email->subdir ? email->subdir->first_email->date : firstdatenum; time_t end_date_num = email && email->subdir ? email->subdir->last_email->date : lastdatenum; bool is_first = TRUE; /* used to print the anchor to the first element (WAI) */ filename = htmlfilename(attname, email, ""); if (isfile(filename)) newfile = 0; else newfile = 1; if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege: where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_showprogress) printf("%s \"%s\"...", lang[MSG_WRITING_ATTACHMENT_INDEX], filename); /* * Print out the index file header */ print_index_header(fp, set_label, set_dir, lang[MSG_BY_ATTACHMENT], attname); /* * Print out archive information links at the top of the index */ print_index_header_links(fp, ATTACHMENT_INDEX, start_date_num, end_date_num, amountmsgs, email ? email->subdir : NULL); fprintf (fp, "\n"); /* * Print out the actual message index lists. Here's the beef. */ if (set_indextable) { fprintf(fp, "
    \n\n\n", lang[MSG_CSUBJECT], lang[MSG_CAUTHOR], lang[MSG_CDATE]); printattachments(fp, datelist, email, &is_first); fprintf(fp, "
    %s%s%s
    \n
    \n"); } else { fprintf (fp, "
    \n"); fprintf(fp, "
      \n"); if (printattachments(fp, datelist, email, &is_first) == 0) fprintf(fp, "
    • Nothing received yet!
    • \n"); fprintf(fp, "
    \n"); fprintf(fp, "
    \n"); } /* * Print out archive information links at the bottom of the index */ printlaststats (fp, end_date_num); print_index_footer_links(fp, ATTACHMENT_INDEX, end_date_num, amountmsgs, email ? email->subdir : NULL); /* * Print the index page footer. */ printfooter(fp, ihtmlfooterfile, set_label, set_dir, lang[MSG_BY_DATE], attname, TRUE); fclose(fp); if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } free(filename); if (set_showprogress) putchar('\n'); } /* ** Write the thread index... */ void writethreads(int amountmsgs, struct emailinfo *email) { int newfile; char *filename; FILE *fp; char *thrdname = index_name[email && email->subdir != NULL][THREAD_INDEX]; time_t start_date_num = email && email->subdir ? email->subdir->first_email->date : firstdatenum; time_t end_date_num = email && email->subdir ? email->subdir->last_email->date : lastdatenum; struct printed *pp; while (printedlist) { /* cleanup needed ?? */ pp = printedlist; printedlist = printedlist->next; free(pp); } printedlist = NULL; filename = htmlfilename(thrdname, email, ""); if (isfile(filename)) newfile = 0; else newfile = 1; if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege: where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_showprogress) printf("%s \"%s\"...", lang[MSG_WRITING_THREAD_INDEX], filename); print_index_header(fp, set_label, set_dir, lang[MSG_BY_THREAD], thrdname); /* * Print out the index page links */ print_index_header_links(fp, THREAD_INDEX, start_date_num, end_date_num, amountmsgs, email ? email->subdir : NULL); fprintf (fp, "\n"); if (set_indextable) { fprintf(fp, "
    \n\n\n", lang[MSG_CSUBJECT], lang[MSG_CAUTHOR], lang[MSG_CDATE]); print_all_threads(fp, -1, -1, email); fprintf(fp, "
    %s%s %s
    \n
    \n"); } else { fprintf (fp, "
    \n"); fprintf(fp, "
      \n"); print_all_threads(fp, -1, -1, email); fprintf(fp, "
    \n"); fprintf (fp, "
    "); } /* * Print out archive information links at the bottom of the index */ printlaststats (fp, end_date_num); print_index_footer_links(fp, THREAD_INDEX, end_date_num, amountmsgs, email ? email->subdir : NULL); printfooter(fp, ihtmlfooterfile, set_label, set_dir, lang[MSG_BY_THREAD], thrdname, TRUE); fclose(fp); if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } free(filename); if (set_showprogress) putchar('\n'); } /* ** Print the subject index pointers alphabetically. */ void printsubjects(FILE *fp, struct header *hp, char **oldsubject, int year, int month, struct emailinfo *subdir_email) { char *subject=NULL, *name=NULL; const char *startline; const char *break_str; const char *endline; static char date_str[DATESTRLEN+40]; /* made static for smaller stack */ static char *first_attributes = ""; if (hp != NULL) { printsubjects(fp, hp->left, oldsubject, year, month, subdir_email); if ((year == -1 || year_of_datenum(hp->data->date) == year) && (month == -1 || month_of_datenum(hp->data->date) == month) && !hp->data->is_deleted && (!subdir_email || subdir_email->subdir == hp->data->subdir)) { #ifdef HAVE_ICONV subject = convchars(hp->data->unre_subject, "utf-8"); name = convchars(hp->data->name, "utf-8"); #else subject = convchars(hp->data->subject, hp->data->charset); name = convchars(hp->data->name, hp->data->charset); #endif if (strcasecmp(hp->data->unre_subject, *oldsubject)) { if (set_indextable) { fprintf(fp, "%s\n", subject); } else { bool is_first; if (*oldsubject && *oldsubject[0] != '\0') { /* close the previous open list */ fprintf(fp, "\n"); is_first = FALSE; } else is_first = TRUE; fprintf(fp, "
  • %s%s\n", (is_first) ? first_attributes : "", subject); fprintf(fp, "
      \n"); } } if(set_indextable) { startline = " "; break_str = ""; strcpy(date_str, getindexdatestr(hp->data->date)); endline = ""; } else { startline = "
    • "; break_str = ""; snprintf(date_str, sizeof(date_str), "(%s)", getindexdatestr(hp->data->date)); endline = "
    • "; } fprintf(fp, "%s%s%s%s %s%s\n", startline, msg_href(hp->data, subdir_email, TRUE), name, break_str, set_fragment_prefix, hp->data->msgnum, set_fragment_prefix, hp->data->msgnum, date_str, endline); *oldsubject = hp->data->unre_subject; free(subject); free(name); } printsubjects(fp, hp->right, oldsubject, year, month, subdir_email); } } /* ** Prints the subject index. */ void writesubjects(int amountmsgs, struct emailinfo *email) { int newfile; char *filename; FILE *fp; char *subjname = index_name[email && email->subdir != NULL][SUBJECT_INDEX]; time_t start_date_num = email && email->subdir ? email->subdir->first_email->date : firstdatenum; time_t end_date_num = email && email->subdir ? email->subdir->last_email->date : lastdatenum; filename = htmlfilename(subjname, email, ""); if (isfile(filename)) newfile = 0; else newfile = 1; if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege: where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_showprogress) printf("%s \"%s\"...", lang[MSG_WRITING_SUBJECT_INDEX], filename); print_index_header(fp, set_label, set_dir, lang[MSG_BY_SUBJECT], subjname); /* * Print out the index page links */ print_index_header_links(fp, SUBJECT_INDEX, start_date_num, end_date_num, amountmsgs, email ? email->subdir : NULL); fprintf (fp, "\n"); if (set_indextable) { fprintf(fp, "
      \n\n\n", lang[MSG_CSUBJECT], lang[MSG_CAUTHOR], lang[MSG_CDATE]); } else { fprintf (fp, "
      \n"); fprintf(fp, "
        \n"); } { char *oldsubject = ""; /* dummy to start with */ printsubjects(fp, subjectlist, &oldsubject, -1, -1, email); } if (set_indextable) { fprintf(fp, "
      %s%s %s
      \n
      \n"); } else { fprintf(fp, "
  • \n"); fprintf(fp, "\n"); fprintf (fp, ""); } /* * Print out archive information links at the bottom of the index */ printlaststats (fp, end_date_num); print_index_footer_links(fp, SUBJECT_INDEX, end_date_num, amountmsgs, email ? email->subdir : NULL); printfooter(fp, ihtmlfooterfile, set_label, set_dir, lang[MSG_BY_SUBJECT], subjname, TRUE); fclose(fp); if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } free(filename); if (set_showprogress) putchar('\n'); } /* ** Prints the author index links sorted alphabetically. */ void printauthors(FILE *fp, struct header *hp, char **oldname, int year, int month, struct emailinfo *subdir_email) { char *subj, *tmpname; const char *startline; const char *break_str; const char *endline; static char date_str[DATESTRLEN+40]; /* made static for smaller stack */ static char *first_attributes = ""; if (hp != NULL) { printauthors(fp, hp->left, oldname, year, month, subdir_email); if ((year == -1 || year_of_datenum(hp->data->date) == year) && (month == -1 || month_of_datenum(hp->data->date) == month) && !hp->data->is_deleted && (!subdir_email || subdir_email->subdir == hp->data->subdir)) { #ifdef HAVE_ICONV subj = convchars(hp->data->subject, "utf-8"); tmpname = convchars(hp->data->name,"utf-8"); #else subj = convchars(hp->data->subject, hp->data->charset); tmpname = convchars(hp->data->name,hp->data->charset); #endif if (strcasecmp(hp->data->name, *oldname)) { if(set_indextable) fprintf(fp, "%s", tmpname); else { bool is_first; if (*oldname && *oldname[0] != '\0') { /* close the previous open list */ fprintf(fp, "\n"); is_first = FALSE; } else is_first = TRUE; fprintf(fp, "
  • %s%s\n", (is_first) ? first_attributes : "", tmpname); fprintf(fp, "
      \n"); } } if(set_indextable) { startline = " "; break_str = ""; strcpy(date_str, getindexdatestr(hp->data->date)); endline = ""; } else { startline = "
    • "; break_str = " "; snprintf(date_str, sizeof(date_str), "(%s)", getindexdatestr(hp->data->date)); endline = "
    • "; } fprintf(fp,"%s%s%s%s%s%s\n", startline, msg_href(hp->data, subdir_email, TRUE), subj, break_str, set_fragment_prefix, hp->data->msgnum, set_fragment_prefix, hp->data->msgnum, date_str, endline); if(subj) free(subj); if(tmpname) free(tmpname); *oldname = hp->data->name; /* avoid copying */ } printauthors(fp, hp->right, oldname, year, month, subdir_email); } } /* ** Prints the author index file and links sorted alphabetically. */ void writeauthors(int amountmsgs, struct emailinfo *email) { int newfile; char *filename; FILE *fp; char *authname = index_name[email && email->subdir != NULL][AUTHOR_INDEX]; time_t start_date_num = email && email->subdir ? email->subdir->first_email->date : firstdatenum; time_t end_date_num = email && email->subdir ? email->subdir->last_email->date : lastdatenum; filename = htmlfilename(authname, email, ""); if (isfile(filename)) newfile = 0; else newfile = 1; if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege: where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_showprogress) printf("%s \"%s\"...", lang[MSG_WRITING_AUTHOR_INDEX], filename); print_index_header(fp, set_label, set_dir, lang[MSG_BY_AUTHOR], authname); /* * Print out the index page links */ print_index_header_links(fp, AUTHOR_INDEX, start_date_num, end_date_num, amountmsgs, email ? email->subdir : NULL); fprintf (fp, "\n"); if (set_indextable) { fprintf(fp, "
      \n\n\n", lang[MSG_CAUTHOR], lang[MSG_CSUBJECT], lang[MSG_CDATE]); } else { fprintf(fp, "
      \n"); fprintf(fp, "
        \n"); } { char *prevauthor = ""; printauthors(fp, authorlist, &prevauthor, -1, -1, email); } if (set_indextable) { fprintf(fp, "
      %s%s %s
      \n
      \n"); } else { fprintf(fp, "
  • \n"); fprintf(fp, "\n"); fprintf(fp, "\n"); } /* * Print out archive information links at the bottom * of the index page */ printlaststats (fp, end_date_num); print_index_footer_links(fp, AUTHOR_INDEX, end_date_num, amountmsgs, email ? email->subdir : NULL); printfooter(fp, ihtmlfooterfile, set_label, set_dir, lang[MSG_BY_AUTHOR], authname, TRUE); fclose(fp); if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } free(filename); if (set_showprogress) putchar('\n'); } /* ** Pretty-prints the items for the haof */ void printhaofitems(FILE *fp, struct header *hp, int year, int month, struct emailinfo *subdir_email) { char *subj, *from_name, *from_emailaddr; if (hp != NULL) { struct emailinfo *em = hp->data; printhaofitems(fp, hp->left, year, month, subdir_email); if ((year == -1 || year_of_datenum(em->date) == year) && (month == -1 || month_of_datenum(em->date) == month) && !em->is_deleted && (!subdir_email || subdir_email->subdir == em->subdir)) { #ifdef HAVE_ICONV subj = convchars(em->subject, "utf-8"); from_name = convchars(em->name, "utf-8"); from_emailaddr = convchars(em->emailaddr, "utf-8"); #else subj = convchars(em->subject, em->charset); from_name = convchars(em->name, em->charset); from_emailaddr = convchars(em->emailaddr, em->charset); #endif fprintf(fp, " \n" " %s\n" " %s\n" " %s\n" " %s\n" " %s\n" " \"%s\"\n" " \n\n", subj, getdatestr(em->date), from_name, from_emailaddr, em->msgid, msg_relpath(em, subdir_email)); free(subj); free(from_name); free(from_emailaddr); } printhaofitems(fp, hp->right, year, month, subdir_email); } } /* ** Write the XML based hypermail archive overview file */ void writehaof(int amountmsgs, struct emailinfo *email) { int newfile; char *filename; FILE *fp; filename = haofname(email); if (isfile(filename)) newfile = 0; else newfile = 1; if ((fp = fopen(filename, "w")) == NULL) { /* AUDIT biege: where? */ snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (set_showprogress) printf("%s \"%s\"...", lang[MSG_WRITING_HAOF], filename); #ifdef HAVE_ICONV fprintf(fp, "\n\n"); #else fprintf(fp, "\n\n"); #endif fprintf(fp, " \n\n"); fprintf(fp, " \n\n"); fprintf(fp, " \n\n"); print_haof_indices(fp, email ? email->subdir : NULL); fprintf(fp, " \n"); printhaofitems(fp, datelist, -1, -1, email); fprintf(fp, " \n"); fprintf(fp, " \n"); fclose(fp); if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } free(filename); if (set_showprogress) putchar('\n'); } static int count_messages(struct header *hp, int year, int mo, long *first_date, long *last_date) { if (hp != NULL) { struct emailinfo *em = hp->data; int cnt = count_messages(hp->left, year, mo, first_date, last_date); if ((year == -1 || year_of_datenum(em->date) == year) && (mo == -1 || month_of_datenum(em->date) == mo) && !em->is_deleted) { ++cnt; if (em->date < *first_date) *first_date = em->date; if (em->date > *last_date) *last_date = em->date; } return cnt + count_messages(hp->right, year, mo, first_date, last_date); } return 0; } static void printmonths(FILE *fp, char *summary_filename, int amountmsgs) { int first_year = year_of_datenum(firstdatenum); int last_year = year_of_datenum(lastdatenum); int y, j, m; char *save_name[NO_INDEX]; char *subject = lang[set_monthly_index ? MSG_MONTHLY_INDEX : MSG_YEARLY_INDEX]; for (j = 0; j <= AUTHOR_INDEX; ++j) save_name[j] = index_name[0][j]; print_index_header(fp, set_label, set_dir, subject, summary_filename); fprintf(fp, "\n"); for (y = first_year; y <= last_year; ++y) { for (m = (set_monthly_index ? 0 : -1); m < (set_monthly_index ? 12 : 0); ++m) { char month_str[80]; char month_str_pub[80]; int started_line = 0; int empties = 0; char period_bufs[NO_INDEX][MAXFILELEN]; long first_date = lastdatenum; long last_date = firstdatenum; int count; if (!datelist->data) continue; count = count_messages(datelist, y, m, &first_date, &last_date); if (set_monthly_index) { sprintf(month_str_pub, "%s %d", months[m], y); sprintf(month_str, "%d%.2d", y, m + 1); } else { sprintf(month_str_pub, "%d", y); sprintf(month_str, "%d", y); } for (j = 0; j <= AUTHOR_INDEX; ++j) { sprintf(period_bufs[j], "%sby%s", month_str, save_name[j]); index_name[0][j] = period_bufs[j]; } for (j = 0; j <= AUTHOR_INDEX; ++j) { char *filename; char buf1[MAXFILELEN]; FILE *fp1; char *prev_text = ""; char subject_title[128]; if (!show_index[0][j]) continue; snprintf(buf1, sizeof(buf1), "%sby%s", month_str, save_name[j]); filename = htmlfilename(buf1, NULL, ""); fp1 = fopen(filename, "w"); if (!fp1) { snprintf(errmsg, sizeof(errmsg), "can't open %s", filename); progerr(errmsg); } snprintf(subject_title, sizeof(subject_title), "%s %s", month_str_pub, indextypename[j]); print_index_header(fp1, set_label, set_dir, subject_title, filename); /* * Print out the index page links */ print_index_header_links(fp1, j, first_date, last_date, count, NULL); if (set_indextable) { fprintf(fp1, "
    \n
    \n\n", lang[j == AUTHOR_INDEX ? MSG_CAUTHOR : MSG_CSUBJECT], lang[j == AUTHOR_INDEX ? MSG_CSUBJECT : MSG_CAUTHOR], lang[MSG_CDATE]); } else { fprintf(fp1, "
      \n"); } switch (j) { case DATE_INDEX: { char prev_date_str[DATESTRLEN + 40]; prev_date_str[0] = '\0'; printdates(fp1, datelist, y, m, NULL, prev_date_str); if (*prev_date_str) /* close the previous date item */ fprintf (fp, "
    \n"); break; } case THREAD_INDEX: print_all_threads(fp1, y, m, NULL); break; case SUBJECT_INDEX: printsubjects(fp1, subjectlist, &prev_text, y, m, NULL); break; case AUTHOR_INDEX: printauthors(fp1, authorlist, &prev_text, y, m, NULL); break; } if (set_indextable) { fprintf(fp1, "
    %s%s %s
    \n\n"); } else { fprintf(fp1, "\n"); } /* * Print out archive information links at the bottom * of the index page */ print_index_footer_links(fp1, j, last_date, count, NULL); printfooter(fp1, ihtmlfooterfile, set_label, set_dir, subject_title, save_name[j], FALSE); fclose(fp1); if (!count) { remove(filename); if (started_line) fprintf(fp, ""); else ++empties; } else { if (!started_line) { fprintf(fp, "%s%d %s", month_str_pub, count, lang[MSG_ARTICLES]); while (empties--) fprintf(fp, ""); started_line = 1; } chmod(filename, set_filemode); fprintf(fp, "%s", month_str, save_name[j], indextypename[j]); } free(filename); } if (started_line) fprintf(fp, "\n"); } } fprintf(fp, "\n"); printfooter(fp, ihtmlfooterfile, set_label, set_dir, subject, summary_filename, FALSE); for (j = 0; j <= AUTHOR_INDEX; ++j) index_name[0][j] = save_name[j]; } void init_index_names(void) { indextypename[DATE_INDEX] = lang[MSG_BY_DATE]; indextypename[THREAD_INDEX] = lang[MSG_BY_THREAD]; indextypename[SUBJECT_INDEX] = lang[MSG_BY_SUBJECT]; indextypename[AUTHOR_INDEX] = lang[MSG_BY_AUTHOR]; indextypename[ATTACHMENT_INDEX] = lang[MSG_ATTACHMENT]; } void write_summary_indices(int amount_new) { if (set_monthly_index || set_yearly_index) { char *filename; FILE *fp; filename = htmlfilename("summary", NULL, set_htmlsuffix); fp = fopen(filename, "w"); /* AUDIT biege: where? */ if (!fp) { snprintf(errmsg, sizeof(errmsg), "Couldn't write \"%s\".", filename); progerr(errmsg); } printmonths(fp, filename, amount_new); fclose(fp); chmod(filename, set_filemode); free(filename); } } void write_toplevel_indices(int amountmsgs) { int i, j, newfile, offset, k; bool first = TRUE; struct emailsubdir *sd; char *subject = lang[MSG_FOLDERS_INDEX]; static char verbose_period_name[DATESTRLEN*2 + 1]; static char abbr_period_name[DATESTRLEN*2 + 1]; char *end_date; char *index_title; char *filename; char *saved_set_dateformat; char *abbr_dateformat = set_describe_folder != NULL ? set_describe_folder : "%d %b %Y"; char *verbose_dateformat = "%A, %e %B %Y"; char *tmpstr; FILE *fp; filename = htmlfilename(index_name[0][FOLDERS_INDEX], NULL, ""); if (isfile(filename)) newfile = 0; else newfile = 1; if (!show_index[0][FOLDERS_INDEX]) fp = NULL; else if ((fp = fopen(filename, "w")) == NULL) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } if (fp) { print_index_header(fp, set_label, set_dir, subject, filename); print_index_header_links(fp, FOLDERS_INDEX, firstdatenum, lastdatenum, amountmsgs, NULL); fprintf (fp, "\n"); fprintf(fp, "\n"); /* find which element of index_name is the default index */ offset = 0; if (set_defaultindex) { tmpstr = setindex(INDEXNAME, INDEXNAME, set_htmlsuffix); for (j = 0; j <= ATTACHMENT_INDEX; ++j) { if (0 == strcmp(tmpstr, index_name[1][j])) { offset = j; break; } } } for (i = 0, j = 0; j <= ATTACHMENT_INDEX; ++j) { if (show_index[1][j]) i++; } /* not sure if the following -- for computing the colspan is correct will work with all configurations. */ if (i > 0) i--; fprintf(fp, "\n \n" " \n \n" " \n" " \n\n" "\n", lang[MSG_PERIOD], i, lang[MSG_RESORTED], lang[MSG_ARTICLES]); } sd = folders; if (set_reverse_folders) while (sd->next_subdir) sd = sd->next_subdir; saved_set_dateformat = set_dateformat; for (; sd != NULL; sd = set_reverse_folders ? sd->prior_subdir : sd->next_subdir) { int started_line = 0; if (!datelist->data) continue; for (j = 0; j <= ATTACHMENT_INDEX; ++j) { /* apply offset so the period column's href points to index.html */ k = (j + offset) % (ATTACHMENT_INDEX + 1); if (!show_index[1][k]) continue; set_dateformat = saved_set_dateformat; switch (k) { case DATE_INDEX: writedates(sd->count, sd->first_email); index_title = lang[MSG_LTITLE_LISTED_BY_DATE]; break; case THREAD_INDEX: writethreads(sd->count, sd->first_email); index_title = lang[MSG_LTITLE_DISCUSSION_THREADS]; break; case SUBJECT_INDEX: writesubjects(sd->count, sd->first_email); index_title = lang[MSG_LTITLE_LISTED_BY_SUBJECT]; break; case AUTHOR_INDEX: writeauthors(sd->count, sd->first_email); index_title = lang[MSG_LTITLE_LISTED_BY_AUTHOR]; break; case ATTACHMENT_INDEX: writeattachments(sd->count, sd->first_email); index_title = lang[MSG_LTITLE_LISTED_BY_ATTACHMENT]; break; default: index_title = ""; break; } if (set_writehaof) writehaof(sd->count, sd->first_email); if (!fp) continue; if (!started_line) { time_t first_date = sd->first_email->fromdate; time_t last_date = sd->last_email->fromdate; if (set_use_sender_date) { first_date = sd->first_email->date; last_date = sd->last_email->date; } set_dateformat = verbose_dateformat; strcpy (verbose_period_name, getdatestr (first_date)); set_dateformat = abbr_dateformat; strcpy (abbr_period_name, getdatestr (first_date)); end_date = getdatestr (last_date); if (strcmp (abbr_period_name, end_date)) { strcat (abbr_period_name, lang[MSG_TO]); strcat (abbr_period_name, end_date); /* do the same thing for the verbose one */ set_dateformat = verbose_dateformat; end_date = getdatestr (last_date); strcat (verbose_period_name, lang[MSG_TO]); strcat (verbose_period_name, end_date); } fprintf(fp, " \n \n"); if (first) first = FALSE; started_line = 1; } else { fprintf(fp, " \n"); } } if (started_line && fp) fprintf(fp, " \n \n", sd->count); } set_dateformat = saved_set_dateformat; if (fp) { fprintf(fp, "\n
    %s%s%s
    %s", (first) ? " class=\"first\"" : "", (first) ? "" : ""); /* only add a link to the index if it is not empty */ if (sd->count > 0) fprintf (fp, "", verbose_period_name, index_title, sd->subdir, index_name[1][k]); fprintf (fp, "%s", abbr_period_name); if (sd->count > 0) fprintf (fp, ""); fprintf (fp, ""); /* only add a link to the index if it is not empty */ if (sd->count > 0) fprintf (fp, "", verbose_period_name, index_title, sd->subdir, index_name[1][k]); fprintf (fp, "%s", indextypename[k]); if (sd->count > 0) fprintf (fp, ""); fprintf (fp, "%d
    \n"); /* * Print out archive information links at the bottom of the index */ print_index_footer_links(fp, FOLDERS_INDEX, lastdatenum, amountmsgs, NULL); printfooter(fp, ihtmlfooterfile, set_label, set_dir, subject, filename, TRUE); fclose(fp); if (newfile && chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "%s \"%s\": %o.", lang[MSG_CANNOT_CHMOD], filename, set_filemode); progerr(errmsg); } } free(filename); } /* ** This writes out the message index... a file giving the old msgno ** and the hash string that corresponds to it. */ void write_messageindex(int startnum, int maxnum) { int num; struct emailinfo *email; FILE *fp; char *filename; char *buf; struct body *bp; if (set_showprogress) printf("%s \"%s\"... ", lang[MSG_WRITING_ARTICLES], set_dir); /* write the intial message and number of messages in the index */ filename = messageindex_name(); fp = fopen(filename, "w"); fprintf(fp, "%.04d %.04d\n", startnum, maxnum - 1); /* write the reference to the message filenames */ num = startnum; while (num < maxnum) { if ((bp = hashnumlookup(num, &email)) != NULL) { buf = message_name(email); fprintf(fp, "%.04d %s\n", num, buf); } num++; } fclose(fp); chmod(filename, set_filemode); free(filename); } /* end write_messageindex () */ ================================================ FILE: src/print.h ================================================ /* ** print.c functions */ #ifdef GDBM int togdbm(void *gp, struct emailinfo *); #endif void printcomment(FILE *, char *, char *); void print_headers(FILE *, struct emailinfo *, int); int print_links(FILE *, struct emailinfo *, int, int); void printbody(FILE *, struct emailinfo *, int, int); char *print_leading_whitespace(FILE *, char *); void update_deletions(int); void writearticles(int, int); void writedates(int, struct emailinfo *); void writesubjects(int, struct emailinfo *); void writethreads(int, struct emailinfo *); void writeauthors(int, struct emailinfo *); void writehaof(int, struct emailinfo *); void writeattachments(int, struct emailinfo *); void printdates(FILE *, struct header *, int, int, struct emailinfo *, char *); void printsubjects(FILE *, struct header *, char **, int, int, struct emailinfo *); void printauthors(FILE *, struct header *, char **, int, int, struct emailinfo *); int printattachments(FILE *, struct header *, struct emailinfo *, bool *); int checkreplies(FILE *, int, int level, int thread_file_depth); void fprint_menu(FILE *, mindex_t, char *, char *, char *, int, struct emailsubdir *); void fprint_menu0(FILE *fp, struct emailinfo *email, int); void fprint_summary(FILE *, int, long, long, int); void print_index_header_links(FILE *, mindex_t, long, long, int, struct emailsubdir *); void print_index_footer_links(FILE *, mindex_t, long, int, struct emailsubdir *); void printhtml(FILE *, char *); int showheader(char *); void ConvURLs(FILE *, char *, char *, char *, char *); char *ConvURLsString(char *, char *, char *, char *); void write_summary_indices(int); void write_toplevel_indices(int); struct emailinfo *nextinthread(int); void init_index_names(void); void write_messageindex (int, int); ================================================ FILE: src/printfile.c ================================================ #include "hypermail.h" #include "setup.h" #include "print.h" #include "printfile.h" #include "struct.h" /* ** printfile - print html header/footer file and fill in values ** substituting for magic cookies. Return allocated ** memory with the header/footer filled in. ** ** Substitution cookies supported ** ** %% - '%' character ** %~ - storage directory ** %a - Other Archives URL ** %b - About Archive URL ** %c - Charset META TAG - Not valid on index pages ** %e - email addr of message author - Not valid on index pages ** %f - file name of the HTML document ** %g - date and time archive generated ** %h - HMURL ** %i - Message-id - Not valid on index pages ** %l - archive label ** %m - Mailto address ** %p - PROGNAME ** %s - Subject of message or Index Title ** %t - path to top directory ("" if no folders; usually "../", ** sometimes "../../" with folders) ** %v - VERSION ** %u - Expanded version link (HMURL,PROGNAME,VERSION) ** %S - Subject META TAG - Not valid on index pages ** %A - Author META TAG - Not valid on index pages ** %D - Date META TAG - Not valid on index pages ** %G - Two character language ** \n - newline character ** \t - tab character ** */ int printfile(FILE *fp, char *format, char *label, char *subject, char *dir, char *name, char *email, char *message_id, char *charset, char *date, char *filename) { register char *cp; register char *aptr; char c; char *ptr,*tmpptr=NULL; size_t tmplen; aptr = format; while ((c = *aptr++)) { if (c == '\\') { switch (*aptr++) { case 'n': /* Add the \n character */ putc('\n', fp); continue; case 't': /* Add the \t character */ putc('\t', fp); continue; default: break; } /* end switch */ } else if (c == '%') { char nextone = *aptr++; switch (nextone) { case '%': /* Add the % character */ putc('%', fp); continue; case '~': /* %~ - storage directory */ for (cp = dir; *cp; cp++) putc(*cp, fp); continue; case 'A': /* %e - email address of message author */ if (email && name) { #ifdef HAVE_ICONV tmpptr=i18n_convstring(name,"UTF-8",charset,&tmplen); cp = convchars(tmpptr,charset); if(tmpptr) free(tmpptr); fprintf(fp, "", cp, obfuscate_email_address(email)); if (cp) free(cp); #else fprintf(fp, "", tmpptr=convchars(name,charset), obfuscate_email_address(email)); if (tmpptr) free(tmpptr); #endif } continue; case 'a': /* %a - Other Archives URL */ if (set_archives) { for (cp = set_archives; *cp; cp++) putc(*cp, fp); } continue; case 'B': printf("Warning: the %%B option has been disabled. Use a\n" "style sheet instead. See the INSTALL file for more info.\n"); continue; case 'b': /* %b - About this archive URL */ if (set_about) { for (cp = set_about; *cp; cp++) putc(*cp, fp); } continue; case 'c': if (charset && *charset) { /* only output this if we have a charset */ fprintf(fp, "\n", charset); } continue; case 'D': /* %D - date of message */ if (date) { fprintf(fp, "", date); } continue; case 'e': /* %e - email address of message author */ if (email) { for (cp = email; *cp; cp++) putc(*cp, fp); } continue; case 'f': /* %f - file name */ if (filename) { for (cp = filename; *cp; cp++) putc(*cp, fp); } continue; case 'g': /* %g - date and time archive generated */ for (cp = getlocaltime(); *cp; cp++) putc(*cp, fp); continue; case 'G': /* %G - Language code */ if (set_language) { for (cp = set_language; *cp; cp++) putc(*cp, fp); } continue; case 'h': /* %h - Hypermail Resource Center */ for (cp = HMURL; *cp; cp++) putc(*cp, fp); continue; case 'i': /* %m - Message-ID of message */ if (message_id) { for (cp = message_id; *cp; cp++) putc(*cp, fp); } continue; case 'l': /* %l - Archive label */ for (cp = label; *cp; cp++) putc(*cp, fp); continue; case 'm': /* %m - mailto */ if (set_mailto) { for (cp = set_mailto; *cp; cp++) putc(*cp, fp); } continue; case 'p': /* %p - PROGNAME */ for (cp = PROGNAME; *cp; cp++) putc(*cp, fp); continue; case 's': /* %s - Subject of message or Index Title */ for (ptr = cp = convchars(subject, charset); *cp; cp++) putc(*cp, fp); free(ptr); continue; case 'S': /* %s - Subject of message or Index Title */ #ifdef HAVE_ICONV tmpptr=i18n_convstring(subject,"UTF-8",charset, &tmplen); fprintf(fp, "", cp = convchars(tmpptr,charset)); #else fprintf(fp, "", cp = convchars(subject, charset)); #endif free(cp); continue; case 't': { struct emailinfo *ep; if(hashnumlookup(0, &ep)) fprintf(fp, ep->subdir ? ep->subdir->rel_path_to_top : ""); continue; } case 'v': /* %v - VERSION */ for (cp = VERSION; *cp; cp++) putc(*cp, fp); continue; case 'u': /* %u - Expanded Version link */ fprintf(fp, "%s %s", HMURL, PROGNAME, VERSION); continue; default: putc('%', fp); putc(nextone, fp); continue; } /* end switch */ } putc(c, fp); } /* end while */ fflush(fp); return (0); } /* ** Prints the standard page header */ void print_main_header(FILE *fp, bool index_header, char *label, char *name, char *email, char *subject, char *charset, char *date, char *filename, int is_deleted, int annotation_robot) { char *title; char *rp; char *rp2; /* @@ JK: Don't know what to do with US-ASCII. If there's no charset, assume the default one is ISO-8859-1 */ if (charset && *charset) rp = charset; else rp = "ISO-8859-1"; fprintf(fp, "\n" "\n", rp); fprintf(fp, "\n", set_language); fprintf(fp, "\n"); if (charset && *charset) { /* charset info "as early as possible within the HEAD of the document" */ fprintf(fp, "\n", charset); } fprintf(fp, "\n", PROGNAME, VERSION, HMURL); /* * Strip off any trailing whitespace in TITLE so weblint is happy. */ /* trio_asprintf(&title, "%s: %s", label, rp = convchars(subject, charset)); */ rp = convchars(subject, charset); if (name && date) { /* assume that this is the title of a message and not the title of an index */ rp2 = convchars(name, charset); trio_asprintf(&title, "%s %s %s %s %s (%s)", rp, lang[MSG_FROM_TITLE], rp2, lang[MSG_ON_TITLE], date, label); free(rp2); } else trio_asprintf(&title, "%s: %s", label, rp); free(rp); rp = title + (strlen(title) - 1); while (isspace(*rp)) *rp-- = '\0'; /* * Assure the title meets HTML recommendations of no longer * than 64 characters. Truncate it if needed. * * JK 13/Aug/2003: This more a style suggestion given in: * http://www.w3.org/Provider/Style/TITLE.html * As the title is truncated regardless of its contents, it can * generate invalid HTML if the cut happens in the middle * of an entity. Dom suggested not enforcing this rule of * thumb so strictly in this case, so I commented it out. */ /* if (strlen(title) > 64) *(title+64) = '\0'; */ fprintf(fp, "%s\n", (is_deleted) ? lang[MSG_SUBJECT_DELETED] : title); free(title); if (name && email){ fprintf(fp, "\n",convchars(name,charset),obfuscate_email_address(email)); } fprintf(fp, "\n", rp = convchars(subject, charset)); free(rp); if (date) fprintf(fp, "\n",date); if (use_mailto) fprintf(fp, "\n", set_mailto); /* robot handling */ if (index_header && set_noindex_onindexes) { fprintf(fp,"\n"); } else if (is_deleted || annotation_robot) { char *value; /* if the message is deleted, avoid bots, else set the value of the robots robots meta tag according to the info supplied by the message */ if (is_deleted) value = "noindex"; else if (annotation_robot == 1) value = "nofollow"; else if (annotation_robot == 2) value = "noindex"; else if (annotation_robot == 3) value = "nofollow, noindex"; fprintf(fp,"\n", value); } /* print the css url according to the type of header */ if (index_header && set_icss_url && *set_icss_url) { fprintf(fp, "\n", set_icss_url); } else if (!index_header && set_mcss_url && *set_mcss_url) { fprintf(fp, "\n", set_mcss_url); } else { /* * if style sheets are not specified, emit a default one. */ /* @@ JK: the new css */ fprintf (fp, "\n"); } if (ihtmlheadfile) fprintf (fp, "%s", ihtmlheadfile); fprintf(fp, "\n"); fprintf(fp, "\n"); } /* ** Prints the header for an index page. */ void print_msg_header(FILE *fp, char *label, char *subject, char *dir, char *name, char *email, char *msgid, char *charset, time_t date, char *filename,int is_deleted, int annotation_robot) { if (mhtmlheaderfile) printfile(fp, mhtmlheaderfile, set_label, subject, set_dir, name, email, msgid, charset, secs_to_iso_meta(date), filename); else { print_main_header(fp, FALSE, set_label, name, email, subject, charset, secs_to_iso_meta(date), filename, is_deleted, annotation_robot); } } /* ** Prints the header for the by_date index page. */ void print_index_header(FILE *fp, char *label, char *dir, char *subject, char *filename) { if (ihtmlheaderfile) #ifdef HAVE_ICONV if (set_i18n){ printfile(fp, ihtmlheaderfile, label, subject, dir, NULL, NULL, "UTF-8", NULL, NULL, filename); }else{ printfile(fp, ihtmlheaderfile, label, subject, dir, NULL, NULL, NULL, NULL, NULL, filename); } #else printfile(fp, ihtmlheaderfile, label, subject, dir, NULL, NULL, NULL, NULL, NULL, filename); #endif else { /* print the navigation bar to upper levels */ #ifdef HAVE_ICONV if (set_i18n){ print_main_header(fp, TRUE, label, NULL, NULL, subject, "UTF-8", NULL, NULL, 0, 0); } else{ print_main_header(fp, TRUE, label, NULL, NULL, subject, NULL, NULL, NULL, 0, 0); } #else print_main_header(fp, TRUE, label, NULL, NULL, subject, NULL, NULL, NULL, 0, 0); #endif fprintf (fp, "
    \n"); if (ihtmlnavbar2upfile) fprintf(fp, "\n%s\n", lang[MSG_NAVBAR2UPPERLEVELS], ihtmlnavbar2upfile); fprintf(fp, "

    %s %s

    \n", label, subject); } } /* ** Prints the HTML page footer. */ void printfooter(FILE *fp, char *htmlfooter, char *label, char *dir, char *subject, char *filename, bool close_div) { printcomment(fp, "trailer", "footer"); if (htmlfooter) printfile(fp, htmlfooter, label, subject, dir, NULL, NULL, NULL, NULL, NULL, filename); else { fprintf(fp, "

    \n"); fprintf(fp, "%s ", lang[MSG_ARCHIVE_GENERATED_BY]); fprintf(fp, "%s %s\n", HMURL, PROGNAME, VERSION); fprintf(fp, ": %s\n", getlocaltime()); fprintf(fp, "

    \n"); } if (close_div) fprintf (fp, "
    \n"); fprintf(fp, "\n\n"); } /* ** Prints the HTML last message and last archived date (used in the indexes). */ void printlaststats (FILE *fp, long lastdatenum) { fprintf (fp, "
      \n"); fprintf (fp, "
    • %s: %s
    • \n", lang[MSG_LAST_MESSAGE_DATE], getdatestr(lastdatenum)); fprintf (fp, "
    • %s: %s
    • \n", lang[MSG_ARCHIVED_ON], getlocaltime()); fprintf (fp, "
    \n"); } ================================================ FILE: src/printfile.h ================================================ /* ** printfile.c functions */ int printfile(FILE *, char *, char *, char *, char *, char *, char *, char *, char *, char *, char *); void print_main_header(FILE *, bool, char *, char *, char *, char *, char *, char *, char *, int, int); void print_msg_header(FILE *, char *, char *, char *, char *, char *, char *, char *, time_t, char *, int, int); void print_index_header(FILE *, char *, char *, char *, char *); void printfooter(FILE *, char *, char *, char *, char *, char *, bool); void printlaststats(FILE *, long); ================================================ FILE: src/proto.h ================================================ #ifndef __PROTO_H_ #define __PROTO_H_ 1 #include "hypermail.h" /* ** Date functions - date.c */ time_t convtoyearsecs(char *); char *getlocaltime(void); void gettimezone(void); void getthisyear(void); char *getdatestr(time_t); char *getindexdatestr(time_t); char *getdateindexdatestr(time_t); char *secs_to_iso(time_t); char *secs_to_iso_meta(time_t); time_t iso_to_secs(char *); int year_of_datenum(time_t); int month_of_datenum(time_t); /* ** domains.c */ int valid_root_domain(char *); /* ** file.c functions */ int isdir(char *); int isfile(char *); void check1dir(char *); void checkdir(char *); char *getfilecontents(char *); char *add_char(char *, char); char *add_string(char *, char *); char *dirpath(char *); void readconfigs(char *, int); int find_max_msgnum(void); int is_empty_archive(void); void symlink_latest(void); struct emailsubdir *msg_subdir(int, time_t); char *msg_href(struct emailinfo *, struct emailinfo *, int); char *msg_relpath(struct emailinfo *, struct emailinfo *); char *articlehtmlfilename(struct emailinfo *); char *htmlfilename(const char *, struct emailinfo *, const char *); char *haofname(struct emailinfo *); int matches_existing(int); char *messageindex_name(void); int find_max_msgnum_id(void); char **read_msgnum_id_table(int); void free_msgnum_id_table(char **, int); char *message_name(struct emailinfo *); /* ** hypermail.c functions */ void version(void); void progerr(char *); void cmderr(char *); void usage(void); char *setindex(char *dfltindex, char *indextype, char *suffix); /* ** lang.c function */ char **valid_language(char *, char **); /* ** lock.c functions */ void lock_archive(char *); void unlock_archive(void); /* ** mem.c function */ void *emalloc(int); /* ** setup.c functions */ #ifdef DEBUG void dump_config(void); #endif /* ** string.c functions */ char *obfuscate_email_address (char *); char *unobfuscate_email_address (char *); char *i18n_convstring(char *, char *, char *, size_t *); char *i18n_utf2numref(char *, int); unsigned char *i18n_numref2utf(char *); int i18n_replace_non_ascii_chars(char *); char *PushByte(struct Push *, char); char *PushString(struct Push *, const char *); char *PushNString(struct Push *, const char *, int); char *strcasestr (const char *, const char *); char *strsav(const char *); char *strreplace(char *, char *); void strcpymax(char *, const char *, int); void strtolower (char *); char *stripzone(char *); int numstrchr(char *, char); char *getvalue(char *); char *getconfvalue(char *, char *, char *); char *unre(char *); char *oneunre(char *); void rfc3676_trim_softlb(char *); char *rfc3676_delsp_quotes(char *); int rfc3676_ishardlb(const char *); int isquote(const char *); char *replace(char *, char *, char *); char *replacechar(char *, char, char *); char *convdash(char *); char *convchars(char *, char *); char *convcharsnospamprotect(char *, char *); char *unconvchars(char *); char *makemailcommand(char *, char *, char *, char *); char *makeinreplytocommand(char *, char *, char *); char *spamify(char *input); char *spamify_small(char *input); char *spamify_replacedomain(char *input, char *antispamdomain); char *unspamify(char *); char *parseemail(char *, char *, char *, parseemail_conversion_t); char *parseurl(char *, char *); char *hm_strchr(const char *, int); void iso2022_state(const char *str, int *state, int *esc); /* ** quotes.c */ const char *get_quote_prefix(void); const char *find_quote_prefix(struct body *bp, int is_reply); char *unquote(char *line); char *remove_hypermail_tags(char *line); int compute_quoted_percent(struct body *bp); int is_sig_start(const char *line); int find_quote_depth(char *); char *find_quote_class(char *); #ifdef NOTDEF #ifdef lint int isspace(int); int isalpha(int); int isalnum(int); int isxdigit(int); #endif #endif #endif ================================================ FILE: src/quotes.c ================================================ /* ** Copyright (C) 1997, Peter McCluskey (pcm@rahul.net) ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "hypermail.h" #include "setup.h" #include "string.h" #include #if ! HAVE_MEMMOVE #include "pcre/internal.h" #endif #define MAX_QPREFIX_GUESSES 8 static char quote_prefix[80]; const char *get_quote_prefix() { return quote_prefix; } static int msg_linkp(char *p3, char *p) { /* has form */ char *ptmp; if(!(isdigit(p3[-4]) && isdigit(p3[-3]) && isdigit(p3[-2]) && isdigit(p3[-1]))) return 0; if (!set_msgsperfolder && !set_folder_by_date) return p3[-5] == '"'; ptmp = strstr(p, "://"); if (ptmp && ptmp < p3) return 0; return 1; /* ought to be more checks here, but they are not easy */ } /* ** Undo the html additions that prior hypermail run did to body ** Returns NULL if line probably didn't exist in original ascii */ char *remove_hypermail_tags(char *line) { char *p, *p1; const char *cp; static int expect_end_anchor = 0; char *buffer = NULL; if (!strcasecmp(line, "

    \n")) return strsav("\n"); else if (!strncasecmp(line, "", 3)) { buffer = strsav(line); memmove(buffer, buffer + 3, strlen(buffer + 3) + 1); if ((p = strcasestr(buffer, "
    \n")) != NULL) { strcpy(p, "\n"); } } else if (!strcasecmp(line, "
    \n")) return NULL; else if ((cp = strcasestr(line, "
    \n")) != NULL) { buffer = strsav(line); strcpy(strcasestr(buffer, "
    \n"), "\n"); } else if (!strcasecmp(line, "


    \n")) return strsav("------------------------------------------------------------------------"); else if (!strcasecmp(line, "
    \n"))
    	return NULL;
        else if (!strcasecmp(line, "
    \n")) return NULL; else if (!strcasecmp(line, "
      \n")) return NULL; else if (!strcasecmp(line, "
        \n")) return NULL; else if (!strcasecmp(line, "
    \n")) return NULL; else if (!strcasecmp(line, "\n")) return NULL; if (!buffer) buffer = strsav(line); if ((p = strcasestr(buffer, "
  • ")) != NULL) { const char *p2 = p; while (p2 > buffer && isspace(*--p2)); if (p2 == buffer) memmove(buffer, p + 4, strlen(p + 4) + 1); } #if 0 "^caps_tag/caps_tag\n" #endif if ((p = strcasestr(buffer, "'); char *p3; char *p4 = strstr(p, "\">"); char suf[80]; sprintf(suf, ".%s", set_htmlsuffix); p3 = strstr(p, suf); if (p2 && p3 && p4 && p2 == p4 + 1 && msg_linkp(p3, p)) { memmove(p, p2 + 1, strlen(p2 + 1) + 1); if ((p = strcasestr(p2, "")) != NULL) memmove(p, p + 4, strlen(p + 4) + 1); } else if (set_mailcommand) { const char *p2 = set_mailcommand; int len = strlen(p2); if (strchr(p2, '$')) len = strchr(p2, '$') - p2; if (!strncmp(p + 9, p2, len)) { char *p3 = strstr(p + 9 + len, "\">"); if (p3) { memmove(p, p3 + 2, strlen(p3 + 2) + 1); p3 = strcasestr(p, ""); if (p3) memmove(p3, p3 + 4, strlen(p3 + 4) + 1); } } } } while ((p = strcasestr(buffer, ""); if (p2 && p < p2) { memmove(p, p2 + 2, strlen(p2 + 2) + 1); ++expect_end_anchor; } else break; } if (expect_end_anchor && !strcasecmp(buffer, "\n")) { --expect_end_anchor; free(buffer); return NULL; } if (expect_end_anchor && (p = strcasestr(buffer, ""))) { --expect_end_anchor; memmove(p, p + 4, strlen(p + 4) + 1); } p = buffer; while ((p = strstr(p, " ")) != NULL) { memmove(p + 1, p + 6, strlen(p + 6) + 1); *p = ' '; /* replace   with space */ } return buffer; } int is_sig_start(const char *line) { return (!strcmp(line, "--\n") || !strcmp(line, "-- \n") || !strcmp(line, "----\n") || !strcmp(line, "---\n")); } /* ** Look for something other than text at the start of a line that might be quote */ static const char *guess_quote(const char *line) { static char buf[80]; int i = 0; int found_printable = 0; while (!isalnum(line[i]) && !(iscntrl(line[i]) && line[i] != '\t') && i < sizeof(buf) - 1) { if (!isspace(line[i])) found_printable = 1; buf[i] = line[i]; ++i; } if (!found_printable) i = 0; buf[i] = 0; if (i > 0 && buf[i - 1] == '<') { if (!strncasecmp(line + i - 1, "line); if (*q_guess) { int match_index = -1; for (i = 0; i < num_guesses; ++i) { if (!strcmp(guess[i], q_guess)) { ++guess_times_found[i]; match_index = i; } else if (!strncmp(guess[i], q_guess, strlen(guess[i]))) ++guess_partial_matches[i]; } if (match_index == -1 && num_guesses < MAX_QPREFIX_GUESSES) { strncpy(guess[num_guesses], q_guess, sizeof(guess[i])); guess_times_found[num_guesses] = 1; if (strchr(q_guess, '>')) /* bias it to std */ guess_times_found[num_guesses] = 5; guess_partial_matches[num_guesses] = 0; for (i = 0; i < num_guesses; ++i) { if (!strncmp (guess[i], guess[num_guesses], strlen(guess[num_guesses]))) guess_partial_matches[num_guesses] += guess_times_found[i]; } ++num_guesses; } } bp = bp->next; } for (i = 0; i < num_guesses; ++i) { if (guess_times_found[i] > best_count || (guess_times_found[i] == best_count && strlen(guess[i]) < strlen(guess[best_index]))) { best_count = guess_times_found[i]; best_index = i; } } for (i = 0; i < num_guesses; ++i) { int pcount = guess_times_found[i] + guess_partial_matches[i]; if (pcount > best_count + 1 && !strncmp(guess[best_index], guess[i], strlen(guess[i]))) { best_count = pcount; best_index = i; } } if (best_count == 1 && (!is_reply || !strchr(guess[best_index], '>'))) { for (i = 0; i < num_guesses; ++i) { if (i != best_index && guess_times_found[i] == best_count && !strncmp(guess[i], guess[best_index], strlen(guess[best_index]))) break; /* found guess pair like {">","> "} */ } if (i >= num_guesses) best_index = -1; /* solitary example, give up */ } if (best_index == -1) strcpy(quote_prefix, ""); else strncpy(quote_prefix, guess[best_index], sizeof(quote_prefix) - 1); if (0) printf("best_count %d has_replies %d quote_prefix=%s.\n", best_count, is_reply, quote_prefix); return quote_prefix; } /* ** remove the prefix that was added by the quoting mechanism */ char *unquote(char *line) { if (*quote_prefix) { int len = strlen(quote_prefix); if (!strncmp(quote_prefix, line, len)) line += len; return line; } else return line; } /* * The find_quote_depth function assumes that the line is already known * to be quoted text. It returns the number of times the line has been * quoted if it decides that is easy to determine, otherwise 1. */ int find_quote_depth(char *line) { int cnt = 0; if (*quote_prefix && !strchr(quote_prefix, '>')) return 1; /* too hard to deal with nonstandard quotes */ for ( ; *line; ++line) { if (isspace(*line)) continue; if (*line == '>') ++cnt; else break; } return cnt; } char *find_quote_class(char *line) { int quote_depth = find_quote_depth(line); if (quote_depth > 4) quote_depth = ((quote_depth - 1) % 4) + 1; if (quote_depth >= 4) return "quotelev4"; if (quote_depth >= 3) return "quotelev3"; if (quote_depth >= 2) return "quotelev2"; if (quote_depth >= 1) return "quotelev1"; return ""; } /* ** Find out what percent of the body consists of lines appearing ** to be quotes of other messages. */ int compute_quoted_percent(struct body *bp) { int inheader = 1; int insig = 0; int count_quoted = 0; int count_lines = 0; while (bp != NULL) { if ((bp->line)[0] == '\n') inheader = 0; else if (inheader) { bp = bp->next; continue; } if (is_sig_start(bp->line)) insig = 1; if (isquote(bp->line)) ++count_quoted; ++count_lines; bp = bp->next; } if (!count_lines) return 0; return (int)(100 * count_quoted / (float)count_lines); } ================================================ FILE: src/search.c ================================================ /* ** Copyright (C) 1997, Peter McCluskey (pcm@rahul.net) ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "hypermail.h" #include #include #include #include "proto.h" #include "setup.h" #include "struct.h" #include "print.h" #include "search.h" static int bigram_count = 0; static struct reply *replylist_tmp; #if 1 typedef unsigned long BIGRAM_TYPE; static const unsigned max_tokens = 400000; /* increase this if you have plenty of RAM */ #else /* for systems with little RAM and archives less than 10 megs? */ typedef unsigned short BIGRAM_TYPE; static const unsigned max_tokens = 0xfff0; #endif struct bigram_list { struct body *bp; short offset; struct bigram_list *next; }; struct bigram_tree_entry { struct bigram_tree_entry *left; struct bigram_tree_entry *right; struct bigram_list list; BIGRAM_TYPE bigram1; BIGRAM_TYPE bigram2; }; static struct bigram_tree_entry *bigram_tree = NULL; #define MAXSEARCHTOKEN 26 struct search_text { struct search_text *left; struct search_text *right; #ifdef BY_TOKEN_STRING char token[MAXSEARCHTOKEN]; #else int token_length; unsigned int token_crc32; #endif /* !BY_TOKEN_STRING */ BIGRAM_TYPE itok; #ifdef COUNT_TOKEN_FREQ int count; #endif }; static struct search_text *text_tree = NULL; static BIGRAM_TYPE next_itoken = 1; static int start_time; static int tree_alloc = 0; static void add_old_replies(void); static void find_replyto_from_html(int num); void set_alt_replylist(struct reply *r) { replylist_tmp = r; } /* change the order of itok entries for more balanced tree */ static BIGRAM_TYPE reverse_bits(BIGRAM_TYPE i) { BIGRAM_TYPE r = 0; int j; for (j = 0; j < 16; ++j) if (i & (1 << j)) r |= (1 << (16 - 1 - j)); return r; } #ifdef BY_TOKEN_STRING #define ENCODE_TOKEN(a) encode_token(a) #define COMPARE_TOKEN(a, b) strcasecmp(a, (b)->token) #else #define ENCODE_TOKEN(a) encode_token((a), strlen(a)) #define COMPARE_TOKEN(a, b) token_digest_order(token_length, token_crc32, (b)) static int token_digest_order(const int token_length, const unsigned int token_crc32, const struct search_text *const p) { return ((token_length > p->token_length) ? 1 : (token_length < p->token_length) ? -1 : (token_crc32 > p->token_crc32) ? 1 : (token_crc32 < p->token_crc32) ? -1 : 0); } /* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* zlib.h is available in /usr/include on many systems. I also see a copy at: http://sunsite.doc.ic.ac.uk/public/packages//NetBSD-current/src/lib/libz/zlib.h */ static unsigned int crc32_lower(register const unsigned char *buf, /* pointer to bytes to pump through */ int len) { /* number of bytes in buf[] */ /* Run a set of bytes through the crc shift register. If buf is a NULL pointer, then initialize the crc shift register contents instead. Return the current crc in either case. */ register unsigned int crc = 0; /* crc shift register */ #ifdef CRC32 # undef CRC32 #endif #define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) #define DO1(buf) crc = CRC32(crc, tolower(*buf++)) /* ======================================================================== * Table of CRC-32's of all single-byte values (made by make_crc_table) */ static const unsigned int crc_table[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; if (buf == NULL) return 0L; crc = crc ^ 0xffffffffL; if (len) do { DO1(buf); } while (--len); return crc ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ } #endif /* !BY_TOKEN_STRING */ static int encode_token(const char *token #ifndef BY_TOKEN_STRING , const int token_length #endif ) { struct search_text *p = text_tree; #ifndef BY_TOKEN_STRING unsigned int token_crc32 = crc32_lower((const unsigned char *)token, token_length); #endif int r; while (1) { if (!p) { return 0; } #ifdef BY_TOKEN_STRING r = COMPARE_TOKEN(token, p); #else r = token_length - p->token_length; if (!r) r = ((token_crc32 > p->token_crc32) ? 1 : (token_crc32 < p->token_crc32) ? -1 : 0); #endif /* !BY_TOKEN_STRING */ if (!r) return p->itok; if (r < 0) p = p->left; else p = p->right; } } static int b_times_entered; static int b_loops_done; static int addb(const char *token, struct body *bp) { struct search_text **pp = &text_tree; struct search_text *p = *pp; int r; #ifndef BY_TOKEN_STRING int token_length = strlen(token); unsigned int token_crc32 = crc32_lower((const unsigned char *)token, token_length); #endif static struct search_text *next_token = NULL; if (!text_tree) { next_token = (struct search_text *)malloc(max_tokens * sizeof(struct search_text)); if (!next_token) { snprintf(errmsg, sizeof(errmsg), "Couldn't allocate %d bytes of memory.", max_tokens * sizeof(struct search_text)); progerr(errmsg); } memset(next_token, 0, max_tokens * sizeof(struct search_text)); } ++b_times_entered; while (1) { ++b_loops_done; p = *pp; if (!p) { *pp = p = next_token++; if (next_token >= text_tree + max_tokens) { snprintf(errmsg, sizeof(errmsg), "Too many distinct tokens(%d)", max_tokens); progerr(errmsg); } p->left = p->right = NULL; #ifdef BY_TOKEN_STRING strncpy(p->token, token, MAXSEARCHTOKEN); p->token[MAXSEARCHTOKEN - 1] = 0; #else p->token_length = token_length; p->token_crc32 = token_crc32; #endif /* !BY_TOKEN_STRING */ p->itok = reverse_bits(next_itoken++); #ifdef COUNT_TOKEN_FREQ p->count = 1; #endif if (!next_itoken >= max_tokens) { snprintf(errmsg, sizeof(errmsg), "Internal error - too many distinct tokens."); progerr(errmsg); } return p->itok; } r = COMPARE_TOKEN(token, p); if (!r) { #ifdef COUNT_TOKEN_FREQ ++p->count; #endif return p->itok; } if (r < 0) pp = &p->left; else pp = &p->right; } } static int bi_times_entered; static void add_bigram(BIGRAM_TYPE b1, BIGRAM_TYPE b2, struct body *bp, char *ptr) { static struct bigram_tree_entry *next_bigram = NULL; struct bigram_tree_entry **pp = &bigram_tree; struct bigram_tree_entry *p = *pp; int r; if (!bigram_tree) { if (0) printf("bigram_count %d\n\n", bigram_count); bigram_tree = (struct bigram_tree_entry *)malloc(bigram_count * sizeof(struct bigram_tree_entry)); if (!bigram_tree) { snprintf(errmsg, sizeof(errmsg), "Couldn't allocate %d bytes of memory.", bigram_count * sizeof(struct bigram_tree_entry)); progerr(errmsg); } memset(bigram_tree, 0, bigram_count * sizeof(struct bigram_tree_entry)); next_bigram = bigram_tree; } ++bi_times_entered; while (1) { p = *pp; if (!p) { *pp = p = next_bigram++; tree_alloc += sizeof(struct bigram_tree_entry); p->bigram1 = b1; p->bigram2 = b2; p->left = p->right = NULL; p->list.offset = ptr - bp->line; p->list.bp = bp; p->list.next = NULL; return; } r = p->bigram1 - b1; if (!r && !(r = p->bigram2 - b2)) { struct bigram_list *old = p->list.next; p->list.next = (struct bigram_list *)next_bigram++; p->list.next->next = old; p->list.next->offset = p->list.offset; p->list.next->bp = p->list.bp; p->list.offset = ptr - bp->line; p->list.bp = bp; return; } if (r < 0) pp = &p->left; else pp = &p->right; } } static struct bigram_list *find_bigram(BIGRAM_TYPE b1, BIGRAM_TYPE b2) { struct bigram_tree_entry *p = bigram_tree; int r; while (1) { if (!p) { return NULL; } r = p->bigram1 - b1; if (!r) r = p->bigram2 - b2; if (!r) { return &p->list; } if (r < 0) p = p->left; else p = p->right; } } static struct body *next_body_pos(struct body *bp, char **ptr) { ++*ptr; while (!**ptr) { bp = bp->next; if (!bp) return NULL; *ptr = bp->line; } return bp; } struct body *tokenize_body(struct body *bp, char *token, char **ptr, int *bigram_index, int ignore) { int i = 0; static const char *ignore_words[] = { "a", /* 0 */ "i", /* 1 */ NULL, /* 2 */ "of", /* 3 */ "is", /* 4 */ "in", /* 5 */ "it", /* 6 */ "to", /* 7 */ "be", /* 8 */ "or", /* 9 */ "on", /* 10 */ "at", /* 11 */ "by", /* 12 */ "as", /* 13 */ NULL, /* 14 */ "the", /* 15 */ "and", /* 16 */ "you", /* 17 */ "are", /* 18 */ "for", /* 19 */ NULL, /* 20 */ "that", /* 21 */ "with", /* 22 */ NULL }; #define MAX_IGNORE_LEN 4 while (bp && **ptr && !isalnum(**ptr)) { bp = next_body_pos(bp, ptr); ++*bigram_index; } if (!**ptr) return NULL; while (bp && isalnum(**ptr) && i < MAXLINE - 1) { token[i++] = **ptr; bp = next_body_pos(bp, ptr); ++*bigram_index; if (bp && *ptr == bp->line) break; /* just passed end of line, treat as end of word */ if (ignore && **ptr == '\'' && isalpha((*ptr)[1])) { token[i++] = **ptr; /* contraction - treat as 1 word */ bp = next_body_pos(bp, ptr); ++*bigram_index; } } token[i] = 0; if (ignore) { switch (i) { case 1: i = 0; break; case 2: i = 3; break; case 3: i = 15; break; case 4: i = 21; break; default: i = 23; break; } for (; ignore_words[i]; ++i) { if (!strcasecmp(token, ignore_words[i])) return tokenize_body(bp, token, ptr, bigram_index, ignore); } } return bp; } static void add_search_text(struct body *bp, int msgnum) { char *ptr = bp->line; int bigram_index = 0; char token[MAXLINE]; if (!start_time) start_time = time(NULL); while ((bp = tokenize_body(bp, token, &ptr, &bigram_index, TRUE)) != NULL) { addb(token, bp); ++bigram_count; } if (0) printf("avg b %d avg bi %d (%d) msgnum %d %d allocated %d elapsed %ld\n", b_loops_done / b_times_entered, 0, bi_times_entered, msgnum, tree_alloc / 1024, time(NULL) - start_time, next_itoken); } static void add_bigrams(struct body *bp, int msgnum) { int last_itok = 0; static int bigram_index = 0; #if 0 struct body *bp = hashnum_set_index(msgnum, bigram_index); #endif char *ptr = bp->line; char token[MAXLINE]; int itok; if (!start_time) start_time = time(NULL); while ((bp = tokenize_body(bp, token, &ptr, &bigram_index, TRUE)) != NULL) { itok = ENCODE_TOKEN(token); if (last_itok) add_bigram(last_itok, itok, bp, ptr); bp->msgnum = msgnum; last_itok = itok; } if (0 && b_times_entered && bi_times_entered) printf("avg b %d msgnum %d %d allocated %d elapsed %ld\n", b_loops_done / b_times_entered, msgnum, tree_alloc / 1024, time(NULL) - start_time, next_itoken); } static void add_old_replies() { struct reply *rp; struct reply *rp2; for (rp2 = replylist_tmp; rp2 != NULL; rp2 = rp2->next) { for (rp = replylist; rp != NULL; rp = rp->next) { /* get rid of old guesses for where this links */ if (rp->frommsgnum == rp2->frommsgnum) { rp->msgnum = rp2->msgnum; rp->maybereply = 0; break; } } if (!rp) { #ifdef FASTREPLYCODE struct emailinfo *email2; hashnumlookup(rp2->frommsgnum, &email2); replylist = addreply2(replylist, email2, rp2->data, 0, &replylist_end); #else replylist = addreply(replylist, rp2->frommsgnum, rp2->data, 0, &replylist_end); #endif } } } static void find_replyto_from_html(int num) { char *filename; char line[MAXLINE]; FILE *fp; char *ptr; static const char *href_str = "\n")) break; } fclose(fp); } free(filename); } void analyze_headers(int max_num) { int i; int min_search_msgnum = 0; int num = max_num; if (set_searchbackmsgnum > 0 && set_increment && num - set_searchbackmsgnum > min_search_msgnum) min_search_msgnum = num - set_searchbackmsgnum; for (i = 0; i < num; ++i) find_replyto_from_html(i); if (set_showprogress) printf("\nparsing bodies for later search.\n"); for (i = min_search_msgnum; i < num; ++i) { struct emailinfo *ep; if (hashnumlookup(i, &ep) && ep->bodylist) { add_search_text(ep->bodylist, i); } } for (i = min_search_msgnum; i < num; ++i) { struct emailinfo *ep; if (hashnumlookup(i, &ep) && ep->bodylist) add_bigrams(ep->bodylist, i); if (set_showprogress) printf("\b\b\b\b%4d articles.\n", i); } add_old_replies(); } static void print_count(struct search_text *t) { if (t->left) print_count(t->left); #ifdef COUNT_TOKEN_FREQ printf("%d\t%s\n", t->count, t->token); #endif if (t->right) print_count(t->right); } static int better_match(struct body *bp, const char *matched_string, const char *last_matched_string) { int i; const char *ptr = bp->line; for (i = 0; 1; ++i) { int last_matches = (last_matched_string[i] == *ptr); int new_matches = (matched_string[i] == *ptr); if (0) printf("better_match? %d,%d @ %d\n%.70s\nVS:\n%.70s\n", new_matches, last_matches, i, last_matched_string + i, matched_string + i); if (!new_matches) return 0; if (!last_matches) return 1; if (!*++ptr) { bp = bp->next; if (!bp) break; ptr = bp->line; if (last_matched_string[i] == '\n' || matched_string[i] == '\n') ++i; } } return 0; } static void check_match(struct bigram_list *bigram, struct body *bp, char *ptr, int max_msgnum, String_Match * match_info, const char *match_start_ptr, const char *exact_line) { int match_len = 1; int alloc_len = 0; int match_len_bytes; struct body *bp2 = bp; struct body *bp3 = NULL; char *ptr2 = ptr; const char *last_ptr = ptr; char *ptr3; char token2[MAXLINE]; char token3[MAXLINE]; int b2_index = 0; int b_index = 0; int msgnum = bigram->bp->msgnum; bp3 = bigram->bp; if (msgnum < max_msgnum && bp3) { ptr3 = bp3->line + bigram->offset; while (1) { bp2 = tokenize_body(bp2, token2, &ptr2, &b2_index, TRUE); bp3 = tokenize_body(bp3, token3, &ptr3, &b_index, TRUE); if (0) printf("compare_match: %d %s, %20.20s\n", match_len, token3, ptr3); if (!bp2 || !bp3) break; if (ENCODE_TOKEN(token2) != ENCODE_TOKEN(token3)) break; ++match_len; last_ptr = ptr2; } { const char *p = match_start_ptr; match_len_bytes = 0; while (p != last_ptr) { ++match_len_bytes; ++p; if (!*p && p != last_ptr) { bp = bp->next; p = bp->line; } } ++match_len_bytes; } if (0) printf("compare_match: %d %d msgnum %d\n", match_len, match_info->match_len_tokens, msgnum); if (match_len > match_info->match_len_tokens || (match_len == match_info->match_len_tokens && better_match(bp, exact_line, match_info->last_matched_string))) { match_info->match_len_tokens = match_len; match_info->match_len_bytes = match_len_bytes; match_info->msgnum = msgnum; match_info->start_match = bigram->bp->line + bigram->offset; match_info->stop_match = ptr3; if (match_info->last_matched_string) free(match_info->last_matched_string); match_len = strlen(bigram->bp->line); alloc_len = match_len + 1000; match_info->last_matched_string = (char *)emalloc(alloc_len); strcpy(match_info->last_matched_string, bigram->bp->line); if (!strchr(match_info->last_matched_string, '\n')) { strcat(match_info->last_matched_string + match_len, "\n"); ++match_len; } for (bp3 = bigram->bp->next; bp3; bp3 = bp3->next) { char *p = match_info->last_matched_string; int add_len = strlen(bp3->line); if (match_len + add_len + 2 > alloc_len) { alloc_len = 2 * (match_len + add_len + 2); match_info->last_matched_string = (char *)realloc(p, alloc_len); } strcat(match_info->last_matched_string + match_len, bp3->line); match_len += add_len; if (add_len > 0 && bp3->line[add_len - 1] != '\n') strcat(match_info->last_matched_string + match_len++, "\n"); } if (0) printf("%d +++ %s; %s\nbp->line %s\n", bigram->bp->msgnum, match_info->last_matched_string, match_info->stop_match, bp->line); } } } /* ** Find the best match for a line from the bodies of prior messages */ int search_for_quote(char *search_line, char *exact_line, int max_msgnum, String_Match * match_info) { char *ptr = search_line; char token[MAXLINE]; int last_itok = 0; int search_len = strlen(search_line); const char *stop_ptr = search_line + (search_len >= 80 ? 40 : (search_len + 1) / 2); static int count_tokens = 0; static int count_matches = 0; static int count_searched = 0; const char *match_start_ptr = ptr; const char *next_match_start_ptr; char *next_exact_ptr; int len; int dummy = 0; struct body *bp; struct body b; b.line = search_line; b.next = NULL; match_info->match_len_tokens = 0; match_info->match_len_bytes = 0; match_info->msgnum = -1; match_info->last_matched_string = NULL; bp = tokenize_body(&b, token, &ptr, &dummy, TRUE); if (!bp) return -1; ++count_searched; last_itok = ENCODE_TOKEN(token); next_match_start_ptr = ptr; next_exact_ptr = exact_line; while ((bp = tokenize_body(bp, token, &ptr, &dummy, TRUE)) != NULL) { int itok = ENCODE_TOKEN(token); struct bigram_list *bigram; bigram = find_bigram(last_itok, itok); if (!bigram) printf("Warning, internal inconsistency in search_for_quote:\n(%d,%d) %s %d best %d, msg %d %s || %s\n", last_itok, itok, token, dummy, match_info->match_len_tokens, max_msgnum, ptr, search_line); ++count_tokens; while (bigram) { ++count_matches; check_match(bigram, bp, ptr, max_msgnum, match_info, match_start_ptr, exact_line); if (match_info->match_len_bytes == search_len) break; bigram = bigram->next; } if (match_info->last_matched_string != NULL && strlen(match_info->last_matched_string) > search_len / 2) break; if (ptr > stop_ptr) /* very little chance of improving match */ break; /* in 2nd half of string */ last_itok = itok; match_start_ptr = next_match_start_ptr; next_match_start_ptr = ptr; exact_line = next_exact_ptr; tokenize_body(bp, token, &next_exact_ptr, &dummy, TRUE); } if (0) printf("%d times %d searches %d tokens %d matches tries %f\n", max_msgnum, count_searched, count_tokens, count_matches, (float)count_matches / count_tokens); len = match_info->match_len_bytes; if (max_msgnum == -1) printf("best_match_len %d (%d) len %d search_len %d %d; %s.\n", match_info->match_len_tokens, match_info->msgnum, len, search_len, match_info->match_len_bytes, match_info->last_matched_string); if (match_info->match_len_tokens > 1 && (len > search_len / 2 || len > 40)) { if ((ptr = strchr(match_info->last_matched_string, '\n')) != NULL) *ptr = 0; /* multi-line used for compares in check_match, but would screw up line-by-line compare outside */ return TRUE; } if (match_info->match_len_tokens > 1 && (len > search_len / 2 || len > 40) && len > match_info->match_len_bytes / 2) if (0) printf("#almost %d best_match_len %d len %d search_len %d %d.\n", max_msgnum, match_info->match_len_tokens, len, search_len, match_info->match_len_bytes); if (match_info->last_matched_string != NULL) free(match_info->last_matched_string); match_info->last_matched_string = NULL; match_info->msgnum = -1; return FALSE; } ================================================ FILE: src/search.h ================================================ #ifndef SEARCH_H_INCLUDED #define SEARCH_H_INCLUDED typedef struct { int msgnum; int match_len_tokens; int match_len_bytes; char *last_matched_string; /* malloc'd by search, free'd by caller if msgnum >= 0 */ const char *start_match; const char *stop_match; } String_Match; int search_for_quote(char *search_line, char *exact_line, int max_msgnum, String_Match * match_info); struct body *tokenize_body(struct body *bp, char *token, char **ptr, int *bigram_index, int ignore); void analyze_headers(int amount_new); void set_alt_replylist(struct reply *r); #endif /* SEARCH_H_INCLUDED */ ================================================ FILE: src/setup.c ================================================ /* ** $Id: setup.c,v 1.23 2013-06-11 18:55:44 kahan Exp $ */ #include "hypermail.h" #ifdef __LCC__ #include "../lcc/defaults.h" #else #include "defaults.h" #endif #include "setup.h" #include "struct.h" #include "print.h" char *set_fragment_prefix; char *set_antispam_at; char *set_htmlmessage_edited; char *set_htmlmessage_deleted_other; char *set_htmlmessage_deleted_spam; char *set_language; char *set_htmlsuffix; char *set_mbox; char *set_archives; char *set_custom_archives; char *set_about; char *set_dir; char *set_defaultindex; char *set_default_top_index; char *set_txtsuffix; char *set_antispamdomain; bool set_email_address_obfuscation; bool set_i18n; bool set_i18n_body; bool set_overwrite; bool set_inlinehtml; bool set_increment; bool set_readone; bool set_reverse; bool set_reverse_folders; bool set_showprogress; bool set_showheaders; bool set_showbr; bool set_showhr; bool set_showreplies; int set_show_msg_links; int set_show_index_links; bool set_usetable; bool set_indextable; bool set_iquotes; bool set_eurodate; bool set_gmtime; bool set_isodate; bool set_require_msgids; bool set_discard_dup_msgids; bool set_usemeta; bool set_userobotmeta; bool set_uselock; bool set_ietf_mbox; bool set_linkquotes; bool set_monthly_index; bool set_yearly_index; bool set_spamprotect; bool set_spamprotect_id; bool set_attachmentsindex; bool set_usegdbm; bool set_writehaof; bool set_append; char *set_append_filename; bool set_nonsequential; bool set_warn_suppressions; bool set_files_by_thread; bool set_href_detection; bool set_mbox_shortened; bool set_report_new_file; bool set_report_new_folder; bool set_use_sender_date; bool set_inline_addlink; bool set_applemail_mimehack; char *set_applemail_ua_header; int set_showhtml; int set_thrdlevels; int set_dirmode; int set_filemode; int set_locktime; int set_searchbackmsgnum; int set_quote_hide_threshold; int set_thread_file_depth; int set_startmsgnum; int set_save_alts; char *set_alts_text; char *set_mailcommand; char *set_newmsg_command; char *set_replymsg_command; char *set_inreplyto_command; char *set_mailto; char *set_hmail; char *set_domainaddr; static char *set_htmlbody; char *set_icss_url; char *set_mcss_url; char *set_label; char *set_dateformat; char *set_indexdateformat; char *set_stripsubject; char *set_link_to_replies; char *set_quote_link_string; struct hmlist *set_text_types = NULL; struct hmlist *set_inline_types = NULL; struct hmlist *set_prefered_types = NULL; struct hmlist *set_ignore_types = NULL; struct hmlist *set_show_headers = NULL; struct hmlist *set_skip_headers = NULL; struct hmlist *set_avoid_indices = NULL; struct hmlist *set_avoid_top_indices = NULL; struct hmlist *set_filter_out = NULL; struct hmlist *set_filter_require = NULL; struct hmlist *set_filter_out_full_body = NULL; struct hmlist *set_filter_require_full_body = NULL; struct hmlist *set_applemail_ua_value; bool set_format_flowed; bool set_format_flowed_disable_quoted; char *set_ihtmlheader; char *set_ihtmlfooter; char *set_ihtmlhead; char *set_ihtmlhelpup; char *set_ihtmlhelplow; char *set_ihtmlnavbar2up; char *set_mhtmlheader; char *set_mhtmlfooter; char *set_attachmentlink; char *set_unsafe_chars; char *set_filename_base; char *set_folder_by_date; char *set_latest_folder; char *set_base_url; char *set_describe_folder; int set_msgsperfolder; bool set_iso2022jp; bool set_noindex_onindexes; struct hmlist *set_annotated = NULL; struct hmlist *set_deleted = NULL; struct hmlist *set_expires = NULL; struct hmlist *set_delete_msgnum = NULL; char *set_delete_older; char *set_delete_newer; bool set_delete_incremental; int set_delete_level; struct Config cfg[] = { {"fragment_prefix", &set_fragment_prefix, "msg", CFG_STRING, "# put this string before the message number in each URI fragment.\n", FALSE}, {"email_address_obfuscation", &set_email_address_obfuscation, BFALSE, CFG_SWITCH, "# set to On to enable email address obfuscation using numeric character references.\n",FALSE}, {"i18n", &set_i18n, BTRUE, CFG_SWITCH, "# Enable I18N features, hypermail must be linked with libiconv.\n",FALSE}, {"i18n_body", &set_i18n_body, BFALSE, CFG_SWITCH, "# Translate message body into UTF-8. \"i18n\" must be enabled.\n",FALSE}, {"htmlmessage_edited", &set_htmlmessage_edited, NULL, CFG_STRING, "# Set this to HTML markup you want to appear in the body of manually\n" "edited messages.\n",FALSE}, {"htmlmessage_deleted_other", &set_htmlmessage_deleted_other, NULL, CFG_STRING, "# Set this to HTML markup you want to appear in the body of deleted\n" "# messages (by reasons other than spam).\n",FALSE}, {"htmlmessage_deleted_spam", &set_htmlmessage_deleted_spam, NULL, CFG_STRING, "# Set this to HTML markup you want to appear in the body of deleted\n" "# messages (by spam reasons).\n",FALSE}, {"antispam_at", &set_antispam_at, ANTISPAM_AT, CFG_STRING, "# replace any @ sign with this string, if spam flags enabled.\n", FALSE}, {"language", &set_language, LANGUAGE, CFG_STRING, "# A two-letter string specifying the language to use!\n" "# For example 'en' for English.\n", FALSE}, {"htmlsuffix", &set_htmlsuffix, HTMLSUFFIX, CFG_STRING, "# Use this to specify the html file suffix to be used\n" "# when Hypermail generates the html files. This is depen-\n" "# dent on local needs. Do not put a '.' in the value. It\n" "# would result in \"file..html\", probably not what you want.\n", FALSE}, {"mbox", &set_mbox, NULL, CFG_STRING, "# This is the mailbox to read messages in from. Set this with \n" "# a value of NONE to read from standard input.\n", FALSE}, {"ietf_mbox", &set_ietf_mbox, BFALSE, CFG_SWITCH, "# Set this to On to read mboxes using the IETF convention.\n", FALSE}, {"archives", &set_archives, NULL, CFG_STRING, "# This will create a link in the archived index pages\n" "# labeled 'Other mail archives' to the specified URL. Set\n" "# this to NONE to omit such a link.\n", FALSE}, {"custom_archives", &set_custom_archives, NULL, CFG_STRING, "# If this variable is defined, a navigation entry will be\n" "# created below the sorted_by_x list entry, with the text\n" "# Other mail archives: followed by the value of this variable.\n" "# Set it to NONE to ommit such an entry.\n", FALSE}, {"about", &set_about, NULL, CFG_STRING, "# This will create a link in the archived index pages\n" "# labeled 'About this archive' to the specified URL. Set\n" "# this to NONE to omit such a link.\n", FALSE}, {"label", &set_label, NULL, CFG_STRING, "# Define this as the label to put in archives.\n", FALSE}, {"dir", &set_dir, NULL, CFG_STRING, "# This is the directory that Hypermail will look for when\n" "# creating and updating archives. If defined as NONE the\n" "# directory will have the same name as the input mailbox.\n", FALSE}, {"defaultindex", &set_defaultindex, DEFAULTINDEX, CFG_STRING, "# This specifies the default index that users can view when\n" "# entering the archive. Valid types are date, thread, author,\n" "# subject, and attachment. When using the folder_by_date or\n" "# msgsperfolder options, this option applies to subdirectories.\n", FALSE}, {"default_top_index", &set_default_top_index, "folders", CFG_STRING, "# This specifies the default index that users can view when\n" "# entering the top level of an archive that uses the folder_by_date\n" "# or msgsperfolder option. Valid types are date, thread, author,\n" "# subject, attachment, and folders.\n", FALSE}, {"avoid_indices", &set_avoid_indices, NULL, CFG_LIST, "# This is a list of index files to not generate. Valid types are\n" "# date, thread, author, and subject. When using the folder_by_date or\n" "# msgsperfolder options, this option applies to subdirectories.\n", FALSE}, {"avoid_top_indices", &set_avoid_top_indices, NULL, CFG_LIST, "# This is a list of index files to not generate for the top\n" "# directory of an archive using the folder_by_date or\n" "# msgsperfolder option. Valid types are date, thread, author, \n" "# subject, folders, and attachment.\n", FALSE}, {"overwrite", &set_overwrite, BFALSE, CFG_SWITCH, "# Set this to On to make Hypermail overwrite existing archives.\n", FALSE}, {"inlinehtml", &set_inlinehtml, BTRUE, CFG_SWITCH, "# Define to On to make text/html parts to get inlined with the mails.\n" "# If set to Off, HTML-parts will be stored as separate files.\n" "# A \"Content-Disposition: attachment;\" line in the mail will\n" "# cause an HTML-part to be stored as a separate file even if this\n" "# option is On.\n", FALSE}, {"increment", &set_increment, BFALSE, CFG_INTEGER, "# Set this to -1 to have hypermail figure out whether the input\n" "# is entirely new messages to be appended or whether it contains\n" "# messages that are already in the archive. A value of -1 cannot be\n" "# used with the mbox_shortened option or with the -i command line\n" "# option or with mbox = NONE. Set this to 0 to always treat\n" "# the input as an mbox that contains messages in the archive if the\n" "# existing archive is not empty.\n" "# Set this to 1 to append the input to existing archive.\n", FALSE}, {"readone", &set_readone, BFALSE, CFG_SWITCH, "# Set this to On to specify there is only one message in the input.\n", FALSE}, {"reverse", &set_reverse, BFALSE, CFG_SWITCH, "# Setting this variable to On will reverse-sort the article\n" "# entries in the date and thread index files by the\n" "# date they were received. That is, the most recent messages\n" "# will appear at the top of the index rather than the other\n" "# way around.\n", FALSE}, {"reverse_folders", &set_reverse_folders, BFALSE, CFG_SWITCH, "# Setting this variable to On will reverse-sort the list of\n" "# folders. That is, the most recent folders will appear at\n" "# the top of the index rather than the other way around.\n", FALSE}, {"progress", &set_showprogress, INT(PROGRESS), CFG_INTEGER, "# Set this to 1 or 2 to always show a progress report as\n" "# Hypermail works. With a setting of 1, hypermail\n" "# overwrites the progress information relating to attachment\n" "# creation. With a setting of 2, attachment creation information\n" "# is listed individually with the number of the message the\n" "# attachments relate to. This is written to stdout.\n", FALSE}, {"showheaders", &set_showheaders, BFALSE, CFG_SWITCH, "# Set this to On to show the article header lines in the archived HTML\n" "# files. These lines typically include the To:, From:, and Subject:\n" "# information found in most email messages.\n", FALSE}, {"showhtml", &set_showhtml, INT(1), CFG_INTEGER, "# Set this to 1 to show the articles in a proportionally-spaced\n" "# font rather than a fixed-width (monospace) font.\n" "# Set this to 2 for more complex conversion to html\n" "# similar to that in txt2html.pl.\n" "# Showhtml = 2 will normally produce nicer looking results than\n" "# showhtml = 1, and showhtml = 0 will look pretty dull, but\n" "# 1 and 2 run risks of altering the appearance in undesired ways.\n", FALSE}, {"showbr", &set_showbr, BTRUE, CFG_SWITCH, "# Set this to On to place
    tags at the end of article lines.\n" "# Otherwise, all non-quoted article lines will word wrap. This\n" "# only takes effect if hm_showhtml is 1.\n", FALSE}, {"showhr", &set_showhr, BFALSE, CFG_SWITCH, "# Set this to On to place horizontal rules before and after articles.\n" "NOTE: THIS OPTION HAS BEEN DEPRECATED BY THE WAI CHANGES. IT WILL BE\n" "IGNORED.\n", FALSE}, {"showreplies", &set_showreplies, BTRUE, CFG_SWITCH, "# Set this to On to show all replies to a message as links\n" "# in article files.\n", FALSE}, {"show_msg_links", &set_show_msg_links, INT(1), CFG_INTEGER, "# Set this to 1 to put the individual message links at the top\n" "# of the individual message pages. Set this to 0 to produce pages\n" "# without the Next, Previous, Reply, In-Reply-To, etc. links. Set\n" "# it to 3 to produce those links only at the top of the message\n" "# pages, or 4 to produce those links only at the bottom of the\n" "# message.\n", FALSE}, {"show_index_links", &set_show_index_links, INT(1), CFG_INTEGER, "# Set this to 1 to show links to index pages from the top and\n" "# bottom of each message file. Set it to 0 to avoid those links.\n" "# Set it to 3 to show the links only at the top of the message\n" "# pages, or 4 to produce those links only at the bottom of the\n" "# message.\n", FALSE}, {"usetable", &set_usetable, BFALSE, CFG_SWITCH, "# Setting this variable to On will tell Hypermail to generate\n" "# an index menu at the top and bottom of each page in a table\n" "# format. Set to Off if you want the standard Hypermail page look\n" "# and feel\n" "NOTE: THIS OPTION HAS BEEN DEPRECATED BY THE WAI CHANGES. IT WILL BE\n" "IGNORED.\n", FALSE}, {"indextable", &set_indextable, BFALSE, CFG_SWITCH, "# Setting this variable to On will tell Hypermail to generate\n" "# message index Subject/Author/Date listings using a nice table\n" "# format. Set to Off if you want the original Hypermail index look.\n", FALSE}, {"iquotes", &set_iquotes, BTRUE, CFG_SWITCH, "# Set this to On to italicize quoted lines.\n", FALSE}, {"eurodate", &set_eurodate, BFALSE, CFG_SWITCH, "# Set this to On to display article received dates with\n" "# days before months instead of months before days.\n", FALSE}, {"isodate", &set_isodate, BFALSE, CFG_SWITCH, "# Set this to On to display article received dates in\n" "# YYYY-MM-DD HH:MM:SS format. If used with the gmtime option, a\n" "# Z will be inserted between the DD and HH.\n", FALSE}, {"gmtime", &set_gmtime, BFALSE, CFG_SWITCH, "# Set this to On to display article received dates using\n" "# Greenwich Mean Time (UTC) rather than local time.\n", FALSE}, {"discard_dup_msgids", &set_discard_dup_msgids, BTRUE, CFG_SWITCH, "# Set this to Off to accept messages with a Message-ID matching\n" "# that of a message already in this archive.\n" "# By default such messages are discarded.\n", FALSE}, {"require_msgids", &set_require_msgids, BTRUE, CFG_SWITCH, "# Set this to Off to accept messages without a Message-ID header.\n" "# By default such messages are discarded.\n", FALSE}, {"usemeta", &set_usemeta, BFALSE, CFG_SWITCH, "# Set this to On to store the content type of a MIME attachment in\n" "# a metadata file.\n", FALSE}, {"userobotmeta", &set_userobotmeta, BFALSE, CFG_SWITCH, "# Set this to On to apply a robot annotation to a MIME attachment in\n" "# a metadata file, using the experimental X-Robots-Tag HTTP header.\n", FALSE}, {"uselock", &set_uselock, BTRUE, CFG_SWITCH, "# Set this to On to use hypermail's internal locking mechanism.\n", FALSE}, {"usegdbm", &set_usegdbm, BFALSE, CFG_SWITCH, "# Set this to On to use gdbm to implement a header cache.\n" "# This will speed up hypermail, especially if your filesystem is slow.\n" "# It will not provide any speedup with the linkquotes option.\n" #ifndef GDBM "# (This particular binary has been build with GDBM disabled.)\n" #endif , FALSE}, {"writehaof", &set_writehaof, BFALSE, CFG_SWITCH, "# Set this to On to let hypermail write an XML archive overview file\n" "# in each directory. The filename is " HAOF_NAME ".\n", FALSE}, {"append", &set_append, BFALSE, CFG_SWITCH, "# Set this to On to maintain a parallel mbox archive. The file\n" "# name defaults to mbox in the directory specified by -d or dir.\n", FALSE}, {"append_filename", &set_append_filename, NULL, CFG_STRING, "# Specifies the filename to be used by the append option.\n" "# $DIR may be used to specify a name relative to the directory\n" "# specified in the -d or dir option.\n" "# The string will be passed to strftime(3) to allow splitting the\n" "# mailbox into yearly or monthy files, such as \"%Y-%m.mbox\".\n" , FALSE}, {"nonsequential", &set_nonsequential, BFALSE, CFG_SWITCH, "# Set this to On to generate filenames that are not sequential, but\n" "# rather a hash of the message properties.\n" #ifndef HAVE_LIBFNV "# (This particular binary has been build with LIBFNV disabled.\n" "# This option won't work)\n" #endif , FALSE}, {"thrdlevels", &set_thrdlevels, INT(4), CFG_INTEGER, "# This specifies the number of thread levels to outline\n" "# in the thread index.\n", FALSE}, {"dirmode", &set_dirmode, INT(0755), CFG_OCTAL, "# This is an octal number representing the permissions\n" "# that new directories are set to when they are created.\n", FALSE}, {"filemode", &set_filemode, INT(0644), CFG_OCTAL, "# This is an octal number representing the file permissions\n" "# that new files are set to when they are created.\n", FALSE}, {"mailcommand", &set_mailcommand, MAILCOMMAND, CFG_STRING, "# This specifies the mail command to use when converting\n" "# email addresses to links. The variables $TO, $SUBJECT,\n" "# and $ID can be used in constructing the command string.\n", FALSE}, {"mailto", &set_mailto, NULL, CFG_STRING, "# The address of the contact point that is put in the HTML header\n" "# line . Setting this to NONE\n" "# disables header generation.\n", FALSE}, {"hmail", &set_hmail, NULL, CFG_STRING, "# Set this to the list's submission address.\n", FALSE}, {"newmsg_command", &set_newmsg_command, "mailto:$TO", CFG_STRING, "# This specifies the mail command to use when converting the\n" "# set_hmail address to links in replies. The variables $TO, $SUBJECT,\n" "# and $ID can be used in constructing the command string.\n", FALSE}, {"replymsg_command", &set_replymsg_command, "not set", CFG_STRING, "# This specifies the mail command to use when converting the\n" "# set_hmail address to links in replies. The variables $TO, $SUBJECT,\n" "# and $ID can be used in constructing the command string. The value\n" "# from mailcommand will be used if this option is not specified.\n", FALSE}, {"inreplyto_command", &set_inreplyto_command, NULL, CFG_STRING, "# This gives a URI template to a script that hypermail will link to\n" "# if it's unable to find in the archive's messages the MID corresponding\n" "# to an In-Reply-To header. The variable $ID is used to specify where the\n" "# Message-Identifier value will appear in the link.\n", FALSE}, {"domainaddr", &set_domainaddr, DOMAINADDR, CFG_STRING, "# Set this to the domainname you want added to a mail address\n" "# appearing in the RFC822 field which lack a hostname.\n", FALSE}, {"body", &set_htmlbody, NULL, CFG_STRING, "# This obsolete entry kept around to help warn users with old config files.\n", FALSE}, {"icss_url", &set_icss_url, NULL, CFG_STRING, "# Specifies a URL to an external CSS stylesheet for the index pages.\n" "# The CSS will be associated to the indexes thru an HTML LINK element.\n" , FALSE}, {"mcss_url", &set_mcss_url, NULL, CFG_STRING, "# Specifies a URL to an external CSS stylesheet for the message pages.\n" "# The CSS will be associated to the indexes thru an HTML LINK element.\n" , FALSE}, {"text_types", &set_text_types, NULL, CFG_LIST, "# This is a list of MIME types that you want hypermail to treat\n" "# exactly as if they were text/plain.\n", FALSE}, {"inline_types", &set_inline_types, INLINE_TYPES, CFG_LIST, "# This is the list of MIME types that you want tags to as\n" "# opposed to simply to from the message.\n", FALSE}, {"inline_addlink", &set_inline_addlink, BTRUE, CFG_SWITCH, "# Set to On to add inline links to content that is stored in the\n" "# attachments subdirectory. 'inline_types' must be enabled.\n", FALSE}, {"prefered_types", &set_prefered_types, NULL, CFG_LIST, "# When mails using multipart/mixed types are scanned, this list of\n" "# MIME types defines which part you want presented in the result.\n" "# See the save_alts option for how non prefered types are treated.\n", FALSE}, {"ignore_types", &set_ignore_types, NULL, CFG_LIST, "# This is the list of MIME attachment types that you do not want\n" "# to do anything with. Two special types may be used here:\n" "# $BINARY - ignore all types that would be stored as separate files.\n" "# $NONPLAIN - ignore all types not treated as text/plain, and all $BINARY types.\n" "# Note: the behavior of these may be affected by the inlinehtml option.\n", FALSE}, {"applemail_mimehack", &set_applemail_mimehack, BFALSE, CFG_SWITCH, "# Set to On to process Apple Mail MIME multipart/alternative\n" "# as if the save_alts was enabled. If the message contains only\n" "# a text/plain and a text/html alternatives, the text/plain one will\n" "# be kept and the text/html alternative will be discared. If the\n" "# message contains text/plain and another kind of alternative, such as\n" "# multipart/mixed or multipart/related, all the alternative elements\n" "# be displayed. This is to take into account Apple Mail's MIME format\n" "# where attachments are associated by default with the text/html alternative.\n" "# Use this option if you're using text/plain as a prefered type.\n" "# This option is ignored if save_alts is enabled or if text/html is\n" "# the prefered type.", FALSE}, {"applemail_ua_header", &set_applemail_ua_header, "X-Mailer", CFG_STRING, "# Set to the header name that Apple Mail uses to identify its mail agent.\n" "# This option is only useful if you enabled the applemail_mimehack configuration\n" "# option.\n", FALSE}, {"applemail_ua_value", &set_applemail_ua_value, APPLE_MAIL_UA, CFG_LIST, "# Set to the list of the header value that Apple Mail uses to identify\n" "# its mail agent. Do not add the version number unless you know what you're doing.\n" "# This option is only useful if you enabled the applemail_mimehack configuration\n" "# option.\n", FALSE}, {"show_headers", &set_show_headers, NULL, CFG_LIST, "# This is the list of headers to be displayed if 'showheaders'\n" "# is set to On). They can be listed comma or space separated\n" "# all on a single line.\n", FALSE}, {"format_flowed", &set_format_flowed, BFALSE, CFG_SWITCH, "# Enable support for RFC3676 format=flowed (EXPERIMENTAL)\n", FALSE}, {"format_flowed_disable_quoted", &set_format_flowed_disable_quoted, BFALSE, CFG_SWITCH, "# If format_flowed is enabled, this option allows you to disable\n" "# format=flowed inside quoted text\n", FALSE}, {"ihtmlheaderfile", &set_ihtmlheader, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to\n" "# included at the top of every index page.\n", FALSE}, {"ihtmlfooterfile", &set_ihtmlfooter, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to\n" "# included at the bottom of every index page.\n", FALSE}, {"ihtmlheadfile", &set_ihtmlhead, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to\n" "# included inside the HTML HEAD element of every index page.\n", FALSE}, {"ihtmlhelpupfile", &set_ihtmlhelpup, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to\n" "# included as information giving help to your archive users," "# in the upper navigation bar.\n", FALSE}, {"ihtmlhelplowfile", &set_ihtmlhelplow, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to\n" "# included as information giving help to your archive users," "# in the lower navigation bar.\n", FALSE}, {"ihtmlnavbar2upfile", &set_ihtmlnavbar2up, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to\n" "# included as information giving links to the hierarchin your archive.\n", FALSE}, {"mhtmlheaderfile", &set_mhtmlheader, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements that you wish to use\n" "# at the top of every message page.\n", FALSE}, {"mhtmlfooterfile", &set_mhtmlfooter, NULL, CFG_STRING, "# Define path as the path to a template file containing\n" "# valid HTML formatting statements you wish to use at the\n" "# bottom of every message page.\n", FALSE}, {"locktime", &set_locktime, INT(3600), CFG_INTEGER, "# Specify number of seconds to wait for a lock before we\n" "# override it! .\n", FALSE}, {"dateformat", &set_dateformat, NULL, CFG_STRING, "# Format (see strftime(3)) for displaying dates.\n", FALSE}, {"indexdateformat", &set_indexdateformat, NULL, CFG_STRING, "# Format (see strftime(3)) for displaying dates in the index pages.\n" "# Will use dateformat if not specified.\n", FALSE}, {"stripsubject", &set_stripsubject, NULL, CFG_STRING, "# A word to be stripped from all subject lines. Helps unclutter\n" "# mailing lists which add tags to subject lines.\n", FALSE}, {"attachmentlink", &set_attachmentlink, NULL, CFG_STRING, "# Format of the attachment links.\n" "# %p for the full path to the attachment\n" "# %f for the file name part only\n" "# %d for the directory name only\n" "# %n for the message number\n" "# %c for the content type string\n", FALSE}, {"spamprotect", &set_spamprotect, BTRUE, CFG_SWITCH, "# Set this to On to make hypermail not output real email addresses\n" "# in the output HTML but instead it will obfuscate them a little.\n" "# You can control the obfuscation with set_antispamdomain.\n", FALSE}, {"antispamdomain", &set_antispamdomain, NULL, CFG_STRING, "# By default hypermail only does a small amount of massaging\n" "# of email addresses. Use this to completely replace the domain\n" "# from which a message originates (everything after the @)\n" "# with some string to confuse screen-scraping programs.\n" "# It is probably wise to make this an invalid mail domain.\n", FALSE}, {"spamprotect_id", &set_spamprotect_id, BTRUE, CFG_SWITCH, "# Set this to On to make hypermail not output real email message\n" "# ids in HTML comments (sometimes used internally by hypermail) but\n" "# instead it will obfuscate them a little so they don't look like\n" "# email addresses to spammers.\n", FALSE}, {"attachmentsindex", &set_attachmentsindex, BTRUE, CFG_SWITCH, "# Set this to Off to make hypermail not output an index of\n" "# messages with attachments.\n", FALSE}, {"linkquotes", &set_linkquotes, BFALSE, CFG_SWITCH, "# Set this to On to create fine-grained links from quoted\n" "# text to the text where the quote originated. It also improves\n" "# the threads index file by more accurately matching messages\n" "# with replies. Note that this may be rather cpu intensive (see\n" "# the searchbackmsgnum option to alter the performance).\n" , FALSE}, {"searchbackmsgnum", &set_searchbackmsgnum, INT(500), CFG_INTEGER, "# If the linkquotes option is on and an incremental update is being" "# done (-u option), this controls the tradeoff between speed and\n" "# the reliability of finding the right source for quoted text.\n" "# Try to set it to the largest number of messages between a\n" "# message and the final direct reply to that message.\n", FALSE}, {"link_to_replies", &set_link_to_replies, NULL, CFG_STRING, "# If the linkquotes option is on, specifying a string here\n" "# causes it to generate links from original quoted text to the\n" "# location(s) in replies which quote them. The string\n" "# is used to display the link.\n", FALSE}, {"quote_hide_threshold", &set_quote_hide_threshold, INT(100), CFG_INTEGER, "# If the linkquotes option is on, setting this to an\n" "# integer less than 100 will cause it to replace quoted\n" "# text with one-line links if the percent of lines in the\n" "# message body (exluding the signature) consisting of\n" "# quoted text exceeds the number indicated by this option.\n", FALSE}, {"quote_link_string", &set_quote_link_string, NULL, CFG_STRING, "# If the quote_hide_threshold option is being used, the\n" "# quote_link_string will be used if available to display the\n" "# link that replaces the quoted text. If no string is specified\n" "# here, the first line of each section of quoted text will used.\n", FALSE}, {"monthly_index", &set_monthly_index, BFALSE, CFG_SWITCH, "# Set this to On to create additional index files broken up\n" "# by month. A summary.html file will provide links to all the\n" "# monthly indices.\n", FALSE}, {"yearly_index", &set_yearly_index, BFALSE, CFG_SWITCH, "# Set this to On to create additional index files broken up\n" "# by year. A summary.html file will provide links to all the\n" "# yearly indices.\n", FALSE}, {"thread_file_depth", &set_thread_file_depth, INT(0), CFG_INTEGER, "# If nonzero, break the threads index file into multiple files,\n" "# with the initial message of each thread in the main index file\n" "# along with links to files containing the replies. Setting this\n" "# to 1 creates one file for each thread that has replies, and is\n" "# recommended for archives with over a few hundred messages.\n" "# Setting this greater than 1 will produce multiple levels of files\n" "# for each thread whose replies are nested by more than 1 level,\n" "# but that is rarely useful. This option is currently disabled\n" "# if the indextable option is turned on, and probably needs to\n" "# be less than thrdlevels.\n", FALSE}, {"startmsgnum", &set_startmsgnum, INT(0), CFG_INTEGER, "# Sets the number of the first message of an archive. This option is\n" "# only active when adding new messages to brand new archive.\n" "# If not set, the default number will be 0000.\n" "# Note that if you change this setting, you are stuck with it. If you\n" "# rebuild your archive, you must use the same value or you'll break any\n" "# link pointing to your archive.\n", FALSE}, {"folder_by_date", &set_folder_by_date, NULL, CFG_STRING, "# This string causes the messages to be put in subdirectories\n" "# by date. The string will be passed to strftime(3) to generate\n" "# subdirectory names based on message dates. Suggested values are\n" "# \"%y%m\" or \"%b%y\" for monthly subdirectories, \"%Y\" for\n" "# yearly, \"%G/%V\" for weekly. Do not alter this for an existing\n" "# archive without removing the old html files. If you use this\n" "# and update the archive incrementally (e.g. with -u), you must\n" "# use the usegdbm option.\n", FALSE}, {"msgsperfolder", &set_msgsperfolder, INT(0), CFG_INTEGER, "# Put messages in subdirectories with this many messages per\n" "# directory. Do not use this and folder_by_date on the same archive.\n" "# Do not alter this for an existing archive without removing the old\n" "# html files. Deleted/expired messages ARE COUNTED for the purpose\n" "# of deciding how many messages to put in a subdirectory.\n", FALSE}, {"describe_folder", &set_describe_folder, NULL, CFG_STRING, "# Controls the labels used in folders.html to describe the\n" "# directories created by the folder_by_date or msgsperfolder\n" "# options. For folder_by_date labels, the describe_folder string\n" "# will be passed to strftime(3) the same as the folder_by_date string.\n" "# For msgsperfolder:\n" "# %d for the directory number (starts with 0)\n" "# %D for the directory number (starts with 1)\n" "# %m for the number of the first message in the directory\n" "# %M for the number of the last message that can be put in the\n" "# directory.\n", FALSE}, {"latest_folder", &set_latest_folder, NULL, CFG_STRING, "# If folder_by_date or msgsperfolder are in use, create\n" "# a symbolic link by this name to the most recently created\n" "# subdirectory. Note that many web servers are configured to\n" "# not follow symbolic links for security reasons. The link will\n" "# be created in the directory specified by the 'dir' or '-d' option.\n", FALSE}, {"base_url", &set_base_url, NULL, CFG_STRING, "# The url of the archive's main directory. This is needed when\n" "# the latest_folder option is used and the folder_by_date makes\n" "# directories more than one level deep (e.g. with '%y/%m').\n", FALSE}, {"iso2022jp", &set_iso2022jp, BFALSE, CFG_SWITCH, "# Set this to On to support ISO-2022-JP messages.\n", FALSE}, {"noindex_onindexes", &set_noindex_onindexes, BFALSE, CFG_SWITCH, "# Set to On to inform search engines that you don't want to index\n" "# the hypermail generated indexes. See the \"annotated\" configuration" "# option for a more detailed description.\n", FALSE}, {"annotated", &set_annotated, "X-Hypermail-Annotated", CFG_LIST, "# This is the list of headers that indicate that a message was annotated.\n" "# When a message contains such a header, the header may have one more comma\n" "# separated values indicatating the annotation type. Order and case are\n" "# not important.\n" "# The possible values of this header are: content and robot annotations.\n" "# Content annotations can have only one of the following values:\n" "# spam : message deleted because it is spam;\n" "# deleted : message deleted, other reasons;\n" "# edited : original received message was manually edited.\n" "# You can customize the markup that\'s shown for content annotations\n" "# by means of the htmlmessage_deleted_other, htmlmessage_deleted_spam\n," "# htmlmessage_edited directives.\n\n" "# robot annotations can have either one or both of the following values:\n" "# nofollow : do not follow the links on this page;\n" "# noindex : prevent search engines from indexing the contents of this message.\n" "# Robot annotations instruct a visiting web robot agent if a message contents\n" "# should be indexed and/or if the outgoing links from the message\n" "# should be followed, doing so thru a specific HTML meta tag. You can use one or\n" "# both values and combine them with the edited content annotation.\n" "# NOTE: Spam or deleted annotation values have an implicit robot \"noindex\"\n" "# annotation In such case, user supplied robot annotations values will be silently\n" "# ignored.\n", FALSE}, {"deleted", &set_deleted, "X-Hypermail-Deleted X-No-Archive", CFG_LIST, "# NOTE: this option has been deprecated by annotated, but it will continue\n" "# being parsed and honored for legacy reasons.\n" "# This is the list of headers that indicate the message should\n" "# not be displayed if the value of this header is 'yes'.\n", FALSE}, {"expires", &set_expires, "Expires", CFG_LIST, "# This is the list of headers that indicate the message should\n" "# not be displayed if the value of this header is a date in the past.\n", FALSE}, {"delete_older", &set_delete_older, NULL, CFG_STRING, "# Any message older than this date should not be displayed.\n", FALSE}, {"delete_newer", &set_delete_newer, NULL, CFG_STRING, "# Any message newer than this date should not be displayed.\n", FALSE}, {"delete_msgnum", &set_delete_msgnum, NULL, CFG_LIST, "# This is the list of message numbers that should be deleted from the\n" "# html archive. The mbox is not changed.\n", FALSE}, {"delete_incremental", &set_delete_incremental, BTRUE, CFG_SWITCH, "# If this option is enabled, hypermail will perform deletions on old\n" "# messages when run in incremental mode (according to the other delete\n" "# configuring option). Note that depending on your hypermail setup,\n" "# the size of the archive, and the complexity of the markup,\n" "# there may be memory and parsing issues, specifically when there are\n" "# non-deleted replies to a deleted message.\n" "# If this option is disabled, deleted messages will only be removed\n" "# when rebuilding the whole archive.\n", FALSE}, {"delete_level", &set_delete_level, INT(DELETE_LEAVES_STUBS), CFG_INTEGER, "# 0 - remove deleted and expired files. Note that with this choice\n" "# threading may be screwed up if there are replies to deleted or\n" "# expired options and the archive is updated incrementally\n" "# 1 - remove message body\n" "# 2 - remove message body for deleted messages, leave expired messages\n" "# 3 - leave all messages\n" "# Deleted and expired messages are removed from the index files\n" "# regardless of the delete_level selection.\n", FALSE}, {"txtsuffix", &set_txtsuffix, NULL, CFG_STRING, "# If you want the original mail messages archived in individual files,\n" "# set this to the extension that you want these messages to have\n" "# (recommended value: txt).\n", FALSE}, {"filter_out", &set_filter_out, NULL, CFG_STRINGLIST, "# Delete from the html archives any message having a header line\n" "# which matches any of these expressions. Uses the same rules for\n" "# deletion as the expires option. The expressions use the same\n" "# syntax as Perl regular expressions.\n", FALSE}, {"filter_require", &set_filter_require, NULL, CFG_STRINGLIST, "# Delete from the html archives any message not having header lines\n" "# which match each of these expressions. Uses the same rules for\n" "# deletion as the expires option. The expressions use the same\n" "# syntax as Perl regular expressions.\n", FALSE}, {"filter_out_full_body", &set_filter_out_full_body, NULL, CFG_STRINGLIST, "# Delete from the html archives any message having a line\n" "# which matches any of these expressions. Uses the same rules for\n" "# deletion as the expires option. The expressions use the same\n" "# syntax as Perl regular expressions.\n", FALSE}, {"filter_require_full_body", &set_filter_require_full_body, NULL, CFG_STRINGLIST, "# Delete from the html archives any message not having lines\n" "# which match each of these expressions. Uses the same rules for\n" "# deletion as the expires option. The expressions use the same\n" "# syntax as Perl regular expressions.\n", FALSE}, {"save_alts", &set_save_alts, INT(0), CFG_INTEGER, "# This controls what happens to alternatives (other than the prefered\n" "# alternative) for multipart/alternative messages.\n" "# 0 - discard non-prefered alternatives\n" "# 1 - show all alternatives inline\n" "# 2 - put non-prefered alternatives in a separate file.\n", FALSE}, {"alts_text", &set_alts_text, NULL, CFG_STRING, "# If save_alts is 1, this text is put between the alternatives.\n" "# If save_alts is 2, this text is used to describe the link to each\n" "# alternative file.\n", FALSE}, {"warn_suppressions", &set_warn_suppressions, BTRUE, CFG_SWITCH, "# Set this to On to get warnings (on stdout) about messages that\n" "# are not converted because of they are missing a msgid (if\n" "# require_msgids is On) or because one of the following options\n" "# suppressed it: deleted expires delete_msgnum filter_out\n" "# filter_require filter_out_full_body filter_require_full_body.\n", FALSE}, {"unsafe_chars", &set_unsafe_chars, NULL, CFG_STRING, "# Any characters listed in this string are removed from user-specified\n" "# attachment filenames. Those characters will be replaced by a \"_\"\n" "# (which means that specifying \"_\" here won't have any effect).\n" "# Note that many characters (including / and \\) are removed by the\n" "# safe_filename in parse.c regardless of what this option says. There\n" "# might be some security problems that can be prevented if you specify\n" "# \".\" here (e.g. if a web server is configured to enable server side\n" "# includes on filenames ending in something other than .shtml), but\n" "# that will prevent browsers from recognizing many file types.\n", FALSE}, {"files_by_thread", &set_files_by_thread, BFALSE, CFG_SWITCH, "# Set this to On to generate (in addition to the usual files),\n" "# a file for each thread that contains all the messages in that\n" "# thread.\n", FALSE}, {"href_detection", &set_href_detection, BTRUE, CFG_SWITCH, "# Set this to On to assume that any string on the body of the message\n" "# that says is a URL, together with its markup\n" "# and treat it as such.\n", TRUE}, {"mbox_shortened", &set_mbox_shortened, BFALSE, CFG_SWITCH, "# Set this to On to enable use of mbox that has had some of its\n" "# initial messages deleted. Requires usegdbm = 1 and increment = 0.\n" "# The first message in the shortened mbox must have a Message-Id header.\n" "# If discard_dup_msgids is 0, the first message in the shortened mbox\n" "# may not have the same Message-Id as a message that was deleted.\n" "# The mbox may not be altered in any way other than deleting from\n" "# beginning of the mbox or appending new messages to the end (unless\n" "# you rebuild the archive from scratch using a complete mbox).\n", FALSE}, {"report_new_folder", &set_report_new_folder, BFALSE, CFG_SWITCH, "# Set this to On to have it print (on stdout) the names of any\n" "# new directories created pursuant to the folder_by_date or\n" "# msgsperfolder option, or the initial creation of the archive.\n" "# It will print the full path if that is what you use to specify\n" "# the archive directory. Does not print anything when attachment\n" "# or metadata directories are created.\n", FALSE}, {"report_new_file", &set_report_new_file, BFALSE, CFG_SWITCH, "# Set this to On to have it print (on stdout) the names of any\n" "# new files created for new messages. It will print the full path\n" "# if that is what you use to specify the archive directory.\n", FALSE}, {"use_sender_date", &set_use_sender_date, BFALSE, CFG_SWITCH, "# Set this to On to have it use the Date: header (created by the\n" "# the system that sent the message) rather than the date/time the\n" "# message was received, for purposes such as putting in folders\n" "# or sorting. Details of which purposes this affects may change\n" "# in the future.\n", FALSE}, {"filename_base", &set_filename_base, NULL, CFG_STRING, "# This option overrides the normal rules for creating attachment\n" "# file names, and creates file names from the string that this\n" "# option is set to plus a file name extension if one can be found\n" "# in the name supplied by the message. This option is mainly for\n" "# languages that use different character sets from English.\n", FALSE}, }; /* ---------------------------------------------------------------- */ void MakeConfig(bool comments) { int i; time_t now = time(NULL); if (comments) { fprintf(stdout, "#################################################################\n" "# This is an automatically generated config file done by\n" "# Hypermail " VERSION " patchlevel " PATCHLEVEL " - %s", ctime(&now)); } for (i = 0; i < sizeof(cfg) / sizeof(cfg[0]); i++) { if (cfg[i].verbose) { if (comments) { fputs("\n", stdout); fputs(cfg[i].verbose, stdout); } switch (cfg[i].flags) { case CFG_STRING: if (cfg[i].changed && *(char **)cfg[i].value) /* they differ, show the actual contents */ fprintf(stdout, "%s = %s\n", cfg[i].label, *(char **)cfg[i].value); else if (comments) /* show the default value, but commented */ /* fprintf(stdout, "#%s = %s\n", cfg[i].label, */ fprintf(stdout, "%s = %s\n", cfg[i].label, cfg[i].def ? (char *)cfg[i].def : ""); break; case CFG_LIST: case CFG_STRINGLIST: if (cfg[i].changed) { print_list(cfg[i].label, *(struct hmlist **)cfg[i].value); } else if (comments) { /* show the default value, but commented */ /* fprintf(stdout, "#%s = %s\n", cfg[i].label, */ fprintf(stdout, "%s = %s\n", cfg[i].label, cfg[i].def ? (char *)cfg[i].def : ""); } break; case CFG_OCTAL: if (cfg[i].changed) /* they differ, show the actual contents */ fprintf(stdout, "%s = %lo\n", cfg[i].label, *(long *)(cfg[i].value)); else if (comments) /* show the default value, but commented */ /* fprintf(stdout, "#%s = %lo\n", cfg[i].label, */ fprintf(stdout, "%s = %lo\n", cfg[i].label, (long)cfg[i].def); break; case CFG_INTEGER: if (cfg[i].changed) /* they differ, show the actual contents */ fprintf(stdout, "%s = %ld\n", cfg[i].label, *(long *)(cfg[i].value)); else if (comments) /* show the default value, but commented */ /* fprintf(stdout, "#%s = %ld\n", cfg[i].label, */ fprintf(stdout, "%s = %ld\n", cfg[i].label, (long)cfg[i].def); break; case CFG_SWITCH: if (cfg[i].changed) /* they differ, show the actual contents */ fprintf(stdout, "%s = %s\n", cfg[i].label, *(int *)(cfg[i].value) ? "On" : "Off"); else if (comments) /* fprintf(stdout, "#%s = %s\n", cfg[i].label, */ fprintf(stdout, "%s = %s\n", cfg[i].label, cfg[i].def ? "On" : "Off"); break; default: break; } /* end of switch() */ } /* end of if() */ } /* end of for() */ } /* end of function */ static bool inited = FALSE; void PreConfig(void) { int i; char name[128] = "HM_"; char *labp; int ind; void *defval; for (i = 0; i < sizeof(cfg) / sizeof(cfg[0]); i++) { cfg[i].changed = FALSE; /* build environment variable to read from */ for (ind = 3, labp = cfg[i].label; *labp; labp++) { name[ind++] = toupper(*labp); } name[ind] = 0; /* we try to get a default value from an environment variable */ defval = getenv(name); if (!defval) /* get the built-in default instead */ defval = cfg[i].def; switch (cfg[i].flags) { case CFG_STRING: if (defval) *(char **)cfg[i].value = strsav(defval); else *(char **)cfg[i].value = NULL; break; case CFG_SWITCH: case CFG_INTEGER: case CFG_OCTAL: if (defval == cfg[i].def) *(int *)cfg[i].value = (intptr_t)defval; else *(int *)cfg[i].value = atoi(defval); break; case CFG_LIST: if (defval) { char *tpstr; tpstr = strsav(defval); *(struct hmlist **)cfg[i].value = NULL; *(struct hmlist **)cfg[i].value = (void *)add_list(*(struct hmlist **)cfg[i].value, tpstr); free(tpstr); } else *(struct hmlist **)cfg[i].value = NULL; break; case CFG_STRINGLIST: if (defval) { char *tpstr; tpstr = strsav(defval); *(struct hmlist **)cfg[i].value = NULL; *(struct hmlist **)cfg[i].value = (void *)add_2_list(*(struct hmlist **)cfg[i].value, tpstr); free(tpstr); } else *(struct hmlist **)cfg[i].value = NULL; break; default: break; } } inited = TRUE; } void PostConfig(void) { int i; /* Keep default behavior the same as it was when mailcommand applied * to the cases now covered by replymsg_command. */ if (!strcmp(set_replymsg_command, "not set")) set_replymsg_command = set_mailcommand; show_index[1][AUTHOR_INDEX] = !inlist(set_avoid_indices, "author"); show_index[1][DATE_INDEX] = !inlist(set_avoid_indices, "date"); show_index[1][SUBJECT_INDEX] = !inlist(set_avoid_indices, "subject"); show_index[1][THREAD_INDEX] = !inlist(set_avoid_indices, "thread"); show_index[1][ATTACHMENT_INDEX] = !inlist(set_avoid_indices, "attachments") && set_attachmentsindex; if (set_folder_by_date || set_msgsperfolder) { show_index[0][AUTHOR_INDEX] = !inlist(set_avoid_top_indices, "author"); show_index[0][DATE_INDEX] = !inlist(set_avoid_top_indices, "date"); show_index[0][SUBJECT_INDEX] = !inlist(set_avoid_top_indices, "subject"); show_index[0][THREAD_INDEX] = !inlist(set_avoid_top_indices, "thread"); show_index[0][ATTACHMENT_INDEX] = !inlist(set_avoid_top_indices, "attachments") && set_attachmentsindex; show_index[0][FOLDERS_INDEX] = !inlist(set_avoid_top_indices, "folders"); } else { for (i = 0; i <= ATTACHMENT_INDEX; ++i) show_index[0][i] = show_index[1][i]; } if (set_htmlbody != NULL) printf("Warning: the body option has been disabled. See the\n" "INSTALL file for instructions on replacing it with a style sheet.\n"); if (set_save_alts < 0 || set_save_alts > 2) { printf("Error: save_alts option value must be between 0 and 2.\n"); exit(0); } if (set_applemail_mimehack && set_save_alts) { printf("Warning: the applemail_mimehack option will be ignored as\n" "the save_alts options is enabled.\n"); set_applemail_mimehack = 0; } if (set_applemail_mimehack && set_prefered_types && !strcasecmp(set_prefered_types->val, "text/html")) { printf("Warning: the applemail_mimehack option will be ignored as\n" "text/html is the prefered type.\n"); set_applemail_mimehack = 0; } if (set_applemail_mimehack) { if (!set_applemail_ua_header || !*set_applemail_ua_header) { printf("Error: the applemail_mimehack option is enabled\n" "but the applemail_ua_header configuration variable is empty.\n"); exit(0); } else if (!set_applemail_ua_value) { printf("Error: the applemail_mimehack option is enabled\n" "but the applemail_ua_value configuration variable is empty.\n"); exit(0); } } } int ConfigAddItem(char *cfg_line) { char keyword[256]; char towhat[1001]; /* increased due to htmlmessage_deleted */ char *keywp; int i; char *line = cfg_line; /* ** This is here to support earlier config file formats. ** The "set " is nolonger needed but has been added ** for backwards compatability. */ if (!strncmp (line, "set ", 4)) line += 4; if (2 <= sscanf(line, " %255[a-zA-Z0-9._] %*[=: ] %500[^\n]", keyword, towhat)) { if ('\"' == towhat[0]) { /* we have a quote as the first character, then we assume we have a "string" to parse instead of just string. */ sscanf(line, " %255[a-zA-Z0-9._] %*[=: ] \"%500[^\"]", keyword, towhat); } else { /* no quotes, we eat all trailing white spaces */ i = strlen(towhat); if (i--) { while ((i >= 0) && isspace(towhat[i])) towhat[i--] = 0; } } if (!strncasecmp(keyword, "hm_", 3)) /* if there is a hm_ prefix, skip it! */ keywp = keyword + 3; else keywp = keyword; for (i = 0; i < sizeof(cfg) / sizeof(cfg[0]); i++) { if (*keywp != *(cfg[i].label)) /* minor speedup */ continue; if (!strcasecmp(keywp, cfg[i].label)) { /* match */ switch (cfg[i].flags) { case CFG_STRING: *(char **)cfg[i].value = strsav(towhat); break; case CFG_SWITCH: if (atoi(towhat) || !strcasecmp("ON", towhat) || !strcasecmp("YES", towhat)) *(int *)cfg[i].value = (int)TRUE; else *(int *)cfg[i].value = (int)FALSE; break; case CFG_INTEGER: /* get an integer using any base */ /* ON/YES support is for options that used to be CFG_SWITCH's */ if (!strcasecmp("ON", towhat) || !strcasecmp("YES", towhat)) *(int *)cfg[i].value = 1; else *(int *)cfg[i].value = (int)strtol(towhat, NULL, 0); break; case CFG_OCTAL: /* get an octal number */ *(int *)cfg[i].value = (int)strtol(towhat, NULL, 8); break; case CFG_LIST: /* Is this the first time that it's been called * for this list ? If so then there is a value * being set for the list via a config file. * In the case of lists we need to replace the * current value with the new material completely. */ if (cfg[i].changed == FALSE) { /* first time through ? */ if (cfg[i].value) { if (*(struct hmlist **)cfg[i].value) free(*(struct hmlist **)cfg[i].value); *(struct hmlist **)cfg[i].value = NULL; } } *(struct hmlist **)cfg[i].value = (void *)add_list(*(struct hmlist **)cfg[i].value,towhat); break; case CFG_STRINGLIST: /* Is this the first time that it's been called * for this list ? If so then there is a value * being set for the list via a config file. * In the case of lists we need to replace the * current value with the new material completely. */ if (cfg[i].changed == FALSE) { /* first time through ? */ if (cfg[i].value) { if (*(struct hmlist **)cfg[i].value) free(*(struct hmlist **)cfg[i].value); *(struct hmlist **)cfg[i].value = NULL; } } *(struct hmlist **)cfg[i].value = (void *)add_2_list(*(struct hmlist **)cfg[i].value,towhat); break; default: break; } cfg[i].changed = TRUE; return 0; } } } return 1; } int ConfigInit(char *filename) { FILE *f; char line[MAXLINE]; int r = TRUE; PreConfig(); if (filename && *filename) { f = fopen(filename, "r"); if (f) { while (fgets(line, MAXLINE, f)) { if ((line[0] != '#') && (line[0] != '\n')) { /* need to error check the format */ ConfigAddItem(line); } } fclose(f); } else r = FALSE; } PostConfig(); return r; } void ConfigCleanup(void) { int i; for (i = 0; i < sizeof(cfg) / sizeof(cfg[0]); i++) { switch (cfg[i].flags) { case CFG_LIST: case CFG_STRINGLIST: if (cfg[i].value) { if (*(struct hmlist **)cfg[i].value) free(*(struct hmlist **)cfg[i].value); } break; case CFG_STRING: if (cfg[i].value) { if (*(char **)cfg[i].value) free(*(char **)cfg[i].value); } break; default: break; } } } #ifdef DEBUG void dump_config(void) { register char *cp; printf("\nConfiguration Values:\n"); printf("set_language = %s\n",set_language ? set_language : "Not Used"); printf("set_htmlsuffix = %s\n",set_htmlsuffix ? set_htmlsuffix : "Not Used"); printf("set_mbox = %s\n", set_mbox ? set_mbox : "Not Used"); printf("set_archives = %s\n",set_archives ? set_archives : "Not set"); printf("set_custom_archives = %s\n",set_custom_archives ? set_custom_archives : "Not set"); printf("set_about = %s\n",set_about ? set_about : "Not set"); printf("set_dir = %s\n",set_dir ? set_dir : "Not set"); printf("set_defaultindex = %s\n",set_defaultindex ? set_defaultindex : "Not set"); printf("set_default_top_index = %s\n",set_default_top_index ? set_default_top_index : "Not set"); printf("set_label = %s\n",set_label ? set_label : "Not set"); printf("set_append_filename = %s\n",set_append_filename ? set_append_filename : "Not set"); printf("set_dateformat = %s\n",set_dateformat ? set_dateformat : "Not set"); printf("set_stripsubject = %s\n",set_stripsubject ? set_stripsubject : "Not set"); printf("set_mailcommand = %s\n",set_mailcommand ? set_mailcommand : "Not set"); printf("set_replymsg_command = %s\n",set_replymsg_command ? set_replymsg_command : "Not set"); printf("set_inreplyto_command = %s\n",set_inreplyto_command ? set_inreplyto_command : "Not set"); printf("set_newmsg_command = %s\n",set_newmsg_command ? set_newmsg_command : "Not set"); printf("set_mailto = %s\n",set_mailto ? set_mailto : "Not set"); printf("set_hmail = %s\n",set_hmail ? set_hmail : "Not set"); printf("set_domainaddr = %s\n",set_domainaddr ? set_domainaddr : "Not set"); printf("set_icss_url = %s\n",set_icss_url ? set_icss_url : "Not set"); printf("set_mcss_url = %s\n",set_mcss_url ? set_mcss_url : "Not set"); printf("set_attachmentlink = %s\n",set_attachmentlink ? set_attachmentlink : "Not set"); printf("set_link_to_replies = %s\n",set_link_to_replies ? set_link_to_replies : "Not set"); printf("set_quote_link_string = %s\n",set_quote_link_string ? set_quote_link_string : "Not set"); printf("set_folder_by_date = %s\n",set_folder_by_date ? set_folder_by_date : "Not set"); printf("set_describe_folder = %s\n",set_describe_folder ? set_describe_folder : "Not set"); printf("set_latest_folder = %s\n",set_latest_folder ? set_latest_folder : "Not set"); printf("set_antispamdomain = %s\n",set_antispamdomain ? set_antispamdomain : "Not set"); printf("set_applemail_ua_header = %s\n",set_applemail_ua_header ? set_applemail_ua_header : "Not set"); /* Boolean or integer */ printf("set_overwrite = %d\n",set_overwrite); printf("set_inlinehtml = %d\n",set_inlinehtml); printf("set_increment = %d\n",set_increment); printf("set_readone = %d\n",set_readone); printf("set_reverse = %d\n",set_reverse); printf("set_showprogress = %d\n",set_showprogress); printf("set_showheaders = %d\n",set_showheaders); printf("set_showhtml = %d\n",set_showhtml); printf("set_showbr = %d\n",set_showbr); printf("set_showhr = %d\n",set_showhr); printf("set_showreplies = %d\n",set_showreplies); printf("set_show_msg_links = %d\n",set_show_msg_links); printf("set_usetable = %d\n",set_usetable); printf("set_indextable = %d\n",set_indextable); printf("set_iquotes = %d\n",set_iquotes); printf("set_eurodate = %d\n",set_eurodate); printf("set_isodate = %d\n",set_isodate); printf("set_gmtime = %d\n",set_gmtime); printf("set_require_msgids = %d\n",set_require_msgids); printf("set_discard_dup_msgids = %d\n",set_discard_dup_msgids); printf("set_usemeta = %d\n",set_usemeta); printf("set_userobotmeta = %d\n",set_userobotmeta); printf("set_uselock = %d\n",set_uselock); printf("set_locktime = %d\n",set_locktime); printf("set_ietf_mbox = %d\n",set_ietf_mbox); printf("set_usegdbm = %d\n",set_usegdbm); printf("set_writehaof = %d\n",set_writehaof); printf("set_append = %d\n",set_append); printf("set_nonsequential = %d\n",set_nonsequential); printf("set_thrdlevels = %d\n",set_thrdlevels); printf("set_dirmode = %04o\n",set_dirmode); printf("set_filemode = %04o\n",set_filemode); printf("set_spamprotect = %04o\n",set_spamprotect); printf("set_attachmentsindex = %04o\n",set_attachmentsindex); printf("set_linkquotes = %d\n",set_linkquotes); printf("set_searchbackmsgnum = %d\n",set_searchbackmsgnum); printf("set_quote_hide_threshold = %d\n",set_quote_hide_threshold); printf("set_thread_file_depth = %d\n",set_thread_file_depth); printf("set_monthly_index = %d\n",set_monthly_index); printf("set_yearly_index = %d\n",set_yearly_index); printf("set_msgsperfolder = %d\n",set_msgsperfolder); printf("set_iso2022jp = %d\n",set_iso2022jp); printf("set_delete_incremental = %d\n",set_delete_incremental); printf("set_delete_level = %d\n",set_delete_level); printf("set_delete_older = %d\n",set_delete_older); printf("set_delete_newer = %d\n",set_delete_newer); printf("set_noindex_onindexes = %d\n",set_noindex_onindexes); printf("set_format_flowed= %d\n",set_format_flowed); printf("set_format_flowed_disable_quoted= %d\n",set_format_flowed_disable_quoted); printf("set_applemail_mimehack = %d\n",set_applemail_mimehack); if (!set_ihtmlheader) printf("set_ihtmlheader = Not set\n"); else { printf("set_ihtmlheader = "); for (cp = set_ihtmlheader; *cp; cp++) putchar(*cp); } if (!set_ihtmlfooter) printf("set_ihtmlfooter = Not set\n"); else { printf("set_ihtmlfooter = "); for (cp = set_ihtmlfooter; *cp; cp++) putchar(*cp); } if (!set_ihtmlhead) printf("set_ihtmlhead = Not set\n"); else { printf("set_ihtmlhead = "); for (cp = set_ihtmlhead; *cp; cp++) putchar(*cp); } if (!set_ihtmlhelpup) printf("set_ihtmlhelpup = Not set\n"); else { printf("set_ihtmlhelpup = "); for (cp = set_ihtmlhelpup; *cp; cp++) putchar(*cp); } if (!set_ihtmlhelplow) printf("set_ihtmlhelplow = Not set\n"); else { printf("set_ihtmlhelplow = "); for (cp = set_ihtmlhelplow; *cp; cp++) putchar(*cp); } if (!set_ihtmlnavbar2up) printf("set_ihtmlnavbar2up = Not set\n"); else { printf("set_ihtmlnavbar2up = "); for (cp = set_ihtmlnavbar2up; *cp; cp++) putchar(*cp); } if (!set_mhtmlheader) printf("set_mhtmlheader = Not set\n"); else { printf("set_mhtmlheader = "); for (cp = set_mhtmlheader; *cp; cp++) putchar(*cp); } if (!set_mhtmlfooter) printf("set_mhtmlfooter = Not set\n"); else { printf("set_mhtmlfooter = "); for (cp = set_mhtmlfooter; *cp; cp++) putchar(*cp); } /* List values */ print_list("set_text_types", set_text_types); print_list("set_inline_types", set_inline_types); print_list("set_prefered_types",set_prefered_types); print_list("set_ignore_types",set_ignore_types); print_list("set_show_headers", set_show_headers); print_list("set_avoid_top_indices", set_avoid_top_indices); print_list("set_avoid_indices", set_avoid_indices); print_list("set_annotated", set_annotated); print_list("set_deleted", set_deleted); print_list("set_expires", set_expires); print_list("set_delete_msgnum", set_delete_msgnum); print_list("set_applemail_ua_value", set_applemail_ua_value); } #endif ================================================ FILE: src/setup.h ================================================ #ifndef __SETUP_H #define __SETUP_H typedef int bool; struct Config { char *label; /* the real-name of what to set */ void *value; /* pointer to the real storage */ void *def; /* default value */ char flags; /* specifies the kind of config setting, see defines below */ char *verbose; /* detailed description of the label */ bool changed; /* read from .config or .set file */ }; #define CFG_INTEGER 0 /* 0 - 2G */ #define CFG_SWITCH 1 /* TRUE / FALSE */ #define CFG_STRING 2 /* regular string, pointing to a static string area */ #define CFG_LIST 3 /* comma seperated list, uses itemlist */ #define CFG_FUNCTION 4 /* function */ #define CFG_OCTAL 5 /* numerical, octal based */ #define CFG_STRINGLIST 6 /* uses itemlist, whole lines used as items */ #define BTRUE (void *)1 #define BFALSE (void *)0 #define INT(x) (void *)x int ConfigInit(char *filename); void ConfigCleanup(void); int ConfigAddItem(char *line); void MakeConfig(bool); /* set to TRUE to include comments */ void PreConfig(void); void PostConfig(void); extern char *set_antispam_at; extern char *set_htmlmessage_edited; extern char *set_htmlmessage_deleted_other; extern char *set_htmlmessage_deleted_spam; extern char *set_fragment_prefix; extern char *set_language; extern char *set_htmlsuffix; extern char *set_mbox; extern char *set_archives; extern char *set_custom_archives; extern char *set_about; extern char *set_dir; extern char *set_defaultindex; extern char *set_default_top_index; extern char *set_txtsuffix; extern bool set_email_address_obfuscation; extern bool set_i18n; extern bool set_i18n_body; extern bool set_overwrite; extern bool set_inlinehtml; extern bool set_increment; extern bool set_readone; extern bool set_reverse; extern bool set_reverse_folders; extern bool set_showprogress; extern bool set_showheaders; extern bool set_showbr; extern bool set_showhr; extern bool set_showreplies; extern int set_show_msg_links; extern int set_show_index_links; extern bool set_usetable; extern bool set_indextable; extern bool set_iquotes; extern bool set_eurodate; extern bool set_gmtime; extern bool set_isodate; extern bool set_require_msgids; extern bool set_discard_dup_msgids; extern bool set_usemeta; extern bool set_userobotmeta; extern bool set_uselock; extern bool set_ietf_mbox; extern bool set_linkquotes; extern bool set_monthly_index; extern bool set_yearly_index; extern bool set_spamprotect; extern bool set_spamprotect_id; extern bool set_attachmentsindex; extern bool set_usegdbm; extern bool set_writehaof; extern bool set_append; extern char *set_append_filename; extern bool set_nonsequential; extern bool set_warn_suppressions; extern bool set_files_by_thread; extern bool set_href_detection; extern bool set_mbox_shortened; extern bool set_report_new_file; extern bool set_report_new_folder; extern bool set_use_sender_date; extern bool set_inline_addlink; extern bool set_applemail_mimehack; extern char *set_applemail_ua_header; extern int set_showhtml; extern int set_thrdlevels; extern int set_dirmode; extern int set_filemode; extern int set_locktime; extern int set_searchbackmsgnum; extern int set_quote_hide_threshold; extern int set_thread_file_depth; extern int set_startmsgnum; extern int set_save_alts; extern char *set_alts_text; extern char *set_label; extern char *set_mailcommand; extern char *set_newmsg_command; extern char *set_replymsg_command; extern char *set_inreplyto_command; extern char *set_mailto; extern char *set_hmail; extern char *set_domainaddr; extern char *set_icss_url; extern char *set_mcss_url; extern char *set_dateformat; extern char *set_indexdateformat; extern char *set_stripsubject; extern char *set_link_to_replies; extern char *set_quote_link_string; extern struct hmlist *set_text_types; extern struct hmlist *set_inline_types; extern struct hmlist *set_prefered_types; extern struct hmlist *set_ignore_types; extern struct hmlist *set_show_headers; extern struct hmlist *set_skip_headers; extern struct hmlist *set_avoid_indices; extern struct hmlist *set_avoid_top_indices; extern struct hmlist *set_filter_out; extern struct hmlist *set_filter_require; extern struct hmlist *set_filter_out_full_body; extern struct hmlist *set_filter_require_full_body; extern struct hmlist *set_applemail_ua_value; extern bool set_format_flowed; extern bool set_format_flowed_disable_quoted; extern char *set_ihtmlheader; extern char *set_ihtmlfooter; extern char *set_ihtmlhead; extern char *set_ihtmlhelpup; extern char *set_ihtmlhelplow; extern char *set_ihtmlnavbar2up; extern char *set_mhtmlheader; extern char *set_mhtmlfooter; extern char *set_attachmentlink; extern char *set_unsafe_chars; extern char *set_filename_base; extern bool set_linkquotes; extern char *set_antispamdomain; extern char *set_folder_by_date; extern char *set_latest_folder; extern char *set_base_url; extern int set_msgsperfolder; extern char *set_describe_folder; extern bool set_iso2022jp; extern bool set_noindex_onindexes; extern struct hmlist *set_annotated; extern struct hmlist *set_deleted; extern struct hmlist *set_expires; extern struct hmlist *set_delete_msgnum; extern char *set_delete_older; extern char *set_delete_newer; extern bool set_delete_incremental; extern int set_delete_level; /* values for delete_level: */ enum { DELETE_REMOVES_FILES, DELETE_LEAVES_STUBS, /* always replace msg body with lang[MSG_DELETED/MSG_EXPIRED] */ DELETE_LEAVES_EXPIRED_TEXT, /* stubs for deleted msgs, full msg for expired */ DELETE_LEAVES_TEXT /* leave full message */ }; #endif ================================================ FILE: src/string.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* ** All the nasty string functions live here. */ #include #include #include #include #include "hypermail.h" #include "setup.h" #include "parse.h" #include "uconvert.h" #ifdef HAVE_STRING_H #include #endif /* ** email address obfuscation */ char *obfuscate_email_address(char *address) { char sbuf[10]; struct Push buf; int at_mailbox=1; char *sentinel; if (!set_email_address_obfuscation){ return address; } sentinel=strlen(address)+address; INIT_PUSH(buf); while (address=uea_sbufsize){ /* broken string */ scount=0; on_error=1; } } } address++; } RETURN_PUSH(buf); } /* I18N hack */ #ifdef HAVE_ICONV_H #include #endif #ifdef HAVE_ICONV struct i18n_alt_charset_table { char *alt; char *formal; }; struct i18n_alt_charset_table i18n_charsettable[] = { /* UTF-8 (RFC2279) */ {"UNICODE-1-1-UTF-8","UTF-8"}, {"UNICODE-2-0-UTF-8","UTF-8"}, {"x-unicode-2-0-utf-8","UTF-8"}, {"ANSI_X3.4-1968","US-ASCII"}, /* US-ASCII (RFC1345) */ {"iso-ir-6","US-ASCII"}, {"ANSI_X3.4-1986","US-ASCII"}, {"ISO_646.irv:1991","US-ASCII"}, {"ASCII","US-ASCII"}, {"ISO646-US","US-ASCII"}, {"us","US-ASCII"}, {"IBM367","US-ASCII"}, {"cp367","US-ASCII"}, {"csASCII","US-ASCII"}, {"iso-ir-6us","US-ASCII"}, /* Arabic (RFC1324) */ {"ISO_8859-6:1987","ISO-8859-6"}, {"iso-ir-127","ISO-8859-6"}, {"ECMA-114","ISO-8859-6"}, {"arabic","ISO-8859-6"}, {"csISOLatinArabic","ISO-8859-6"}, {"8859_6","ISO-8859-6"}, {"ISO8859_6","ISO-8859-6"}, {"iso8859-6","ISO-8859-6"}, {"windows-1256","CP1256"}, /* Korean (RFC1557) */ {"KS_C_5601-1987","CP949"}, {"KS_C_5601-1989","CP949"}, /* Thai */ {"windows-874","CP874"}, /* Chinese */ {"x-gbk","GB18030"}, /* Cyrillic */ {"x-mac-cyrillic","MacCyrillic"}, {"ibm866","CP866"} }; #define I18N_CHARSET_TABLE_SIZE (sizeof(i18n_charsettable)/sizeof(struct i18n_alt_charset_table)) char *i18n_canonicalize_charset(char *cs){ int x=0; while(x 0; i-=2){ p=(unsigned char)*ucs*256+(unsigned char)*(ucs+1); if (p<128){ /* keep ASCII characters human readable */ if (escape){ switch (p){ case '<': PushString(&buff, "<"); break; case '>': PushString(&buff, ">"); break; case '&': PushString(&buff, "&"); break; case '\"': PushString(&buff, """); break; case '\'': PushString(&buff, "'"); break; default: PushByte(&buff,p); } }else{ PushByte(&buff,p); } }else{ snprintf(strbuf,10,"&#%04d;",p); PushString(&buff,strbuf); } ucs+=2; } free(headofucs); RETURN_PUSH(buff); } unsigned char *i18n_numref2utf(char *string){ int status,len; unsigned short int utf; unsigned char convbuf[5],*utfstr,*headofutfstr; len=strlen(string); utfstr=headofutfstr=malloc(len); memset(headofutfstr,0,len); status=0; while (*string!=0x0){ switch (*string){ case '&': string++; status++; break; case '#': string++; status++; break; case ';': string++; status=0; break; default: if(status==2){ convbuf[0]=*string++; convbuf[1]=*string++; convbuf[2]=*string++; convbuf[3]=*string++; convbuf[4]=0x0; utf=strtol((const char *)&convbuf[0], NULL,10); if(utf<256){ *utfstr=(unsigned char)utf; utfstr++; }else{ /* BE */ *utfstr=(unsigned char)(utf>>8); *(utfstr+1)=(unsigned char)(utf%256); utfstr+=2; } } } } *utfstr=0x0; return headofutfstr; } /* replaces all non 7-bit ascii chars in string by a ? ** returns the number of replaced chars */ int i18n_replace_non_ascii_chars(char *string) { char *ptr = string; int count = 0; while (*ptr) { if (!isascii(*ptr) || (*ptr < 0x20 && *ptr != 0x0a && *ptr != 0x0d && *ptr != 0x09)) { *ptr = '?'; count++; } ptr++; } return count; } #endif /* end of I18N hack */ /* ** Push byte onto a buffer realloc the buffer if needed. ** ** Returns the (new) buffer pointer. */ char *PushByte(struct Push *push, char byte) { /* byte to append */ #define PUSH_DEFAULT 32 /* default strings are this big */ if (!push) return NULL; /* this is a sever error */ if (!push->string) { push->string = (char *)malloc(PUSH_DEFAULT); if (!push->string) return NULL; /* error again */ push->alloc = PUSH_DEFAULT; push->len = 0; #ifdef DEBUG_PUSH fprintf(stderr, "PUSH: INIT at index 0 alloc %d\n", PUSH_DEFAULT); #endif } else if ((push->len + 2) >= push->alloc) { char *newptr; newptr = (char *)realloc(push->string, push->alloc * 2); /* double the size */ if (!newptr) { return push->string; /* live on the old one! */ } push->alloc *= 2; /* enlarge the alloc size */ push->string = newptr; /* use the new buffer */ #ifdef DEBUG_PUSH fprintf(stderr, "PUSH: REALLOC at index %d to alloc %d\n", push->len, push->alloc); #endif } #ifdef DEBUG_PUSH fprintf(stderr, "PUSH: WRITE '%c' at index %d\n", byte, push->len); #endif push->string[push->len++] = byte; push->string[push->len] = 0; /* zero terminate */ return push->string; /* current buffer */ } /* ** Push a string onto a buffer, and realloc the buffer if needed. ** ** Returns the (new) buffer pointer. */ char *PushString(struct Push *push, const char *append) { /* string to append */ char *string = NULL; #if 1 return PushNString(push, append, strlen(append)); #else while (*append) { /* continue until zero termination */ string = PushByte(push, *append); append++; /* get next character */ } #endif return string; /* this is the new buffer */ } /* ** Push a limited string onto a buffer, and realloc the buffer if needed. ** ** Returns the (new) buffer pointer. */ char *PushNString(struct Push *push, const char *append,/* string to append */ int size) { /* maximum number of bytes to copy */ char *string = NULL; #if 1 if (!push) return NULL; /* this is a sever error */ if (!push->string) { push->string = (char *)malloc(PUSH_DEFAULT + size); if (!push->string) return NULL; /* error again */ push->alloc = PUSH_DEFAULT + size; push->len = 0; #ifdef DEBUG_PUSH fprintf(stderr, "PUSH: INIT at index 0 alloc %d\n", PUSH_DEFAULT); #endif } else if ((push->len + size + 1) >= push->alloc) { char *newptr; push->alloc = 2*push->alloc + size; /* enlarge the alloc size */ newptr = (char *)realloc(push->string, push->alloc); /* double the size */ if (!newptr) { return push->string; /* live on the old one! */ } push->string = newptr; /* use the new buffer */ #ifdef DEBUG_PUSH fprintf(stderr, "PUSH: REALLOC at index %d to alloc %d\n", push->len, push->alloc); #endif } #ifdef DEBUG_PUSH fprintf(stderr, "PUSH: WRITE '%s' at index %d\n", append, push->len); #endif strncpy(push->string + push->len, append, size); push->len += size; push->string[push->len] = 0; string = push->string; /* current buffer */ #else while (*append && size--) { /* continue until zero termination */ string = PushByte(push, *append); append++; /* get next character */ } #endif return string; /* this is the new buffer */ } /* ** Malloc() out a string, give it to whoever asked for it. */ char *strsav(const char *s) { char *p; if (NULL == s) s = ""; /* Daniel's kludge to survive better */ p = (char *)emalloc(strlen(s) + 1); strcpy(p, s); return p; } char *strreplace(char *present, char *new) { char *retval; int len; if (new == NULL) { free(present); return NULL; } len = strlen(new) + 1; if (present == NULL) retval = (char *)malloc(len); else retval = (char *)realloc(present, len); return strcpy(retval, new); /* CCC is safe, buffer allocated for it by length of string 'new' */ } /* ** strcpymax() - copies a string, but max N bytes. It guarantees the ** destination string to be zero terminated. That is, if the destination ** buffer is X bytes, set N to X. */ void strcpymax(char *dest, const char *src, int n) { int i; if (n) { n--; /* decrease one to allow for the termination byte */ for (i = 0; *src && (i < n); i++) *dest++ = *src++; } *dest = 0; } /* ** strtolower - converts a string to lower case. */ void strtolower(char *string) { char *ptr; if (!string) return; ptr = string; while (*ptr) { if (isalpha (*ptr)) *ptr = tolower (*ptr); ptr++; } } #ifndef HAVE_STRCASESTR /* ** strcasestr() - case insensitive strstr() */ /* Stolen-- stolen!-- from glibc 2.1. Please don't sue me. */ char *strcasestr (const char *phaystack, const char *pneedle) { register unsigned char *haystack; register const unsigned char *needle; register unsigned b, c; haystack = (unsigned char *) phaystack; needle = (const unsigned char *) pneedle; b = tolower (*needle); if (b != '\0') { haystack--; /* possible ANSI violation */ do { c = *++haystack; if (c == '\0') goto ret0; } while (tolower (c) != b); c = tolower (*++needle); if (c == '\0') goto foundneedle; ++needle; goto jin; for (;;) { register unsigned a; register unsigned char *rhaystack; register const unsigned char *rneedle; do { a = *++haystack; if (a == '\0') goto ret0; if (tolower (a) == b) break; a = *++haystack; if (a == '\0') goto ret0; shloop: ; } while (tolower (a) != b); jin: a = *++haystack; if (a == '\0') goto ret0; if (tolower (a) != c) goto shloop; rhaystack = haystack-- + 1; rneedle = needle; a = tolower (*rneedle); if (tolower (*rhaystack) == a) do { if (a == '\0') goto foundneedle; ++rhaystack; a = tolower (*++needle); if (tolower (*rhaystack) != a) break; if (a == '\0') goto foundneedle; ++rhaystack; a = tolower (*++needle); } while (tolower (*rhaystack) == a); needle = rneedle; /* took the register-poor approach */ if (a == '\0') break; } } foundneedle: return (char*) haystack; ret0: return 0; } #endif /* ** Strips the timezone information from long date strings, so more correct ** comparisons can be made between dates when looking for article replies. ** Y2K ok. */ char *stripzone(char *date) { int num; static char tmpdate[DATESTRLEN]; if (!strcmp(date, NODATE)) return (date); if (!strchr(date, ':')) return (date); strcpymax(tmpdate, date, DATESTRLEN); num = strlen(tmpdate); while (tmpdate[num] != ':') num--; num += 3; while (tmpdate[num]) tmpdate[num++] = '\0'; return (tmpdate); } /* ** How many times does the character c appear in string s? */ int numstrchr(char *s, char c) { int i; for (i = 0; *s != '\0'; s++) { if (*s == c) i++; } return i; } /* ** Grabs whatever happens to be between the outermost double quotes in a line. ** This is for grabbing the values in comments. */ char *getvalue(char *line) { int i; int len; char *c, *d; struct Push buff; INIT_PUSH(buff); c = strchr(line, '\"'); d = strrchr(line, '\"'); if (c == NULL) return ""; for (c++, i = 0, len = MAXLINE - 1; *c && c != d && i < len; c++) PushByte(&buff, *c); RETURN_PUSH(buff); } /* ** Get rid of Re:'s in a subject and strips spaces at the end ** of subjects. Make the subject index much less cluttered. ** ** Returns an ALLOCATED string. */ char *unre(char *subject) { int ws = 0; char *c, *s; struct Push buff; INIT_PUSH(buff); s = subject; while (findre(s, &c)) { s = c; /* get position after next re-string */ } while (*s && isspace(*s)) s++; c = s; /* the first non-space position after the last re: */ while (*c) { if (c && isspace(*c)) ws++; else { if (ws) { PushByte(&buff, ' '); ws = 0; } PushByte(&buff, *c); } c++; } if (!PUSH_STRLEN(buff)) { PushByte(&buff, '\0'); } RETURN_PUSH(buff); } /* ** Only gets rid of one re: in a subject, so messages the subject is a reply to ** can be guessed. */ char *oneunre(char *subject) { char *c; struct Push buff; INIT_PUSH(buff); if (isre(subject, &c)) { if (*c && isspace(*c)) c++; subject = c; PushString(&buff, subject); RETURN_PUSH(buff); } return NULL; } /* remove space from spacecrlf eol ff sequence */ void rfc3676_trim_softlb(char *line) { char *eold; eold = strrchr (line, '\n'); if (line != eold) { if (*(eold - 1) == '\r') eold--; } if (line != eold) { if (*(eold - 1) == ' ') { /* remove the space stuffing and copy the end of line */ char *ptr = eold - 1; while (*ptr != '\0') { *ptr = *(ptr + 1); ptr++; } } } } /* ** Deletes space stuffing after quotes ** If spaces are deleted, returns a buffer that the caller must free */ char *rfc3676_delsp_quotes (char *line) { char *c = line; while (*c == '>') { c++; } if (*c == ' ') { struct Push buf; char tmp_c; INIT_PUSH(buf); tmp_c = *c; *c = '\0'; PushString(&buf, line); PushString(&buf, c+1); *c = tmp_c; RETURN_PUSH(buf); } return NULL; } /* ** returns true if line ends with a \n or \r\n */ int rfc3676_ishardlb(const char *line) { int res; if (*line == '\n' || (*line == '\r' && *(line+1) == '\n')) { res = TRUE; } else { res = FALSE; } return res; } /* ** Is a line in an article body part of a quoted passage? */ int isquote(const char *line) { const char *lp; const char *quote_prefix = get_quote_prefix(); if (!line) return (0); if (*quote_prefix) { return !strncmp(quote_prefix, line, strlen(quote_prefix)); } if (*line == '>') return 1; lp = line; #ifdef RECOGNIZE_SUPERCITE_QUOTES /* ** If there is a ":" in the first column, ** it means the text is quoted. */ if (*lp == ':') { const char *cp; /* ** Check to make sure that smileys are not ** intrepreted as Supercite Quotes. */ cp = lp + 1; if (*cp && *cp != '-' && *cp != ']' && *cp != '>' && *cp != '(' && *cp != ')' && *cp != '^') return 1; } #endif while (*lp && (*lp == ' ' || *lp == '\t')) lp++; if (!(*lp)) return 0; #ifdef RECOGNIZE_SUPERCITE_QUOTES /* ** recognize citations in the form " Jane>" */ while (*lp && ((*lp >= 'A' && *lp <= 'Z') || (*lp >= 'a' && *lp <= 'z'))) lp++; #endif if (*lp == '>') return 1; return 0; } /* ** A ripoff from convchars, for a special case. ** Converts - to –. Used for storing strings ** in XML comments. ** ** Returns an ALLOCATED string! */ char *convdash (char *line) { struct Push buff; INIT_PUSH(buff); /* init macro */ /* avoid strlen() for speed */ for (; *line; line++) { if (*line == '-') PushString(&buff, "–"); else PushByte(&buff, *line); } RETURN_PUSH(buff); } /* end convdash() */ /* ** Converts <, >, and & to <, > and &. ** It was ugly. Now its better. And probably faster. ** ** Returns an ALLOCATED string! */ char *convcharsreal(char *line, char *charset, int spamprotect) { struct Push buff; int in_ascii = TRUE, esclen = 0; int seen_at = FALSE; bool is_iso_8859_1; if (charset && !strcasecmp ("iso-8859-1", charset)) is_iso_8859_1 = TRUE; else is_iso_8859_1 = FALSE; INIT_PUSH(buff); /* init macro */ /* avoid strlen() for speed */ for (; *line; line++) { if (set_iso2022jp) { iso2022_state(line, &in_ascii, &esclen); if (esclen && in_ascii == FALSE) { for (; in_ascii == FALSE && *line; line++) { PushByte(&buff, *line); iso2022_state(line, &in_ascii, &esclen); } line--; continue; } } /* @@ JK : try to convert from the WinLatin1 code */ if (is_iso_8859_1 && (unsigned char) (*line) >= 0x80 && (unsigned char) (*line) <= 0x9f) { char *unicode_entity; trio_asprintf (&unicode_entity, "&#x%x;", WIN1252CP[(unsigned char) (*line) - WIN1252CP_length]); if (unicode_entity) { PushString(&buff, (const char *) unicode_entity); free (unicode_entity); } continue; } switch (*line) { case '<': PushString(&buff, "<"); break; case '>': PushString(&buff, ">"); break; case '&': PushString(&buff, "&"); break; case '\"': PushString(&buff, """); break; case '@': /* pkn added: simple "antispam" measure */ PushString(&buff, "@"); seen_at = TRUE; break; case '.': /* pkn added */ if (seen_at && spamprotect) { PushString(&buff, "."); seen_at = FALSE; break; } /* fall through */ default: PushByte(&buff, *line); } } RETURN_PUSH(buff); } /* end convcharsreal() */ char *convcharsnospamprotect(char *line, char *charset) { return convcharsreal(line, charset, FALSE); } char *convchars(char *line, char *charset) { return convcharsreal(line, charset, set_spamprotect); } /* ** Converts from an Unicode entity to the equivalent winlatin charset */ static bool unconvwinlatin1 (char *entity, char *conv_char) { int i; int value = 0; if (!entity || *entity == '\0' || *entity != '#') return FALSE; if (sscanf (entity, "#x%x;", &value) != 1 || value == 0) return FALSE; for (i = 0; i < WIN1252CP_length; i++) { if (WIN1252CP[i] == value) break; } if (i == WIN1252CP_length) return FALSE; *conv_char = (char) (i + 0x80); return TRUE; } /* end unconvwinlatin1 */ /* ** Just the opposite of convchars(). ** Completely rewritten 17th Nov 1998 by Daniel. */ char *unconvchars(char *line) { char conv_char; struct Push buff; INIT_PUSH(buff); for (; *line; line++) { if (*line == '&') { if (!strncmp("lt;", line + 1, 3)) { PushByte(&buff, '<'); line += 3; } else if (!strncmp("gt;", line + 1, 3)) { PushByte(&buff, '>'); line += 3; } else if (!strncmp("amp;", line + 1, 4)) { PushByte(&buff, '&'); line += 4; } else if (!strncmp(".", line + 1, 18)) { PushByte(&buff, '.'); line += 18; } else if (!strncmp("quot;", line + 1, 5)) { PushByte(&buff, '\"'); line += 5; } else if (!strncmp("#64;", line + 1, 4)) { PushByte(&buff, '@'); line += 4; } else if (!strncmp("ndash;", line + 1, 6)) { PushByte(&buff, '-'); line += 6; } else if (unconvwinlatin1 (line + 1, &conv_char)) { PushByte(&buff, conv_char); } else PushByte(&buff, *line); } else PushByte(&buff, *line); } RETURN_PUSH(buff); } /* * translatechars() is just a ripoff of convertchars() * with a different argument list. */ static void translatechars(char *start, char *end, struct Push *buff) { char *p; int in_ascii = TRUE, esclen = 0; for (p = start; p <= end; p++) { if (set_iso2022jp) { iso2022_state(p, &in_ascii, &esclen); if (esclen && in_ascii == FALSE) { for (; in_ascii == FALSE && p <= end; p++) { PushByte(buff, *p); iso2022_state(p, &in_ascii, &esclen); } p--; continue; } } switch (*p) { case '<': PushString(buff, "<"); break; case '>': PushString(buff, ">"); break; case '&': PushString(buff, "&"); break; case '\"': PushString(buff, """); break; default: PushByte(buff, *p); } } } /* * translateurl(), to escape URI strings only. * this should be divided from convchars(). * * in_mailcommand: line is MAILCOMMAND, if 1 * */ static char *translateurl(char *line, int in_mailcommand) { int hexbuflen; char hexbuf[16]; struct Push buff; INIT_PUSH(buff); /* init macro */ for(; *line; line++){ if(isalnum((int)*line)){ PushByte(&buff,*line); }else{ switch (*line){ /* we can use unreserved characters, others should be escaped */ /* RFC2396: */ /* unreserved = alphanum | mark */ /* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" */ case '-': PushByte(&buff,*line); break; case '_': PushByte(&buff,*line); break; case '.': PushByte(&buff,*line); break; case '!': PushByte(&buff,*line); break; case '~': PushByte(&buff,*line); break; case '*': PushByte(&buff,*line); break; case '\'': PushByte(&buff,*line); break; case '(': PushByte(&buff,*line); break; case ')': PushByte(&buff,*line); break; /* * following characters are reserved, but used in MAILCOMMAND */ case ':': if (in_mailcommand){ PushByte(&buff,*line); break; } case '?': if (in_mailcommand){ PushByte(&buff,*line); break; } case '&': if (in_mailcommand){ /* ...to reduce CPU cycles */ PushString(&buff,"&"); break; } case '=': if (in_mailcommand){ PushByte(&buff,*line); break; } case '$': if (in_mailcommand){ PushByte(&buff,*line); break; } default: /* URIs MUST NOT have non-ascii characters */ /* otherwise, we must use IRI */ hexbuflen=snprintf(hexbuf,4,"%%%02X",*line); PushString(&buff,hexbuf); break; } } } RETURN_PUSH(buff); } /* Given a string, replaces all instances of "oldpiece" with "newpiece". ** ** Modified this routine to eliminate recursion and to avoid infinite ** expansion of string when newpiece contains oldpiece. --Byron Darrah ** ** 1998-11-17 (Daniel) modified to deal with any length strings and dynamic ** buffers. */ char *replace(char *string, char *oldpiece, char *newpiece) { int str_index, newstr_index, oldpiece_index, end, new_len, old_len, cpy_len; char *c; struct Push buff; INIT_PUSH(buff); if ((c = (char *)strstr(string, oldpiece)) == NULL) { /* push the whole thing */ PushString(&buff, string); RETURN_PUSH(buff); } new_len = strlen(newpiece); old_len = strlen(oldpiece); end = strlen(string) - old_len; oldpiece_index = c - string; newstr_index = 0; str_index = 0; while (str_index <= end && c != NULL) { /* Copy characters from the left of matched pattern occurence */ cpy_len = oldpiece_index - str_index; PushNString(&buff, string + str_index, cpy_len); newstr_index += cpy_len; str_index += cpy_len; /* Copy replacement characters instead of matched pattern */ PushString(&buff, newpiece); newstr_index += new_len; str_index += old_len; /* Check for another pattern match */ if ((c = (char *)strstr(string + str_index, oldpiece)) != NULL) oldpiece_index = c - string; } /* Copy remaining characters from the right of last matched pattern */ PushString(&buff, string + str_index); RETURN_PUSH(buff); } char *replacechar(char *string, char old, char *new) { struct Push buff; int in_ascii = TRUE, esclen = 0; INIT_PUSH(buff); for (; *string; string++) { if (set_iso2022jp) iso2022_state(string, &in_ascii, &esclen); if (in_ascii == TRUE && *string == old) { PushString(&buff, new); } else PushByte(&buff, *string); } RETURN_PUSH(buff); } /* ** Generates the mail command to use from the default mail command, ** the current recipient's email address, the current ID of the ** message, and the current subject. ** ** Returns an ALLOCATED string! */ char *makemailcommand(char *mailcommand, char *email, char *id, char *subject) { char *newcmd = NULL, *newcmd2=NULL, *cp; char *tmpsubject=NULL; char *convsubj=NULL,*convemail=NULL,*convid=NULL; if ((cp = strrchr(email, ' ')) != NULL) *cp = '\0'; /* prepare "Re: " string, should this be localized? */ if(subject && isre(subject,NULL)){ trio_asprintf(&tmpsubject, "%s",subject); }else{ trio_asprintf(&tmpsubject, "Re: %s",subject); } /* escape strings */ convsubj=translateurl(tmpsubject,0); free(tmpsubject); if(set_email_address_obfuscation){ convemail=obfuscate_email_address(email); }else{ convemail=translateurl(email,0); } convid=translateurl(id,0); /* escape mailcommand, with keeping some delimiters */ newcmd = translateurl(mailcommand,1); /* put email address */ if (strlen(email)>0){ newcmd2 = replace(newcmd, "$TO", convemail); }else{ newcmd2 = replace(newcmd, "$TO", ""); } free(convemail); free(newcmd); /* put message-id */ if (strlen(id)>0){ newcmd = replace(newcmd2, "$ID", convid); }else{ newcmd = replace(newcmd2, "$ID", ""); } free(convid); free(newcmd2); /* put subject */ if (subject && strlen(subject)>0){ newcmd2 = replace(newcmd, "$SUBJECT", convsubj); }else{ newcmd2 = replace(newcmd, "$SUBJECT", ""); } free(newcmd); free(convsubj); return newcmd2; } /* ** Generates the inreplyto command to use from the ** default inreplyto command and the the current ID of the ** message, ** ** Returns an ALLOCATED string! */ char *makeinreplytocommand(char *inreplytocommand, char *subject, char *id) { char *newcmd = NULL; char *convid = NULL; /* if id was interpolated from the subject, skip it */ if (strstr (subject, id)) { return NULL; } /* escape id */ if (set_email_address_obfuscation){ convid = obfuscate_email_address (id); } else { convid = translateurl (id, 0); } /* replace message-id */ if (strlen (id)>0) { newcmd = replace (inreplytocommand, "$ID", convid); } else { newcmd = replace (inreplytocommand, "$ID", ""); } free (convid); return newcmd; } char *spamify(char *input) { if (set_antispamdomain) { return spamify_replacedomain(input, set_antispamdomain); } else { return spamify_small(input); } } char *spamify_small(char *input) { /* we should replace the @-letter in the email address */ char *atptr = strchr(input, '@'); if (atptr) { char *newbuf = replacechar(input, '@', set_antispam_at); /* correct the pointer and free the old */ free(input); return newbuf; } /* weird email, bail out */ return input; } char *spamify_replacedomain(char *input, char *antispamdomain) { char *atptr = strchr(input, '@'); if (atptr) { char *buff; buff = parseemail(input, NULL, antispamdomain, REPLACE_DOMAIN); free(input); return(buff); } /* weird email, bail out */ return input; } char *unspamify(char *s) { char *p; if (!s) return s; if (!strchr(s, '@') && ((p = strstr(s, set_antispam_at)) != NULL)) { struct Push buff; INIT_PUSH(buff); PushNString(&buff, s, p - s); PushByte(&buff, '@'); PushString(&buff, p + strlen(set_antispam_at)); return PUSH_STRING(buff); } return strsav(s); } /* ** RFC 1738 ** Thus, only alphanumerics, the special characters "$-_.+!*'(),", and ** reserved characters used for their reserved purposes may be used ** unencoded within a URL. ** ** ** //:@:/ ** ** Some or all of the parts ":@", ":", ** ":", and "/" may be excluded. The scheme specific ** data start with a double slash "//" to indicate that it complies with ** the common Internet scheme syntax. ** */ char *parseemail(char *input, /* string to parse */ char *mid, /* message ID */ char *msubject, parseemail_conversion_t conversion) /* how to output parsed mail */ { /* message subject */ char mailbuff[256]; char mailaddr[MAILSTRLEN]; char tempbuff[MAXLINE]; char *ptr; char *lastpos = input; char *start = NULL; struct Push buff; char *at; int at_len; int in_ascii = TRUE, esclen = 0; if(set_spamprotect) at=set_antispam_at; else at="@"; if (strchr(input, '@') == NULL && strstr(input, "@") == NULL) { /* nothing to do here */ return strsav(input); } INIT_PUSH(buff); while (*input) { /* skip detection if this is an escape or non-ascii sequence */ if (set_iso2022jp) { iso2022_state(input, &in_ascii, &esclen); if (esclen != 0) { input += esclen; continue; } if (in_ascii == FALSE) { input++; start = NULL; continue; } } if (start == NULL) { start = input; } ptr = NULL; if (*input == '@') { ptr = input; at_len = 1; } else if (strncmp(input, "@", 5) == 0) { ptr = input; at_len = 5; } if (ptr) { /* found a @ */ char *email = ptr - 1; char content[2]; int backoff = ptr - start; /* max */ #define VALID_IN_EMAIL_USERNAME "a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~" #define VALID_IN_EMAIL_DOMAINNAME "a-zA-Z0-9.-" /* check left side */ while (backoff) { int res; res = sscanf(email, "%1[" VALID_IN_EMAIL_USERNAME "]", content); /* for some reason, if we have ,name sscanf will interpret the , as if were declared in VALID_IN_EMAIL_USERNAME, thus the additional check */ if (res && content[0] != ',') { email--; backoff--; } else break; } if (backoff > 2 && email[0] == '/' && email[-1] == '/' && email[-2] == ':') { ; /* part of a url such as ftp://user@host.com */ } else if (email != ptr - 1) { /* bigger chance this is an address */ email++; if (sscanf (ptr + at_len, "%255[" VALID_IN_EMAIL_DOMAINNAME "]", mailbuff) == 1) { /* a valid mail right-end */ if (lastpos < email) { PushNString(&buff, lastpos, email - lastpos); } trio_snprintf(mailaddr, sizeof(mailaddr),"%.*s%s%s", ptr-email, email, at, mailbuff); if (valid_root_domain(mailaddr)) { if (conversion == MAKEMAILCOMMAND) { char *mailcmd = makemailcommand(set_mailcommand, mailaddr, mid, msubject); trio_snprintf(tempbuff, sizeof(tempbuff), "%s", mailcmd, obfuscate_email_address(mailaddr)); free(mailcmd); } else if (conversion == REPLACE_DOMAIN) { trio_snprintf(tempbuff, sizeof(mailaddr),"%.*s%s%s", ptr-email, email, at, msubject); } else { strcpy (tempbuff, mailaddr); } PushString(&buff, tempbuff); input = ptr + strlen(mailbuff) + at_len; start = input; lastpos = input; continue; } else { /* bad address */ PushString(&buff, mailaddr); input = ptr + strlen(mailbuff) + at_len; start = input; lastpos = input; continue; } } } /* no address, continue from here */ input = ptr + at_len; start = input; continue; } else input++; } if (lastpos < input) { PushNString(&buff, lastpos, input - lastpos); } RETURN_PUSH(buff); } /* ** Convert stuff that looks like a URL in a plain text string into a ** corresponding html reference to the URL. ** ** Returns the allocated and converted string. ** ** This function is run on each and every body line, so it pays to make it ** run quickly. **/ /* See https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml for current URI schemes */ static char *url[] = { "http://", "https://", "news:", "ftp://", #if 0 "file://",/* can expose private files outside the archive in some cases? */ #endif "gopher://", "nntp://", "telnet://", /* "mailto:", *//* Can't have mailto: as it will be converted twice */ "tel:", "rtsp://", "im:", /* im:to[?header=value&header2=value] */ "sip:", "sips:", "cap://", /* some non RFC or experimental or de-facto ones */ "webcal://", "irc://", /* URIs we used to support and that are now deprecated */ /* "feed://",*/ /* deprecated, not used anymore */ /* "prospero://",*/ /* deprecated */ /* "wais://", */ /* deprecated */ /* "fax:", */ /* deprecated by rfc3966 */ /* "callto:", */ /* deprecated by rfc3966, maybe supported for skype calls in browsers */ /* callto: is more complex than convurl can currently handle */ NULL }; char *parseurl(char *input, char *charset) { struct Push buff; /* output buffer */ char urlbuff[256]; char tempbuff[MAXLINE]; char *inputp; char *match[sizeof(url) / sizeof(char **)]; int first; char *c; if (!input || !*input) return NULL; /* * All our protocol prefixes have this ":" substring in them. Most * of the lines we process don't have any URL. Let's not spend any * time looking for URLs in lines that we can prove cheaply don't * have any; it will be a big win for average input if we follow * this trivial heuristic. */ first = FALSE; c = strstr(input, ":"); if (c == input) { /* first char in line */ c++; c = strstr(c, ":"); } /* !c === not found */ while (c) { if (*(c+1) == '\0') /* last char in line */ break; else if ( !isalpha(*(c-1)) /* not between alpha/graph */ || !isgraph(*(c+1))) { c++; c = strstr(c, ":"); } else { first = TRUE; break; } } if (!first) { return convchars(input, charset); } INIT_PUSH(buff); /* * Iterate on possible URLs in the input string. There might * be more than one! */ inputp = input; first = TRUE; while (1) { char *leftmost = NULL; char **up; char thisprotocol[256]; char *p; /* Loop on protocol prefixes, searching for the leftmost. */ for (up = url; *up; up++) { int i; if (first) { /* * we haven't looked for this one yet, so do so and remember * any match we find */ match[up - url] = p = strcasestr(inputp, *up); } else if (match[i = up - url]) { /* * we looked for it before, and we found it before, so if the * match is to the right of the input we have processed so * far, we can simply reuse it; else, search again. */ if (match[i] <= inputp) match[i] = p = strcasestr(inputp, *up); else p = match[i]; } else { /* * we looked for it before, and we didn't find it before, so * we aren't bloody likely to find it this time; don't waste * time looking again */ continue; } if (p) { /* * Found a protocol prefix. We want the leftmost such, * so note the match and keep looking for other protocols. */ if (!leftmost || p < leftmost) { char *endp; int len; int url_suffix_len; leftmost = p; memset(thisprotocol, 0, sizeof(thisprotocol)); if (p[strlen(*up) - 1] == '/') { endp = strstr(p, "://"); url_suffix_len = 3; } else { endp = strstr(p, ":"); url_suffix_len = 1; } if (endp) { len = endp - p + url_suffix_len; /* really means something else is wrong, but prevent buffer overflow */ if (len >= sizeof(thisprotocol)) len = sizeof(thisprotocol) - 1; strncpy(thisprotocol, p, len); thisprotocol[len] = '\0'; } } } } first = FALSE; if (leftmost) { /* we found at least one protocol prefix */ int accepted = FALSE; int urlscan = FALSE; int istelprotocol = !strcasecmp(thisprotocol, "tel:"); /* * all the charaters between the position where we started * looking for a protocol prefix and the protocol prefix * need to be checked for character translations */ translatechars(inputp, leftmost-1, &buff); inputp = leftmost + strlen(thisprotocol); /* * If nothing follows the protocol URL, consider it's not a URL * and skip it */ if (*inputp != '\0' && !isblank(*inputp) && ((istelprotocol && (*inputp == '+' || isdigit(*inputp))) || (!istelprotocol && !ispunct(*inputp)))) { if (set_iso2022jp) urlscan = sscanf(inputp, "%255[^] \033)<>\"\'\n[\t\\]", urlbuff); else urlscan = sscanf(inputp, "%255[^] )<>\"\'\n[\t\\]", urlbuff); } if (urlscan == 1) { char *r; /* * A valid url: up to 255 characters in a run containing legal * URL characters. But let's nibble off any punctuation other * than slashes at the end, because they are not likely part * of the URL. E.g. a trailing comma. */ for(r = strchr(urlbuff, '\0') - 1; *r != '/' && ispunct(*r) && r > urlbuff; r--); if(r++ > urlbuff) { /* * there should be something left in the URL after we chew * away the trailing punctuation if we are going to call it * valid */ accepted = TRUE; if(*r) { *r = '\0'; } } } if(accepted) { /* string is already escaped in URI context */ char *urlbuff2 = convcharsnospamprotect(urlbuff,"us-ascii"); trio_snprintf(tempbuff, sizeof(tempbuff), "%s%s", thisprotocol, urlbuff2, thisprotocol, urlbuff2); PushString(&buff, tempbuff); /* append the tag buffer */ inputp += strlen(urlbuff); free(urlbuff2); } else { PushString(&buff, thisprotocol); } } else { /* * no prospects found; translate the characters in the rest of * the string and return */ translatechars(inputp, strchr(inputp, '\0') - 1, &buff); break; } } RETURN_PUSH(buff); } /* end parseurl() */ /* * Support RFC1468 (and RFC1554, 94 character sets) * * reference * - RFC1468: Japanese Character Encoding for Internet Messages (ISO-2022-JP) * - RFC1554: ISO-2022-JP-2: Multilingual Extension of ISO-2022-JP * - RFC1557: Korean Character Encoding for Internet Messages * - RFC2234: Japanese Character Encoding for Internet Messages */ /* * state * TRUE: ascii (default) * FALSE: non-ascii * esclen * n: escape sequence length */ void iso2022_state(const char *str, int *state, int *esclen) { if (*state != TRUE && *state != FALSE) *state = TRUE; if (*str != '\033') { *esclen = 0; return; } switch (*(str+1)) { case '$': if (*(str+2) == 'B' || *(str+2) == '@' || *(str+2) == 'A') { /* * ESC $ B JIS X 0208-1983 to G0 * ESC $ @ JIS X 0208-1976 to G0 * ESC $ A GB2312-1980 to G0 */ *state = FALSE; *esclen = 3; } else if ((*(str+2) == '(' && *(str+3) == 'C') || (*(str+2) == '(' && *(str+3) == 'D')) { /* * ESC $ ) C KSC 5601-1987 to G0 * ESC $ ( D JIS X 0212-1990 to G0 */ *state = FALSE; *esclen = 4; } else { /* keep state */ *esclen = 1; } break; case '(': if (*(str+2) == 'B' || *(str+2) == 'J') { /* * ESC ( B ASCII to G0 * ESC ( J JIS X 0201-Roman to G0 */ *state = TRUE; *esclen = 3; } else { /* keep state */ *esclen = 1; } break; default: /* keep state */ *esclen = 1; } } char * hm_strchr(const char *str, int ch) { if (!set_iso2022jp) { return(strchr(str, ch)); } else { int in_ascii = TRUE, esclen = 0; for (; *str; str++) { iso2022_state(str, &in_ascii, &esclen); if (esclen) str += esclen; if (in_ascii == TRUE) { if (*str == ch) return((char *)str); } } return((char *)NULL); } } #if ! HAVE_STRERROR /************************************************* * Provide strerror() for non-ANSI libraries * *************************************************/ /* Some old-fashioned systems still around (e.g. SunOS4) don't have strerror() in their libraries, but can provide the same facility by this simple alternative function. */ extern int sys_nerr; extern char *sys_errlist[]; char * strerror(int n) { if (n < 0 || n >= sys_nerr) return "unknown error number"; return sys_errlist[n]; } #endif /* HAVE_STRERROR */ ================================================ FILE: src/struct.c ================================================ /* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Define the following define to enable better date debugging */ /*#define PH_DATE_DEBUG */ int rbs = 0; int rbs_bigtime = 0; #include "hypermail.h" #include "dmatch.h" #include "setup.h" #include "struct.h" #include "parse.h" #include "getname.h" #define HAVE_PCRE #ifdef HAVE_PCRE #ifdef __LCC__ #include "../lcc/pcre.h" #else #include #endif #endif struct body *hashnumlookup(int, struct emailinfo **); /* ** Ladies and germs - the hash function. */ unsigned hash(char *s) { unsigned hashval; /* We MUST deal with NULL pointers passed to this */ if (!s) return HASHSIZE - 1; /* (Daniel) I think a high value is fun ;-) */ for (hashval = 0; *s; s++) hashval = *s + 31 * hashval; return (hashval % HASHSIZE); } void reinit_structs() { int i; for (i = 0; i < HASHSIZE; ++i) { if (etable[i]) { free(etable[i]); etable[i] = NULL; } } } void fill_email_dates(struct emailinfo *e, char *date, char *fromdate, char *isodate, char *isofromdate) { bool fromdate_valid = 1, date_valid = 1; /* fromdate may be empty (zero length string rather than NULL) * date will always have something in it - either a date or * the NODATE string "(no date)" */ if (isodate != NULL && isofromdate != NULL) { e->date = iso_to_secs(isodate); e->fromdate = iso_to_secs(isofromdate); e->fromdatestr = strsav(fromdate); e->datestr = strsav(date); } else { e->date = e->fromdate = -1; if (date == NULL) date = NODATE; if (!strcmp(date, NODATE)) { date_valid = 0; } else { if ((e->date = convtoyearsecs(date)) == -1) date_valid = 0; } if (!*fromdate) { fromdate_valid = 0; } else { if ((e->fromdate = convtoyearsecs(fromdate)) == -1) fromdate_valid = 0; } if (fromdate_valid && !date_valid) { #ifdef PH_DATE_DEBUG fprintf(stderr, "%d: %s: using fromdate '%s' for both (date '%s')\n", num, msgid, fromdate, date); #endif e->fromdatestr = strsav(fromdate); e->datestr = strsav(fromdate); e->date = e->fromdate; } else if (!fromdate_valid && date_valid) { #ifdef PH_DATE_DEBUG fprintf(stderr, "%d: %s: using date '%s' for both (fromdate '%s')\n", num, msgid, date, fromdate); #endif e->fromdatestr = strsav(date); e->datestr = strsav(date); e->fromdate = e->date; } else if (!fromdate_valid && !date_valid) { #ifdef PH_DATE_DEBUG fprintf(stderr, "%d: %s: fromdate '%s' and date '%s' both bad\n", num, msgid, fromdate, date); #endif e->fromdatestr = strsav(fromdate); e->datestr = strsav(date); } else { e->fromdatestr = strsav(fromdate); e->datestr = strsav(date); #ifdef PH_DATE_DEBUG if (e->date > e->fromdate) { rbs++; if ((e->date - e->fromdate) > 4200) { /* if more than 1:10 off */ char fromdate_parsed[26]; char date_parsed[26]; strcpy(fromdate_parsed, ctime(&(e->fromdate))); strcpy(date_parsed, ctime(&(e->date))); date_parsed[24] = '\0'; fromdate_parsed[24] = '\0'; rbs_bigtime++; fprintf(stderr, "%d [%d:%d]: %s: received before sent\n %-38.38s %-30.38s\n %-38.38s %-38.38s\n", num, rbs, rbs_bigtime, msgid, fromdate, date, fromdate_parsed, date_parsed); } } #endif } } } /* ** The structure most of everything else depends on. ** Hashes a message - header info, pointer to a list of body lines - ** by number, message ID, date, and subject, so an article can be ** handily looked up and retrieved using any of these criteria. */ struct emailinfo *addhash(int num, char *date, char *name, char *email, char *msgid, char *subject, char *inreply, char *fromdate, char *charset, char *isodate, char *isofromdate, struct body *sp) { struct emailinfo *e; struct hashemail *h; unsigned hashval; char numstr[NUMSTRLEN]; bool msgid_dup = 0; bool msgid_missing = 0; static int freedummy = 0; char *newmsgid; if (!msgid) { /* SEVERE ERROR, all mails MUST have a Message-ID, ignore it! */ if (set_require_msgids) { if (set_warn_suppressions) printf("Message-ID is missing, ignoring message with subject '%s'.\n", subject ? subject : ""); return NULL; } else { msgid_missing = 1; } } if (!msgid_missing) { h = (struct hashemail *)etable[hash(msgid)]; while (h) { if (!strcmp(h->data->msgid, msgid)) { msgid_dup = 1; break; } h = h->next; } } if (msgid_dup && set_discard_dup_msgids) { if (set_showprogress) printf("%d: Message-ID collision, '%s' already present - discarding message.\n", num, msgid); return NULL; } if (msgid_dup || msgid_missing) { /* * This is broken. It needs to be corrected so that * the original message id is a component of the * generated message-id instead of a total unrelated * dummy msg-id. Good enough for now though... */ newmsgid = emalloc(MSGDSTRLEN); do { msgid_dup = 0; sprintf(newmsgid, "%d.%4.4d@hypermail.dummy", time(NULL), freedummy); h = (struct hashemail *)etable[hash(newmsgid)]; while (h) { if (!strcmp(h->data->msgid, newmsgid)) { msgid_dup = 1; break; } h = h->next; } freedummy++; } while (msgid_dup && (freedummy < 1000)); if (!msgid_dup) { if (set_showprogress) { if (msgid_missing) printf("\n%d Message-ID missing, using %s instead.\n", num, newmsgid); else printf("\n%d Message-ID collision, '%s' already present - using %s instead.\n", num, msgid, newmsgid); } msgid = newmsgid; } else { if (set_showprogress) { if (msgid_missing) printf("\n%d Message-ID missing, failed to find free id - dropping message.\n", num); else printf("\n%d Message-ID collision, '%s' already present - failed to find free id - dropping message.\n", num, msgid); } return NULL; } } e = (struct emailinfo *)emalloc(sizeof(struct emailinfo)); #ifdef FASTREPLYCODE e->replylist = NULL; e->isreply = 0; #endif e->msgnum = num; if (num > max_msgnum) max_msgnum = num; e->emailaddr = strsav(email); if ((name == NULL) || (*name == '\0')) e->name = strsav(email); else e->name = strsav(name); fill_email_dates(e, date, fromdate, isodate, isofromdate); e->subdir = msg_subdir(e->msgnum, set_use_sender_date ? e->date : e->fromdate); if (e->subdir && set_increment != -1) { if (!e->subdir->first_email) e->subdir->first_email = e; e->subdir->last_email = e; ++e->subdir->count; } e->msgid = strsav(msgid); e->subject = strsav(subject); e->unre_subject = unre(subject); e->inreplyto = strsav(inreply); e->charset = strsav(charset); e->flags = 0; e->is_deleted = 0; e->deletion_completed = -1; e->exp_time = -1; e->bodylist = sp; e->initial_next_in_thread = -1; /* Added by Daniel 1999-03-19, we need this hash later to find the mail we replied to */ h = (struct hashemail *)emalloc(sizeof(struct hashemail)); hashval = hash(inreply); h->next = etable[hashval]; h->data = e; etable[hashval] = h; h = (struct hashemail *)emalloc(sizeof(struct hashemail)); hashval = hash(date); h->next = etable[hashval]; h->data = e; etable[hashval] = h; h = (struct hashemail *)emalloc(sizeof(struct hashemail)); #if 0 printf("ADD msgid %s to HASH!\n", msgid); #endif hashval = hash(msgid); h->next = etable[hashval]; h->data = e; etable[hashval] = h; h = (struct hashemail *)emalloc(sizeof(struct hashemail)); hashval = hash(subject); h->next = etable[hashval]; h->data = e; etable[hashval] = h; h = (struct hashemail *)emalloc(sizeof(struct hashemail)); sprintf(numstr, "%d", num); hashval = hash(numstr); h->next = etable[hashval]; h->data = e; etable[hashval] = h; return e; /* the actual mail struct pointer */ } int insert_in_lists(struct emailinfo *emp, const bool * require_filter, int rlen) { int i; if (set_delete_msgnum) { char num_str[32]; sprintf(num_str, "%d", emp->msgnum); if (inlist(set_delete_msgnum, num_str)) { #if 0 if (!emp->is_deleted) { if (emp->subdir) --emp->subdir->count; } #endif emp->is_deleted = FILTERED_DELETE; } } for (i = 0; i < rlen; ++i) { if (!require_filter[i]) { emp->is_deleted = FILTERED_REQUIRED; } } if (emp->is_deleted) { struct hashemail *h; h = (struct hashemail *)malloc(sizeof(struct hashemail)); h->data = emp; h->next = deletedlist; deletedlist = h; if (set_warn_suppressions && require_filter) { const char *option = "??"; switch (emp->is_deleted) { case FILTERED_DELETE: option = "deleted or delete_msgnum"; break; case FILTERED_EXPIRE: option = "expires"; break; case FILTERED_OUT: option = "filter_out or filter_out_full_body"; break; case FILTERED_REQUIRED: option = "filter_require or filter_require_full_body"; break; case FILTERED_OLD: option = "delete_older"; break; case FILTERED_NEW: option = "delete_newer"; break; } printf("message %d deleted under option %s. msgid: %s\n", emp->msgnum + 1, option, emp->msgid); } } else { authorlist = addheader(authorlist, emp, 1, 0); subjectlist = addheader(subjectlist, emp, 0, 0); } datelist = addheader(datelist, emp, 2, 0); return !emp->is_deleted; } /* * Given an "in-reply-to:" field and a message number, this function * retrieves information about the message that this message is a * reply to. * If all else fails but a reply is * found by comparing subjects, issubjmatch is set to 1. * * Daniel 1999-03-19. Changed return type and parameters. */ #ifdef USE_OBSOLETE_HASHREPLYLOOKUP struct emailinfo *hashreplylookup(int msgnum, char *inreply, int *issubjmatch) { struct hashemail *ep; #if DEBUG_THREAD fprintf(stderr, "hashreplylookup(%d, '%s'...)\n", msgnum, inreply); #endif *issubjmatch = 0; ep = etable[hash(inreply)]; while (ep) { if ((msgnum != ep->data->msgnum) && (strcmp(inreply, ep->data->msgid) == 0)) { #if DEBUG_THREAD fprintf(stderr, "match on msgid [%d]\n", ep->data->msgnum); #endif return ep->data; } ep = ep->next; } ep = etable[hash(inreply)]; while (ep != NULL) { if ((msgnum != ep->data->msgnum) && (strstr(inreply, ep->data->datestr))) { #if DEBUG_THREAD fprintf(stderr, "match on date [%d]\n", ep->data->msgnum); #endif return ep->data; } ep = ep->next; } ep = etable[hash(inreply)]; while (ep != NULL) { if ((msgnum != ep->data->msgnum) && (strcmp(inreply, ep->data->subject) == 0)) { *issubjmatch = 1; #if DEBUG_THREAD fprintf(stderr, "match on subject [%d]\n", ep->data->msgnum); #endif return ep->data; } ep = ep->next; } return NULL; } #endif /* * Given an "message-id:" field, this tries to retrieve information * about an article that has replied. If all else fails but a reply is * found by comparing subjects, issubjmatch is set to 1. * * Daniel 1999-03-24. New. */ struct emailinfo *hashmsgidlookup(char *msgid, int *issubjmatch) { struct hashemail *ep; *issubjmatch = 0; ep = etable[hash(msgid)]; while (ep) { if (strcmp(msgid, ep->data->inreplyto) == 0) { return ep->data; } ep = ep->next; } return NULL; } /* * Given an "in-reply-to:" field and a message number, this function * retrieves information about the message that this message is a * reply to. * If all else fails but a reply is * found by comparing subjects, maybereply is set to 1. */ struct emailinfo *hashreplylookup(int msgnum, char *inreply, char *subject, int *maybereply) { struct hashemail *ep; #if DEBUG_THREAD > 1 fprintf(stderr, "hashreplynumlookup(%d, '%s'...)\n", msgnum, (inreply == NULL) ? "" : inreply); #endif *maybereply = 0; if ((inreply != NULL) && *inreply) { ep = etable[hash(inreply)]; while (ep) { if (strcmp(inreply, ep->data->msgid) == 0) { #if DEBUG_THREAD fprintf(stderr, "match on msgid %4d %4d\n", msgnum, ep->data->msgnum); #endif return ep->data; } ep = ep->next; } ep = etable[hash(inreply)]; while (ep) { if ((msgnum != ep->data->msgnum) && (strstr(inreply, ep->data->datestr))) { #if DEBUG_THREAD fprintf(stderr, "match on date %4d %4d\n", msgnum, ep->data->msgnum); #endif return ep->data; } ep = ep->next; } ep = etable[hash(inreply)]; while (ep != NULL) { if ((msgnum != ep->data->msgnum) && (strcmp(inreply, ep->data->subject) == 0)) { *maybereply = 1; #if DEBUG_THREAD fprintf(stderr, "match on subject %4d %4d\n", msgnum, ep->data->msgnum); #endif return ep->data; } ep = ep->next; } } /* end of matching on inreply */ /* No match so far. Now try matching on the subject, removing * one instance of "re: " from the front of the subject each * time round the loop. */ { #define MAX_SUBJ_LEN 300 char *s, *saved_s; struct emailinfo *lowest_so_far = NULL; int match = 0; size_t subj_len; subj_len = strlen(subject) > MAX_SUBJ_LEN ? MAX_SUBJ_LEN : strlen(subject); s = emalloc(subj_len + 1); saved_s = strncpy(s, subject, subj_len); s[subj_len] = '\0'; #ifdef NOTDEF /* AUDIT biege: can we trigger a DoS here by using a very long "Subject"? */ s = emalloc(strlen(subject) + 1); saved_s = strcpy(s, subject); #endif if (isre(s, NULL)) do { #if DEBUG_THREAD > 1 fprintf(stderr, "extra %s\n", s); #endif ep = etable[hash(s)]; while (ep != NULL) { if ((strcasecmp(s, ep->data->subject) == 0) && (msgnum != ep->data->msgnum)) { match = 1; if (lowest_so_far == NULL || ep->data->msgnum < lowest_so_far->msgnum) lowest_so_far = ep->data; } ep = ep->next; } s = oneunre(s); } while (s != NULL); free(saved_s); if (match) { *maybereply = 1; if (lowest_so_far != NULL && lowest_so_far->msgnum < msgnum) { #if DEBUG_THREAD fprintf(stderr, "match on extra %4d %4d\n", msgnum, lowest_so_far->msgnum); #endif return lowest_so_far; } else { #if DEBUG_THREAD fprintf(stderr, "match on extra %4d %4d discarded - less than %d\n", msgnum, lowest_so_far ? lowest_so_far->msgnum : -1, msgnum); #endif return NULL; } } } #if DEBUG_THREAD fprintf(stderr, "match NO MATCH %4d\n", msgnum); #endif return NULL; } /* ** Same as the above function, but only returns the article number. */ int hashreplynumlookup(int msgnum, char *inreply, char *subject, int *maybereply) { struct emailinfo *email = hashreplylookup(msgnum, inreply, subject, maybereply); return email != NULL ? email->msgnum : -1; } /* * From an article's number, retrieve all information associated with * that article. */ struct body *hashnumlookup(int num, struct emailinfo **emailp) { struct hashemail *ep; struct body *lp_tmp; char numstr[NUMSTRLEN]; sprintf(numstr, "%d", num); for (ep = etable[hash(numstr)]; ep != NULL; ep = ep->next) { if (ep->data && (num == ep->data->msgnum)) { /* return a mere pointer to it! */ *emailp = ep->data; if (!ep->data->bodylist) ep->data->bodylist = addbody(NULL, &lp_tmp, "\n", 0); return ep->data->bodylist; } } return NULL; } /* * returns info about the first message associated with the given msgid. */ struct emailinfo *hashlookupbymsgid(char *msgid) { struct hashemail *ep; if (!msgid || !*msgid) return NULL; ep = etable[hash(msgid)]; while (ep) { if (strcmp(msgid, ep->data->msgid) == 0) { return ep->data; } ep = ep->next; } return NULL; } int insert_older_msgs(int num) { int i; int num_added = 0; for(i = set_startmsgnum; i < num; ++i) { struct emailinfo *emp; if (hashnumlookup(i, &emp)) { authorlist = addheader(authorlist, emp, 1, 0); subjectlist = addheader(subjectlist, emp, 0, 0); datelist = addheader(datelist, emp, 2, 0); ++num_added; } } return num_added; } /* * Find the nearest non-deleted email to num by adding direction to num. */ struct emailinfo *neighborlookup(int num, int direction) { struct hashemail *ep; char numstr[NUMSTRLEN]; num += direction; while (num >= 0 && num <= max_msgnum) { sprintf(numstr, "%d", num); for (ep = etable[hash(numstr)]; ep != NULL; ep = ep->next) if (ep->data && (num == ep->data->msgnum)) { if (ep->data->is_deleted) break; /* return a mere pointer to it! */ return ep->data; } num += direction; } return NULL; } /* ** Add a line to a linked list that makes up a boundary stack. This new one ** should be the new "active" boundary. ** ** "Adding" a NULL will retrieve the formerly used boundary pointer. */ struct boundary *bound(struct boundary *bnd, char *line) { struct boundary *newnode = NULL; if (line) { newnode = (struct boundary *)emalloc(sizeof(struct boundary)); newnode->line = strsav(line); newnode->next = NULL; newnode->prev = bnd; if (bnd) bnd->next = newnode; bnd = newnode; } else { if (bnd->prev) { /* go back to the previous */ bnd = bnd->prev; /* free the latest one */ free(bnd->next->line); free(bnd->next); bnd->next = NULL; } else { /* this is the last node */ free(bnd->line); free(bnd); bnd = NULL; } } return bnd; /* the new "active" boundary */ } /* ** Add a line to a linked list that makes up a multipart stack. This new one ** should be the new "active" multipart. ** ** "Adding" a NULL will retrieve the formerly used multipart pointer. ** ** We reuse the boundary function as we don't have any different ** procedure to distinguish from it. */ struct boundary *multipart(struct boundary *bnd, char *line) { return bound(bnd, line); } struct charset_stack *charsets(struct charset_stack *bnd, char *charset, char *charsetsave) { struct charset_stack *newnode = NULL; if (charset || charsetsave) { newnode = (struct charset_stack *)emalloc(sizeof(struct charset_stack)); newnode->charset = (charset) ? strsav(charset) : NULL; newnode->charsetsave = (charsetsave) ? strsav(charsetsave) : NULL; newnode->next = NULL; newnode->prev = bnd; if (bnd) bnd->next = newnode; bnd = newnode; } else { if (bnd->prev) { /* go back to the previous */ bnd = bnd->prev; /* free the latest one */ if (bnd->next->charset) { free(bnd->next->charset); } free(bnd->next->charsetsave); free(bnd->next); bnd->next = NULL; } else { /* this is the last node */ if (bnd->charset) { free(bnd->charset); } free(bnd->charsetsave); free(bnd); bnd = NULL; } } return bnd; /* the new "active" boundary */ } /* returns the first element in the stack */ struct charset_stack *charsets_head(struct charset_stack *bnd) { struct charset_stack *cursor = bnd; if (cursor) { while (cursor->prev) { cursor = cursor->prev; } } return cursor; } /* ** Frees the memory allocated to a boundary structure/ ** Returns the number of elements freed. */ static int free_boundary(struct boundary *bnd) { struct boundary *cursor = bnd; struct boundary *tmp; int counter = 0; if (bnd && bnd->next) { fprintf (stderr, "free_boundary(): Error: boundary has a non-empty next element.\nLINE : %s\n", bnd->line); } cursor = bnd; while (cursor) { tmp = cursor->prev; counter++; if (cursor->line) { #ifdef DEBUG_PARSE fprintf (stderr, "free_boundary(): freeing %s\n", cursor->line); #endif free (cursor->line); } free (cursor); cursor = tmp; } return counter; } int free_bound(struct boundary *bnd) { int t; t = free_boundary (bnd); #if DEBUG_PARSE fprintf (stderr, "free_bound: freed %d elements\n", t); #endif return t; } int free_multipart(struct boundary *mp) { int t; t = free_boundary (mp); #if DEBUG_PARSE fprintf (stderr, "free_multipart: freed %d elements\n", t); #endif return t; } int free_charsets(struct charset_stack *cs) { struct charset_stack *cursor = cs; struct charset_stack *tmp; int counter = 0; if (cs && cs->next) { fprintf (stderr, "free_charsets(): Error: boundary has a non-empty next element.\n charset = %s ; charsetsave = %s\n", cs->charset, cs->charsetsave); } cursor = cs; while (cursor) { counter++; tmp = cursor->prev; #ifdef DEBUG_PARSE fprintf (stderr, "free_charsets(): freeing charset = %s ; charsetsave = %s\n", cursor->charset, cursor->charsetsave); #endif if (cursor->charset) { free (cursor->charset); } if (cursor->charsetsave) { free (cursor->charsetsave); } free (cursor); cursor = tmp; } #if DEBUG_PARSE fprintf (stderr, "free_charset_stack: freed %d elements\n", counter); #endif return counter; } /* ** Returns TRUE if a given boundary stack has an element of the given mime_type */ bool has_multipart (const struct boundary *multipartp, char *mime_type) { const struct boundary *tempnode; bool res = FALSE; if (mime_type != NULL && *mime_type != '\0') { for (tempnode = multipartp; tempnode; tempnode = tempnode->prev) { if (!strcasecmp (tempnode->line, mime_type)) { res = TRUE; break; } } } return res; } /* ** Add a line to a linked list that makes up an article's body. */ struct body *addbody(struct body *bp, struct body **lp, /* points to the last pointer */ char *line, int flags) { struct body *tempnode; struct body *newnode = NULL; char *unstuffed_line = line; int free_unstuffed_line = 0; /* delete both space stuffing and quotes where applicable for f=f */ if (flags & BODY_DEL_SSQ) { if (flags & BODY_CONTINUE) { /* delete all quote levels, we're reusing those of the precedent line */ while (*unstuffed_line == '>') { unstuffed_line++; } } /* deleting space-stuffing at beginning of line */ if (unstuffed_line[0] == ' ') { unstuffed_line++; } else if (unstuffed_line[0] == '>') { char *delsp_line = rfc3676_delsp_quotes(unstuffed_line); if (delsp_line) { unstuffed_line = delsp_line; free_unstuffed_line = 1; } } } if (!(flags & BODY_CONTINUE)) { newnode = (struct body *)emalloc(sizeof(struct body)); memset(newnode, 0, sizeof(struct body)); newnode->line = spamify(strsav(unstuffed_line)); newnode->html = (flags & BODY_HTMLIZED) ? 1 : 0; newnode->header = (flags & BODY_HEADER) ? 1 : 0; newnode->attached = (flags & BODY_ATTACHED) ? 1 : 0; newnode->format_flowed = (flags & BODY_FORMAT_FLOWED) ? 1 : 0; newnode->next = NULL; } if (bp == NULL) { bp = newnode; *lp = bp; } else { tempnode = *lp; /* get pointer right away */ if (flags & BODY_CONTINUE) { /* this is a continuation of the previous line */ int newlen; char *newbuf; /* get the new size + 1 for the terminating zero */ newlen = strlen(tempnode->line) + strlen(unstuffed_line) + 1; /* extend the former memory area: */ newbuf = (char *)realloc(tempnode->line, newlen); /* if successful, continue */ if (newbuf) { /* remove LF from the first part: */ char *lf; lf = strchr(newbuf, '\n'); if (lf) *lf = 0; /* append the new part */ strcat(newbuf, unstuffed_line); /* point out the new buffer instead */ tempnode->line = newbuf; } } else { tempnode->next = newnode; *lp = newnode; } } if (free_unstuffed_line) { free(unstuffed_line); } return bp; } /* ** Remove the last empty lines, if any, from an article body's linked list. */ int rmlastlines(struct body *bp) { struct body *tempnode; if (NULL == bp) return 0; for (tempnode = bp; tempnode->next != NULL && (tempnode->next->line)[0] != '\0'; tempnode = tempnode->next); if ((tempnode->line)[0] == '\n') { (tempnode->line)[0] = '\0'; return 1; } return 0; } /* copy bp on to the end of origbp, deallocate bp */ struct body *append_body(struct body *origbp, struct body **origlp, struct body *bp) { while (bp) { struct body *next; origbp = addbody(origbp, origlp, bp->line, (bp->header ? BODY_HEADER : 0) | (bp->html ? BODY_HTMLIZED : 0) | (bp->attached ? BODY_ATTACHED : 0)); next = bp->next; free(bp->line); free(bp); bp = next; } return origbp; } void free_body(struct body *bp) { while (bp != NULL) { struct body *cp = bp->next; if (bp->line) free(bp->line); free(bp); bp = cp; } } /* ** If a message is a reply to another, that message's number and the number of ** the message it may be referring to is put in this list. */ struct reply *addreply(struct reply *rp, int fromnum, struct emailinfo *email, int maybereply, struct reply **last_node) { struct reply *tempnode, *newnode; newnode = (struct reply *)emalloc(sizeof(struct reply)); newnode->frommsgnum = fromnum; if (email == NULL) newnode->msgnum = -1; else { newnode->msgnum = email->msgnum; #ifdef FASTREPLYCODE email->isreply = 1; #endif } newnode->data = email; newnode->maybereply = maybereply; newnode->next = NULL; if (!rp) { rp = newnode; #ifdef FASTREPLYCODE if (!threadlist && threadlist_by_msgnum && email) threadlist_by_msgnum[email->msgnum] = rp; #endif } else { #ifdef FASTREPLYCODE for (tempnode = (last_node ? *last_node : rp); tempnode->next != NULL; tempnode = tempnode->next); tempnode->next = newnode; if (rp == threadlist && threadlist_by_msgnum && email) threadlist_by_msgnum[email->msgnum] = tempnode; #else for (tempnode = rp; tempnode->next != NULL; tempnode = tempnode->next); tempnode->next = newnode; #endif } if (last_node) *last_node = newnode; return rp; } struct reply *addreply2(struct reply *rp, struct emailinfo *from_email, struct emailinfo *email, int maybereply, struct reply **last_node) { #ifdef FASTREPLYCODE struct reply *tempnode; for (tempnode = rp; tempnode != NULL; tempnode = tempnode->next) { if (tempnode->msgnum == email->msgnum) { /* duplicate? */ if (tempnode->maybereply) tempnode->maybereply = maybereply; return rp; /* don't add 2nd time */ } } from_email->replylist = addreply(from_email->replylist, from_email->msgnum, email, maybereply, NULL); #endif return addreply(rp, from_email->msgnum, email, maybereply, last_node); } /* ** Mark an article number as having been printed. */ struct printed *markasprinted(struct printed *pp, int num) { struct printed *tempnode, *newnode; newnode = (struct printed *)emalloc(sizeof(struct printed)); newnode->msgnum = num; newnode->next = NULL; if (pp == NULL) pp = newnode; else { for (tempnode = pp; tempnode->next != NULL; tempnode = tempnode->next); tempnode->next = newnode; } return pp; } /* ** Has an article already been printed? */ int wasprinted(struct printed *list, int num) { struct printed *pp; for (pp = list; pp != NULL; pp = pp->next) if (pp->msgnum == num) return 1; return 0; } /* ** Add article header information to a binary tree and sort by date, ** subject, or author. This is necessary for printing the index files. */ struct header *addheader(struct header *hp, struct emailinfo *email, int sorttype, int depth) { int isbigger; long yearsecs; static int max_depth, count_d; isbigger = 0; if (hp == NULL) { max_depth = depth; hp = (struct header *)emalloc(sizeof(struct header)); if (!hp) return NULL; hp->data = email; if (sorttype == 2) { yearsecs = hp->data->datenum = email->fromdate; if (set_use_sender_date) yearsecs = hp->data->datenum = email->date; if (!firstdatenum || yearsecs < firstdatenum) firstdatenum = yearsecs; if (yearsecs > lastdatenum) lastdatenum = yearsecs; } else hp->data->datenum = 0; hp->left = hp->right = NULL; return hp; } switch (sorttype) { case 1: isbigger = (strcasecmp(email->name, hp->data->name) > 0) ? 0 : 1; break; case 0: isbigger = (strcasecmp(email->unre_subject, hp->data->unre_subject) > 0) ? 0 : 1; break; case 2: yearsecs = email->fromdate; if (set_use_sender_date) yearsecs = email->date; if (set_reverse) isbigger = (yearsecs < hp->data->datenum) ? 0 : 1; else isbigger = (yearsecs >= hp->data->datenum) ? 0 : 1; if (!firstdatenum || yearsecs < firstdatenum) firstdatenum = yearsecs; if (yearsecs > lastdatenum) lastdatenum = yearsecs; break; } if (isbigger) hp->left = addheader(hp->left, email, sorttype, depth + 1); else hp->right = addheader(hp->right, email, sorttype, depth + 1); if (sorttype == 2 && depth < max_depth / 2 && !(++count_d % 3)) { /* semi-random rebalancing */ struct header **hpp = (set_reverse ? &hp->left : &hp->right); struct header *hp1 = *hpp; if (hp1 != NULL && (hp1->right != NULL || hp1->left != NULL)) { if (hp1->right != NULL && (hp1->left == NULL || (count_d & 1))) { struct header *p = hp1->right; hp1->right = p->left; p->left = hp1; *hpp = p; } else { struct header *p = hp1->left; hp1->left = p->right; p->right = hp1; *hpp = p; } } } return hp; } struct emailsubdir *new_subdir(char *subdir, struct emailsubdir *last_subdir, char *description, time_t date) { struct emailsubdir *sd = folders; struct emailsubdir *new_sd; struct emailsubdir *insert_point = NULL; int count; char *p; while (sd) { if (!strcmp(subdir, sd->subdir)) return sd; if (sd->a_date < date && (!insert_point || sd->a_date > insert_point->a_date)) insert_point = sd; if (sd->next_subdir == NULL) break; sd = sd->next_subdir; } new_sd = (struct emailsubdir *)emalloc(sizeof(struct emailsubdir)); new_sd->next_subdir = NULL; new_sd->prior_subdir = NULL; if (insert_point == NULL) insert_point = sd; if (insert_point == NULL) folders = (set_increment == -1 ? NULL : new_sd); else if (date < folders->a_date) { new_sd->next_subdir = folders; folders->prior_subdir = new_sd; folders = new_sd; } else { new_sd->next_subdir = insert_point->next_subdir; insert_point->next_subdir = new_sd; new_sd->prior_subdir = insert_point; if (new_sd->next_subdir) new_sd->next_subdir->prior_subdir = new_sd; } new_sd->first_email = NULL; new_sd->last_email = NULL; new_sd->count = 0; new_sd->subdir = strsav(subdir); new_sd->description = description; new_sd->a_date = date; if (set_base_url != NULL) { if (set_base_url[strlen(set_base_url) - 1] != '/') trio_asprintf(&new_sd->rel_path_to_top, "%s/", set_base_url); else new_sd->rel_path_to_top = strsav(set_base_url); } else { new_sd->rel_path_to_top = strsav("../"); count = 0; for (p = subdir; *p; ++p) count += (*p == '/'); while (--count > 0) { trio_asprintf(&p, "../%s", new_sd->rel_path_to_top); free(new_sd->rel_path_to_top); new_sd->rel_path_to_top = p; } if (set_latest_folder != NULL && set_folder_by_date != NULL && strchr(set_folder_by_date, '/')) { static int warned = 0; if (!warned) { fprintf(stderr, "Warning: the latest_folder option combined with " "a folder_by_date option that includes a '/' will produce " "some invalid links unless you use the base_url option!!.\n"); warned = 1; } } } trio_asprintf(&new_sd->full_path, "%s%s", set_dir, subdir); if (!isdir(new_sd->full_path)) { checkdir(new_sd->full_path); /* make subdir(s) if needed */ if (set_latest_folder) latest_folder_path = new_sd->subdir; } return new_sd; } /* ** And Now The List Addition Routines! */ void print_list(char *listname, struct hmlist *list) { struct hmlist *tlist; int set = 0; int len = 0; int line = 0; /* Daniel remade Nov 23 1998. Use a single line as far as possible */ for (tlist = list; tlist != NULL; tlist = tlist->next) { set++; if (!line++) { printf("%s = ", listname); len = strlen(listname) + 3; } else { if (len + strlen(tlist->val) > 78) { printf("\n%s = ", listname); len = strlen(listname) + 3; } else { printf(","); len++; } } printf("%s", tlist->val); len += strlen(tlist->val); } if (!set) printf("%s: %s\n", listname, lang[MSG_NO_ELEMENTS]); else printf("\n"); } /* ** Is the requested element in the list ? */ int inlist(struct hmlist *listname, char *wildcard) { struct hmlist *tlist; for (tlist = listname; tlist != NULL; tlist = tlist->next) { /* wildcard checks enabled! */ if (Match(wildcard, tlist->val)) return 1; } return 0; } /* ** What is the position of the requested element in the list ? */ int inlist_pos(struct hmlist *listname, char *wildcard) { struct hmlist *tlist; int i; for (i = 0, tlist = listname; tlist != NULL; i++, tlist = tlist->next) { /* wildcard checks enabled! */ if (Match(wildcard, tlist->val)) return i; } return -1; } static int regex_index(struct hmlist *listname, int index) { static int start[5] = { -1, -1, -1, -1, -1 }; if (start[0] == -1) { struct hmlist *tlist; start[1] = start[0] = 0; for (tlist = set_filter_out; tlist != NULL; tlist = tlist->next) ++start[1]; start[2] = start[1]; for (tlist = set_filter_require; tlist != NULL; tlist = tlist->next) ++start[2]; start[3] = start[2]; for (tlist = set_filter_out_full_body; tlist != NULL; tlist = tlist->next) ++start[3]; start[4] = start[3]; for (tlist = set_filter_require_full_body; tlist != NULL; tlist = tlist->next) ++start[4]; } if (index == -1) return start[4]; if (listname == set_filter_out) return start[0] + index; if (listname == set_filter_require) return start[1] + index; if (listname == set_filter_out_full_body) return start[2] + index; if (listname == set_filter_require_full_body) return start[3] + index; return -1; } /* ** like inlist_pos, but does regex search */ int inlist_regex_pos(struct hmlist *listname, char *str) { struct hmlist *tlist; int i; for (i = 0, tlist = listname; tlist != NULL; i++, tlist = tlist->next) { #ifdef HAVE_PCRE int r; const char *errptr; int epos; int index = regex_index(listname, i); static pcre *p, **pcre_list; static pcre_extra *extra, **extra_list; if (!pcre_list) { int n = regex_index(NULL, -1); int i; pcre_list = (pcre **) emalloc(n * sizeof(pcre *)); extra_list = (pcre_extra **) emalloc(n * sizeof(pcre_extra *)); for (i = 0; i < n; ++i) { pcre_list[i] = NULL; extra_list[i] = NULL; } } if ((p = pcre_list[index]) == NULL) { p = pcre_compile(tlist->val, 0, &errptr, &epos, NULL); if (!p) { snprintf(errmsg, sizeof(errmsg), "Error at position %d of regular expression '%s': %s", epos, tlist->val, errptr); progerr(errmsg); } extra = pcre_study(p, 0, &errptr); if (errptr) { snprintf(errmsg, sizeof(errmsg), "Error studying regular expression '%s': %s", tlist->val, errptr); progerr(errmsg); } pcre_list[index] = p; extra_list[index] = extra; } extra = extra_list[index]; r = pcre_exec(p, extra, str, strlen(str), 0, 0, NULL, 0); if (r >= 0) return i; #else static int warned = 0; if (set_showprogress && !warned) { warned = 1; printf("warning - regex not available\n"); } if (strstr(tlist->val, str)) return i; #endif } return -1; } /* ** Add element to the specified list */ struct hmlist *add_2_list(struct hmlist *listname, char *value) { struct hmlist *tnode, *newnode; newnode = (struct hmlist *)emalloc(sizeof(struct hmlist)); newnode->val = strsav(value); newnode->next = NULL; if (listname == NULL) listname = newnode; else { for (tnode = listname; tnode->next != NULL; tnode = tnode->next); tnode->next = newnode; } return listname; } struct hmlist *add_list(struct hmlist *listname, char *value) { register char *cp; register char *valp; /* * This needs to support lists specified on a single line, such as * inline = image/jpeg image/gif ... * inline = image/jpeg,image/gif ... * as well as lists specified on multiple lines. */ valp = value; cp = valp; while (*cp) { if (*cp == ' ' || *cp == ',') { if (*valp != ' ' && *valp != ',') { *cp = '\0'; listname = add_2_list(listname, valp); } valp = cp + 1; } cp++; } if (*valp) listname = add_2_list(listname, valp); return listname; } ================================================ FILE: src/struct.h ================================================ /* ** struct.c functions */ unsigned hash(char *); void reinit_structs(void); void fill_email_dates(struct emailinfo *, char *, char *, char *, char *); struct emailinfo *addhash(int, char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, struct body *); int insert_in_lists(struct emailinfo *, const bool *, int); struct emailinfo *hashreplylookup(int, char *, char *, int *); struct emailinfo *hashmsgidlookup(char *, int *); int hashreplynumlookup(int, char *, char *, int *); struct emailinfo *hashlookupbymsgid(char *); int insert_older_msgs(int); struct body *hashnumlookup(int, struct emailinfo **); struct emailinfo *neighborlookup(int, int); struct body *addbody(struct body *, struct body **, char *, int); struct body *append_body(struct body *, struct body **, struct body *); void free_body(struct body *); struct reply *addreply(struct reply *, int, struct emailinfo *, int, struct reply **); struct reply *addreply2(struct reply *, struct emailinfo *, struct emailinfo *, int, struct reply **); int rmlastlines(struct body *); struct emailsubdir *new_subdir(char *, struct emailsubdir *, char *, time_t); struct printed *markasprinted(struct printed *, int); int wasprinted(struct printed *, int); struct header *addheader(struct header *, struct emailinfo *, int, int); struct boundary *bound(struct boundary *, char *); int free_bound(struct boundary *); struct boundary *multipart(struct boundary *, char *); int free_multipart(struct boundary *); bool has_multipart(const struct boundary *, char *); struct charset_stack *charsets(struct charset_stack *, char *, char *); struct charset_stack *charsets_head(struct charset_stack *); int free_charsets(struct charset_stack *); void print_list(char *, struct hmlist *); int inlist(struct hmlist *, char *); int inlist_pos(struct hmlist *, char *); int inlist_regex_pos(struct hmlist *, char *); struct hmlist *add_2_list(struct hmlist *, char *); struct hmlist *add_list(struct hmlist *, char *); ================================================ FILE: src/threadprint.c ================================================ #include "hypermail.h" #include "setup.h" #include "struct.h" #include "threadprint.h" #include "printfile.h" #include "print.h" static void format_thread_info(FILE *, struct emailinfo *, int, int *, struct emailinfo *, FILE *, int, bool); static int finish_thread_levels(FILE **, int, int, int *, FILE **, char **, char **, int, struct emailinfo *, struct emailinfo *, char *, FILE *); static void finish_thread_file(FILE *, struct emailinfo *, char *); /* Define this to make it print a whole lot of debug output to stdout: */ /* #define DEBUG_THREAD */ #define MAXSTACK 200 /* A counter to know how many open li elements we have */ static int num_open_li[MAXSTACK + 1]; /* ** If year and/or month are != -1, only messages within the specified time ** period will be printed. */ void print_all_threads(FILE *fp, int year, int month, struct emailinfo *email) { int level = 0; int newlevel; int i; int prev = -1; int hide_level = 0; int thread_file_depth = (year == -1 && month == -1 ? set_thread_file_depth : 0); static int reply_list_count = 0; int stack[MAXSTACK + 1]; /* should be dynamic - this will do for now */ FILE *fp_stack[MAXSTACK + 1]; int num_replies[MAXSTACK + 1]; char *filename_stack[MAXSTACK + 1]; char *subject_stack[MAXSTACK + 1]; struct emailsubdir *subdir = email ? email->subdir : NULL; struct emailinfo *last_email; FILE *fp_body = NULL; char *filenameb = NULL; int threadnum = 0; bool is_first = TRUE; struct reply *rp = threadlist; last_email = rp->data; if (!last_email && rp->msgnum == -1 && set_files_by_thread) { progerr("files_by_thread error start with rp->msgnum == -1"); } for (i = 0; i <= MAXSTACK; i++) num_replies[i] = num_open_li[i] = 0; while (rp != NULL) { #if DEBUG_THREAD fprintf(stderr, "print_all_threads: message %d prev %d level %d\n", rp->msgnum, prev, level); #endif if (rp->msgnum == -1) { level = finish_thread_levels(&fp, level, 0, num_replies, fp_stack, filename_stack, subject_stack, thread_file_depth, email, last_email, filenameb, fp_body); filenameb = NULL; rp = rp->next; continue; } else if(level == 0 && subdir && rp->data->subdir != subdir) { rp = rp->next; continue; } #if DEBUG_THREAD fprintf(stderr, "print_all_threads: %d: %s\n", rp->msgnum, rp->data->name); #endif if (prev == -1) { level = finish_thread_levels(&fp, level, 0, num_replies, fp_stack, filename_stack, subject_stack, thread_file_depth, email, rp->data, filenameb, fp_body); filenameb = NULL; stack[level] = rp->msgnum; } else if (hide_level) { ; /* don't change level */ } else if (rp->frommsgnum == prev) { if (level < MAXSTACK) level++; else fprintf(stderr, "thread level too deep - sticking at %d\n", MAXSTACK); stack[level] = rp->msgnum; num_replies[level] = 0; if (!set_indextable) { if (level < set_thrdlevels) { if (level > thread_file_depth) { fprintf(fp, "
      \n"); } else if (level < MAXSTACK) { char *filename; char subject[TITLESTRLEN]; trio_asprintf(&filename_stack[level], "%u%s", reply_list_count, index_name[subdir != NULL][THREAD_INDEX]); filename = htmlfilename(filename_stack[level], email, ""); /* AUDIT biege: What about using remove() to handle direc.c too? */ unlink(filename); /* so chmod won't fail if someone else owned it */ fp_stack[level - 1] = fp; if ((fp = fopen(filename, "w")) == NULL) { snprintf(errmsg,sizeof(errmsg),"Couldn't write \"%s\".", filename); progerr(errmsg); } sprintf(subject, "thread index level %d", level + 1); subject_stack[level] = strsav(subject); print_index_header(fp, set_label, set_dir, subject, filename); fprintf(fp, "
        \n"); free(filename); ++reply_list_count; } } else { /* if we go over the thread limit, we just close the last open li */ if (!set_indextable && num_open_li[level - 1] != 0) { fprintf (fp, "\n"); num_open_li[level - 1]--; } } } } else { /* There are (I think) some optimisations possible here. * 1. could start loop at level-1 * Previous branch is just a special case of this branch - * possibly more efficient - probably not worth worrying about. * Paul 12-may-1999 */ for (i = level; i >= 0; i--) { if (stack[i] == rp->frommsgnum) { break; } } newlevel = i + 1; if (newlevel == level) { /* same level, close the previous item */ if (!set_indextable && num_open_li[level] != 0) { fprintf (fp, "\n"); num_open_li[level]--; } } else if (newlevel > level) { /* I don't think this branch will be used - do the right thing anyway */ #if DEBUG_THREAD fprintf(stderr, "print_all_threads: unexpected: message %d - level changing from %d to %d\n", rp->msgnum, level, newlevel); #endif if (newlevel >= MAXSTACK) { fprintf(stderr, "thread level too deep - sticking at %d\n", MAXSTACK); newlevel = MAXSTACK; } if (!set_indextable) { while (level < newlevel) { if (level < set_thrdlevels) { fprintf(fp, "
        • \n"); ++num_open_li[level]; } level++; } } } else { level = finish_thread_levels(&fp, level, newlevel, num_replies, fp_stack, filename_stack, subject_stack, thread_file_depth, email, rp->data, filenameb, fp_body); if (newlevel == 0) filenameb = NULL; } stack[newlevel] = rp->msgnum; } if (set_files_by_thread && level == 0) { char thread_id[256]; if (filenameb && last_email) { finish_thread_file(fp_body, last_email, filenameb); filenameb = NULL; } sprintf(thread_id, "thread_body%d", ++threadnum); filenameb = htmlfilename(thread_id, email, set_htmlsuffix); if ((fp_body = fopen(filenameb, "w")) == NULL) { snprintf(errmsg, sizeof(errmsg), "Couldn't write \"%s\".", filenameb); progerr(errmsg); } print_index_header(fp_body, set_label, set_dir, lang[MSG_BY_THREAD], filenameb); fprint_menu0(fp_body, rp->data, PAGE_TOP); } /* Now print this mail */ if ((year == -1 || year_of_datenum(rp->data->date) == year) && (month == -1 || month_of_datenum(rp->data->date) == month) && !rp->data->is_deleted) { format_thread_info(fp, rp->data, level, num_replies, email, fp_body, threadnum, is_first); if (is_first) is_first = FALSE; } prev = rp->msgnum; hide_level = (rp->data->is_deleted && rp->frommsgnum != rp->msgnum); last_email = rp->data; rp = rp->next; } if (!set_indextable && num_open_li[0] != 0) fprintf (fp, "\n"); if (set_files_by_thread && filenameb && last_email) { finish_thread_file(fp_body, last_email, filenameb); filenameb = NULL; } } static void format_thread_info(FILE *fp, struct emailinfo *email, int level, int *num_replies, struct emailinfo* subdir_email, FILE *fp_body, int threadnum, bool is_first) { char *subj, *tmpname; char *href = NULL; char buffer[256]; char *first_attributes = (is_first) ? " accesskey=\"j\" name=\"first\" id=\"first\"" : ""; #ifdef HAVE_ICONV subj = convchars(email->subject, "utf-8"); tmpname = convchars(email->name, "utf-8"); #else subj = convchars(email->subject, email->charset); tmpname = convchars(email->name, email->charset); #endif if (set_files_by_thread) { int maybe_reply = 0; int is_reply = 1; fprintf(fp_body, "", email->msgnum, email->msgnum); print_headers(fp_body, email, TRUE); if ((set_show_msg_links && set_show_msg_links != 4) || !set_usetable) { fprintf(fp_body, "
        \n"); } /* maybe_reply only affects code in finelink.c which we don't want to run twice? */ printbody(fp_body, email, maybe_reply, is_reply); if (level == 0) { sprintf(buffer, "thread_body%d.%s", threadnum, set_htmlsuffix); href = buffer; } is_reply = print_links(fp_body, email, PAGE_TOP, TRUE); } if (!href) href = msg_href(email, subdir_email, FALSE); /* Print the thread info */ if (set_indextable) { fprintf(fp, "%s%s" "%s" "%s\n", level > 1 ? "--> " : "", href, first_attributes, subj, set_fragment_prefix, email->msgnum, set_fragment_prefix, email->msgnum, tmpname, getindexdatestr(email->date)); } else { if (num_open_li[level] != 0) { fprintf (fp, "
      • \n"); num_open_li[level]--; } fprintf(fp, "
      • %s " "%s (%s)\n", href, first_attributes, subj, set_fragment_prefix, email->msgnum, set_fragment_prefix, email->msgnum, tmpname, getindexdatestr(email->date)); } if (subj) free(subj); if (tmpname) free(tmpname); ++num_replies[level]; if (!set_indextable) ++num_open_li[level]; email->flags |= PRINT_THREAD; /* its written now */ } int isreplyto(int msgnum, int parent) { /* returns true if message msgnum is a reply to message parent */ struct reply *rp = replylist; while (rp != NULL) { if (rp->frommsgnum == parent) { if (rp->msgnum == msgnum) { return 1; } } rp = rp->next; } return 0; } static void finish_thread_file(FILE *fp_body, struct emailinfo *email, char *filenameb) { fprint_menu0(fp_body, email, PAGE_BOTTOM); printfooter(fp_body, mhtmlfooterfile, set_label, set_dir, email->subject, filenameb, TRUE); fclose(fp_body); if (chmod(filenameb, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "Couldn't chmod \"%s\" to %o.", filenameb, set_filemode); progerr(errmsg); } free(filenameb); } static int finish_thread_levels(FILE **fp, int level, int newlevel, int *num_replies, FILE **fp_stack, char **filename_stack, char **subject_stack, int thread_file_depth, struct emailinfo *subdir_email, struct emailinfo *email, char *filenameb, FILE *fp_body) { if (newlevel == 0 && filenameb && set_files_by_thread) { finish_thread_file(fp_body, email, filenameb); } if (!set_indextable) { while (level > newlevel) { num_replies[level - 1] += num_replies[level]; if (level < set_thrdlevels) { if (level > thread_file_depth) { if (num_open_li[level] != 0) { fprintf(*fp, "
      • "); num_open_li[level]--; } fprintf(*fp, "
      \n"); if (num_open_li[level] != 0) { fprintf(*fp, ""); num_open_li[level]--; } } else if (level < MAXSTACK) { char *filename = htmlfilename(filename_stack[level], subdir_email, ""); fprintf(*fp, "
    \n"); if (num_open_li[level] != 0) { fprintf(*fp, "
  • "); num_open_li[level]--; } fprintf (*fp, ""); printfooter(*fp, ihtmlfooterfile, set_label, set_dir, subject_stack[level], filename, TRUE); fclose(*fp); *fp = fp_stack[level - 1]; if (num_replies[level]) { fprintf(*fp, "\n", filename_stack[level], num_replies[level]); if (chmod(filename, set_filemode) == -1) { snprintf(errmsg, sizeof(errmsg), "Couldn't chmod \"%s\" to %o.", filename, set_filemode); progerr(errmsg); } num_open_li[level]++; } else remove(filename); free(filename_stack[level]); free(filename); } } else { if (num_open_li[level] != 0) { fprintf(*fp, ""); num_open_li[level]--; } } level--; } } else { level = newlevel; } return level; } ================================================ FILE: src/threadprint.h ================================================ void print_all_threads(FILE *, int, int, struct emailinfo *); int isreplyto(int, int); ================================================ FILE: src/trio/CHANGES ================================================ CHANGES -- trio The changes listed without a name attributed to them were most likely done by Bjorn Reese and/or Daniel Stenberg. Version 1.16 - 2014/07/16 ------------------------- * Stephen Kitt Fixed accuracy problems on platforms with double-double support. * Stephen Kitt Added support for GCC format attribute. * Balint Reczey Fixed several visibility problems. * David Turner Changed trionan to use sigaction() instead of signal(). * Chris Liddell Fixed compiler warnings. Version 1.15 - 2010/09/12 ------------------------- * Jiri Hruska Added the trio_cprintff() and trio_cscanff() function. * Fixed calculation of fraction digits for %#g numbers involving rounding (reported by Lajos Foldy). Version 1.14 - 2010/01/26 ------------------------- * David Byron Added trio_xstring_append_max. * Fixed compilation problem on Cygwin due to lack of long double math (reported by Matthias Andree). * David Boyce Added #undef of standard stdio function names before assigning trio functions to them. * Matthias Andree Upgraded configure.in to use new macros instead of obsoleted macros. * Matthias Andree Added VPATH to Makefile.in * Tom Honermann Fixed problem with subnormal numbers which caused an infinite loop outputting leading spaces. * Adam McLaurin Improved parsing performance by avoiding memset() and memcpy() on character arrays. * Gideon Smeding Fixed %u scanning of signed numbers. * Gideon Smeding Fixed group scanning for non-matching input. * Fixed missing undo of look-ahead reading for scanf functions. This does only work for the scanf* and fscanf* functions, not dscanf* and cscanf* functions (reported by Gideon Smeding). * If the format string is empty, scanf does not attempt to read any input. * Ralf Junker Fixed Borland compilation for user-defined specifiers. Version 1.13 - 2008/11/09 ------------------------- * Ives Aerts Added the $ format for user-defined specifiers, which is compatible with compiler warnings about mismatches between specifiers and arguments. * Added TRIO_DEPRECATED flag (reported by David Boyce) * Fixed rounding adjustment for long double (reported as bug item #2136686). * Added Makefile dependency for test target (reported as bug item #2136636). * David Boyce Fixed long long support for MSVC. * Fixed potential problem with read after buffer end for non-zero terminated strings (reported as bug item #1828465). * Andreas Stricker Added WinCE support. * Fixed number of significant digits for %g. Version 1.12 - 2006/10/22 ------------------------- * Fixed scanning of floats (reported by Bernd Ahlers). * Fixed configure.in for GCC on Tru64 and MIPSpro on IRIX (reported by Andreas Maus). * Olli Savia Added support for LynxOS. Version 1.11 - 2006/04/08 ------------------------- * Mark Pickelmann Fixed trio_unregister. If the first element was removed, the remaining list would be removed as well. * Fixed unintended formatting of %e that would result in non-zero numbers starting with zero (reported by Mark Pickelmann and Gisli Ottarsson). * Fixed compilation with Sun Workshop 6 (reported by Matthias Andree). * Fixed accuracy for denormalized numbers (bug item #758327). * Glen Davidson Fixed scanning of floating-point numbers without a decimal-point (bug item #1370427). * David Byron Fixed more compiler warnings. * Fixed compilation of trio_to_long_double and TRIO_FEATURE_FLOAT (reported by David Byron). * Fixed precision of large floating-point numbers (bug item #1314524). * Karl Bochert Fixed trio_fpclassify_and_signbit to only restore the floating-point precision. * Fixed detection of need for ieee option on FreeBSD/Alpha. * Added TRIO_SNPRINTF_ONLY compilation. * Fixed trio_to_double by not using strtod() on Tru64/DECC because it does not support hex-floats. * Fixed crash on 64 bits machines related to a previous workaround in version 1.9 for uninitialized va_list (reported by Nicolai Tufar, suggestion by Douglas Gwyn). * Patrick Jessee Fixed width calculation for %g. * Added macros for internal features. * Jon Foster Added macros for conditional compilation of many features. Documented all the features. * Karl Bochert Fixed problem with Borland C++, which changes the floating-point precision for certain math functions (log10() and _fpclass()). * Karl Bochert Fixed compilation warnings on Borland C++. * Removed any occurrence of #elif because Borland C++ reports wrong line numbers when they are present (reported by Karl Bochert). * David Byron Added trio_asprintfv. * Brian Chapman Fixed Mac OS X compilation. * David Byron Fixed several compiler warnings. * Fixed printing of out-of-range arguments for %hhd and %hd. These arguments can be out of range because of default integer promotion. * Bob Friesenhahn Fixed installation of header files. * Joe Orton Added SHELL to Makefile.in to avoid problems with CShells. * Shaun Tancheff Fixed regresion tests for MSVC. * Craig Berry Fixed the VMS C99 workaround. Version 1.10 - 2003/03/06 ------------------------- * Rearranged some include files to accommodate large file support (reported by Albert Chin-A-Young). * Added support for SunOS 4.1.x lack of strerror, tolower, and toupper (reported by Peter McCluskey). * Fixed pedantic compilation with TRIO_MINIMAL. * Jose Kahan Moved to avoid redefinition problems. * Fixed hex-float exponents (reported by Matthias Clasen). * Fixed handling of negative width and precision via paramters (reported by Jacob Navia). * Nigel Hall Fixed TRIO_VA_START for VMS. * Rune Enggaard Lausen Fixed compilation for Borland C++ Builder. * Fixed precision of hex-float numbers (reported by James Antill). * Fixed plus sign only to be added for signed numbers. * Fixed printing of integers with value and precision of zero (reported by James Antill). * Fixed %#.o to only print one zero if the value is zero (reported by James Antill). * Rewrote check for IEEE compilation option to remove dependency on additional scripts. * Mehdi Lavasani Makefile install target fixed to work with older install programs. * Collapsed the DECC, MSVC, HP-UX, and AIX code for trio_fpclassify_and_sign() with further preprocessing. Version 1.9 - 2002/10/13 ------------------------ * Fixed trio_fpclassify_and_signbit on AIX 3.2 * Added configure check for -ieee/-mieee compilation option for Alpha machines. * Craig Berry Fixed compilation on VMS. * Albert Chin-A-Young Fixed incorrect conditional expression in trio_isinf. * Fixed the warnings about uninitialized va_list in the printfv and scanfv family without the use of compiler specific pragmas (suggested by Ian Pilcher). * Fixed space flag for floating-point numbers (reported by Ian Main). Version 1.8 - 2002/07/10 ------------------------ * Fixed infinite loop in multibyte handling (reported by Gisli Ottarsson). * Added the customizable cprintf/cscanf family which enables to user to specify input and output stream functions (suggested by Florian Schulze). * Fixed trio_isinf by removing the HP-UX workaround, and instead making sure that the C99 macro will adhere to the trio return values (reported by Luke Dunstan). * Alexander Lukyanov Fixed boundary case for scanning and EOF. * Jacob Navia Enabled the L modifier for formatting. * Added TRIO_MINIMAL to build trio without the string functions. * Added the R modifier to print rounded floating-point numbers. * Added trio_to_long_double and long double scanning (the L modifier). * Added trio_locale_decimal_point, trio_locale_thousand_separator, trio_locale_grouping to overwrite locale settings. * Rewrote TrioWriteDouble to avoid temporary buffers and thus the danger of buffer overflows (for instance %.5000f). * Improved floating-point formatting accuracy. * Fixed formatting of non-decimal exponents. * Fixed thousand separator checking. * Fixed %f scanning to get a float and %lf to get a double. * Fixed WIN32 compilation (reported by Emmanuel Mogenet) * Fixed regression test cases to exclude disabled features. Version 1.7 - 2002/05/07 ------------------------ * Fixed trio_to_double to handle hex-floats properly. * Fixed printing of %a-format to be like %e, not like %g. * Fixed floating-point printing of values beyond the machine accuracy. * Fixed %f for printing with large precision. * Fixed the usage of C99 nan(), which caused a crash on OSF/1 (reported by Georg Bolz) * Joe Orton Fixed %p on 64-bit platforms. * Made trio compile with K&R compilers. * Emmanuel Mogenet Fixed bug in trio_asprintf. * Emmanuel Mogenet Various WIN32 fixes. * Joe Orton Fixed trio_isinf() on HP-UX, and added test cases. * Joe Orton Fixed non-portable use of $^ in Makefile. * Joe Orton Added autoconf. * Alexander Lukyanov Fixed a number of bugs in the scanning of EOF and the count specifier. * Richard Jinks Added trio_nzero * Fixed incorrect handling of return code from TrioReadChar (reported by Henrik Lf) * Fixed parsing of character class expressions. * Fixed trio_to_double which did not work with long fractions. * Fixed %f for printing of large numbers. * Fixed %#s to handle whitespaces as non-printable characters. * Added trio_isfinite, trio_signbit, and trio_fpclassify. * Added new test cases. Version 1.6 - 2002/01/13 ------------------------ * Added dynamic string functions. * Rewrote and extended documentation in JavaDoc (using Doxygen). * Moved and renamed strio functions to triostr. * Robert Collins Added definition for Cygwin. * Markus Henke Added long double workaround for the HP C/iX compiler. * Marc Verwerft Improved error handling for dynamically allocated strings. * John Fotheringham Made trionan compile on OpenVMS. * Added 'd' and 'D' as exponent letters when using TRIO_MICROSOFT. * Fixed uninitial memory read for the parameter modifiers. Version 1.5 - 2001/09/08 ------------------------ * Merged with libxml changes. * Moved NaN and Inf handling to separate file to enable reuse in other projects. * Igor Zlatkovic Fixed TrioGenerateNan for MSVC. * Fixed lots of preprocessor macros and internal data structure names. Version 1.4 - 2001/06/03 ------------------------ * Added hex-float (%a and %A) for scanning. * Added wide character arguments (%ls, %ws, %S, %lc, %wc, and %C) for both printf and scanf. * Added mutex callbacks for user-specified specifiers to enable applications to add thread-safety. These are registered with trio_register, where the namespace is set to either ":enter" to lock a mutex, or ":leave" to unlock a mutex. * Added equivalence class expressions for scanning. For example, %[[=a=]] scans for all letters in the same equivalence class as the letter 'a' as defined by the locale. * Changed character class expressions for scanning. The expressions must now be embedded withing an extra set of brackets, e.g. %[[:alpha:]]. This was done to adhere to the syntax of UNIX98 regular expressions. * Added the possibility to specify standard support (TRIO_C99 etc.) as compiler options. * Fixed conversion of hex-float in StrToDouble. * Fixed formatting of hex-float numbers. * Stan Boehm Fixed crash on QNX, which happend because some buffers on the stack were too big. * Fixed default precision for %f and %g (reported by Jose Ortiz) * Howard Kapustein Added the I8, I16, I32, and I64 modifiers. * Jose Ortiz Fixed rounding problem for %e. * Jose Ortiz Fixed various problems with the xlC and Sun C++ compilers. Version 1.3 - 2001/05/16 ------------------------ * trio's treatment of the field width when the %e code was used was not correct (reported by Gisli Ottarsson). It turns out the fraction part should be zero-padded by default and the exponent part should be zero-prefixed if it is only one digit. At least that's how the GNU and Sun libc's work. The trio floating point output looks identical to them now. * Fixed group scanning with modifiers. * Fixed compilation for 64-bit Digital Unix. * Igor Zlatkovic Fixed compilation of dprintf, which uses read/write, for MSVC. * Fixed various compilation problems on Digital Unix (mainly associated with va_list). Version 1.2 - 2001/04/11 ------------------------ * Added autoconf integration. If compiled with HAVE_CONFIG_H the following happens. Firstly, is included. Secondly, trio will only be compiled if WITH_TRIO is defined herein. Thirdly, if TRIO_REPLACE_STDIO is defined, only stdio functions that have not been detected by autoconf, i.e. those not defined by HAVE_PRINTF or similar, will be replaced by trio functions (suggested by Daniel Veillard). * Fixed '%m.nf' output. Previously trio did not treat the width properly in all cases (reported by Gisli Ottarsson). * Added explicit promotion for the scanfv family. * Fixed more C++ compilation warnings. Version 1.1 - 2001/02/25 ------------------------ * Added explicit promotion for the printfv familiy. A float must be specified by %hf. * Fixed positionals for printfv (reported by Gisli Ottarsson). * Fixed an integer to pointer conversion problem on the SGI MIPS C compiler (reported by Gisli Ottarsson). * Fixed ANSI C++ warnings (type casting, and namespace is a reserved keyword). * Added \n to all examples in the documentation to prevent confusion. * Fixed StrSubstringMax Version 1.0 - 2000/12/10 ------------------------ * Bumped Version number. Version 0.25 - 2000/12/09 ------------------------- * Wrote more documentation. * Improved NaN support and added NaN to regression test. * Fixed C99 support. * Added missing getter/setter functions. Version 0.24 - 2000/12/02 ------------------------- * Added callback functionality for the user-defined specifier (<>). All the necessary functions are defined in triop.h header file. See the documentation for trio_register for further detail. * Wrote initial documentation on the callback functionality. * Added the printfv and scanfv family of functions, which takes a pointer array rather than variadic arguments. Each pointer in the array must point to the associated data (requested by Bruce Korb). * As indicated in version 0.21 the extension modifiers (<>) have now been completely removed. * Added skipping of thousand-separators in floating-point number scanning. Version 0.23 - 2000/10/21 ------------------------- * Added width to scanning of floating-point numbers. * Wrote more documentation on trio_printf. * Fixed problem with trailing zeroes after decimal-point. Version 0.22 - 2000/08/06 ------------------------- * Added LC_CTYPE locale dependent character class expressions to scan lists. Included are [:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:], [:xdigit:] * Added C escapes to alternative string formatting and scanning. * Added StrSubstringMax. * Wrote a little more documentation. * Fixed scanf return values. * Fixed a sign error for non-ascii characters. Version 0.21 - 2000/07/19 ------------------------- * Converted the documentation to TeX. With latex2man the documentation can automatically be converted into man pages. * Added trio_scanf, trio_vscanf, trio_fscanf, and trio_vfscanf. * Added trio_dprintf, trio_vdprintf, trio_dscanf, and trio_vdscanf. These functions can be used to write and read directly to pipes and sockets (the assume blocking sockets). Stdio buffering is surpassed, so the functions are async-safe. However, reading from stdin (STDIN_FILENO) or writing to stdout (STDOUT_FILENO) reintroduces the buffering. * Paul Janzen Added trio_asprintf and trio_vasprintf, which are compatible with the GNU and BSD interfaces. * Added scanlist ranges for group scanning (%[]). * Added width for scanning (missing for floating-point numbers though). * Added variable size modifier (&) to handle system defined types of unknown size. This modifier makes certain assumptions about the integer sizes, which may not be valid on any machine. Consequently, the modifier will remain undocumented, as it may be removed later. * Added \777 and \xFF to alternative string scanning (%#s) * Added the TRIO_REPLACE_STDIO check in the header. * Improved performance of the multibyte character parsing. * Fixed positionals (%n$) which had stopped working. * Fixed hh and ll modifiers to allow exactly two letters and no more. * Fixed ANSI C++ warnings. Also fixed the compiler warning about casting between integer and pointer (this has been annoying me for ages). * Fixed snprintf and vsnprintf with zero buffer size. * Fixed NAN problems (reported by Keith Briggs). * Fixed parsing of multibyte characters. The format string was not correctly advanced in case of a multibyte character. * Renamed many of the internal functions to have more consistant names. * Removed the and modifiers. They are not really worth including. The other <> modifiers may disappear as well. Version 0.20 - 2000/06/05 ------------------------- * Added intmax_t and ptrdiff_t support. * Added support for LC_NUMERIC grouping. * Added double-dot notation for the conversion base. The style is now %width.precision.base, where any argument can be a number, an asterix indicating a parameter, or be omitted entirely. For example, %*..2i is to specify binary numbers without precision, and with width as a parameter on the va_list. * Added sticky modifier (!), which makes subsequent specifiers of the same type reuse the current modifiers. Inspired by a suggestion from Gary Porter. * Added group scanning (%[]). Scanlist ranges and multibyte sequences are not supported yet. * Added count scanning (%n). * Changed the number scanning to accept thousand separators and any base. * Fixed positional for parameters. It is possible to write something like %3$*1$.*2$d (which happens to be the same as %*.*d). * Fixed precision of integers. * Fixed parameter flags. Before trio could only handle one parameter flag per specifier, although two (three with double-dot base) were possible. * Fixed isinf() for those platforms where it is unimplemented. Version 0.18 - 2000/05/27 ------------------------- * Rewrote the entire floating-point formatting function (Danny Dulai had reported several errors and even supplied some patches, which unfortunately were lost due to the refactoring). * Removed the use of strlen() in the declaration of a stack array. This caused problems on some compilers (besides it isn't really ANSI C compliant anyways). Using some arbitrarily chosen maximum value; should examine if some standard defines an upper limit on the length of decimal-point and thousands-separator (sizeof(wchar_t) perhaps?) * Changed the parsing of the format string to be multibyte aware. Version 0.17 - 2000/05/19 ------------------------- * Added INF, -INF, and NAN for floating-point numbers. * Fixed %#.9g -- alternative with precision. * Ken Gibson Fixed printing of negative hex numbers * Joerg (last name unknown) Fixed convertion of non-ASCII characters Version 0.16 - 1999/08/06 ------------------------- * Changed the constness of the second argument of StrFloat and StrDouble. The lack of parameter overloading in C is the reason for the strange use of constness in strtof and strtod. * Cleaned up constness. Version 0.15 - 1999/07/23 ------------------------- * Fixed the internal representation of numbers from signed to unsigned. Signed numbers posed a problem for large unsigned numbers (reported by Tero) * Fixed a tiny bug in trio_vsprintfcat * Changed the meaning of the max argument of StrAppendMax to be consistant with StrFormatAppendMax. Now it is the maximal size of the entire target buffer, not just the appended size. This makes it easier to avoid buffer overflows (requested by Tero) Version 0.14 - 1999/05/16 ------------------------- * Added size_t support (just waiting for a C99 compliant compiler to add ptrdiff_t and intmax_t) * Rewrote TrioOutStreamDouble so it does not use the libc sprintf to emulate floating-point anylonger. * Fixed width, precision, and adjustment for numbers and doubles. Version 0.13 - 1999/05/06 ------------------------- * Fixed zero padding for %d. Now %d will only zero pad if explicitly requested to do so with the 0 flag (reported by Tero). * Fixed an incorrect while() condition in TrioGetString (reported by Tero). Version 0.12 - 1999/04/19 ------------------------- * Fixed incorrect zero padding of pointers * Added StrHash with STRIO_HASH_PLAIN * Added StrFormatDateMax Version 0.11 - 1999/03/25 ------------------------- * Made it compile under cygwin * Fixed a bug were TrioPreprocess would return an error if no formatting chars were found (reported by Tero). Version - 1999/03/19 -------------------- * Added trio_strerror and TRIO_ERROR_NAME. * Changed the error codes to be positive (as errno) * Fixed two reads of uninitialized memory reported by Purify * Added binary specifiers 'b' and 'B' (like SCO.) ThousandSeparator can be used to separate nibbles (4 bit) * Renamed all Internal* functions to Trio*, which seems like a better namespace (even though it is of no practical interest because these functions are not visible beyond the scope of this file.) Version - 1999/03/12 -------------------- * Added hex-float format for StrToDouble * Double references and gaps in the arguments are not allowed (for the %n$ format) and in both cases an error code is returned. * Added StrToDouble (and StrToFloat) Version - 1999/03/08 -------------------- * Added InStream and OutStream to the trio_T structure. * Started work on TrioScan. * Return values for errors changed. Two macros to unpack the error code has been added to the header. * Shortshort (hh) flag added. * %#s also quotes the quote-char now. * Removed the 'errorInFormat' boolean, which isn't used anymore after the functions bail out with an error instead. Version - 1999/03/04 -------------------- * More than MAX_PARAMETERS parametes will now cause the TrioPreprocess() function to return error. * Unknown flags and/or specifiers cause errors too. * Added trio_snprintfcat and trio_vsnprintfcat and the defined name StrFormatAppendMax. They append a formatted string to the end of a string. * Define MAX_PARAMETERS to 128 at all times instead of using NL_ARGMAX when that exists. * Added platform fixes for Amiga as suggested by Tero Jnk Version - 1999/01/31 -------------------- * vaprintf did add a zero byte even when it had failed. * Cleaned up the code for locale handling and thousand separator * Added trio_aprintf() and trio_vaprintf(). They return an allocated string. * Added thousands separator for numbers * Added floating point support for *printf Version - 1998/10/20 -------------------- * StrMatchCase() called StrMatch() instead of itself recursively * Rewrote the implementation of *printf and *scanf and put all the code in this file. Extended qualifiers and qualifiers from other standards were added. * Added StrSpanFunction, StrToLong, and StrToUnsignedLong Version - 1998/05/23 -------------------- * Made the StrEqual* functions resistant to NULL pointers * Turns out strdup() is no standard at all, and some platforms (I seem to recall HP-UX) has problems with it. Made our own StrDuplicate() instead. * Added StrFormat() and StrFormatMax() to serve as sprintf() and snprintf() respectively. ================================================ FILE: src/trio/FILES ================================================ FILES README CHANGES Makefile.in strio.h trio.c trio.h triodef.h trionan.c trionan.h triop.h triostr.c triostr.h compare.c regression.c configure configure.in install-sh autogen.sh ================================================ FILE: src/trio/Makefile.in ================================================ SHELL = @SHELL@ CC = @CC@ CFLAGS = @CFLAGS@ -I. -DDEBUG -fPIC -fvisibility=hidden OBJS = triostr.o trio.o trionan.o TARGETLIB = libtrio.a #TARGETSHLIB = $(TARGETLIB:.a=.so.2.0.0) TARGETSHLIB = TARGETINCS = trio.h triop.h triodef.h trionan.h triostr.h LDFLAGS = -L. -ltrio -lm AR = ar RANLIB = @RANLIB@ ERASE = rm -f MKDIR = mkdir -p GENDOC = doxygen srcdir = @srcdir@ # VPATH doesn't seem to work with /usr/xpg4/bin/make on Solaris # (use /usr/ccs/bin/make), and doesn't work on older Solaris make # such as Solaris 2.6. VPATH = @srcdir@ # Installation settings INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ prefix = @prefix@ exec_prefix = @exec_prefix@ includedir = @includedir@ libdir = @libdir@ all: $(TARGETLIB) $(TARGETSHLIB) $(TARGET) .PHONY: all check test install doc clean $(srcdir)/configure: configure.in cd $(srcdir) && autoconf Makefile: Makefile.in config.status CONFIG_COMMANDS= CONFIG_LINKS= CONFIG_HEADERS= \ CONFIG_FILES=Makefile ./config.status config.status: configure ./config.status --recheck check: test test: regression ./regression install: $(TARGETLIB) $(TARGETSHLIB) $(MKDIR) $(libdir) $(MKDIR) $(includedir) $(INSTALL_DATA) $(TARGETLIB) $(TARGETSHLIB) $(libdir)/ for i in $(TARGETINCS);do \ (set -x;$(INSTALL_DATA) $(srcdir)/$$i $(includedir)); \ done regression: regression.o $(TARGETLIB) $(CC) $(CFLAGS) regression.o $(LDFLAGS) -o $@ example: example.o $(TARGETLIB) $(CC) $(CFLAGS) example.o $(LDFLAGS) -o $@ compare: compare.o $(TARGETLIB) $(CC) $(CFLAGS) compare.o $(LDFLAGS) -o $@ userdef: userdef.o $(TARGETLIB) $(CC) $(CFLAGS) userdef.o $(LDFLAGS) -o $@ $(TARGETLIB): $(OBJS) $(AR) ruv $(TARGETLIB) $(OBJS) $(RANLIB) $(TARGETLIB) $(TARGETSHLIB): $(TARGETLIB) $(CC) -lm -shared -Wl,-soname,$(patsubst %.so.2.0.0,%.so.2,$@) -Wl,--whole-archive,$< -Wl,--no-whole-archive -o $@ doc:: (cd $(srcdir) && $(GENDOC) doc/trio.cfg) clean: $(ERASE) *~ core core.* regression example $(TOBJS) $(OBJS) $(TARGET) $(TARGETLIB) $(TARGETSHLIB) example.o regression.o ================================================ FILE: src/trio/README ================================================ README -- trio Trio is a package with portable string functions. Including printf() clones and others. Copyright (C) 1998-2001 by Bjorn Reese and Daniel Stenberg. Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. Trio is intended to be an integral part of another application, so we have not done anything to create a proper installation. Compile with 'make' (edit the Makefile if you want a release build) Test the package with 'make test' Install by copying trio.h, triop.h, and libtrio.a (and man/man?/* if you want documentation) to the appropriate directories. Catch some usage examples in example.c Send feedback and patches to the mailing list, subscription and other information is found here: http://lists.sourceforge.net/lists/listinfo/ctrio-talk Enjoy! Trio web page http://daniel.haxx.se/trio/ ================================================ FILE: src/trio/README.hypermail ================================================ This is the ctrio 1.16 [1] release, stripped of its documentation and with some patches to fix compilation problems when using -DTRIO_MINIMAL. The generation of the libtrio shared library is also disabled as we're doing a static link. See the hypermail-patches.diff file for the exact changes. -Jose Kahan 09/10/2018 [1] https://sourceforge.net/projects/ctrio/ ================================================ FILE: src/trio/autogen.sh ================================================ #!/bin/sh autoconf rm -rf autom4te.cache ================================================ FILE: src/trio/compare.c ================================================ #include "trio.h" #define compare(format, value) printf("FORMAT: %s\n", format); printf("TRIO: "); trio_printf(format,value); printf("\nLIBC: "); \ printf(format,value); printf("\n\n"); int main() { compare("\"%e\"",2.342E+02); compare("\"%10.4e\"",-2.342E-02); compare("\"%11.4e\"",-2.342E-02); compare("\"%12.4e\"",-2.342E-02); compare("\"%13.4e\"",-2.342E-02); compare("\"%14.4e\"",-2.342E-02); compare("\"%15.4e\"",-2.342E-02); compare("\"%16.4e\"",-2.342E-02); compare("\"%16.4e\"",-2.342E-22); compare("\"%G\"",-2.342E-02); compare("\"%G\"",3.1415e-6); compare("%016e", 3141.5); compare("%16e", 3141.5); compare("%-16e", 3141.5); compare("%010.3e", 3141.5); compare("*%5f*", 3.3); compare("*%5f*", 3.0); compare("*%5f*", .999999E-4); compare("*%5f*", .99E-3); compare("*%5f*", 3333.0); compare("*%5g*", 3.3); compare("*%5g*", 3.0); compare("*%5g*", .999999E-4); compare("*%5g*", .99E-3); compare("*%5g*", 3333.0); compare("*%5g*", 0.01); compare("*%5.g*", 3.3); compare("*%5.g*", 3.0); compare("*%5.g*", .999999E-4); compare("*%5.g*", 1.0E-4); compare("*%5.g*", .99E-3); compare("*%5.g*", 3333.0); compare("*%5.g*", 0.01); compare("*%5.2g*", 3.3); compare("*%5.2g*", 3.0); compare("*%5.2g*", .999999E-4); compare("*%5.2g*", .99E-3); compare("*%5.2g*", 3333.0); compare("*%5.2g*", 0.01); return 0; } ================================================ FILE: src/trio/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="triodef.h" ac_subst_vars='LTLIBOBJS LIBOBJS RANLIB INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu case $ac_cv_prog_cc_stdc in #( no) : ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 else ac_cv_prog_cc_stdc=no fi fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 $as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } if ${ac_cv_prog_cc_stdc+:} false; then : $as_echo_n "(cached) " >&6 fi case $ac_cv_prog_cc_stdc in #( no) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; #( '') : { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 $as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IEEE compilation options" >&5 $as_echo_n "checking for IEEE compilation options... " >&6; } if ${ac_cv_ieee_option+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS))) # error "Option needed" typedef int option_needed[-1]; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE)) # error "Option needed" typedef int option_needed-1; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_ieee_option="-ieee" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__)))) # error "Option needed" typedef int option_needed-1; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_ieee_option="-mieee" else ac_cv_ieee_option="none" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ieee_option" >&5 $as_echo "$ac_cv_ieee_option" >&6; } if test $ac_cv_ieee_option != none; then CFLAGS="${CFLAGS} ${ac_cv_ieee_option}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sigaction()" >&5 $as_echo_n "checking for sigaction()... " >&6; } if ${ac_cv_sigaction+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !defined(SA_SIGINFO) # error "SA_SIGINFO not defined" #endif int main () { struct sigaction s; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sigaction="true" else ac_cv_sigaction="false" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sigaction" >&5 $as_echo "$ac_cv_sigaction" >&6; } if test $ac_cv_sigaction != false; then CFLAGS="${CFLAGS} -DHAVE_STRUCT_SIGACTION" fi ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: src/trio/configure.in ================================================ dnl dnl Configuration for trio dnl AC_INIT AC_CONFIG_SRCDIR([triodef.h]) AC_PREREQ(2.55) dnl autoconf 2.55 was released in 2002 AC_PROG_CC ifdef([AC_PROG_CC_STDC], [AC_PROG_CC_STDC]) AC_LANG([C]) AC_PROG_INSTALL AC_PROG_RANLIB dnl dnl Alpha floating-point compiler option. dnl AC_MSG_CHECKING(for IEEE compilation options) AC_CACHE_VAL(ac_cv_ieee_option, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[[ #if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__))) && (defined(VMS) || defined(__VMS))) # error "Option needed" typedef int option_needed[-1]; #endif ]])], ac_cv_ieee_option="/IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE", AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[[ #if !(defined(__alpha) && (defined(__DECC) || defined(__DECCXX) || (defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__))) && !(defined(VMS) || defined(__VMS)) && !defined(_CFE)) # error "Option needed" typedef int option_needed[-1]; #endif ]])], ac_cv_ieee_option="-ieee", AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[[ #if !(defined(__alpha) && (defined(__GNUC__) && (defined(__osf__) || defined(__linux__)))) # error "Option needed" typedef int option_needed[-1]; #endif ]])], ac_cv_ieee_option="-mieee", ac_cv_ieee_option="none" ) ) ) ]) AC_MSG_RESULT($ac_cv_ieee_option) if test $ac_cv_ieee_option != none; then CFLAGS="${CFLAGS} ${ac_cv_ieee_option}" fi dnl dnl Check for sigaction() dnl AC_MSG_CHECKING(for sigaction()) AC_CACHE_VAL(ac_cv_sigaction, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #if !defined(SA_SIGINFO) # error "SA_SIGINFO not defined" #endif ]],[[ struct sigaction s; ]])], ac_cv_sigaction="true", ac_cv_sigaction="false" ) ]) AC_MSG_RESULT($ac_cv_sigaction) if test $ac_cv_sigaction != false; then CFLAGS="${CFLAGS} -DHAVE_STRUCT_SIGACTION" fi AC_CONFIG_FILES([Makefile]) AC_OUTPUT ================================================ FILE: src/trio/hypermail-patches.diff ================================================ Only in /tmp/trio-1.16: doc Only in /tmp/trio-1.16: example.c diff -u -r /tmp/trio-1.16/FILES trio/FILES --- /tmp/trio-1.16/FILES 2013-06-13 11:17:24.000000000 +0200 +++ trio/FILES 2018-10-09 17:10:51.000445950 +0200 @@ -2,7 +2,6 @@ README CHANGES Makefile.in -maketgz strio.h trio.c trio.h @@ -13,21 +12,8 @@ triostr.c triostr.h compare.c -example.c regression.c configure configure.in install-sh autogen.sh -doc/doc.h -doc/doc_dynamic.h -doc/doc_printf.h -doc/doc_register.h -doc/doc_scanf.h -doc/doc_static.h -doc/footer.html -doc/header.html -doc/trio.cfg -doc/trio.css -html/trio.css -html/*.html Only in /tmp/trio-1.16: html diff -u -r /tmp/trio-1.16/Makefile.in trio/Makefile.in --- /tmp/trio-1.16/Makefile.in 2013-09-18 14:48:43.000000000 +0200 +++ trio/Makefile.in 2018-10-09 17:19:35.318110225 +0200 @@ -3,7 +3,8 @@ CFLAGS = @CFLAGS@ -I. -DDEBUG -fPIC -fvisibility=hidden OBJS = triostr.o trio.o trionan.o TARGETLIB = libtrio.a -TARGETSHLIB = $(TARGETLIB:.a=.so.2.0.0) +#TARGETSHLIB = $(TARGETLIB:.a=.so.2.0.0) +TARGETSHLIB = TARGETINCS = trio.h triop.h triodef.h trionan.h triostr.h LDFLAGS = -L. -ltrio -lm AR = ar Only in /tmp/trio-1.16: maketgz diff -u -r /tmp/trio-1.16/trionan.c trio/trionan.c --- /tmp/trio-1.16/trionan.c 2014-07-16 11:53:46.000000000 +0200 +++ trio/trionan.c 2018-10-09 17:18:14.320616383 +0200 @@ -68,6 +68,9 @@ #if !defined(TRIO_PRIVATE_NAN) # define TRIO_PRIVATE_NAN TRIO_PRIVATE #endif +#if !defined(TRIO_INLINE_NAN) +# define TRIO_INLINE_NAN TRIO_INLINE +#endif #define TRIO_TRUE (1 == 1) #define TRIO_FALSE (0 == 1) @@ -427,7 +430,7 @@ #if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT) -TRIO_PRIVATE_NAN TRIO_INLINE int +TRIO_PRIVATE_NAN TRIO_INLINE_NAN int c99_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, @@ -452,7 +455,7 @@ #if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT) -TRIO_PRIVATE_NAN TRIO_INLINE int +TRIO_PRIVATE_NAN TRIO_INLINE_NAN int decc_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, @@ -570,7 +573,7 @@ #if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT) -TRIO_PRIVATE_NAN TRIO_INLINE int +TRIO_PRIVATE_NAN TRIO_INLINE_NAN int hp_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, @@ -619,7 +622,7 @@ #if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT) -TRIO_PRIVATE_NAN TRIO_INLINE int +TRIO_PRIVATE_NAN TRIO_INLINE_NAN int xlc_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, diff -u -r /tmp/trio-1.16/trionan.h trio/trionan.h --- /tmp/trio-1.16/trionan.h 2013-06-13 11:17:24.000000000 +0200 +++ trio/trionan.h 2018-10-09 17:17:48.128130318 +0200 @@ -71,6 +71,10 @@ # endif # endif +# if !defined(TRIO_INLINE_NAN) +# define TRIO_INLINE_NAN +# endif + #else /* diff -u -r /tmp/trio-1.16/triostr.h trio/triostr.h --- /tmp/trio-1.16/triostr.h 2013-06-13 11:17:24.000000000 +0200 +++ trio/triostr.h 2018-10-09 17:41:29.676952564 +0200 @@ -119,6 +119,9 @@ # if !defined(TRIO_FUNC_TO_LONG_DOUBLE) # define TRIO_FUNC_TO_LONG_DOUBLE # endif +# if !defined(TRIO_FUNC_TO_FLOAT) +# define TRIO_FUNC_TO_FLOAT +# endif # endif # if defined(TRIO_FUNC_STRING_TERMINATE) ================================================ FILE: src/trio/install-sh ================================================ #!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 ================================================ FILE: src/trio/regression.c ================================================ /************************************************************************* * Regression test */ #include "triodef.h" #if defined(TRIO_COMPILER_ANCIENT) # include #else # include #endif #include #include #include #include #include "trio.h" #include "triop.h" #if defined(TRIO_EMBED_NAN) # define TRIO_PUBLIC_NAN static # define TRIO_FUNC_NINF # define TRIO_FUNC_PINF # define TRIO_FUNC_NAN # define TRIO_FUNC_ISINF # define TRIO_FUNC_ISNAN # if TRIO_FEATURE_FLOAT # define TRIO_FUNC_NZERO # endif #endif #include "trionan.h" #if defined(TRIO_EMBED_STRING) # define TRIO_PUBLIC_STRING static # define TRIO_FUNC_EQUAL_CASE #endif #include "triostr.h" #undef printf #if TRIO_FEATURE_WIDECHAR # include #endif #define QUOTE(x) #x #define DOUBLE_EQUAL(x,y) (((x)>(y)-DBL_EPSILON) && ((x)<(y)+DBL_EPSILON)) #define FLOAT_EQUAL(x,y) (((x)>(y)-FLT_EPSILON) && ((x)<(y)+FLT_EPSILON)) static TRIO_CONST char rcsid[] = "@(#)$Id$"; #if defined(TRIO_EMBED_NAN) # include "trionan.c" #endif #if defined(TRIO_EMBED_STRING) # include "triostr.c" #endif /************************************************************************* * */ static void Dump TRIO_ARGS2((buffer, rc), char *buffer, int rc) { if (rc < 0) { printf("Err = %d (%s), Pos = %d\n", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); } else if (buffer) printf("buffer[% 3d] = \"%s\"\n", rc, buffer); } /************************************************************************* * */ static void Report0 TRIO_ARGS2((file, line), TRIO_CONST char *file, int line) { printf("Verification failed in %s:%d.\n", file, line); } /************************************************************************* * */ static void Report TRIO_ARGS4((file, line, expected, got), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *got) { Report0(file, line); printf(" Expected \"%s\"\n", expected); printf(" Got \"%s\"\n", got); } /************************************************************************* * */ int Compare TRIO_ARGS4((file, line, expected, got), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *got) { if (!trio_equal_case(expected, got)) { Report(file, line, expected, got); return 1; } return 0; } /************************************************************************* * */ int Verify TRIO_VARGS5((file, line, result, fmt, va_alist), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *fmt, TRIO_VA_DECL) { int rc; va_list args; char buffer[4096]; TRIO_VA_START(args, fmt); rc = trio_vsnprintf(buffer, sizeof(buffer), fmt, args); if (rc < 0) Dump(buffer, rc); TRIO_VA_END(args); return Compare(file, line, expected, buffer); } /************************************************************************* * */ int VerifyV TRIO_ARGS5((file, line, result, fmt, args), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *fmt, trio_pointer_t args) { int rc; char buffer[4096]; rc = trio_snprintfv(buffer, sizeof(buffer), fmt, args); if (rc < 0) Dump(buffer, rc); return Compare(file, line, expected, buffer); } /************************************************************************* * */ int VerifyReturnValues(TRIO_NOARGS) { int nerrors = 0; int rc; int count; char *expected; char buffer[4096]; char result[4096]; rc = trio_sprintf(buffer, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 10 0123456789"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } rc = trio_snprintf(buffer, sizeof(buffer), "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 10 0123456789"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } rc = trio_snprintf(buffer, 4, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 3 012"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } /* The output buffer contains the empty string */ rc = trio_snprintf(buffer, 1, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 0 "; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } /* The output buffer should be left untouched when max size is 0 */ trio_sprintf(buffer, "DO NOT TOUCH"); rc = trio_snprintf(buffer, 0, "%s%n", "0123456789", &count); trio_sprintf(result, "%d %d %s", rc, count, buffer); expected = "10 0 DO NOT TOUCH"; if (!trio_equal_case(result, expected)) { nerrors++; Report(__FILE__, __LINE__, expected, result); } return nerrors; } /************************************************************************* * */ #define TEST_STRING "0123456789" int VerifyAllocate(TRIO_NOARGS) { int nerrors = 0; #if TRIO_FEATURE_DYNAMICSTRING int rc; char *string; int count; int test_size = sizeof(TEST_STRING) - 1; /* Allocate a string with the result */ rc = trio_asprintf(&string, "%s%n", TEST_STRING, &count); if (rc < 0) { nerrors++; Dump(string, rc); } else if (count != test_size) { nerrors++; printf("Validation failed in %s:%d\n", __FILE__, __LINE__); printf(" Expected %%n = %d\n", test_size); printf(" Got %%n = %d\n", count); } else if (!trio_equal_case(string, TEST_STRING)) { nerrors++; Report(__FILE__, __LINE__, TEST_STRING, string); } if (string) free(string); #endif return nerrors; } /************************************************************************* * */ int VerifyFormattingStrings(TRIO_NOARGS) { int nerrors = 0; /* Normal text */ nerrors += Verify(__FILE__, __LINE__, "Hello world", "Hello world"); /* String */ nerrors += Verify(__FILE__, __LINE__, "Hello world", "%s", "Hello world"); return nerrors; } /************************************************************************* * */ int VerifyFormattingIntegers(TRIO_NOARGS) { int nerrors = 0; char buffer[256]; /* Integer */ nerrors += Verify(__FILE__, __LINE__, "Number 42", "Number %d", 42); nerrors += Verify(__FILE__, __LINE__, "Number -42", "Number %d", -42); nerrors += Verify(__FILE__, __LINE__, "Number 42", "Number %ld", 42L); nerrors += Verify(__FILE__, __LINE__, "Number -42", "Number %ld", -42L); /* Integer width */ nerrors += Verify(__FILE__, __LINE__, " 1234", "%6d", 1234); nerrors += Verify(__FILE__, __LINE__, " 1234", "%*d", 6, 1234); /* Integer width overrun */ nerrors += Verify(__FILE__, __LINE__, "123456", "%4d", 123456); /* Integer precision */ nerrors += Verify(__FILE__, __LINE__, "0012", "%.4d", 12); nerrors += Verify(__FILE__, __LINE__, "0012", "%.*d", 4, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%6.*d", 4, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%*.*d", 6, 4, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%*.*.*d", 6, 4, 2, 12); nerrors += Verify(__FILE__, __LINE__, " 0012", "%*.*.*i", 6, 4, 10, 12); /* Integer sign, zero-padding, and width */ nerrors += Verify(__FILE__, __LINE__, "+01234", "%+06d", 1234); nerrors += Verify(__FILE__, __LINE__, " 01234", "% 06d", 1234); nerrors += Verify(__FILE__, __LINE__, "+01234", "% +06d", 1234); /* Integer adjust, zero-padding, and width */ nerrors += Verify(__FILE__, __LINE__, "12 ", "%-08d", 12); /* Integer zero-padding, width, and precision */ nerrors += Verify(__FILE__, __LINE__, " 000012", "%08.6d", 12); /* Integer base */ nerrors += Verify(__FILE__, __LINE__, "42", "%u", 42); nerrors += Verify(__FILE__, __LINE__, "-1", "%d", -1); nerrors += Verify(__FILE__, __LINE__, "52", "%o", 42); nerrors += Verify(__FILE__, __LINE__, "052", "%#o", 42); nerrors += Verify(__FILE__, __LINE__, "0", "%#o", 0); nerrors += Verify(__FILE__, __LINE__, "2a", "%x", 42); nerrors += Verify(__FILE__, __LINE__, "2A", "%X", 42); nerrors += Verify(__FILE__, __LINE__, "0x2a", "%#x", 42); nerrors += Verify(__FILE__, __LINE__, "0X2A", "%#X", 42); nerrors += Verify(__FILE__, __LINE__, "0x00c ", "%-#6.3x", 12); nerrors += Verify(__FILE__, __LINE__, "", "%.d", 0); nerrors += Verify(__FILE__, __LINE__, "", "%#.d", 0); nerrors += Verify(__FILE__, __LINE__, "42", "%.d", 42); nerrors += Verify(__FILE__, __LINE__, "", "%.o", 0); nerrors += Verify(__FILE__, __LINE__, " 0000", "%8.4o", 0); nerrors += Verify(__FILE__, __LINE__, " 0", "%8o", 0); nerrors += Verify(__FILE__, __LINE__, "00000000", "%08o", 0); nerrors += Verify(__FILE__, __LINE__, "0", "%#.o", 0); nerrors += Verify(__FILE__, __LINE__, "52", "%.o", 42); nerrors += Verify(__FILE__, __LINE__, "", "%.x", 0); nerrors += Verify(__FILE__, __LINE__, "", "%#.x", 0); nerrors += Verify(__FILE__, __LINE__, "2a", "%.x", 42); sprintf(buffer, "%u", UINT_MAX); nerrors += Verify(__FILE__, __LINE__, buffer, "%u", -1); sprintf(buffer, "%x", UINT_MAX); nerrors += Verify(__FILE__, __LINE__, buffer, "%x", -1); return nerrors; } /************************************************************************* * */ int VerifyFormattingFloats(TRIO_NOARGS) { int nerrors = 0; #if TRIO_FEATURE_FLOAT /* Double */ nerrors += Verify(__FILE__, __LINE__, "3141.000000", "%f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.500000", "%f", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3.141000e+03", "%e", 3141.0); nerrors += Verify(__FILE__, __LINE__, " -2.3420e-02", "%16.4e", -2.342E-02); nerrors += Verify(__FILE__, __LINE__, " -2.3420e-22", "%16.4e", -2.342E-22); nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02", "% 16.4e", 2.342E-02); nerrors += Verify(__FILE__, __LINE__, " 2.3420e-02", "% 1.4e", 2.342E-02); nerrors += Verify(__FILE__, __LINE__, "3.141000E-44", "%E", 3.141e-44); nerrors += Verify(__FILE__, __LINE__, "0", "%g", 0.0); nerrors += Verify(__FILE__, __LINE__, "-0", "%g", trio_nzero()); nerrors += Verify(__FILE__, __LINE__, "3141.5", "%g", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3.1415E-06", "%G", 3.1415e-6); nerrors += Verify(__FILE__, __LINE__, "+3141.000000", "%+f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "-3141.000000", "%+f", -3141.0); nerrors += Verify(__FILE__, __LINE__, "0.333333", "%f", 1.0/3.0); nerrors += Verify(__FILE__, __LINE__, "0.666667", "%f", 2.0/3.0); /* Beyond accuracy */ nerrors += Verify(__FILE__, __LINE__, "0.000000", "%f", 1.234567890123456789e-20); # if defined(TRIO_BREESE) nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580299875", "%.32g", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991118215802998748", "%.32f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.3999999999999999111821580300", "%.28f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.399999999999999911182158", "%.24f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.39999999999999991", "%.17f", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.40000000000000", "%.14f", 1.4); nerrors += Verify(__FILE__, __LINE__, "39413.800000000002910383045673370361", "%.30f", 39413.80); # endif /* 2^-1 + 2^-15 */ nerrors += Verify(__FILE__, __LINE__, "0.500030517578125", "%.*g", DBL_DIG + 10, 0.500030517578125); /* Double decimal point */ nerrors += Verify(__FILE__, __LINE__, "3141", "%.0f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3142", "%.0f", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3141", "%.f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "12", "%.f", 12.34); nerrors += Verify(__FILE__, __LINE__, "3141.000", "%.3f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.000000", "%#f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "0.0000", "%#.4f", 0.0); nerrors += Verify(__FILE__, __LINE__, "0.000", "%#.4g", 0.0); nerrors += Verify(__FILE__, __LINE__, "0.001000", "%#.4g", 1e-3); nerrors += Verify(__FILE__, __LINE__, "3141.0000", "%#.4f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.", "%#.0f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3141.", "%#.f", 3141.0); nerrors += Verify(__FILE__, __LINE__, "11.0000", "%#.4f", 11.0); nerrors += Verify(__FILE__, __LINE__, "100.00", "%.2f", 99.9999); nerrors += Verify(__FILE__, __LINE__, "3e+03", "%.e", 3141.0); nerrors += Verify(__FILE__, __LINE__, "3.e+03", "%#.e", 3141.0); nerrors += Verify(__FILE__, __LINE__, "1.23457e+06", "%g", 1234567.0); nerrors += Verify(__FILE__, __LINE__, "1e+02", "%.2g", 99.9999); nerrors += Verify(__FILE__, __LINE__, "1.0e+02", "%#.2g", 99.9999); nerrors += Verify(__FILE__, __LINE__, "0.123", "%0g", 0.123); nerrors += Verify(__FILE__, __LINE__, "1.00e+00", "%.2e", 0.9999); nerrors += Verify(__FILE__, __LINE__, "1", "%.2g", 0.9999); nerrors += Verify(__FILE__, __LINE__, "2", "%.0g", 1.5); nerrors += Verify(__FILE__, __LINE__, "2", "%.g", 1.5); nerrors += Verify(__FILE__, __LINE__, "0.01", "%.2g", 0.01); nerrors += Verify(__FILE__, __LINE__, "0.010", "%#.2g", 0.01); nerrors += Verify(__FILE__, __LINE__, "1e-04", "%5.g", 0.999999e-4); /* Double width and precision */ nerrors += Verify(__FILE__, __LINE__, " 1e-05", "%11.5g", 1e-5); nerrors += Verify(__FILE__, __LINE__, " 0.0001", "%11.5g", 1e-4); nerrors += Verify(__FILE__, __LINE__, " 0.001", "%11.5g", 1e-3); nerrors += Verify(__FILE__, __LINE__, " 0.01", "%11.5g", 1e-2); nerrors += Verify(__FILE__, __LINE__, " 0.1", "%11.5g", 1e-1); nerrors += Verify(__FILE__, __LINE__, " 1", "%11.5g", 1e0); nerrors += Verify(__FILE__, __LINE__, " 10", "%11.5g", 1e1); nerrors += Verify(__FILE__, __LINE__, " 100", "%11.5g", 1e2); nerrors += Verify(__FILE__, __LINE__, " 1000", "%11.5g", 1e3); nerrors += Verify(__FILE__, __LINE__, " 10000", "%11.5g", 1e4); nerrors += Verify(__FILE__, __LINE__, " 1e+05", "%11.5g", 1e5); nerrors += Verify(__FILE__, __LINE__, " 9.9e-05", "%11.2g", 0.99e-4); nerrors += Verify(__FILE__, __LINE__, " 0.00099", "%11.2g", 0.99e-3); nerrors += Verify(__FILE__, __LINE__, " 0.0099", "%11.2g", 0.99e-2); nerrors += Verify(__FILE__, __LINE__, " 0.099", "%11.2g", 0.99e-1); nerrors += Verify(__FILE__, __LINE__, " 0.99", "%11.2g", 0.99e0); nerrors += Verify(__FILE__, __LINE__, " 9.9", "%11.2g", 0.99e1); nerrors += Verify(__FILE__, __LINE__, " 99", "%11.2g", 0.99e2); nerrors += Verify(__FILE__, __LINE__, " 9.9e+02", "%11.2g", 0.99e3); nerrors += Verify(__FILE__, __LINE__, " 9.9e+03", "%11.2g", 0.99e4); nerrors += Verify(__FILE__, __LINE__, " 9.9e+04", "%11.2g", 0.99e5); /* Double width, precision, and alternative */ nerrors += Verify(__FILE__, __LINE__, " 1.0000e-05", "%#11.5g", 1e-5); nerrors += Verify(__FILE__, __LINE__, " 0.00010000", "%#11.5g", 1e-4); nerrors += Verify(__FILE__, __LINE__, " 0.0010000", "%#11.5g", 1e-3); nerrors += Verify(__FILE__, __LINE__, " 0.0010000", "%#11.5g", 0.999999e-3); nerrors += Verify(__FILE__, __LINE__, " 0.010000", "%#11.5g", 1e-2); nerrors += Verify(__FILE__, __LINE__, " 0.010000", "%#11.5g", 0.999999e-2); nerrors += Verify(__FILE__, __LINE__, " 0.10000", "%#11.5g", 1e-1); nerrors += Verify(__FILE__, __LINE__, " 0.10000", "%#11.5g", 0.999999e-1); nerrors += Verify(__FILE__, __LINE__, " 1.0000", "%#11.5g", 1e0); nerrors += Verify(__FILE__, __LINE__, " 1.0000", "%#11.5g", 0.999999e0); nerrors += Verify(__FILE__, __LINE__, " 10.000", "%#11.5g", 1e1); nerrors += Verify(__FILE__, __LINE__, " 100.00", "%#11.5g", 1e2); nerrors += Verify(__FILE__, __LINE__, " 1000.0", "%#11.5g", 1e3); nerrors += Verify(__FILE__, __LINE__, " 10000.", "%#11.5g", 1e4); nerrors += Verify(__FILE__, __LINE__, " 1.0000e+05", "%#11.5g", 1e5); nerrors += Verify(__FILE__, __LINE__, " 9.9e-05", "%#11.2g", 0.99e-4); nerrors += Verify(__FILE__, __LINE__, " 0.00099", "%#11.2g", 0.99e-3); nerrors += Verify(__FILE__, __LINE__, " 0.0099", "%#11.2g", 0.99e-2); nerrors += Verify(__FILE__, __LINE__, " 0.099", "%#11.2g", 0.99e-1); nerrors += Verify(__FILE__, __LINE__, " 0.99", "%#11.2g", 0.99e0); nerrors += Verify(__FILE__, __LINE__, " 9.9", "%#11.2g", 0.99e1); nerrors += Verify(__FILE__, __LINE__, " 99.", "%#11.2g", 0.99e2); nerrors += Verify(__FILE__, __LINE__, " 9.9e+02", "%#11.2g", 0.99e3); nerrors += Verify(__FILE__, __LINE__, " 9.9e+03", "%#11.2g", 0.99e4); nerrors += Verify(__FILE__, __LINE__, " 9.9e+04", "%#11.2g", 0.99e5); /* Double width, precision, and zero padding */ nerrors += Verify(__FILE__, __LINE__, "00003.141500e+03", "%016e", 3141.5); nerrors += Verify(__FILE__, __LINE__, " 3.141500e+03", "%16e", 3141.5); nerrors += Verify(__FILE__, __LINE__, "3.141500e+03 ", "%-16e", 3141.5); nerrors += Verify(__FILE__, __LINE__, "03.142e+03", "%010.3e", 3141.5); #if !defined(TRIO_COMPILER_ANCIENT) /* Long double */ nerrors += Verify(__FILE__, __LINE__, "1.400000", "%Lf", 1.4L); #endif /* Special cases */ nerrors += Verify(__FILE__, __LINE__, "1.00", "%.2f", 0.999); nerrors += Verify(__FILE__, __LINE__, "100", "%.0f", 99.9); nerrors += Verify(__FILE__, __LINE__, "inf", "%f", trio_pinf()); nerrors += Verify(__FILE__, __LINE__, "-inf", "%f", trio_ninf()); nerrors += Verify(__FILE__, __LINE__, "INF", "%F", trio_pinf()); nerrors += Verify(__FILE__, __LINE__, "-INF", "%F", trio_ninf()); /* May fail if NaN is unsupported */ nerrors += Verify(__FILE__, __LINE__, "nan", "%f", trio_nan()); nerrors += Verify(__FILE__, __LINE__, "NAN", "%F", trio_nan()); # if TRIO_FEATURE_HEXFLOAT nerrors += Verify(__FILE__, __LINE__, "0x2.ap+4", "%a", 42.0); nerrors += Verify(__FILE__, __LINE__, "-0x2.ap+4", "%a", -42.0); nerrors += Verify(__FILE__, __LINE__, "0x1.8p+0", "%a", 1.5); nerrors += Verify(__FILE__, __LINE__, "0x1.6666666666666p+0", "%a", 1.4); nerrors += Verify(__FILE__, __LINE__, "0xc.45p+8", "%a", 3141.0); nerrors += Verify(__FILE__, __LINE__, "0XC.45P+8", "%A", 3141.0); nerrors += Verify(__FILE__, __LINE__, "0xb.351c434a98fa8p-148", "%a", 3.141e-44); # endif #endif /* TRIO_FEATURE_FLOAT */ return nerrors; } /************************************************************************* * */ #if TRIO_EXTENSION int number_writer(void *ref) { const char *format; int *data; format = trio_get_format(ref); if ((format) && trio_equal(format, "integer")) { data = trio_get_argument(ref); if (data) { trio_print_int(ref, *data); } } return 0; } #endif int VerifyFormattingUserDefined(TRIO_NOARGS) { int nerrors = 0; #if TRIO_EXTENSION void *number_handle; int integer = 123; number_handle = trio_register(number_writer, "number"); /* Old style */ nerrors += Verify(__FILE__, __LINE__, "123", "%", &integer); /* New style */ nerrors += Verify(__FILE__, __LINE__, "123", "$", &integer); nerrors += Verify(__FILE__, __LINE__, "123", "$", number_handle, &integer); nerrors += Verify(__FILE__, __LINE__, "$", "$integer|%d>", 123); trio_unregister(number_handle); #endif return nerrors; } /************************************************************************* * */ int VerifyFormattingRegression(TRIO_NOARGS) { int nerrors = 0; #if TRIO_FEATURE_FLOAT /* 0.6 was formatted as 0.600000e+00 */ nerrors += Verify(__FILE__, __LINE__, "5.000000e-01", "%e", 0.5); nerrors += Verify(__FILE__, __LINE__, "6.000000e-01", "%e", 0.6); /* Calculate the correct number of fractional digits while rounding */ nerrors += Verify(__FILE__, __LINE__, "7654321.0", "%#.8g", 7654320.99); #endif return nerrors; } /************************************************************************* * */ int VerifyFormattingArgarray(TRIO_NOARGS) { int nerrors = 0; int rc; trio_pointer_t argarray[4]; int value = 42; double number = 123.456; float smallNumber = 123.456; argarray[0] = &value; nerrors += VerifyV(__FILE__, __LINE__, "42", "%d", argarray); argarray[0] = "my string"; nerrors += VerifyV(__FILE__, __LINE__, "my string", "%s", argarray); argarray[0] = &number; argarray[1] = &smallNumber; nerrors += VerifyV(__FILE__, __LINE__, "123.456000 123.456001", "%f %hf", argarray); return nerrors; } /************************************************************************* * */ int VerifyFormatting(TRIO_NOARGS) { int nerrors = 0; #if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER char buffer[256]; #endif nerrors += VerifyFormattingStrings(); nerrors += VerifyFormattingIntegers(); nerrors += VerifyFormattingFloats(); nerrors += VerifyFormattingRegression(); nerrors += VerifyFormattingUserDefined(); nerrors += VerifyFormattingArgarray(); /* Pointer */ if (sizeof(void *) == 4) { nerrors += Verify(__FILE__, __LINE__, "Pointer 0x01234567", "Pointer %p", 0x1234567); } #if defined(TRIO_COMPILER_SUPPORTS_LL) else if (sizeof(void *) == 8) { nerrors += Verify(__FILE__, __LINE__, "Pointer 0x0123456789012345", "Pointer %p", 0x123456789012345LL); } #endif /* Nil pointer */ nerrors += Verify(__FILE__, __LINE__, "Pointer (nil)", "Pointer %p", NULL); /* Char width alignment */ nerrors += Verify(__FILE__, __LINE__, "Char X .", "Char %-4c.", 'X'); /* String width / precision */ nerrors += Verify(__FILE__, __LINE__, " testing", "%8s", "testing"); nerrors += Verify(__FILE__, __LINE__, "testing ", "%-8s", "testing"); nerrors += Verify(__FILE__, __LINE__, " testing", "%*s", 8, "testing"); nerrors += Verify(__FILE__, __LINE__, "testing ", "%*s", -8, "testing"); nerrors += Verify(__FILE__, __LINE__, "test", "%.4s", "testing"); nerrors += Verify(__FILE__, __LINE__, "test", "%.*s", 4, "testing"); nerrors += Verify(__FILE__, __LINE__, "testing", "%.*s", -4, "testing"); #if TRIO_FEATURE_POSITIONAL /* Positional */ nerrors += Verify(__FILE__, __LINE__, "222 111", "%2$s %1$s", "111", "222"); nerrors += Verify(__FILE__, __LINE__, "123456 12345 0001234 00123", "%4$d %3$*8$d %2$.*7$d %1$*6$.*5$d", 123, 1234, 12345, 123456, 5, 6, 7, 8); #endif #if TRIO_FEATURE_SIZE_T_UPPER nerrors += Verify(__FILE__, __LINE__, "256", "%Zd", sizeof(buffer)); #endif #if TRIO_FEATURE_ERRNO errno = EINTR; # if defined(TRIO_PLATFORM_LYNX) # if defined(PREDEF_STANDARD_POSIX_1996) nerrors += Verify(__FILE__, __LINE__, "Interrupted system call ", "%m"); # else nerrors += Verify(__FILE__, __LINE__, "System call interrupted", "%m"); # endif # else nerrors += Verify(__FILE__, __LINE__, "Interrupted system call", "%m"); # endif #endif #if TRIO_FEATURE_QUAD # if defined(TRIO_COMPILER_SUPPORTS_LL) /* This may fail if the preprocessor does not recognize LL */ nerrors += Verify(__FILE__, __LINE__, "42", "%qd", 42LL); # endif #endif #if TRIO_FEATURE_SIZE_T nerrors += Verify(__FILE__, __LINE__, "256", "%zd", sizeof(buffer)); #endif #if TRIO_FEATURE_PTRDIFF_T nerrors += Verify(__FILE__, __LINE__, "42", "%td", 42); #endif #if TRIO_FEATURE_INTMAX_T # if defined(TRIO_COMPILER_SUPPORTS_LL) /* Some compilers may not handle the LL suffix correctly */ nerrors += Verify(__FILE__, __LINE__, "42", "%jd", 42LL); # endif #endif #if TRIO_FEATURE_WIDECHAR nerrors += Verify(__FILE__, __LINE__, "Hello World", "%ls", L"Hello World"); nerrors += Verify(__FILE__, __LINE__, "\\aHello World", "%#ls", L"\aHello World"); nerrors += Verify(__FILE__, __LINE__, "A", "%lc", L'A'); nerrors += Verify(__FILE__, __LINE__, "\\a", "%#lc", L'\a'); #endif #if TRIO_FEATURE_FIXED_SIZE nerrors += Verify(__FILE__, __LINE__, "42", "%I8d", 42); nerrors += Verify(__FILE__, __LINE__, "ffffffff", "%I16x", -1); #endif #if TRIO_EXTENSION nerrors += Verify(__FILE__, __LINE__, " 42 86", "%!4d %d", 42, 86); nerrors += Verify(__FILE__, __LINE__, "0042 0086", "%!04d %d", 42, 86); nerrors += Verify(__FILE__, __LINE__, "42", "%&d", sizeof(long), 42L); /* Non-printable string */ nerrors += Verify(__FILE__, __LINE__, "NonPrintable \\x01 \\a \\\\", "NonPrintable %#s", "\01 \07 \\"); nerrors += Verify(__FILE__, __LINE__, "\\a \\b \\t \\n \\v \\f \\r", "%#s", "\007 \010 \011 \012 \013 \014 \015"); /* Quote flag */ nerrors += Verify(__FILE__, __LINE__, "Another \"quoted\" string", "Another %'s string", "quoted"); /* Integer base */ nerrors += Verify(__FILE__, __LINE__, "Number 42 == 1120 (base 3)", "Number %d == %..3i (base 3)", 42, 42); /* Integer base (specifier base must be used instead of base modifier) */ nerrors += Verify(__FILE__, __LINE__, "42", "%..3d", 42); nerrors += Verify(__FILE__, __LINE__, "52", "%..3o", 42); nerrors += Verify(__FILE__, __LINE__, "2a", "%..3x", 42); /* Integer thousand separator */ nerrors += Verify(__FILE__, __LINE__, "Number 100", "Number %'d", 100); nerrors += Verify(__FILE__, __LINE__, "Number 1,000,000", "Number %'d", 1000000); # if TRIO_FEATURE_FLOAT /* Float thousand separator */ nerrors += Verify(__FILE__, __LINE__, "31,415.200000", "%'f", 31415.2); nerrors += Verify(__FILE__, __LINE__, "1,000,000.000000", "%'f", 1000000.0); /* Rounding modifier */ nerrors += Verify(__FILE__, __LINE__, "1.4", "%.32Rf", 1.4); nerrors += Verify(__FILE__, __LINE__, "1.4", "%.17Rf", 1.4); nerrors += Verify(__FILE__, __LINE__, "39413.8", "%.30Rf", 39413.80); # if !defined(TRIO_COMPILER_ANCIENT) && !defined(TRIO_DOUBLE_DOUBLE) /* Long double */ nerrors += Verify(__FILE__, __LINE__, "1.4", "%RLf", 1.4L); nerrors += Verify(__FILE__, __LINE__, "1.4", "%.30RLf", 1.4L); # endif # endif #endif #if defined(TRIO_BREESE) /* * These results depends on issues beyond our control. For example, * the accuracy of floating-point numbers depends on the underlying * floating-point hardware (e.g. whether IEEE 754 double or extended- * double format is used). * * These tests are therefore not part of the normal regression test, * but we keep them here for development purposes. */ nerrors += Verify(__FILE__, __LINE__, "123456789012345680868.000000", "%f", 1.234567890123456789e20); nerrors += Verify(__FILE__, __LINE__, "1.23456789012345677901e-20", "%.20e", 1.2345678901234567e-20); nerrors += Verify(__FILE__, __LINE__, "0.666666666666666629659233", "%.*g", DBL_DIG + 10, 2.0/3.0); nerrors += Verify(__FILE__, __LINE__, "123456789012345700000", "%Rf", 1.234567890123456789e20); # if !defined(TRIO_COMPILER_ANCIENT) nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667", "%RLf", (2.0L/3.0L)); nerrors += Verify(__FILE__, __LINE__, "0.666666666666666667", "%.30RLf", (2.0L/3.0L)); # endif #endif return nerrors; } /************************************************************************* * */ int VerifyErrors(TRIO_NOARGS) { char buffer[512]; int rc; int nerrors = 0; /* Error: Invalid argument 1 */ rc = trio_snprintf(buffer, sizeof(buffer), "%d %r", 42, "text"); #if TRIO_FEATURE_ERRORCODE # if TRIO_FEATURE_STRERR trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 5", "%s", buffer); # else trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 5", "%s", buffer); # endif #else nerrors += (rc != -1); #endif /* Error: Invalid argument 2 */ rc = trio_snprintf(buffer, sizeof(buffer), "%#"); #if TRIO_FEATURE_ERRORCODE # if TRIO_FEATURE_STRERR trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3", "%s", buffer); # else trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3", "%s", buffer); # endif #else nerrors += (rc != -1); #endif /* Error: Invalid argument 3 */ rc = trio_snprintf(buffer, sizeof(buffer), "%hhhd", 42); #if TRIO_FEATURE_ERRORCODE # if TRIO_FEATURE_STRERR trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 4", "%s", buffer); # else trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_POSITION(rc)); nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 4", "%s", buffer); # endif #else nerrors += (rc != -1); #endif /* Error: Double reference */ rc = trio_snprintf(buffer, sizeof(buffer), "hello %1$d %1$d", 31, 32); #if TRIO_FEATURE_ERRORCODE # if TRIO_FEATURE_STRERR trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); # if TRIO_UNIX98 nerrors += Verify(__FILE__, __LINE__, "Err = 4 (Double reference), Pos = 0", "%s", buffer); # else nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 9", "%s", buffer); # endif # else trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_POSITION(rc)); # if TRIO_UNIX98 nerrors += Verify(__FILE__, __LINE__, "Err = 4, Pos = 0", "%s", buffer); # else nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 9", "%s", buffer); # endif # endif #else nerrors += (rc != -1); #endif /* Error: Reference gap */ rc = trio_snprintf(buffer, sizeof(buffer), "%3$d %1$d", 31, 32, 33); #if TRIO_FEATURE_ERRORCODE # if TRIO_FEATURE_STRERR trio_snprintf(buffer, sizeof(buffer), "Err = %d (%s), Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_NAME(rc), TRIO_ERROR_POSITION(rc)); # if TRIO_UNIX98 nerrors += Verify(__FILE__, __LINE__, "Err = 5 (Reference gap), Pos = 1", "%s", buffer); # else nerrors += Verify(__FILE__, __LINE__, "Err = 2 (Invalid argument), Pos = 3", "%s", buffer); # endif # else trio_snprintf(buffer, sizeof(buffer), "Err = %d, Pos = %d", TRIO_ERROR_CODE(rc), TRIO_ERROR_POSITION(rc)); # if TRIO_UNIX98 nerrors += Verify(__FILE__, __LINE__, "Err = 5, Pos = 1", "%s", buffer); # else nerrors += Verify(__FILE__, __LINE__, "Err = 2, Pos = 3", "%s", buffer); # endif # endif #else nerrors += (rc != -1); #endif return nerrors; } /************************************************************************* * */ #if TRIO_FEATURE_SCANF int VerifyScanningOneInteger TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, int original) { int number; char data[512]; trio_snprintf(data, sizeof(data), format, original); trio_sscanf(data, format, &number); return Verify(file, line, expected, format, number); } int VerifyScanningIntegers(TRIO_NOARGS) { int nerrors = 0; nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42", "%i", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42", "%d", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "-42", "%d", -42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2147483647", "%d", 2147483647); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "42", "%u", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "2a", "%x", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "52", "%o", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "101010", "%..2i", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "0x2a", "%#x", 42); nerrors += VerifyScanningOneInteger(__FILE__, __LINE__, "052", "%#o", 42); return nerrors; } #endif /************************************************************************* * */ #if TRIO_FEATURE_SCANF int VerifyScanningOneFloat TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, double original) { float number; char data[512]; trio_snprintf(data, sizeof(data), format, original); trio_sscanf(data, format, &number); return Verify(file, line, expected, format, number); } int VerifyScanningOneDouble TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, double original) { double number; char data[512]; trio_snprintf(data, sizeof(data), format, original); trio_sscanf(data, format, &number); return Verify(file, line, expected, format, number); } int VerifyScanningFloats(TRIO_NOARGS) { int nerrors = 0; #if TRIO_FEATURE_FLOAT nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42.000000", "%f", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-42.000000", "%f", -42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000e+01", "%e", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "4.200000E+01", "%E", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "42", "%g", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06", "%g", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e-06", "%g", 1.234567e-6); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457E+06", "%G", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06", "%12e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234500e+00", "%6e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.234567e+06", "%.6e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.2345670000e+06", "%.10e", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1.23457e+06", "%.6g", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "1234567", "%.10g", 1234567.0); # if TRIO_FEATURE_HEXFLOAT nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x2.ap+4", "%a", 42.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0x1.2d687p+20", "%a", 1234567.0); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "0X1.2D687P+20", "%A", 1234567.0); # endif nerrors += VerifyScanningOneDouble(__FILE__, __LINE__, "1.79769e+308", "%lg", 1.79769e+308); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "nan", "%f", trio_nan()); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "NAN", "%F", trio_nan()); nerrors += VerifyScanningOneFloat(__FILE__, __LINE__, "-inf", "%f", trio_ninf()); #endif return nerrors; } #endif /************************************************************************* * */ #if TRIO_FEATURE_SCANF int VerifyScanningOneString TRIO_ARGS5((file, line, expected, format, original), TRIO_CONST char *file, int line, TRIO_CONST char *expected, TRIO_CONST char *format, char *original) { char string[512]; char data[512]; trio_snprintf(data, sizeof(data), "%s", original); string[0] = 0; trio_sscanf(data, format, string); return Verify(file, line, expected, "%s", string); } int VerifyScanningStrings(TRIO_NOARGS) { int nerrors = 0; nerrors += VerifyScanningOneString(__FILE__, __LINE__, "", "hello", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "", "", ""); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello", "%s", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello", "%s", "hello world"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello world", "%[^\n]", "hello world"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "(nil)", "%s", NULL); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "hello", "%20s", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "he", "%2s", "hello"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ab", "%[ab]", "abcba"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba", "%[abc]", "abcba"); nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba", "%[a-c]", "abcba"); #if TRIO_EXTENSION nerrors += VerifyScanningOneString(__FILE__, __LINE__, "abcba", "%[[:alpha:]]", "abcba"); #endif nerrors += VerifyScanningOneString(__FILE__, __LINE__, "ba", "%*[ab]c%[^\n]", "abcba"); return nerrors; } #endif /************************************************************************* * */ #if TRIO_FEATURE_SCANF int VerifyScanningRegression(TRIO_NOARGS) { int nerrors = 0; int rc; #if TRIO_FEATURE_FLOAT int offset; double dnumber; # if defined(TRIO_BREESE) trio_long_double_t ldnumber; # endif #endif long lnumber; int number; char ch; char buffer[4096]; FILE *stream; #if TRIO_FEATURE_FLOAT rc = trio_sscanf("1.5", "%lf%n", &dnumber, &offset); nerrors += Verify(__FILE__, __LINE__, "1 3 1.500000", "%d %d %f", rc, offset, dnumber); #endif rc = trio_sscanf("q 123", "%c%ld", &ch, &lnumber); nerrors += Verify(__FILE__, __LINE__, "q 123", "%c %ld", ch, lnumber); rc = trio_sscanf("abc", "%*s%n", &number); nerrors += Verify(__FILE__, __LINE__, "0 3", "%d %d", rc, number); rc = trio_sscanf("abc def", "%*s%n", &number); nerrors += Verify(__FILE__, __LINE__, "0 3", "%d %d", rc, number); #if TRIO_FEATURE_FLOAT rc = trio_sscanf("0.141882295971771490", "%lf", &dnumber); /* FIXME: Verify */ #endif number = 33; rc = trio_sscanf("total 1", "total %d", &number); nerrors += Verify(__FILE__, __LINE__, "1 1", "%d %d", rc, number); #if defined(TRIO_BREESE) # if TRIO_FEATURE_FLOAT nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771488", "%d %.18f", rc, dnumber); rc = trio_sscanf("0.141882295971771490", "%Lf", &ldnumber); nerrors += Verify(__FILE__, __LINE__, "1 0.141882295971771490", "%d %.18Lf", rc, ldnumber); # endif #endif #if TRIO_FEATURE_FLOAT rc = trio_sscanf("1.e-6", "%lg", &dnumber); nerrors += Verify(__FILE__, __LINE__, "1e-06", "%g", dnumber); rc = trio_sscanf("1e-6", "%lg", &dnumber); nerrors += Verify(__FILE__, __LINE__, "1e-06", "%g", dnumber); #endif /* Do not overwrite result on matching error */ ch = 'a'; rc = trio_sscanf("0123456789", "%1[c]", &ch); nerrors += Verify(__FILE__, __LINE__, "a", "%c", ch); /* Scan plus prefix for unsigned integer */ rc = trio_sscanf("+42", "%u", &number); nerrors += Verify(__FILE__, __LINE__, "1 42", "%d %u", rc, number); /* Scan minus prefix even for unsigned integer */ rc = trio_sscanf("-42", "%u", &number); sprintf(buffer, "1 %u", -42U); nerrors += Verify(__FILE__, __LINE__, buffer, "%d %u", rc, number); /* A scangroup match failure should not bind its argument, * i.e., it shouldn't match the empty string. */ sprintf(buffer, "SPQR"); rc = trio_sscanf("asdf", "%[c]", buffer); nerrors += Verify(__FILE__, __LINE__, "0 SPQR", "%d %s", rc, buffer); /* Even whitespace scanning shouldn't try to read past EOF */ stream = tmpfile(); trio_fprintf(stream, ""); rewind(stream); rc = trio_fscanf(stream, " "); nerrors += Verify(__FILE__, __LINE__, "0", "%d", rc); fclose(stream); /* Idem, after a succesfull read */ stream = tmpfile(); trio_fprintf(stream, "123"); rewind(stream); rc = trio_fscanf(stream, "%i ", &number); nerrors += Verify(__FILE__, __LINE__, "1 123", "%d %i", rc, number); fclose(stream); /* The scanner should unget its read-ahead char */ stream = tmpfile(); trio_fprintf(stream, "123"); rewind(stream); trio_fscanf(stream, "%*c"); trio_fscanf(stream, "%c", &ch); nerrors += Verify(__FILE__, __LINE__, "2", "%c", ch); fclose(stream); return nerrors; } #endif /************************************************************************* * */ int VerifyScanning(TRIO_NOARGS) { int nerrors = 0; #if TRIO_FEATURE_SCANF nerrors += VerifyScanningIntegers(); nerrors += VerifyScanningFloats(); nerrors += VerifyScanningStrings(); nerrors += VerifyScanningRegression(); #endif return nerrors; } /************************************************************************* * */ int VerifyStrings(TRIO_NOARGS) { int nerrors = 0; #if !defined(TRIO_MINIMAL) char buffer[512]; #if TRIO_FEATURE_FLOAT double dnumber; float fnumber; #endif char *end; /* Comparison */ trio_copy(buffer, "Find me now"); if (trio_length(buffer) != sizeof("Find me now") - 1) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal(buffer, "Find me now")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal_case(buffer, "Find me now")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_equal_case(buffer, "FIND ME NOW")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal_max(buffer, sizeof("Find me") - 1, "Find ME")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_contains(buffer, "me")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_contains(buffer, "and me")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_substring(buffer, "me") == NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_substring_max(buffer, 4, "me") != NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_match(buffer, "* me *")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_match_case(buffer, "* ME *")) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_index(buffer, 'n') == NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_index(buffer, '_') != NULL) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_index_last(buffer, 'n') == NULL) { nerrors++; Report0(__FILE__, __LINE__); } /* Append */ trio_copy(buffer, "Find me now"); if (!trio_append(buffer, " and again")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal(buffer, "Find me now and again")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_append_max(buffer, 0, "should not appear")) { nerrors++; Report0(__FILE__, __LINE__); } if (!trio_equal(buffer, "Find me now and again")) { nerrors++; Report0(__FILE__, __LINE__); } /* To upper/lower */ trio_copy(buffer, "Find me now"); trio_upper(buffer); if (!trio_equal_case(buffer, "FIND ME NOW")) { nerrors++; Report0(__FILE__, __LINE__); } trio_lower(buffer); if (!trio_equal_case(buffer, "find me now")) { nerrors++; Report0(__FILE__, __LINE__); } #if TRIO_FEATURE_FLOAT /* Double conversion */ trio_copy(buffer, "3.1415"); dnumber = trio_to_double(buffer, NULL); if (!DOUBLE_EQUAL(dnumber, 3.1415)) { nerrors++; Report0(__FILE__, __LINE__); } fnumber = trio_to_float(buffer, NULL); if (!FLOAT_EQUAL(fnumber, 3.1415)) { nerrors++; Report0(__FILE__, __LINE__); } #endif /* Long conversion */ trio_copy(buffer, "3.1415"); if (trio_to_long(buffer, NULL, 10) != 3L) { nerrors++; Report0(__FILE__, __LINE__); } if (trio_to_long(buffer, NULL, 4) != 3L) { nerrors++; Report0(__FILE__, __LINE__); } trio_to_long(buffer, &end, 2); if (end != buffer) { nerrors++; Report0(__FILE__, __LINE__); } #endif /* !defined(TRIO_MINIMAL) */ return nerrors; } /************************************************************************* * */ int VerifyDynamicStrings(TRIO_NOARGS) { int nerrors = 0; #if !defined(TRIO_MINIMAL) trio_string_t *string; const char no_terminate[5] = { 'h', 'e', 'l', 'l', 'o' }; string = trio_xstring_duplicate("Find me now"); if (string == NULL) { nerrors++; goto error; } if (!trio_xstring_equal(string, "FIND ME NOW")) nerrors++; if (!trio_xstring_append(string, " and again") || !trio_xstring_equal(string, "FIND ME NOW AND AGAIN")) nerrors++; if (!trio_xstring_contains(string, "me")) nerrors++; if (trio_xstring_contains(string, "ME")) nerrors++; if (!trio_xstring_match(string, "* me *")) nerrors++; if (trio_xstring_match_case(string, "* ME *")) nerrors++; if (!trio_xstring_append_max(string, no_terminate, 5) || !trio_xstring_equal(string, "FIND ME NOW AND AGAINhello")) nerrors++; error: if (string) trio_string_destroy(string); #endif /* !defined(TRIO_MINIMAL) */ return nerrors; } /************************************************************************* * */ int VerifyNaN(TRIO_NOARGS) { double ninf_number = trio_ninf(); double pinf_number = trio_pinf(); double nan_number = trio_nan(); int nerrors = 0; nerrors += Verify(__FILE__, __LINE__, "-1", "%d", trio_isinf(ninf_number)); nerrors += Verify(__FILE__, __LINE__, "0", "%d", trio_isinf(42.0)); nerrors += Verify(__FILE__, __LINE__, "1", "%d", trio_isinf(pinf_number)); nerrors += Verify(__FILE__, __LINE__, "1", "%d", trio_isnan(nan_number)); nerrors += Verify(__FILE__, __LINE__, "0", "%d", trio_isnan(42.0)); return nerrors; } /************************************************************************* * */ int main(TRIO_NOARGS) { int nerrors = 0; printf("%s\n", rcsid); #if TRIO_EXTENSION /* Override system locale settings */ trio_locale_set_decimal_point("."); trio_locale_set_thousand_separator(","); trio_locale_set_grouping("\3"); #endif printf("Verifying strings\n"); nerrors += VerifyStrings(); printf("Verifying dynamic strings\n"); nerrors += VerifyDynamicStrings(); printf("Verifying special quantities\n"); nerrors += VerifyNaN(); printf("Verifying formatting\n"); nerrors += VerifyFormatting(); printf("Verifying scanning\n"); nerrors += VerifyScanning(); printf("Verifying return values\n"); nerrors += VerifyErrors(); nerrors += VerifyReturnValues(); printf("Verifying allocation\n"); nerrors += VerifyAllocate(); if (nerrors == 0) printf("Regression test succeeded\n"); else printf("Regression test failed in %d instance(s)\n", nerrors); return nerrors ? 1 : 0; } ================================================ FILE: src/trio/strio.h ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************ * * This maintains backwards compatibility with the strio functions. * ************************************************************************/ #ifndef TRIO_STRIO_H #define TRIO_STRIO_H #if !(defined(DEBUG) || defined(NDEBUG)) # define NDEBUG #endif #include "triostr.h" enum { STRIO_HASH_NONE = TRIO_HASH_NONE, STRIO_HASH_PLAIN = TRIO_HASH_PLAIN, STRIO_HASH_TWOSIGNED = TRIO_HASH_TWOSIGNED }; #define StrAlloc(n) trio_create(n) #define StrAppend(x,y) ((void)trio_append((x),(y)),(x)) #define StrAppendMax(x,n,y) ((void)trio_append_max((x),(n),(y)),(x)) #define StrContains(x,y) trio_contains((x),(y)) #define StrCopy(x,y) ((void)trio_copy((x),(y)),(x)) #define StrCopyMax(x,n,y) ((void)trio_copy_max((x),(n),(y)),(x)) #define StrDuplicate(x) trio_duplicate(x) #define StrDuplicateMax(x,n) trio_duplicate((x),(n)) #define StrEqual(x,y) trio_equal((x),(y)) #define StrEqualCase(x,y) trio_equal_case((x),(y)) #define StrEqualCaseMax(x,n,y) trio_equal_case_max((x),(n),(y)) #define StrEqualLocale(x,y) trio_equal_locale((x),(y)) #define StrEqualMax(x,n,y) trio_equal_max((x),(n),(y)) #define StrError(n) trio_error(n) #define StrFree(x) trio_destroy(x) #define StrFormat trio_sprintf #define StrFormatAlloc trio_aprintf #define StrFormatAppendMax trio_snprintfcat #define StrFormatDateMax(x,n,y,t) trio_format_date_max((x),(n),(y),(t)) #define StrFormatMax trio_snprintf #define StrHash(x,n) trio_hash((x),(n)) #define StrIndex(x,y) trio_index((x),(y)) #define StrIndexLast(x,y) trio_index_last((x),(y)) #define StrLength(x) trio_length((x)) #define StrMatch(x,y) trio_match((x),(y)) #define StrMatchCase(x,y) trio_match_case((x),(y)) #define StrScan trio_sscanf #define StrSpanFunction(x,f) trio_span_function((x),(f)) #define StrSubstring(x,y) trio_substring((x),(y)) #define StrSubstringMax(x,n,y) trio_substring_max((x),(n),(y)) #define StrToDouble(x,y) trio_to_double((x),(y)) #define StrToFloat(x,y) trio_to_float((x),(y)) #define StrTokenize(x,y) trio_tokenize((x),(y)) #define StrToLong(x,y,n) trio_to_long((x),(y),(n)) #define StrToUnsignedLong(x,y,n) trio_to_unsigned_long((x),(n),(y)) #define StrToUpper(x) trio_upper(x) #endif /* TRIO_STRIO_H */ ================================================ FILE: src/trio/trio.c ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 1998, 2009 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************* * * A note to trio contributors: * * Avoid heap allocation at all costs to ensure that the trio functions * are async-safe. The exceptions are the printf/fprintf functions, which * uses fputc, and the asprintf functions and the modifier, which * by design are required to allocate form the heap. * ************************************************************************/ /* * TODO: * - Scan is probably too permissive about its modifiers. * - C escapes in %#[] ? * - Multibyte characters (done for format parsing, except scan groups) * - Complex numbers? (C99 _Complex) * - Boolean values? (C99 _Bool) * - C99 NaN(n-char-sequence) missing. The n-char-sequence can be used * to print the mantissa, e.g. NaN(0xc000000000000000) * - Should we support the GNU %a alloc modifier? GNU has an ugly hack * for %a, because C99 used %a for other purposes. If specified as * %as or %a[ it is interpreted as the alloc modifier, otherwise as * the C99 hex-float. This means that you cannot scan %as as a hex-float * immediately followed by an 's'. * - Scanning of collating symbols. */ /************************************************************************* * Trio include files */ #include "triodef.h" #include "trio.h" #include "triop.h" #if defined(TRIO_EMBED_NAN) # define TRIO_PUBLIC_NAN static # if TRIO_FEATURE_FLOAT # define TRIO_FUNC_NAN # define TRIO_FUNC_NINF # define TRIO_FUNC_PINF # define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT # define TRIO_FUNC_ISINF # endif #endif #include "trionan.h" #if defined(TRIO_EMBED_STRING) # define TRIO_PUBLIC_STRING static # define TRIO_FUNC_LENGTH # define TRIO_FUNC_LENGTH_MAX # define TRIO_FUNC_TO_LONG # if TRIO_FEATURE_LOCALE # define TRIO_FUNC_COPY_MAX # endif # if TRIO_FEATURE_DYNAMICSTRING # define TRIO_FUNC_XSTRING_DUPLICATE # endif # if TRIO_EXTENSION && TRIO_FEATURE_SCANF # define TRIO_FUNC_EQUAL_LOCALE # endif # if TRIO_FEATURE_ERRNO # define TRIO_FUNC_ERROR # endif # if TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF # define TRIO_FUNC_TO_DOUBLE # endif # if TRIO_FEATURE_DYNAMICSTRING # define TRIO_FUNC_STRING_EXTRACT # endif # if TRIO_FEATURE_DYNAMICSTRING # define TRIO_FUNC_STRING_TERMINATE # endif # if TRIO_FEATURE_USER_DEFINED # define TRIO_FUNC_DUPLICATE # endif # if TRIO_FEATURE_DYNAMICSTRING # define TRIO_FUNC_STRING_DESTROY # endif # if TRIO_FEATURE_USER_DEFINED # define TRIO_FUNC_DESTROY # endif # if TRIO_FEATURE_USER_DEFINED || (TRIO_FEATURE_FLOAT && TRIO_FEATURE_SCANF) # define TRIO_FUNC_EQUAL # endif # if TRIO_FEATURE_USER_DEFINED || TRIO_FEATURE_SCANF # define TRIO_FUNC_EQUAL_CASE # endif # if (TRIO_EXTENSION && TRIO_FEATURE_SCANF) # define TRIO_FUNC_EQUAL_MAX # endif # if TRIO_FEATURE_SCANF # define TRIO_FUNC_TO_UPPER # endif # if TRIO_FEATURE_DYNAMICSTRING # define TRIO_FUNC_XSTRING_APPEND_CHAR # endif #endif #include "triostr.h" /************************************************************************** * * Definitions * *************************************************************************/ #include #if TRIO_FEATURE_FLOAT # include # include #endif #if defined(__STDC_ISO_10646__) || defined(MB_LEN_MAX) || defined(USE_MULTIBYTE) || TRIO_FEATURE_WIDECHAR # if !defined(TRIO_PLATFORM_WINCE) # define TRIO_COMPILER_SUPPORTS_MULTIBYTE # if !defined(MB_LEN_MAX) # define MB_LEN_MAX 6 # endif # endif #endif #if (defined(TRIO_COMPILER_VISUALC) && (TRIO_COMPILER_VISUALC >= 1100)) || defined(TRIO_COMPILER_BORLAND) # define TRIO_COMPILER_SUPPORTS_VISUALC_INT #endif #if TRIO_FEATURE_FLOAT # if defined(PREDEF_STANDARD_C99) \ || defined(PREDEF_STANDARD_UNIX03) # if !defined(HAVE_FLOORL) && !defined(TRIO_NO_FLOORL) # define HAVE_FLOORL # endif # if !defined(HAVE_CEILL) && !defined(TRIO_NO_CEILL) # define HAVE_CEILL # endif # if !defined(HAVE_POWL) && !defined(TRIO_NO_POWL) # define HAVE_POWL # endif # if !defined(HAVE_FMODL) && !defined(TRIO_NO_FMODL) # define HAVE_FMODL # endif # if !defined(HAVE_LOG10L) && !defined(TRIO_NO_LOG10L) # define HAVE_LOG10L # endif # endif # if defined(TRIO_COMPILER_VISUALC) # if defined(floorl) # define HAVE_FLOORL # endif # if defined(ceill) # define HAVE_CEILL # endif # if defined(powl) # define HAVE_POWL # endif # if defined(fmodl) # define HAVE_FMODL # endif # if defined(log10l) # define HAVE_LOG10L # endif # endif #endif /************************************************************************* * Generic definitions */ #if !(defined(DEBUG) || defined(NDEBUG)) # define NDEBUG #endif #include #include #if defined(PREDEF_STANDARD_C99) && !defined(isascii) # define isascii(x) ((x) & 0x7F) #endif #if defined(TRIO_COMPILER_ANCIENT) # include #else # include #endif #include #if defined(TRIO_PLATFORM_WINCE) extern int errno; #else # include #endif #ifndef NULL # define NULL 0 #endif #define NIL ((char)0) #ifndef FALSE # define FALSE (1 == 0) # define TRUE (! FALSE) #endif #define BOOLEAN_T int /* mincore() can be used for debugging purposes */ #define VALID(x) (NULL != (x)) #if TRIO_FEATURE_ERRORCODE /* * Encode the error code and the position. This is decoded * with TRIO_ERROR_CODE and TRIO_ERROR_POSITION. */ # define TRIO_ERROR_RETURN(x,y) (- ((x) + ((y) << 8))) #else # define TRIO_ERROR_RETURN(x,y) (-1) #endif typedef unsigned long trio_flags_t; /************************************************************************* * Platform specific definitions */ #if defined(TRIO_PLATFORM_UNIX) # include # include # include # if !defined(TRIO_FEATURE_LOCALE) # define USE_LOCALE # endif #endif /* TRIO_PLATFORM_UNIX */ #if defined(TRIO_PLATFORM_VMS) # include #endif #if defined(TRIO_PLATFORM_WIN32) # if defined(TRIO_PLATFORM_WINCE) int read(int handle, char *buffer, unsigned int length); int write(int handle, const char *buffer, unsigned int length); # else # include # define read _read # define write _write # endif #endif /* TRIO_PLATFORM_WIN32 */ #if TRIO_FEATURE_WIDECHAR # if defined(PREDEF_STANDARD_C94) # include # include typedef wchar_t trio_wchar_t; typedef wint_t trio_wint_t; # else typedef char trio_wchar_t; typedef int trio_wint_t; # define WCONST(x) L ## x # define WEOF EOF # define iswalnum(x) isalnum(x) # define iswalpha(x) isalpha(x) # define iswcntrl(x) iscntrl(x) # define iswdigit(x) isdigit(x) # define iswgraph(x) isgraph(x) # define iswlower(x) islower(x) # define iswprint(x) isprint(x) # define iswpunct(x) ispunct(x) # define iswspace(x) isspace(x) # define iswupper(x) isupper(x) # define iswxdigit(x) isxdigit(x) # endif #endif /************************************************************************* * Compiler dependent definitions */ /* Support for long long */ #ifndef __cplusplus # if !defined(USE_LONGLONG) # if defined(TRIO_COMPILER_GCC) && !defined(__STRICT_ANSI__) # define USE_LONGLONG # else # if defined(TRIO_COMPILER_SUNPRO) # define USE_LONGLONG # else # if defined(TRIO_COMPILER_MSVC) && (_MSC_VER >= 1400) # define USE_LONGLONG # else # if defined(_LONG_LONG) || defined(_LONGLONG) # define USE_LONGLONG # endif # endif # endif # endif # endif #endif /* The extra long numbers */ #if defined(USE_LONGLONG) typedef signed long long int trio_longlong_t; typedef unsigned long long int trio_ulonglong_t; #else # if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT) typedef signed __int64 trio_longlong_t; typedef unsigned __int64 trio_ulonglong_t; # else typedef TRIO_SIGNED long int trio_longlong_t; typedef unsigned long int trio_ulonglong_t; # endif #endif /* Maximal and fixed integer types */ #if defined(PREDEF_STANDARD_C99) # include typedef intmax_t trio_intmax_t; typedef uintmax_t trio_uintmax_t; typedef int8_t trio_int8_t; typedef int16_t trio_int16_t; typedef int32_t trio_int32_t; typedef int64_t trio_int64_t; #else # if defined(PREDEF_STANDARD_UNIX98) # include typedef intmax_t trio_intmax_t; typedef uintmax_t trio_uintmax_t; typedef int8_t trio_int8_t; typedef int16_t trio_int16_t; typedef int32_t trio_int32_t; typedef int64_t trio_int64_t; # else # if defined(TRIO_COMPILER_SUPPORTS_VISUALC_INT) typedef trio_longlong_t trio_intmax_t; typedef trio_ulonglong_t trio_uintmax_t; typedef __int8 trio_int8_t; typedef __int16 trio_int16_t; typedef __int32 trio_int32_t; typedef __int64 trio_int64_t; # else typedef trio_longlong_t trio_intmax_t; typedef trio_ulonglong_t trio_uintmax_t; # if defined(TRIO_INT8_T) typedef TRIO_INT8_T trio_int8_t; # else typedef TRIO_SIGNED char trio_int8_t; # endif # if defined(TRIO_INT16_T) typedef TRIO_INT16_T trio_int16_t; # else typedef TRIO_SIGNED short trio_int16_t; # endif # if defined(TRIO_INT32_T) typedef TRIO_INT32_T trio_int32_t; # else typedef TRIO_SIGNED int trio_int32_t; # endif # if defined(TRIO_INT64_T) typedef TRIO_INT64_T trio_int64_t; # else typedef trio_longlong_t trio_int64_t; # endif # endif # endif #endif #if defined(HAVE_FLOORL) # define trio_floor(x) floorl((x)) #else # define trio_floor(x) floor((double)(x)) #endif #if defined(HAVE_CEILL) # define trio_ceil(x) ceill((x)) #else # define trio_ceil(x) ceil((double)(x)) #endif #if defined(HAVE_FMODL) # define trio_fmod(x,y) fmodl((x),(y)) #else # define trio_fmod(x,y) fmod((double)(x),(double)(y)) #endif #if defined(HAVE_POWL) # define trio_pow(x,y) powl((x),(y)) #else # define trio_pow(x,y) pow((double)(x),(double)(y)) #endif #if defined(HAVE_LOG10L) # define trio_log10(x) log10l((x)) #else # define trio_log10(x) log10((double)(x)) #endif #if TRIO_FEATURE_FLOAT # define TRIO_FABS(x) (((x) < 0.0) ? -(x) : (x)) #endif /************************************************************************* * Internal Definitions */ #if TRIO_FEATURE_FLOAT # if !defined(DECIMAL_DIG) # define DECIMAL_DIG DBL_DIG # endif /* Long double sizes */ # ifdef LDBL_DIG # define MAX_MANTISSA_DIGITS LDBL_DIG # define MAX_EXPONENT_DIGITS 4 # define MAX_DOUBLE_DIGITS LDBL_MAX_10_EXP # else # define MAX_MANTISSA_DIGITS DECIMAL_DIG # define MAX_EXPONENT_DIGITS 3 # define MAX_DOUBLE_DIGITS DBL_MAX_10_EXP # endif # if defined(TRIO_COMPILER_ANCIENT) || !defined(LDBL_DIG) # undef LDBL_DIG # undef LDBL_MANT_DIG # undef LDBL_EPSILON # define LDBL_DIG DBL_DIG # define LDBL_MANT_DIG DBL_MANT_DIG # define LDBL_EPSILON DBL_EPSILON # endif #endif /* TRIO_FEATURE_FLOAT */ /* The maximal number of digits is for base 2 */ #define MAX_CHARS_IN(x) (sizeof(x) * CHAR_BIT) /* The width of a pointer. The number of bits in a hex digit is 4 */ #define POINTER_WIDTH ((sizeof("0x") - 1) + sizeof(trio_pointer_t) * CHAR_BIT / 4) #if TRIO_FEATURE_FLOAT /* Infinite and Not-A-Number for floating-point */ # define INFINITE_LOWER "inf" # define INFINITE_UPPER "INF" # define LONG_INFINITE_LOWER "infinite" # define LONG_INFINITE_UPPER "INFINITE" # define NAN_LOWER "nan" # define NAN_UPPER "NAN" #endif /* Various constants */ enum { TYPE_PRINT = 1, #if TRIO_FEATURE_SCANF TYPE_SCAN = 2, #endif /* Flags. FLAGS_LAST must be less than ULONG_MAX */ FLAGS_NEW = 0, FLAGS_STICKY = 1, FLAGS_SPACE = 2 * FLAGS_STICKY, FLAGS_SHOWSIGN = 2 * FLAGS_SPACE, FLAGS_LEFTADJUST = 2 * FLAGS_SHOWSIGN, FLAGS_ALTERNATIVE = 2 * FLAGS_LEFTADJUST, FLAGS_SHORT = 2 * FLAGS_ALTERNATIVE, FLAGS_SHORTSHORT = 2 * FLAGS_SHORT, FLAGS_LONG = 2 * FLAGS_SHORTSHORT, FLAGS_QUAD = 2 * FLAGS_LONG, FLAGS_LONGDOUBLE = 2 * FLAGS_QUAD, FLAGS_SIZE_T = 2 * FLAGS_LONGDOUBLE, FLAGS_PTRDIFF_T = 2 * FLAGS_SIZE_T, FLAGS_INTMAX_T = 2 * FLAGS_PTRDIFF_T, FLAGS_NILPADDING = 2 * FLAGS_INTMAX_T, FLAGS_UNSIGNED = 2 * FLAGS_NILPADDING, FLAGS_UPPER = 2 * FLAGS_UNSIGNED, FLAGS_WIDTH = 2 * FLAGS_UPPER, FLAGS_WIDTH_PARAMETER = 2 * FLAGS_WIDTH, FLAGS_PRECISION = 2 * FLAGS_WIDTH_PARAMETER, FLAGS_PRECISION_PARAMETER = 2 * FLAGS_PRECISION, FLAGS_BASE = 2 * FLAGS_PRECISION_PARAMETER, FLAGS_BASE_PARAMETER = 2 * FLAGS_BASE, FLAGS_FLOAT_E = 2 * FLAGS_BASE_PARAMETER, FLAGS_FLOAT_G = 2 * FLAGS_FLOAT_E, FLAGS_QUOTE = 2 * FLAGS_FLOAT_G, FLAGS_WIDECHAR = 2 * FLAGS_QUOTE, FLAGS_IGNORE = 2 * FLAGS_WIDECHAR, FLAGS_IGNORE_PARAMETER = 2 * FLAGS_IGNORE, FLAGS_VARSIZE_PARAMETER = 2 * FLAGS_IGNORE_PARAMETER, FLAGS_FIXED_SIZE = 2 * FLAGS_VARSIZE_PARAMETER, FLAGS_LAST = FLAGS_FIXED_SIZE, /* Reused flags */ FLAGS_EXCLUDE = FLAGS_SHORT, FLAGS_USER_DEFINED = FLAGS_IGNORE, FLAGS_USER_DEFINED_PARAMETER = FLAGS_IGNORE_PARAMETER, FLAGS_ROUNDING = FLAGS_INTMAX_T, /* Compounded flags */ FLAGS_ALL_VARSIZES = FLAGS_LONG | FLAGS_QUAD | FLAGS_INTMAX_T | FLAGS_PTRDIFF_T | FLAGS_SIZE_T, FLAGS_ALL_SIZES = FLAGS_ALL_VARSIZES | FLAGS_SHORTSHORT | FLAGS_SHORT, NO_POSITION = -1, NO_WIDTH = 0, NO_PRECISION = -1, NO_SIZE = -1, /* Do not change these */ NO_BASE = -1, MIN_BASE = 2, MAX_BASE = 36, BASE_BINARY = 2, BASE_OCTAL = 8, BASE_DECIMAL = 10, BASE_HEX = 16, /* Maximal number of allowed parameters */ MAX_PARAMETERS = 64, /* Maximal number of characters in class */ MAX_CHARACTER_CLASS = UCHAR_MAX + 1, #if TRIO_FEATURE_USER_DEFINED /* Maximal string lengths for user-defined specifiers */ MAX_USER_NAME = 64, MAX_USER_DATA = 256, #endif /* Maximal length of locale separator strings */ MAX_LOCALE_SEPARATOR_LENGTH = MB_LEN_MAX, /* Maximal number of integers in grouping */ MAX_LOCALE_GROUPS = 64 }; #define NO_GROUPING ((int)CHAR_MAX) /* Fundamental formatting parameter types */ #define FORMAT_SENTINEL -1 /* marks end of parameters array */ #define FORMAT_UNKNOWN 0 #define FORMAT_INT 1 #define FORMAT_DOUBLE 2 #define FORMAT_CHAR 3 #define FORMAT_STRING 4 #define FORMAT_POINTER 5 #define FORMAT_COUNT 6 #define FORMAT_PARAMETER 7 #define FORMAT_GROUP 8 #define FORMAT_ERRNO 9 #define FORMAT_USER_DEFINED 10 /* Character constants */ #define CHAR_IDENTIFIER '%' #define CHAR_ALT_IDENTIFIER '$' #define CHAR_BACKSLASH '\\' #define CHAR_QUOTE '\"' #define CHAR_ADJUST ' ' #if TRIO_EXTENSION /* Character class expressions */ # define CLASS_ALNUM "[:alnum:]" # define CLASS_ALPHA "[:alpha:]" # define CLASS_BLANK "[:blank:]" # define CLASS_CNTRL "[:cntrl:]" # define CLASS_DIGIT "[:digit:]" # define CLASS_GRAPH "[:graph:]" # define CLASS_LOWER "[:lower:]" # define CLASS_PRINT "[:print:]" # define CLASS_PUNCT "[:punct:]" # define CLASS_SPACE "[:space:]" # define CLASS_UPPER "[:upper:]" # define CLASS_XDIGIT "[:xdigit:]" #endif /* * SPECIFIERS: * * * a Hex-float * A Hex-float * c Character * C Widechar character (wint_t) * d Decimal * e Float * E Float * F Float * F Float * g Float * G Float * i Integer * m Error message * n Count * o Octal * p Pointer * s String * S Widechar string (wchar_t *) * u Unsigned * x Hex * X Hex * [] Group * <> User-defined * * Reserved: * * D Binary Coded Decimal %D(length,precision) (OS/390) */ #define SPECIFIER_CHAR 'c' #define SPECIFIER_STRING 's' #define SPECIFIER_DECIMAL 'd' #define SPECIFIER_INTEGER 'i' #define SPECIFIER_UNSIGNED 'u' #define SPECIFIER_OCTAL 'o' #define SPECIFIER_HEX 'x' #define SPECIFIER_HEX_UPPER 'X' #if TRIO_FEATURE_FLOAT # define SPECIFIER_FLOAT_E 'e' # define SPECIFIER_FLOAT_E_UPPER 'E' # define SPECIFIER_FLOAT_F 'f' # define SPECIFIER_FLOAT_F_UPPER 'F' # define SPECIFIER_FLOAT_G 'g' # define SPECIFIER_FLOAT_G_UPPER 'G' #endif #define SPECIFIER_POINTER 'p' #if TRIO_FEATURE_SCANF # define SPECIFIER_GROUP '[' # define SPECIFIER_UNGROUP ']' #endif #define SPECIFIER_COUNT 'n' #if TRIO_UNIX98 # define SPECIFIER_CHAR_UPPER 'C' # define SPECIFIER_STRING_UPPER 'S' #endif #define SPECIFIER_HEXFLOAT 'a' #define SPECIFIER_HEXFLOAT_UPPER 'A' #define SPECIFIER_ERRNO 'm' #if TRIO_FEATURE_BINARY # define SPECIFIER_BINARY 'b' # define SPECIFIER_BINARY_UPPER 'B' #endif #if TRIO_FEATURE_USER_DEFINED # define SPECIFIER_USER_DEFINED_BEGIN '<' # define SPECIFIER_USER_DEFINED_END '>' # define SPECIFIER_USER_DEFINED_SEPARATOR ':' # define SPECIFIER_USER_DEFINED_EXTRA '|' #endif /* * QUALIFIERS: * * * Numbers = d,i,o,u,x,X * Float = a,A,e,E,f,F,g,G * String = s * Char = c * * * 9$ Position * Use the 9th parameter. 9 can be any number between 1 and * the maximal argument * * 9 Width * Set width to 9. 9 can be any number, but must not be postfixed * by '$' * * h Short * Numbers: * (unsigned) short int * * hh Short short * Numbers: * (unsigned) char * * l Long * Numbers: * (unsigned) long int * String: * as the S specifier * Char: * as the C specifier * * ll Long Long * Numbers: * (unsigned) long long int * * L Long Double * Float * long double * * # Alternative * Float: * Decimal-point is always present * String: * non-printable characters are handled as \number * * Spacing * * + Sign * * - Alignment * * . Precision * * * Parameter * print: use parameter * scan: no parameter (ignore) * * q Quad * * Z size_t * * w Widechar * * ' Thousands/quote * Numbers: * Integer part grouped in thousands * Binary numbers: * Number grouped in nibbles (4 bits) * String: * Quoted string * * j intmax_t * t prtdiff_t * z size_t * * ! Sticky * @ Parameter (for both print and scan) * * I n-bit Integer * Numbers: * The following options exists * I8 = 8-bit integer * I16 = 16-bit integer * I32 = 32-bit integer * I64 = 64-bit integer */ #define QUALIFIER_POSITION '$' #define QUALIFIER_SHORT 'h' #define QUALIFIER_LONG 'l' #define QUALIFIER_LONG_UPPER 'L' #define QUALIFIER_ALTERNATIVE '#' #define QUALIFIER_SPACE ' ' #define QUALIFIER_PLUS '+' #define QUALIFIER_MINUS '-' #define QUALIFIER_DOT '.' #define QUALIFIER_STAR '*' #define QUALIFIER_CIRCUMFLEX '^' /* For scanlists */ #define QUALIFIER_SIZE_T 'z' #define QUALIFIER_PTRDIFF_T 't' #define QUALIFIER_INTMAX_T 'j' #define QUALIFIER_QUAD 'q' #define QUALIFIER_SIZE_T_UPPER 'Z' #if TRIO_MISC # define QUALIFIER_WIDECHAR 'w' #endif #define QUALIFIER_FIXED_SIZE 'I' #define QUALIFIER_QUOTE '\'' #define QUALIFIER_STICKY '!' #define QUALIFIER_VARSIZE '&' /* This should remain undocumented */ #define QUALIFIER_ROUNDING_UPPER 'R' #if TRIO_EXTENSION # define QUALIFIER_PARAM '@' /* Experimental */ # define QUALIFIER_COLON ':' /* For scanlists */ # define QUALIFIER_EQUAL '=' /* For scanlists */ #endif /************************************************************************* * * Internal Structures * *************************************************************************/ /* Parameters */ typedef struct { /* An indication of which entry in the data union is used */ int type; /* The flags */ trio_flags_t flags; /* The width qualifier */ int width; /* The precision qualifier */ int precision; /* The base qualifier */ int base; /* Base from specifier */ int baseSpecifier; /* The size for the variable size qualifier */ int varsize; /* Offset of the first character of the specifier */ int beginOffset; /* Offset of the first character after the specifier */ int endOffset; /* Position in the argument list that this parameter refers to */ int position; /* The data from the argument list */ union { char *string; #if TRIO_FEATURE_WIDECHAR trio_wchar_t *wstring; #endif trio_pointer_t pointer; union { trio_intmax_t as_signed; trio_uintmax_t as_unsigned; } number; #if TRIO_FEATURE_FLOAT double doubleNumber; double *doublePointer; trio_long_double_t longdoubleNumber; trio_long_double_t *longdoublePointer; #endif int errorNumber; } data; #if TRIO_FEATURE_USER_DEFINED /* For the user-defined specifier */ union { char namespace[MAX_USER_NAME]; int handler; /* if flags & FLAGS_USER_DEFINED_PARAMETER */ } user_defined; char user_data[MAX_USER_DATA]; #endif } trio_parameter_t; /* Container for customized functions */ typedef struct { union { trio_outstream_t out; trio_instream_t in; } stream; trio_pointer_t closure; } trio_custom_t; /* General trio "class" */ typedef struct _trio_class_t { /* * The function to write characters to a stream. */ void (*OutStream) TRIO_PROTO((struct _trio_class_t *, int)); /* * The function to read characters from a stream. */ void (*InStream) TRIO_PROTO((struct _trio_class_t *, int *)); /* * The function to undo read characters from a stream. */ void (*UndoStream) TRIO_PROTO((struct _trio_class_t *)); /* * The current location in the stream. */ trio_pointer_t location; /* * The character currently being processed. */ int current; /* * The number of characters that would have been written/read * if there had been sufficient space. */ int processed; union { /* * The number of characters that are actually written. Processed and * committed will only differ for the *nprintf functions. */ int committed; /* * The number of look-ahead characters read. */ int cached; } actually; /* * The upper limit of characters that may be written/read. */ int max; /* * The last output error that was detected. */ int error; } trio_class_t; /* References (for user-defined callbacks) */ typedef struct _trio_reference_t { trio_class_t *data; trio_parameter_t *parameter; } trio_reference_t; #if TRIO_FEATURE_USER_DEFINED /* Registered entries (for user-defined callbacks) */ typedef struct _trio_userdef_t { struct _trio_userdef_t *next; trio_callback_t callback; char *name; } trio_userdef_t; #endif /************************************************************************* * * Internal Variables * *************************************************************************/ static TRIO_CONST char rcsid[] = "@(#)$Id$"; #if TRIO_FEATURE_FLOAT /* * Need this to workaround a parser bug in HP C/iX compiler that fails * to resolves macro definitions that includes type 'long double', * e.g: va_arg(arg_ptr, long double) */ # if defined(TRIO_PLATFORM_MPEIX) static TRIO_CONST trio_long_double_t ___dummy_long_double = 0; # endif #endif static TRIO_CONST char internalNullString[] = "(nil)"; #if defined(USE_LOCALE) static struct lconv *internalLocaleValues = NULL; #endif /* * UNIX98 says "in a locale where the radix character is not defined, * the radix character defaults to a period (.)" */ #if TRIO_FEATURE_FLOAT || TRIO_FEATURE_LOCALE || defined(USE_LOCALE) static int internalDecimalPointLength = 1; static char internalDecimalPoint = '.'; static char internalDecimalPointString[MAX_LOCALE_SEPARATOR_LENGTH + 1] = "."; #endif #if TRIO_FEATURE_QUOTE || TRIO_FEATURE_LOCALE || TRIO_EXTENSION static int internalThousandSeparatorLength = 1; static char internalThousandSeparator[MAX_LOCALE_SEPARATOR_LENGTH + 1] = ","; static char internalGrouping[MAX_LOCALE_GROUPS] = { (char)NO_GROUPING }; #endif static TRIO_CONST char internalDigitsLower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static TRIO_CONST char internalDigitsUpper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; #if TRIO_FEATURE_SCANF static BOOLEAN_T internalDigitsUnconverted = TRUE; static int internalDigitArray[128]; # if TRIO_EXTENSION static BOOLEAN_T internalCollationUnconverted = TRUE; static char internalCollationArray[MAX_CHARACTER_CLASS][MAX_CHARACTER_CLASS]; # endif #endif #if TRIO_FEATURE_USER_DEFINED static TRIO_VOLATILE trio_callback_t internalEnterCriticalRegion = NULL; static TRIO_VOLATILE trio_callback_t internalLeaveCriticalRegion = NULL; static trio_userdef_t *internalUserDef = NULL; #endif /************************************************************************* * * Internal Functions * ************************************************************************/ #if defined(TRIO_EMBED_NAN) # include "trionan.c" #endif #if defined(TRIO_EMBED_STRING) # include "triostr.c" #endif /************************************************************************* * TrioInitializeParameter * * Description: * Initialize a trio_parameter_t struct. */ TRIO_PRIVATE void TrioInitializeParameter TRIO_ARGS1((parameter), trio_parameter_t *parameter) { parameter->type = FORMAT_UNKNOWN; parameter->flags = 0; parameter->width = 0; parameter->precision = 0; parameter->base = 0; parameter->baseSpecifier = 0; parameter->varsize = 0; parameter->beginOffset = 0; parameter->endOffset = 0; parameter->position = 0; parameter->data.pointer = 0; #if TRIO_FEATURE_USER_DEFINED parameter->user_defined.handler = 0; parameter->user_data[0] = 0; #endif } /************************************************************************* * TrioCopyParameter * * Description: * Copies one trio_parameter_t struct to another. */ TRIO_PRIVATE void TrioCopyParameter TRIO_ARGS2((target, source), trio_parameter_t *target, TRIO_CONST trio_parameter_t *source) { #if TRIO_FEATURE_USER_DEFINED size_t i; #endif target->type = source->type; target->flags = source->flags; target->width = source->width; target->precision = source->precision; target->base = source->base; target->baseSpecifier = source->baseSpecifier; target->varsize = source->varsize; target->beginOffset = source->beginOffset; target->endOffset = source->endOffset; target->position = source->position; target->data = source->data; #if TRIO_FEATURE_USER_DEFINED target->user_defined = source->user_defined; for (i = 0U; i < sizeof(target->user_data); ++i) { if ((target->user_data[i] = source->user_data[i]) == NIL) break; } #endif } /************************************************************************* * TrioIsQualifier * * Description: * Remember to add all new qualifiers to this function. * QUALIFIER_POSITION must not be added. */ TRIO_PRIVATE BOOLEAN_T TrioIsQualifier TRIO_ARGS1((character), TRIO_CONST char character) { /* QUALIFIER_POSITION is not included */ switch (character) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case QUALIFIER_PLUS: case QUALIFIER_MINUS: case QUALIFIER_SPACE: case QUALIFIER_DOT: case QUALIFIER_STAR: case QUALIFIER_ALTERNATIVE: case QUALIFIER_SHORT: case QUALIFIER_LONG: case QUALIFIER_CIRCUMFLEX: case QUALIFIER_LONG_UPPER: case QUALIFIER_SIZE_T: case QUALIFIER_PTRDIFF_T: case QUALIFIER_INTMAX_T: case QUALIFIER_QUAD: case QUALIFIER_SIZE_T_UPPER: #if defined(QUALIFIER_WIDECHAR) case QUALIFIER_WIDECHAR: #endif case QUALIFIER_QUOTE: case QUALIFIER_STICKY: case QUALIFIER_VARSIZE: #if defined(QUALIFIER_PARAM) case QUALIFIER_PARAM: #endif case QUALIFIER_FIXED_SIZE: case QUALIFIER_ROUNDING_UPPER: return TRUE; default: return FALSE; } } /************************************************************************* * TrioSetLocale */ #if defined(USE_LOCALE) TRIO_PRIVATE void TrioSetLocale(TRIO_NOARGS) { internalLocaleValues = (struct lconv *)localeconv(); if (internalLocaleValues) { if ((internalLocaleValues->decimal_point) && (internalLocaleValues->decimal_point[0] != NIL)) { internalDecimalPointLength = trio_length(internalLocaleValues->decimal_point); if (internalDecimalPointLength == 1) { internalDecimalPoint = internalLocaleValues->decimal_point[0]; } else { internalDecimalPoint = NIL; trio_copy_max(internalDecimalPointString, sizeof(internalDecimalPointString), internalLocaleValues->decimal_point); } } # if TRIO_EXTENSION if ((internalLocaleValues->thousands_sep) && (internalLocaleValues->thousands_sep[0] != NIL)) { trio_copy_max(internalThousandSeparator, sizeof(internalThousandSeparator), internalLocaleValues->thousands_sep); internalThousandSeparatorLength = trio_length(internalThousandSeparator); } # endif # if TRIO_EXTENSION if ((internalLocaleValues->grouping) && (internalLocaleValues->grouping[0] != NIL)) { trio_copy_max(internalGrouping, sizeof(internalGrouping), internalLocaleValues->grouping); } # endif } } #endif /* defined(USE_LOCALE) */ #if TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE TRIO_PRIVATE int TrioCalcThousandSeparatorLength TRIO_ARGS1((digits), int digits) { int count = 0; int step = NO_GROUPING; char *groupingPointer = internalGrouping; while (digits > 0) { if (*groupingPointer == CHAR_MAX) { /* Disable grouping */ break; /* while */ } else if (*groupingPointer == 0) { /* Repeat last group */ if (step == NO_GROUPING) { /* Error in locale */ break; /* while */ } } else { step = *groupingPointer++; } if (digits > step) count += internalThousandSeparatorLength; digits -= step; } return count; } #endif /* TRIO_FEATURE_FLOAT && TRIO_FEATURE_QUOTE */ #if TRIO_FEATURE_QUOTE TRIO_PRIVATE BOOLEAN_T TrioFollowedBySeparator TRIO_ARGS1((position), int position) { int step = 0; char *groupingPointer = internalGrouping; position--; if (position == 0) return FALSE; while (position > 0) { if (*groupingPointer == CHAR_MAX) { /* Disable grouping */ break; /* while */ } else if (*groupingPointer != 0) { step = *groupingPointer++; } if (step == 0) break; position -= step; } return (position == 0); } #endif /* TRIO_FEATURE_QUOTE */ /************************************************************************* * TrioGetPosition * * Get the %n$ position. */ TRIO_PRIVATE int TrioGetPosition TRIO_ARGS2((format, offsetPointer), TRIO_CONST char *format, int *offsetPointer) { #if TRIO_FEATURE_POSITIONAL char *tmpformat; int number = 0; int offset = *offsetPointer; number = (int)trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL); offset = (int)(tmpformat - format); if ((number != 0) && (QUALIFIER_POSITION == format[offset++])) { *offsetPointer = offset; /* * number is decreased by 1, because n$ starts from 1, whereas * the array it is indexing starts from 0. */ return number - 1; } #endif return NO_POSITION; } /************************************************************************* * TrioFindNamespace * * Find registered user-defined specifier. * The prev argument is used for optimization only. */ #if TRIO_FEATURE_USER_DEFINED TRIO_PRIVATE trio_userdef_t * TrioFindNamespace TRIO_ARGS2((name, prev), TRIO_CONST char *name, trio_userdef_t **prev) { trio_userdef_t *def; if (internalEnterCriticalRegion) (void)internalEnterCriticalRegion(NULL); for (def = internalUserDef; def; def = def->next) { /* Case-sensitive string comparison */ if (trio_equal_case(def->name, name)) break; if (prev) *prev = def; } if (internalLeaveCriticalRegion) (void)internalLeaveCriticalRegion(NULL); return def; } #endif /************************************************************************* * TrioPower * * Description: * Calculate pow(base, exponent), where number and exponent are integers. */ #if TRIO_FEATURE_FLOAT TRIO_PRIVATE trio_long_double_t TrioPower TRIO_ARGS2((number, exponent), int number, int exponent) { trio_long_double_t result; if (number == 10) { switch (exponent) { /* Speed up calculation of common cases */ case 0: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E-1); break; case 1: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+0); break; case 2: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+1); break; case 3: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+2); break; case 4: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+3); break; case 5: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+4); break; case 6: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+5); break; case 7: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+6); break; case 8: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+7); break; case 9: result = (trio_long_double_t)number * TRIO_SUFFIX_LONG(1E+8); break; default: result = trio_pow((trio_long_double_t)number, (trio_long_double_t)exponent); break; } } else { return trio_pow((trio_long_double_t)number, (trio_long_double_t)exponent); } return result; } #endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * TrioLogarithm */ #if TRIO_FEATURE_FLOAT TRIO_PRIVATE trio_long_double_t TrioLogarithm TRIO_ARGS2((number, base), trio_long_double_t number, int base) { trio_long_double_t result; if (number <= 0.0) { /* xlC crashes on log(0) */ result = (number == 0.0) ? trio_ninf() : trio_nan(); } else { if (base == 10) { result = trio_log10(number); } else { result = trio_log10(number) / trio_log10((double)base); } } return result; } #endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * TrioLogarithmBase */ #if TRIO_FEATURE_FLOAT TRIO_PRIVATE double TrioLogarithmBase TRIO_ARGS1((base), int base) { switch (base) { case BASE_BINARY : return 1.0; case BASE_OCTAL : return 3.0; case BASE_DECIMAL: return 3.321928094887362345; case BASE_HEX : return 4.0; default : return TrioLogarithm((double)base, 2); } } #endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * TrioParseQualifiers * * Description: * Parse the qualifiers of a potential conversion specifier */ TRIO_PRIVATE int TrioParseQualifiers TRIO_ARGS4((type, format, offset, parameter), int type, TRIO_CONST char *format, int offset, trio_parameter_t *parameter) { char ch; int dots = 0; /* Count number of dots in modifier part */ char *tmpformat; parameter->beginOffset = offset - 1; parameter->flags = FLAGS_NEW; parameter->position = TrioGetPosition(format, &offset); /* Default values */ parameter->width = NO_WIDTH; parameter->precision = NO_PRECISION; parameter->base = NO_BASE; parameter->varsize = NO_SIZE; while (TrioIsQualifier(format[offset])) { ch = format[offset++]; switch (ch) { case QUALIFIER_SPACE: parameter->flags |= FLAGS_SPACE; break; case QUALIFIER_PLUS: parameter->flags |= FLAGS_SHOWSIGN; break; case QUALIFIER_MINUS: parameter->flags |= FLAGS_LEFTADJUST; parameter->flags &= ~FLAGS_NILPADDING; break; case QUALIFIER_ALTERNATIVE: parameter->flags |= FLAGS_ALTERNATIVE; break; case QUALIFIER_DOT: if (dots == 0) /* Precision */ { dots++; /* Skip if no precision */ if (QUALIFIER_DOT == format[offset]) break; /* After the first dot we have the precision */ parameter->flags |= FLAGS_PRECISION; if ((QUALIFIER_STAR == format[offset]) #if defined(QUALIFIER_PARAM) || (QUALIFIER_PARAM == format[offset]) #endif ) { offset++; parameter->flags |= FLAGS_PRECISION_PARAMETER; parameter->precision = TrioGetPosition(format, &offset); } else { parameter->precision = trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL); offset = (int)(tmpformat - format); } } else if (dots == 1) /* Base */ { dots++; /* After the second dot we have the base */ parameter->flags |= FLAGS_BASE; if ((QUALIFIER_STAR == format[offset]) #if defined(QUALIFIER_PARAM) || (QUALIFIER_PARAM == format[offset]) #endif ) { offset++; parameter->flags |= FLAGS_BASE_PARAMETER; parameter->base = TrioGetPosition(format, &offset); } else { parameter->base = trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL); if (parameter->base > MAX_BASE) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); offset = (int)(tmpformat - format); } } else { return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); } break; /* QUALIFIER_DOT */ #if defined(QUALIFIER_PARAM) case QUALIFIER_PARAM: parameter->type = TYPE_PRINT; /* FALLTHROUGH */ #endif case QUALIFIER_STAR: /* This has different meanings for print and scan */ if (TYPE_PRINT == type) { /* Read with from parameter */ int width = TrioGetPosition(format, &offset); parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER); if (NO_POSITION != width) parameter->width = width; /* else keep parameter->width = NO_WIDTH which != NO_POSITION */ } #if TRIO_FEATURE_SCANF else { /* Scan, but do not store result */ parameter->flags |= FLAGS_IGNORE; } #endif break; /* QUALIFIER_STAR */ case '0': if (! (parameter->flags & FLAGS_LEFTADJUST)) parameter->flags |= FLAGS_NILPADDING; /* FALLTHROUGH */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': parameter->flags |= FLAGS_WIDTH; /* * &format[offset - 1] is used to "rewind" the read * character from format */ parameter->width = trio_to_long(&format[offset - 1], &tmpformat, BASE_DECIMAL); offset = (int)(tmpformat - format); break; case QUALIFIER_SHORT: if (parameter->flags & FLAGS_SHORTSHORT) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); else if (parameter->flags & FLAGS_SHORT) parameter->flags |= FLAGS_SHORTSHORT; else parameter->flags |= FLAGS_SHORT; break; case QUALIFIER_LONG: if (parameter->flags & FLAGS_QUAD) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); else if (parameter->flags & FLAGS_LONG) parameter->flags |= FLAGS_QUAD; else parameter->flags |= FLAGS_LONG; break; #if TRIO_FEATURE_LONGDOUBLE case QUALIFIER_LONG_UPPER: parameter->flags |= FLAGS_LONGDOUBLE; break; #endif #if TRIO_FEATURE_SIZE_T case QUALIFIER_SIZE_T: parameter->flags |= FLAGS_SIZE_T; /* Modify flags for later truncation of number */ if (sizeof(size_t) == sizeof(trio_ulonglong_t)) parameter->flags |= FLAGS_QUAD; else if (sizeof(size_t) == sizeof(long)) parameter->flags |= FLAGS_LONG; break; #endif #if TRIO_FEATURE_PTRDIFF_T case QUALIFIER_PTRDIFF_T: parameter->flags |= FLAGS_PTRDIFF_T; if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t)) parameter->flags |= FLAGS_QUAD; else if (sizeof(ptrdiff_t) == sizeof(long)) parameter->flags |= FLAGS_LONG; break; #endif #if TRIO_FEATURE_INTMAX_T case QUALIFIER_INTMAX_T: parameter->flags |= FLAGS_INTMAX_T; if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t)) parameter->flags |= FLAGS_QUAD; else if (sizeof(trio_intmax_t) == sizeof(long)) parameter->flags |= FLAGS_LONG; break; #endif #if TRIO_FEATURE_QUAD case QUALIFIER_QUAD: parameter->flags |= FLAGS_QUAD; break; #endif #if TRIO_FEATURE_FIXED_SIZE case QUALIFIER_FIXED_SIZE: if (parameter->flags & FLAGS_FIXED_SIZE) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); if (parameter->flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE | FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER)) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); if ((format[offset] == '6') && (format[offset + 1] == '4')) { parameter->varsize = sizeof(trio_int64_t); offset += 2; } else if ((format[offset] == '3') && (format[offset + 1] == '2')) { parameter->varsize = sizeof(trio_int32_t); offset += 2; } else if ((format[offset] == '1') && (format[offset + 1] == '6')) { parameter->varsize = sizeof(trio_int16_t); offset += 2; } else if (format[offset] == '8') { parameter->varsize = sizeof(trio_int8_t); offset++; } else return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); parameter->flags |= FLAGS_FIXED_SIZE; break; #endif /* TRIO_FEATURE_FIXED_SIZE */ #if defined(QUALIFIER_WIDECHAR) case QUALIFIER_WIDECHAR: parameter->flags |= FLAGS_WIDECHAR; break; #endif #if TRIO_FEATURE_SIZE_T_UPPER case QUALIFIER_SIZE_T_UPPER: break; #endif #if TRIO_FEATURE_QUOTE case QUALIFIER_QUOTE: parameter->flags |= FLAGS_QUOTE; break; #endif #if TRIO_FEATURE_STICKY case QUALIFIER_STICKY: parameter->flags |= FLAGS_STICKY; break; #endif #if TRIO_FEATURE_VARSIZE case QUALIFIER_VARSIZE: parameter->flags |= FLAGS_VARSIZE_PARAMETER; break; #endif #if TRIO_FEATURE_ROUNDING case QUALIFIER_ROUNDING_UPPER: parameter->flags |= FLAGS_ROUNDING; break; #endif default: /* Bail out completely to make the error more obvious */ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); } } /* while qualifier */ parameter->endOffset = offset; return 0; } /************************************************************************* * TrioParseSpecifier * * Description: * Parse the specifier part of a potential conversion specifier */ TRIO_PRIVATE int TrioParseSpecifier TRIO_ARGS4((type, format, offset, parameter), int type, TRIO_CONST char *format, int offset, trio_parameter_t *parameter) { parameter->baseSpecifier = NO_BASE; switch (format[offset++]) { #if defined(SPECIFIER_CHAR_UPPER) case SPECIFIER_CHAR_UPPER: parameter->flags |= FLAGS_WIDECHAR; /* FALLTHROUGH */ #endif case SPECIFIER_CHAR: if (parameter->flags & FLAGS_LONG) parameter->flags |= FLAGS_WIDECHAR; else if (parameter->flags & FLAGS_SHORT) parameter->flags &= ~FLAGS_WIDECHAR; parameter->type = FORMAT_CHAR; break; #if defined(SPECIFIER_STRING_UPPER) case SPECIFIER_STRING_UPPER: parameter->flags |= FLAGS_WIDECHAR; /* FALLTHROUGH */ #endif case SPECIFIER_STRING: if (parameter->flags & FLAGS_LONG) parameter->flags |= FLAGS_WIDECHAR; else if (parameter->flags & FLAGS_SHORT) parameter->flags &= ~FLAGS_WIDECHAR; parameter->type = FORMAT_STRING; break; #if defined(SPECIFIER_GROUP) case SPECIFIER_GROUP: if (TYPE_SCAN == type) { int depth = 1; parameter->type = FORMAT_GROUP; if (format[offset] == QUALIFIER_CIRCUMFLEX) offset++; if (format[offset] == SPECIFIER_UNGROUP) offset++; if (format[offset] == QUALIFIER_MINUS) offset++; /* Skip nested brackets */ while (format[offset] != NIL) { if (format[offset] == SPECIFIER_GROUP) { depth++; } else if (format[offset] == SPECIFIER_UNGROUP) { if (--depth <= 0) { offset++; break; } } offset++; } } break; #endif /* defined(SPECIFIER_GROUP) */ case SPECIFIER_INTEGER: parameter->type = FORMAT_INT; break; case SPECIFIER_UNSIGNED: parameter->flags |= FLAGS_UNSIGNED; parameter->type = FORMAT_INT; break; case SPECIFIER_DECIMAL: parameter->baseSpecifier = BASE_DECIMAL; parameter->type = FORMAT_INT; break; case SPECIFIER_OCTAL: parameter->flags |= FLAGS_UNSIGNED; parameter->baseSpecifier = BASE_OCTAL; parameter->type = FORMAT_INT; break; #if TRIO_FEATURE_BINARY case SPECIFIER_BINARY_UPPER: parameter->flags |= FLAGS_UPPER; /* FALLTHROUGH */ case SPECIFIER_BINARY: parameter->flags |= FLAGS_NILPADDING; parameter->baseSpecifier = BASE_BINARY; parameter->type = FORMAT_INT; break; #endif case SPECIFIER_HEX_UPPER: parameter->flags |= FLAGS_UPPER; /* FALLTHROUGH */ case SPECIFIER_HEX: parameter->flags |= FLAGS_UNSIGNED; parameter->baseSpecifier = BASE_HEX; parameter->type = FORMAT_INT; break; #if defined(SPECIFIER_FLOAT_E) # if defined(SPECIFIER_FLOAT_E_UPPER) case SPECIFIER_FLOAT_E_UPPER: parameter->flags |= FLAGS_UPPER; /* FALLTHROUGH */ # endif case SPECIFIER_FLOAT_E: parameter->flags |= FLAGS_FLOAT_E; parameter->type = FORMAT_DOUBLE; break; #endif #if defined(SPECIFIER_FLOAT_G) # if defined(SPECIFIER_FLOAT_G_UPPER) case SPECIFIER_FLOAT_G_UPPER: parameter->flags |= FLAGS_UPPER; /* FALLTHROUGH */ # endif case SPECIFIER_FLOAT_G: parameter->flags |= FLAGS_FLOAT_G; parameter->type = FORMAT_DOUBLE; break; #endif #if defined(SPECIFIER_FLOAT_F) # if defined(SPECIFIER_FLOAT_F_UPPER) case SPECIFIER_FLOAT_F_UPPER: parameter->flags |= FLAGS_UPPER; /* FALLTHROUGH */ # endif case SPECIFIER_FLOAT_F: parameter->type = FORMAT_DOUBLE; break; #endif #if defined(TRIO_COMPILER_VISUALC) # pragma warning( push ) # pragma warning( disable : 4127 ) /* Conditional expression is constant */ #endif case SPECIFIER_POINTER: if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t)) parameter->flags |= FLAGS_QUAD; else if (sizeof(trio_pointer_t) == sizeof(long)) parameter->flags |= FLAGS_LONG; parameter->type = FORMAT_POINTER; break; #if defined(TRIO_COMPILER_VISUALC) # pragma warning( pop ) #endif case SPECIFIER_COUNT: parameter->type = FORMAT_COUNT; break; #if TRIO_FEATURE_HEXFLOAT case SPECIFIER_HEXFLOAT_UPPER: parameter->flags |= FLAGS_UPPER; /* FALLTHROUGH */ case SPECIFIER_HEXFLOAT: parameter->baseSpecifier = BASE_HEX; parameter->type = FORMAT_DOUBLE; break; #endif #if TRIO_FEATURE_ERRNO case SPECIFIER_ERRNO: parameter->type = FORMAT_ERRNO; break; #endif #if TRIO_FEATURE_USER_DEFINED case SPECIFIER_USER_DEFINED_BEGIN: { unsigned int max; int without_namespace = TRUE; char* tmpformat = (char *)&format[offset]; int ch; parameter->type = FORMAT_USER_DEFINED; parameter->user_defined.namespace[0] = NIL; while ((ch = format[offset]) != NIL) { offset++; if ((ch == SPECIFIER_USER_DEFINED_END) || (ch == SPECIFIER_USER_DEFINED_EXTRA)) { if (without_namespace) /* No namespace, handler will be passed as an argument */ parameter->flags |= FLAGS_USER_DEFINED_PARAMETER; /* Copy the user data */ max = (unsigned int)(&format[offset] - tmpformat); if (max > MAX_USER_DATA) max = MAX_USER_DATA; trio_copy_max(parameter->user_data, max, tmpformat); /* Skip extra data (which is only there to keep the compiler happy) */ while ((ch != NIL) && (ch != SPECIFIER_USER_DEFINED_END)) ch = format[offset++]; break; /* while */ } if (ch == SPECIFIER_USER_DEFINED_SEPARATOR) { without_namespace = FALSE; /* Copy the namespace for later looking-up */ max = (int)(&format[offset] - tmpformat); if (max > MAX_USER_NAME) max = MAX_USER_NAME; trio_copy_max(parameter->user_defined.namespace, max, tmpformat); tmpformat = (char *)&format[offset]; } } if (ch != SPECIFIER_USER_DEFINED_END) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); } break; #endif /* TRIO_FEATURE_USER_DEFINED */ default: /* Bail out completely to make the error more obvious */ return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); } parameter->endOffset = offset; return 0; } /************************************************************************* * TrioParse * * Description: * Parse the format string */ TRIO_PRIVATE int TrioParse TRIO_ARGS6((type, format, parameters, arglist, argfunc, argarray), int type, TRIO_CONST char *format, trio_parameter_t *parameters, va_list arglist, trio_argfunc_t argfunc, trio_pointer_t *argarray) { /* Count the number of times a parameter is referenced */ unsigned short usedEntries[MAX_PARAMETERS]; /* Parameter counters */ int parameterPosition; int maxParam = -1; /* Utility variables */ int offset; /* Offset into formatting string */ BOOLEAN_T positional; /* Does the specifier have a positional? */ #if TRIO_FEATURE_STICKY BOOLEAN_T gotSticky = FALSE; /* Are there any sticky modifiers at all? */ #endif /* * indices specifies the order in which the parameters must be * read from the va_args (this is necessary to handle positionals) */ int indices[MAX_PARAMETERS]; int pos = 0; /* Various variables */ #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) int charlen; #endif int save_errno; int i = -1; int num; trio_parameter_t workParameter; int status; /* Both must be set or none must be set */ assert(((argfunc == NULL) && (argarray == NULL)) || ((argfunc != NULL) && (argarray != NULL))); /* * The 'parameters' array is not initialized, but we need to * know which entries we have used. */ memset(usedEntries, 0, sizeof(usedEntries)); save_errno = errno; offset = 0; parameterPosition = 0; #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) charlen = mblen(NULL, 0); #endif while (format[offset]) { TrioInitializeParameter(&workParameter); #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) if (! isascii(format[offset])) { /* * Multibyte characters cannot be legal specifiers or * modifiers, so we skip over them. */ charlen = mblen(&format[offset], MB_LEN_MAX); offset += (charlen > 0) ? charlen : 1; continue; /* while */ } #endif /* TRIO_COMPILER_SUPPORTS_MULTIBYTE */ switch(format[offset++]) { case CHAR_IDENTIFIER: { if (CHAR_IDENTIFIER == format[offset]) { /* skip double "%" */ offset++; continue; /* while */ } status = TrioParseQualifiers(type, format, offset, &workParameter); if (status < 0) return status; /* Return qualifier syntax error */ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter); if (status < 0) return status; /* Return specifier syntax error */ } break; #if TRIO_EXTENSION case CHAR_ALT_IDENTIFIER: { status = TrioParseQualifiers(type, format, offset, &workParameter); if (status < 0) continue; /* False alert, not a user defined specifier */ status = TrioParseSpecifier(type, format, workParameter.endOffset, &workParameter); if ((status < 0) || (FORMAT_USER_DEFINED != workParameter.type)) continue; /* False alert, not a user defined specifier */ } break; #endif default: continue; /* while */ } /* now handle the parsed conversion specification */ positional = (NO_POSITION != workParameter.position); /* * Parameters only need the type and value. The value is * read later. */ if (workParameter.flags & FLAGS_WIDTH_PARAMETER) { if (workParameter.width == NO_WIDTH) { workParameter.width = parameterPosition++; } else { if (! positional) workParameter.position = workParameter.width + 1; } usedEntries[workParameter.width] += 1; if (workParameter.width > maxParam) maxParam = workParameter.width; parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[workParameter.width] = pos; workParameter.width = pos++; } if (workParameter.flags & FLAGS_PRECISION_PARAMETER) { if (workParameter.precision == NO_PRECISION) { workParameter.precision = parameterPosition++; } else { if (! positional) workParameter.position = workParameter.precision + 1; } usedEntries[workParameter.precision] += 1; if (workParameter.precision > maxParam) maxParam = workParameter.precision; parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[workParameter.precision] = pos; workParameter.precision = pos++; } if (workParameter.flags & FLAGS_BASE_PARAMETER) { if (workParameter.base == NO_BASE) { workParameter.base = parameterPosition++; } else { if (! positional) workParameter.position = workParameter.base + 1; } usedEntries[workParameter.base] += 1; if (workParameter.base > maxParam) maxParam = workParameter.base; parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[workParameter.base] = pos; workParameter.base = pos++; } #if TRIO_FEATURE_VARSIZE if (workParameter.flags & FLAGS_VARSIZE_PARAMETER) { workParameter.varsize = parameterPosition++; usedEntries[workParameter.varsize] += 1; if (workParameter.varsize > maxParam) maxParam = workParameter.varsize; parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = 0; indices[workParameter.varsize] = pos; workParameter.varsize = pos++; } #endif #if TRIO_FEATURE_USER_DEFINED if (workParameter.flags & FLAGS_USER_DEFINED_PARAMETER) { workParameter.user_defined.handler = parameterPosition++; usedEntries[workParameter.user_defined.handler] += 1; if (workParameter.user_defined.handler > maxParam) maxParam = workParameter.user_defined.handler; parameters[pos].type = FORMAT_PARAMETER; parameters[pos].flags = FLAGS_USER_DEFINED; indices[workParameter.user_defined.handler] = pos; workParameter.user_defined.handler = pos++; } #endif if (NO_POSITION == workParameter.position) { workParameter.position = parameterPosition++; } if (workParameter.position > maxParam) maxParam = workParameter.position; if (workParameter.position >= MAX_PARAMETERS) { /* Bail out completely to make the error more obvious */ return TRIO_ERROR_RETURN(TRIO_ETOOMANY, offset); } indices[workParameter.position] = pos; /* Count the number of times this entry has been used */ usedEntries[workParameter.position] += 1; /* Find last sticky parameters */ #if TRIO_FEATURE_STICKY if (workParameter.flags & FLAGS_STICKY) { gotSticky = TRUE; } else if (gotSticky) { for (i = pos - 1; i >= 0; i--) { if (parameters[i].type == FORMAT_PARAMETER) continue; if ((parameters[i].flags & FLAGS_STICKY) && (parameters[i].type == workParameter.type)) { /* Do not overwrite current qualifiers */ workParameter.flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY); if (workParameter.width == NO_WIDTH) workParameter.width = parameters[i].width; if (workParameter.precision == NO_PRECISION) workParameter.precision = parameters[i].precision; if (workParameter.base == NO_BASE) workParameter.base = parameters[i].base; break; } } } #endif if (workParameter.base == NO_BASE) workParameter.base = BASE_DECIMAL; offset = workParameter.endOffset; TrioCopyParameter(¶meters[pos++], &workParameter); } /* while format characters left */ parameters[pos].type = FORMAT_SENTINEL; /* end parameter array with sentinel */ parameters[pos].beginOffset = offset; for (num = 0; num <= maxParam; num++) { if (usedEntries[num] != 1) { if (usedEntries[num] == 0) /* gap detected */ return TRIO_ERROR_RETURN(TRIO_EGAP, num); else /* double references detected */ return TRIO_ERROR_RETURN(TRIO_EDBLREF, num); } i = indices[num]; /* * FORMAT_PARAMETERS are only present if they must be read, * so it makes no sense to check the ignore flag (besides, * the flags variable is not set for that particular type) */ if ((parameters[i].type != FORMAT_PARAMETER) && (parameters[i].flags & FLAGS_IGNORE)) continue; /* for all arguments */ /* * The stack arguments are read according to ANSI C89 * default argument promotions: * * char = int * short = int * unsigned char = unsigned int * unsigned short = unsigned int * float = double * * In addition to the ANSI C89 these types are read (the * default argument promotions of C99 has not been * considered yet) * * long long * long double * size_t * ptrdiff_t * intmax_t */ switch (parameters[i].type) { case FORMAT_GROUP: case FORMAT_STRING: #if TRIO_FEATURE_WIDECHAR if (parameters[i].flags & FLAGS_WIDECHAR) { parameters[i].data.wstring = (argfunc == NULL) ? va_arg(arglist, trio_wchar_t *) : (trio_wchar_t *)(argfunc(argarray, num, TRIO_TYPE_PWCHAR)); } else #endif { parameters[i].data.string = (argfunc == NULL) ? va_arg(arglist, char *) : (char *)(argfunc(argarray, num, TRIO_TYPE_PCHAR)); } break; #if TRIO_FEATURE_USER_DEFINED case FORMAT_USER_DEFINED: #endif case FORMAT_POINTER: case FORMAT_COUNT: case FORMAT_UNKNOWN: parameters[i].data.pointer = (argfunc == NULL) ? va_arg(arglist, trio_pointer_t ) : argfunc(argarray, num, TRIO_TYPE_POINTER); break; case FORMAT_CHAR: case FORMAT_INT: #if TRIO_FEATURE_SCANF if (TYPE_SCAN == type) { if (argfunc == NULL) parameters[i].data.pointer = (trio_pointer_t)va_arg(arglist, trio_pointer_t); else { if (parameters[i].type == FORMAT_CHAR) parameters[i].data.pointer = (trio_pointer_t)((char *)argfunc(argarray, num, TRIO_TYPE_CHAR)); else if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.pointer = (trio_pointer_t)((short *)argfunc(argarray, num, TRIO_TYPE_SHORT)); else parameters[i].data.pointer = (trio_pointer_t)((int *)argfunc(argarray, num, TRIO_TYPE_INT)); } } else #endif /* TRIO_FEATURE_SCANF */ { #if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE if (parameters[i].flags & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE)) { int varsize; if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER) { /* * Variable sizes are mapped onto the fixed sizes, in * accordance with integer promotion. * * Please note that this may not be portable, as we * only guess the size, not the layout of the numbers. * For example, if int is little-endian, and long is * big-endian, then this will fail. */ varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned; } else { /* Used for the I modifiers */ varsize = parameters[i].varsize; } parameters[i].flags &= ~FLAGS_ALL_VARSIZES; if (varsize <= (int)sizeof(int)) ; else if (varsize <= (int)sizeof(long)) parameters[i].flags |= FLAGS_LONG; #if TRIO_FEATURE_INTMAX_T else if (varsize <= (int)sizeof(trio_longlong_t)) parameters[i].flags |= FLAGS_QUAD; else parameters[i].flags |= FLAGS_INTMAX_T; #else else parameters[i].flags |= FLAGS_QUAD; #endif } #endif /* TRIO_FEATURE_VARSIZE */ #if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER if (parameters[i].flags & FLAGS_SIZE_T) parameters[i].data.number.as_unsigned = (argfunc == NULL) ? (trio_uintmax_t)va_arg(arglist, size_t) : (trio_uintmax_t)(*((size_t *)argfunc(argarray, num, TRIO_TYPE_SIZE))); else #endif #if TRIO_FEATURE_PTRDIFF_T if (parameters[i].flags & FLAGS_PTRDIFF_T) parameters[i].data.number.as_unsigned = (argfunc == NULL) ? (trio_uintmax_t)va_arg(arglist, ptrdiff_t) : (trio_uintmax_t)(*((ptrdiff_t *)argfunc(argarray, num, TRIO_TYPE_PTRDIFF))); else #endif #if TRIO_FEATURE_INTMAX_T if (parameters[i].flags & FLAGS_INTMAX_T) parameters[i].data.number.as_unsigned = (argfunc == NULL) ? (trio_uintmax_t)va_arg(arglist, trio_intmax_t) : (trio_uintmax_t)(*((trio_intmax_t *)argfunc(argarray, num, TRIO_TYPE_UINTMAX))); else #endif if (parameters[i].flags & FLAGS_QUAD) parameters[i].data.number.as_unsigned = (argfunc == NULL) ? (trio_uintmax_t)va_arg(arglist, trio_ulonglong_t) : (trio_uintmax_t)(*((trio_ulonglong_t *)argfunc(argarray, num, TRIO_TYPE_ULONGLONG))); else if (parameters[i].flags & FLAGS_LONG) parameters[i].data.number.as_unsigned = (argfunc == NULL) ? (trio_uintmax_t)va_arg(arglist, long) : (trio_uintmax_t)(*((long *)argfunc(argarray, num, TRIO_TYPE_LONG))); else { if (argfunc == NULL) parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(arglist, int); else { if (parameters[i].type == FORMAT_CHAR) parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argfunc(argarray, num, TRIO_TYPE_CHAR))); else if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argfunc(argarray, num, TRIO_TYPE_SHORT))); else parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argfunc(argarray, num, TRIO_TYPE_INT))); } } } break; case FORMAT_PARAMETER: /* * The parameter for the user-defined specifier is a pointer, * whereas the rest (width, precision, base) uses an integer. */ if (parameters[i].flags & FLAGS_USER_DEFINED) parameters[i].data.pointer = (argfunc == NULL) ? va_arg(arglist, trio_pointer_t ) : argfunc(argarray, num, TRIO_TYPE_POINTER); else parameters[i].data.number.as_unsigned = (argfunc == NULL) ? (trio_uintmax_t)va_arg(arglist, int) : (trio_uintmax_t)(*((int *)argfunc(argarray, num, TRIO_TYPE_INT))); break; #if TRIO_FEATURE_FLOAT case FORMAT_DOUBLE: # if TRIO_FEATURE_SCANF if (TYPE_SCAN == type) { if (parameters[i].flags & FLAGS_LONGDOUBLE) parameters[i].data.longdoublePointer = (argfunc == NULL) ? va_arg(arglist, trio_long_double_t *) : (trio_long_double_t *)argfunc(argarray, num, TRIO_TYPE_LONGDOUBLE); else { if (parameters[i].flags & FLAGS_LONG) parameters[i].data.doublePointer = (argfunc == NULL) ? va_arg(arglist, double *) : (double *)argfunc(argarray, num, TRIO_TYPE_DOUBLE); else parameters[i].data.doublePointer = (argfunc == NULL) ? (double *)va_arg(arglist, float *) : (double *)argfunc(argarray, num, TRIO_TYPE_DOUBLE); } } else # endif /* TRIO_FEATURE_SCANF */ { if (parameters[i].flags & FLAGS_LONGDOUBLE) parameters[i].data.longdoubleNumber = (argfunc == NULL) ? va_arg(arglist, trio_long_double_t) : (trio_long_double_t)(*((trio_long_double_t *)argfunc(argarray, num, TRIO_TYPE_LONGDOUBLE))); else { if (argfunc == NULL) parameters[i].data.longdoubleNumber = (trio_long_double_t)va_arg(arglist, double); else { if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.longdoubleNumber = (trio_long_double_t)(*((float *)argfunc(argarray, num, TRIO_TYPE_FLOAT))); else parameters[i].data.longdoubleNumber = (trio_long_double_t)(*((double *)argfunc(argarray, num, TRIO_TYPE_DOUBLE))); } } } break; #endif /* TRIO_FEATURE_FLOAT */ #if TRIO_FEATURE_ERRNO case FORMAT_ERRNO: parameters[i].data.errorNumber = save_errno; break; #endif default: break; } } /* for all specifiers */ return num; } /************************************************************************* * * FORMATTING * ************************************************************************/ /************************************************************************* * TrioWriteNumber * * Description: * Output a number. * The complexity of this function is a result of the complexity * of the dependencies of the flags. */ TRIO_PRIVATE void TrioWriteNumber TRIO_ARGS6((self, number, flags, width, precision, base), trio_class_t *self, trio_uintmax_t number, trio_flags_t flags, int width, int precision, int base) { BOOLEAN_T isNegative; BOOLEAN_T isNumberZero; BOOLEAN_T isPrecisionZero; BOOLEAN_T ignoreNumber; char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1]; char *bufferend; char *pointer; TRIO_CONST char *digits; int i; #if TRIO_FEATURE_QUOTE int length; char *p; #endif int count; int digitOffset; assert(VALID(self)); assert(VALID(self->OutStream)); assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; if (base == NO_BASE) base = BASE_DECIMAL; isNumberZero = (number == 0); isPrecisionZero = (precision == 0); ignoreNumber = (isNumberZero && isPrecisionZero && !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL))); if (flags & FLAGS_UNSIGNED) { isNegative = FALSE; flags &= ~FLAGS_SHOWSIGN; } else { isNegative = ((trio_intmax_t)number < 0); if (isNegative) number = -((trio_intmax_t)number); } if (flags & FLAGS_QUAD) number &= (trio_ulonglong_t)-1; else if (flags & FLAGS_LONG) number &= (unsigned long)-1; else number &= (unsigned int)-1; /* Build number */ pointer = bufferend = &buffer[sizeof(buffer) - 1]; *pointer-- = NIL; for (i = 1; i < (int)sizeof(buffer); i++) { digitOffset = number % base; *pointer-- = digits[digitOffset]; number /= base; if (number == 0) break; #if TRIO_FEATURE_QUOTE if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1)) { /* * We are building the number from the least significant * to the most significant digit, so we have to copy the * thousand separator backwards */ length = internalThousandSeparatorLength; if (((int)(pointer - buffer) - length) > 0) { p = &internalThousandSeparator[length - 1]; while (length-- > 0) *pointer-- = *p--; } } #endif } if (! ignoreNumber) { /* Adjust width */ width -= (bufferend - pointer) - 1; } /* Adjust precision */ if (NO_PRECISION != precision) { precision -= (bufferend - pointer) - 1; if (precision < 0) precision = 0; flags |= FLAGS_NILPADDING; } /* Calculate padding */ count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION))) ? precision : 0; /* Adjust width further */ if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) width--; if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) { switch (base) { case BASE_BINARY: case BASE_HEX: width -= 2; break; case BASE_OCTAL: if (!(flags & FLAGS_NILPADDING) || (count == 0)) width--; break; default: break; } } /* Output prefixes spaces if needed */ if (! ((flags & FLAGS_LEFTADJUST) || ((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION)))) { while (width-- > count) self->OutStream(self, CHAR_ADJUST); } /* width has been adjusted for signs and alternatives */ if (isNegative) self->OutStream(self, '-'); else if (flags & FLAGS_SHOWSIGN) self->OutStream(self, '+'); else if (flags & FLAGS_SPACE) self->OutStream(self, ' '); /* Prefix is not written when the value is zero */ if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero) { switch (base) { case BASE_BINARY: self->OutStream(self, '0'); self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b'); break; case BASE_OCTAL: if (!(flags & FLAGS_NILPADDING) || (count == 0)) self->OutStream(self, '0'); break; case BASE_HEX: self->OutStream(self, '0'); self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); break; default: break; } /* switch base */ } /* Output prefixed zero padding if needed */ if (flags & FLAGS_NILPADDING) { if (precision == NO_PRECISION) precision = width; while (precision-- > 0) { self->OutStream(self, '0'); width--; } } if (! ignoreNumber) { /* Output the number itself */ while (*(++pointer)) { self->OutStream(self, *pointer); } } /* Output trailing spaces if needed */ if (flags & FLAGS_LEFTADJUST) { while (width-- > 0) self->OutStream(self, CHAR_ADJUST); } } /************************************************************************* * TrioWriteStringCharacter * * Description: * Output a single character of a string */ TRIO_PRIVATE void TrioWriteStringCharacter TRIO_ARGS3((self, ch, flags), trio_class_t *self, int ch, trio_flags_t flags) { if (flags & FLAGS_ALTERNATIVE) { if (! isprint(ch)) { /* * Non-printable characters are converted to C escapes or * \number, if no C escape exists. */ self->OutStream(self, CHAR_BACKSLASH); switch (ch) { case '\007': self->OutStream(self, 'a'); break; case '\b': self->OutStream(self, 'b'); break; case '\f': self->OutStream(self, 'f'); break; case '\n': self->OutStream(self, 'n'); break; case '\r': self->OutStream(self, 'r'); break; case '\t': self->OutStream(self, 't'); break; case '\v': self->OutStream(self, 'v'); break; case '\\': self->OutStream(self, '\\'); break; default: self->OutStream(self, 'x'); TrioWriteNumber(self, (trio_uintmax_t)ch, FLAGS_UNSIGNED | FLAGS_NILPADDING, 2, 2, BASE_HEX); break; } } else if (ch == CHAR_BACKSLASH) { self->OutStream(self, CHAR_BACKSLASH); self->OutStream(self, CHAR_BACKSLASH); } else { self->OutStream(self, ch); } } else { self->OutStream(self, ch); } } /************************************************************************* * TrioWriteString * * Description: * Output a string */ TRIO_PRIVATE void TrioWriteString TRIO_ARGS5((self, string, flags, width, precision), trio_class_t *self, TRIO_CONST char *string, trio_flags_t flags, int width, int precision) { int length; int ch; assert(VALID(self)); assert(VALID(self->OutStream)); if (string == NULL) { string = internalNullString; length = sizeof(internalNullString) - 1; #if TRIO_FEATURE_QUOTE /* Disable quoting for the null pointer */ flags &= (~FLAGS_QUOTE); #endif width = 0; } else { if (precision == 0) { length = trio_length(string); } else { length = trio_length_max(string, precision); } } if ((NO_PRECISION != precision) && (precision < length)) { length = precision; } width -= length; #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) self->OutStream(self, CHAR_QUOTE); #endif if (! (flags & FLAGS_LEFTADJUST)) { while (width-- > 0) self->OutStream(self, CHAR_ADJUST); } while (length-- > 0) { /* The ctype parameters must be an unsigned char (or EOF) */ ch = (int)((unsigned char)(*string++)); TrioWriteStringCharacter(self, ch, flags); } if (flags & FLAGS_LEFTADJUST) { while (width-- > 0) self->OutStream(self, CHAR_ADJUST); } #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) self->OutStream(self, CHAR_QUOTE); #endif } /************************************************************************* * TrioWriteWideStringCharacter * * Description: * Output a wide string as a multi-byte sequence */ #if TRIO_FEATURE_WIDECHAR TRIO_PRIVATE int TrioWriteWideStringCharacter TRIO_ARGS4((self, wch, flags, width), trio_class_t *self, trio_wchar_t wch, trio_flags_t flags, int width) { int size; int i; int ch; char *string; char buffer[MB_LEN_MAX + 1]; if (width == NO_WIDTH) width = sizeof(buffer); size = wctomb(buffer, wch); if ((size <= 0) || (size > width) || (buffer[0] == NIL)) return 0; string = buffer; i = size; while ((width >= i) && (width-- > 0) && (i-- > 0)) { /* The ctype parameters must be an unsigned char (or EOF) */ ch = (int)((unsigned char)(*string++)); TrioWriteStringCharacter(self, ch, flags); } return size; } #endif /* TRIO_FEATURE_WIDECHAR */ /************************************************************************* * TrioWriteWideString * * Description: * Output a wide character string as a multi-byte string */ #if TRIO_FEATURE_WIDECHAR TRIO_PRIVATE void TrioWriteWideString TRIO_ARGS5((self, wstring, flags, width, precision), trio_class_t *self, TRIO_CONST trio_wchar_t *wstring, trio_flags_t flags, int width, int precision) { int length; int size; assert(VALID(self)); assert(VALID(self->OutStream)); #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) /* Required by TrioWriteWideStringCharacter */ (void)mblen(NULL, 0); #endif if (wstring == NULL) { TrioWriteString(self, NULL, flags, width, precision); return; } if (NO_PRECISION == precision) { length = INT_MAX; } else { length = precision; width -= length; } #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) self->OutStream(self, CHAR_QUOTE); #endif if (! (flags & FLAGS_LEFTADJUST)) { while (width-- > 0) self->OutStream(self, CHAR_ADJUST); } while (length > 0) { size = TrioWriteWideStringCharacter(self, *wstring++, flags, length); if (size == 0) break; /* while */ length -= size; } if (flags & FLAGS_LEFTADJUST) { while (width-- > 0) self->OutStream(self, CHAR_ADJUST); } #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) self->OutStream(self, CHAR_QUOTE); #endif } #endif /* TRIO_FEATURE_WIDECHAR */ /************************************************************************* * TrioWriteDouble * * http://wwwold.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_211.htm * * "5.2.4.2.2 paragraph #4 * * The accuracy [...] is implementation defined, as is the accuracy * of the conversion between floating-point internal representations * and string representations performed by the libray routine in * " */ /* FIXME: handle all instances of constant long-double number (L) * and *l() math functions. */ #if TRIO_FEATURE_FLOAT TRIO_PRIVATE void TrioWriteDouble TRIO_ARGS6((self, number, flags, width, precision, base), trio_class_t *self, trio_long_double_t number, trio_flags_t flags, int width, int precision, int base) { trio_long_double_t integerNumber; trio_long_double_t fractionNumber; trio_long_double_t workNumber; int integerDigits; int fractionDigits; int exponentDigits; int workDigits; int baseDigits; int integerThreshold; int fractionThreshold; int expectedWidth; int exponent = 0; unsigned int uExponent = 0; int exponentBase; trio_long_double_t dblBase; trio_long_double_t dblFractionBase; trio_long_double_t integerAdjust; trio_long_double_t fractionAdjust; trio_long_double_t workFractionNumber; trio_long_double_t workFractionAdjust; int fractionDigitsInspect; BOOLEAN_T isNegative; BOOLEAN_T isExponentNegative = FALSE; BOOLEAN_T requireTwoDigitExponent; BOOLEAN_T isHex; TRIO_CONST char *digits; # if TRIO_FEATURE_QUOTE char *groupingPointer; # endif int i; int offset; BOOLEAN_T hasOnlyZeroes; int leadingFractionZeroes = -1; register int trailingZeroes; BOOLEAN_T keepTrailingZeroes; BOOLEAN_T keepDecimalPoint; trio_long_double_t epsilon; trio_long_double_t epsilonCorrection; BOOLEAN_T adjustNumber = FALSE; assert(VALID(self)); assert(VALID(self->OutStream)); assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE)); /* Determine sign and look for special quantities */ switch (trio_fpclassify_and_signbit(number, &isNegative)) { case TRIO_FP_NAN: TrioWriteString(self, (flags & FLAGS_UPPER) ? NAN_UPPER : NAN_LOWER, flags, width, precision); return; case TRIO_FP_INFINITE: if (isNegative) { /* Negative infinity */ TrioWriteString(self, (flags & FLAGS_UPPER) ? "-" INFINITE_UPPER : "-" INFINITE_LOWER, flags, width, precision); return; } else { /* Positive infinity */ TrioWriteString(self, (flags & FLAGS_UPPER) ? INFINITE_UPPER : INFINITE_LOWER, flags, width, precision); return; } default: /* Finitude */ break; } /* Normal numbers */ if (flags & FLAGS_LONGDOUBLE) { baseDigits = (base == 10) ? LDBL_DIG : (int)trio_floor(LDBL_MANT_DIG / TrioLogarithmBase(base)); epsilon = LDBL_EPSILON; } else if (flags & FLAGS_SHORT) { baseDigits = (base == BASE_DECIMAL) ? FLT_DIG : (int)trio_floor(FLT_MANT_DIG / TrioLogarithmBase(base)); epsilon = FLT_EPSILON; } else { baseDigits = (base == BASE_DECIMAL) ? DBL_DIG : (int)trio_floor(DBL_MANT_DIG / TrioLogarithmBase(base)); epsilon = DBL_EPSILON; } digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower; isHex = (base == BASE_HEX); if (base == NO_BASE) base = BASE_DECIMAL; dblBase = (trio_long_double_t)base; /* * Some log10() functions can "err by almost 3 ulps" according to * http://www.cs.berkeley.edu/~wkahan/LOG10HAF.TXT */ epsilonCorrection = 3 * epsilon; keepTrailingZeroes = !( (flags & FLAGS_ROUNDING) || ( (flags & FLAGS_FLOAT_G) && !(flags & FLAGS_ALTERNATIVE) ) ); # if TRIO_FEATURE_ROUNDING if (flags & FLAGS_ROUNDING) { precision = baseDigits; } # endif if (precision == NO_PRECISION) { if (isHex) { keepTrailingZeroes = FALSE; precision = FLT_MANT_DIG; } else { precision = FLT_DIG; } } if (isNegative) { number = -number; } if (isHex) { flags |= FLAGS_FLOAT_E; } reprocess: if (flags & FLAGS_FLOAT_G) { if (precision == 0) precision = 1; if ( (number < TRIO_SUFFIX_LONG(1.0E-4)) || (number >= TrioPower(base, (trio_long_double_t)precision)) ) { /* Use scientific notation */ flags |= FLAGS_FLOAT_E; } else if (number < 1.0) { /* * Use normal notation. If the integer part of the number is * zero, then adjust the precision to include leading fractional * zeros. */ workNumber = TrioLogarithm(number, base); workNumber = TRIO_FABS(workNumber); if (workNumber - trio_floor(workNumber) < epsilon) workNumber--; leadingFractionZeroes = (int)trio_floor(workNumber); } } if (flags & FLAGS_FLOAT_E) { /* Scale the number */ workNumber = TrioLogarithm(number, base); if (trio_isinf(workNumber) == -1) { exponent = 0; /* Undo setting */ if (flags & FLAGS_FLOAT_G) flags &= ~FLAGS_FLOAT_E; } else { exponent = (int)trio_floor(workNumber + epsilonCorrection); workNumber = number; /* * We want to apply A / 10^B but the equivalent A * 10^-B gives better * accuracy on platforms with true long double support. */ #if defined(TRIO_DOUBLE_DOUBLE) workNumber /= TrioPower(dblBase, (trio_long_double_t)exponent); #else workNumber *= TrioPower(dblBase, (trio_long_double_t)-exponent); #endif if (trio_isinf(workNumber)) { /* * Scaling is done it two steps to avoid problems with subnormal * numbers. */ workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent / 2)); workNumber /= TrioPower(dblBase, (trio_long_double_t)(exponent - (exponent / 2))); } number = workNumber; isExponentNegative = (exponent < 0); uExponent = (isExponentNegative) ? -exponent : exponent; if (isHex) uExponent *= 4; /* log16(2) */ #if TRIO_FEATURE_QUOTE /* No thousand separators */ flags &= ~FLAGS_QUOTE; #endif } } integerNumber = trio_floor(number); fractionNumber = number - integerNumber; /* * Truncated number. * * Precision is number of significant digits for FLOAT_G and number of * fractional digits for others. */ integerDigits = 1; if (integerNumber > epsilon) { integerDigits += (int)(TrioLogarithm(integerNumber, base) + epsilonCorrection); } fractionDigits = precision; if (flags & FLAGS_FLOAT_G) { if (leadingFractionZeroes > 0) { fractionDigits += leadingFractionZeroes; } if ((integerNumber > epsilon) || (number <= epsilon)) { fractionDigits -= integerDigits; } } dblFractionBase = TrioPower(base, fractionDigits); if (integerNumber < 1.0) { workNumber = number * dblFractionBase + TRIO_SUFFIX_LONG(0.5); if (trio_floor(number * dblFractionBase) != trio_floor(workNumber)) { adjustNumber = TRUE; /* Remove a leading fraction zero if fraction is rounded up */ if ((int)(TrioLogarithm(number * dblFractionBase, base) + epsilonCorrection) != (int)(TrioLogarithm(workNumber, base) + epsilonCorrection)) { --leadingFractionZeroes; } } workNumber /= dblFractionBase; } else { workNumber = number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase; adjustNumber = (trio_floor(number) != trio_floor(workNumber)); } if (adjustNumber) { if ((flags & FLAGS_FLOAT_G) && !(flags & FLAGS_FLOAT_E)) { /* The adjustment may require a change to scientific notation */ if ( (workNumber < TRIO_SUFFIX_LONG(1.0E-4)) || (workNumber >= TrioPower(base, (trio_long_double_t)precision)) ) { /* Use scientific notation */ flags |= FLAGS_FLOAT_E; goto reprocess; } } if (flags & FLAGS_FLOAT_E) { workDigits = 1 + (TrioLogarithm(trio_floor(workNumber), base) + epsilonCorrection); if (integerDigits == workDigits) { /* Adjust if the same number of digits are used */ number += TRIO_SUFFIX_LONG(0.5) / dblFractionBase; integerNumber = trio_floor(number); fractionNumber = number - integerNumber; } else { /* Adjust if number was rounded up one digit (ie. 0.99 to 1.00) */ exponent++; isExponentNegative = (exponent < 0); uExponent = (isExponentNegative) ? -exponent : exponent; if (isHex) uExponent *= 4; /* log16(2) */ workNumber = (number + TRIO_SUFFIX_LONG(0.5) / dblFractionBase) / dblBase; integerNumber = trio_floor(workNumber); fractionNumber = workNumber - integerNumber; } } else { if (workNumber > 1.0) { /* Adjust if number was rounded up one digit (ie. 99 to 100) */ integerNumber = trio_floor(workNumber); fractionNumber = 0.0; integerDigits = (integerNumber > epsilon) ? 1 + (int)(TrioLogarithm(integerNumber, base) + epsilonCorrection) : 1; if (flags & FLAGS_FLOAT_G) { if (flags & FLAGS_ALTERNATIVE) { fractionDigits = precision; if ((integerNumber > epsilon) || (number <= epsilon)) { fractionDigits -= integerDigits; } } else { fractionDigits = 0; } } } else { integerNumber = trio_floor(workNumber); fractionNumber = workNumber - integerNumber; if (flags & FLAGS_FLOAT_G) { if (flags & FLAGS_ALTERNATIVE) { fractionDigits = precision; if (leadingFractionZeroes > 0) { fractionDigits += leadingFractionZeroes; } if ((integerNumber > epsilon) || (number <= epsilon)) { fractionDigits -= integerDigits; } } } } } } /* Estimate accuracy */ integerAdjust = fractionAdjust = TRIO_SUFFIX_LONG(0.5); # if TRIO_FEATURE_ROUNDING if (flags & FLAGS_ROUNDING) { if (integerDigits > baseDigits) { integerThreshold = baseDigits; fractionDigits = 0; dblFractionBase = 1.0; fractionThreshold = 0; precision = 0; /* Disable decimal-point */ integerAdjust = TrioPower(base, integerDigits - integerThreshold - 1); fractionAdjust = 0.0; } else { integerThreshold = integerDigits; fractionThreshold = fractionDigits - integerThreshold; fractionAdjust = 1.0; } } else # endif { integerThreshold = INT_MAX; fractionThreshold = INT_MAX; } /* * Calculate expected width. * sign + integer part + thousands separators + decimal point * + fraction + exponent */ fractionAdjust /= dblFractionBase; hasOnlyZeroes = (trio_floor((fractionNumber + fractionAdjust) * dblFractionBase) < epsilon); keepDecimalPoint = ( (flags & FLAGS_ALTERNATIVE) || !((precision == 0) || (!keepTrailingZeroes && hasOnlyZeroes)) ); expectedWidth = integerDigits + fractionDigits; if (!keepTrailingZeroes) { trailingZeroes = 0; workFractionNumber = fractionNumber; workFractionAdjust = fractionAdjust; fractionDigitsInspect = fractionDigits; if (integerDigits > integerThreshold) { fractionDigitsInspect = 0; } else if (fractionThreshold <= fractionDigits) { fractionDigitsInspect = fractionThreshold + 1; } trailingZeroes = fractionDigits - fractionDigitsInspect; for (i = 0; i < fractionDigitsInspect; i++) { workFractionNumber *= dblBase; workFractionAdjust *= dblBase; workNumber = trio_floor(workFractionNumber + workFractionAdjust); workFractionNumber -= workNumber; offset = (int)trio_fmod(workNumber, dblBase); if (offset == 0) { trailingZeroes++; } else { trailingZeroes = 0; } } expectedWidth -= trailingZeroes; } if (keepDecimalPoint) { expectedWidth += internalDecimalPointLength; } #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) { expectedWidth += TrioCalcThousandSeparatorLength(integerDigits); } #endif if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE)) { expectedWidth += sizeof("-") - 1; } exponentDigits = 0; if (flags & FLAGS_FLOAT_E) { exponentDigits = (uExponent == 0) ? 1 : (int)trio_ceil(TrioLogarithm((double)(uExponent + 1), (isHex) ? 10 : base)); } requireTwoDigitExponent = ((base == BASE_DECIMAL) && (exponentDigits == 1)); if (exponentDigits > 0) { expectedWidth += exponentDigits; expectedWidth += (requireTwoDigitExponent ? sizeof("E+0") - 1 : sizeof("E+") - 1); } if (isHex) { expectedWidth += sizeof("0X") - 1; } /* Output prefixing */ if (flags & FLAGS_NILPADDING) { /* Leading zeros must be after sign */ if (isNegative) self->OutStream(self, '-'); else if (flags & FLAGS_SHOWSIGN) self->OutStream(self, '+'); else if (flags & FLAGS_SPACE) self->OutStream(self, ' '); if (isHex) { self->OutStream(self, '0'); self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); } if (!(flags & FLAGS_LEFTADJUST)) { for (i = expectedWidth; i < width; i++) { self->OutStream(self, '0'); } } } else { /* Leading spaces must be before sign */ if (!(flags & FLAGS_LEFTADJUST)) { for (i = expectedWidth; i < width; i++) { self->OutStream(self, CHAR_ADJUST); } } if (isNegative) self->OutStream(self, '-'); else if (flags & FLAGS_SHOWSIGN) self->OutStream(self, '+'); else if (flags & FLAGS_SPACE) self->OutStream(self, ' '); if (isHex) { self->OutStream(self, '0'); self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x'); } } /* Output the integer part and thousand separators */ for (i = 0; i < integerDigits; i++) { workNumber = trio_floor(((integerNumber + integerAdjust) / TrioPower(base, integerDigits - i - 1))); if (i > integerThreshold) { /* Beyond accuracy */ self->OutStream(self, digits[0]); } else { self->OutStream(self, digits[(int)trio_fmod(workNumber, dblBase)]); } #if TRIO_FEATURE_QUOTE if (((flags & (FLAGS_FLOAT_E | FLAGS_QUOTE)) == FLAGS_QUOTE) && TrioFollowedBySeparator(integerDigits - i)) { for (groupingPointer = internalThousandSeparator; *groupingPointer != NIL; groupingPointer++) { self->OutStream(self, *groupingPointer); } } #endif } /* Insert decimal point and build the fraction part */ trailingZeroes = 0; if (keepDecimalPoint) { if (internalDecimalPoint) { self->OutStream(self, internalDecimalPoint); } else { for (i = 0; i < internalDecimalPointLength; i++) { self->OutStream(self, internalDecimalPointString[i]); } } } for (i = 0; i < fractionDigits; i++) { if ((integerDigits > integerThreshold) || (i > fractionThreshold)) { /* Beyond accuracy */ trailingZeroes++; } else { fractionNumber *= dblBase; fractionAdjust *= dblBase; workNumber = trio_floor(fractionNumber + fractionAdjust); if (workNumber > fractionNumber) { /* fractionNumber should never become negative */ fractionNumber = 0.0; fractionAdjust = 0.0; } else { fractionNumber -= workNumber; } offset = (int)trio_fmod(workNumber, dblBase); if (offset == 0) { trailingZeroes++; } else { while (trailingZeroes > 0) { /* Not trailing zeroes after all */ self->OutStream(self, digits[0]); trailingZeroes--; } self->OutStream(self, digits[offset]); } } } if (keepTrailingZeroes) { while (trailingZeroes > 0) { self->OutStream(self, digits[0]); trailingZeroes--; } } /* Output exponent */ if (exponentDigits > 0) { self->OutStream(self, isHex ? ((flags & FLAGS_UPPER) ? 'P' : 'p') : ((flags & FLAGS_UPPER) ? 'E' : 'e')); self->OutStream(self, (isExponentNegative) ? '-' : '+'); /* The exponent must contain at least two digits */ if (requireTwoDigitExponent) self->OutStream(self, '0'); if (isHex) base = 10; exponentBase = (int)TrioPower(base, exponentDigits - 1); for (i = 0; i < exponentDigits; i++) { self->OutStream(self, digits[(uExponent / exponentBase) % base]); exponentBase /= base; } } /* Output trailing spaces */ if (flags & FLAGS_LEFTADJUST) { for (i = expectedWidth; i < width; i++) { self->OutStream(self, CHAR_ADJUST); } } } #endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * TrioFormatProcess * * Description: * This is the main engine for formatting output */ TRIO_PRIVATE int TrioFormatProcess TRIO_ARGS3((data, format, parameters), trio_class_t *data, TRIO_CONST char *format, trio_parameter_t *parameters) { int i; #if TRIO_FEATURE_ERRNO TRIO_CONST char *string; #endif trio_pointer_t pointer; trio_flags_t flags; int width; int precision; int base; int offset; offset = 0; i = 0; for (;;) { /* Skip the parameter entries */ while (parameters[i].type == FORMAT_PARAMETER) i++; /* Copy non conversion-specifier part of format string */ while (offset < parameters[i].beginOffset) { if (CHAR_IDENTIFIER == format[offset] && CHAR_IDENTIFIER == format[offset + 1]) { data->OutStream(data, CHAR_IDENTIFIER); offset += 2; } else { data->OutStream(data, format[offset++]); } } /* Abort if we reached end of format string */ if (parameters[i].type == FORMAT_SENTINEL) break; /* Ouput parameter */ flags = parameters[i].flags; /* Find width */ width = parameters[i].width; if (flags & FLAGS_WIDTH_PARAMETER) { /* Get width from parameter list */ width = (int)parameters[width].data.number.as_signed; if (width < 0) { /* * A negative width is the same as the - flag and * a positive width. */ flags |= FLAGS_LEFTADJUST; flags &= ~FLAGS_NILPADDING; width = -width; } } /* Find precision */ if (flags & FLAGS_PRECISION) { precision = parameters[i].precision; if (flags & FLAGS_PRECISION_PARAMETER) { /* Get precision from parameter list */ precision = (int)parameters[precision].data.number.as_signed; if (precision < 0) { /* * A negative precision is the same as no * precision */ precision = NO_PRECISION; } } } else { precision = NO_PRECISION; } /* Find base */ if (NO_BASE != parameters[i].baseSpecifier) { /* Base from specifier has priority */ base = parameters[i].baseSpecifier; } else if (flags & FLAGS_BASE_PARAMETER) { /* Get base from parameter list */ base = parameters[i].base; base = (int)parameters[base].data.number.as_signed; } else { /* Use base from format string */ base = parameters[i].base; } switch (parameters[i].type) { case FORMAT_CHAR: #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) data->OutStream(data, CHAR_QUOTE); #endif if (! (flags & FLAGS_LEFTADJUST)) { while (--width > 0) data->OutStream(data, CHAR_ADJUST); } #if TRIO_FEATURE_WIDECHAR if (flags & FLAGS_WIDECHAR) { TrioWriteWideStringCharacter(data, (trio_wchar_t)parameters[i].data.number.as_signed, flags, NO_WIDTH); } else #endif { TrioWriteStringCharacter(data, (int)parameters[i].data.number.as_signed, flags); } if (flags & FLAGS_LEFTADJUST) { while(--width > 0) data->OutStream(data, CHAR_ADJUST); } #if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) data->OutStream(data, CHAR_QUOTE); #endif break; /* FORMAT_CHAR */ case FORMAT_INT: TrioWriteNumber(data, parameters[i].data.number.as_unsigned, flags, width, precision, base); break; /* FORMAT_INT */ #if TRIO_FEATURE_FLOAT case FORMAT_DOUBLE: TrioWriteDouble(data, parameters[i].data.longdoubleNumber, flags, width, precision, base); break; /* FORMAT_DOUBLE */ #endif case FORMAT_STRING: #if TRIO_FEATURE_WIDECHAR if (flags & FLAGS_WIDECHAR) { TrioWriteWideString(data, parameters[i].data.wstring, flags, width, precision); } else #endif { TrioWriteString(data, parameters[i].data.string, flags, width, precision); } break; /* FORMAT_STRING */ case FORMAT_POINTER: { trio_reference_t reference; reference.data = data; reference.parameter = ¶meters[i]; trio_print_pointer(&reference, parameters[i].data.pointer); } break; /* FORMAT_POINTER */ case FORMAT_COUNT: pointer = parameters[i].data.pointer; if (NULL != pointer) { /* * C99 paragraph 7.19.6.1.8 says "the number of * characters written to the output stream so far by * this call", which is data->actually.committed */ #if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER if (flags & FLAGS_SIZE_T) *(size_t *)pointer = (size_t)data->actually.committed; else #endif #if TRIO_FEATURE_PTRDIFF_T if (flags & FLAGS_PTRDIFF_T) *(ptrdiff_t *)pointer = (ptrdiff_t)data->actually.committed; else #endif #if TRIO_FEATURE_INTMAX_T if (flags & FLAGS_INTMAX_T) *(trio_intmax_t *)pointer = (trio_intmax_t)data->actually.committed; else #endif if (flags & FLAGS_QUAD) { *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)data->actually.committed; } else if (flags & FLAGS_LONG) { *(long int *)pointer = (long int)data->actually.committed; } else if (flags & FLAGS_SHORT) { *(short int *)pointer = (short int)data->actually.committed; } else { *(int *)pointer = (int)data->actually.committed; } } break; /* FORMAT_COUNT */ case FORMAT_PARAMETER: break; /* FORMAT_PARAMETER */ #if TRIO_FEATURE_ERRNO case FORMAT_ERRNO: string = trio_error(parameters[i].data.errorNumber); if (string) { TrioWriteString(data, string, flags, width, precision); } else { data->OutStream(data, '#'); TrioWriteNumber(data, (trio_uintmax_t)parameters[i].data.errorNumber, flags, width, precision, BASE_DECIMAL); } break; /* FORMAT_ERRNO */ #endif /* TRIO_FEATURE_ERRNO */ #if TRIO_FEATURE_USER_DEFINED case FORMAT_USER_DEFINED: { trio_reference_t reference; trio_userdef_t *def = NULL; if (parameters[i].flags & FLAGS_USER_DEFINED_PARAMETER) { /* Use handle */ if ((i > 0) || (parameters[i - 1].type == FORMAT_PARAMETER)) def = (trio_userdef_t *)parameters[i - 1].data.pointer; } else { /* Look up namespace */ def = TrioFindNamespace(parameters[i].user_defined.namespace, NULL); } if (def) { reference.data = data; reference.parameter = ¶meters[i]; def->callback(&reference); } } break; #endif /* TRIO_FEATURE_USER_DEFINED */ default: break; } /* switch parameter type */ /* Prepare for next */ offset = parameters[i].endOffset; i++; } return data->processed; } /************************************************************************* * TrioFormatRef */ #if TRIO_EXTENSION TRIO_PRIVATE int TrioFormatRef TRIO_ARGS5((reference, format, arglist, argfunc, argarray), trio_reference_t *reference, TRIO_CONST char *format, va_list arglist, trio_argfunc_t argfunc, trio_pointer_t *argarray) { int status; trio_parameter_t parameters[MAX_PARAMETERS]; status = TrioParse(TYPE_PRINT, format, parameters, arglist, argfunc, argarray); if (status < 0) return status; status = TrioFormatProcess(reference->data, format, parameters); if (reference->data->error != 0) { status = reference->data->error; } return status; } #endif /* TRIO_EXTENSION */ /************************************************************************* * TrioFormat */ TRIO_PRIVATE int TrioFormat TRIO_ARGS7((destination, destinationSize, OutStream, format, arglist, argfunc, argarray), trio_pointer_t destination, size_t destinationSize, void (*OutStream) TRIO_PROTO((trio_class_t *, int)), TRIO_CONST char *format, va_list arglist, trio_argfunc_t argfunc, trio_pointer_t *argarray) { int status; trio_class_t data; trio_parameter_t parameters[MAX_PARAMETERS]; assert(VALID(OutStream)); assert(VALID(format)); memset(&data, 0, sizeof(data)); data.OutStream = OutStream; data.location = destination; data.max = destinationSize; data.error = 0; #if defined(USE_LOCALE) if (NULL == internalLocaleValues) { TrioSetLocale(); } #endif status = TrioParse(TYPE_PRINT, format, parameters, arglist, argfunc, argarray); if (status < 0) return status; status = TrioFormatProcess(&data, format, parameters); if (data.error != 0) { status = data.error; } return status; } /************************************************************************* * TrioOutStreamFile */ #if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO TRIO_PRIVATE void TrioOutStreamFile TRIO_ARGS2((self, output), trio_class_t *self, int output) { FILE *file; assert(VALID(self)); assert(VALID(self->location)); file = (FILE *)self->location; self->processed++; if (fputc(output, file) == EOF) { self->error = TRIO_ERROR_RETURN(TRIO_EOF, 0); } else { self->actually.committed++; } } #endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */ /************************************************************************* * TrioOutStreamFileDescriptor */ #if TRIO_FEATURE_FD TRIO_PRIVATE void TrioOutStreamFileDescriptor TRIO_ARGS2((self, output), trio_class_t *self, int output) { int fd; char ch; assert(VALID(self)); fd = *((int *)self->location); ch = (char)output; self->processed++; if (write(fd, &ch, sizeof(char)) == -1) { self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); } else { self->actually.committed++; } } #endif /* TRIO_FEATURE_FD */ /************************************************************************* * TrioOutStreamCustom */ #if TRIO_FEATURE_CLOSURE TRIO_PRIVATE void TrioOutStreamCustom TRIO_ARGS2((self, output), trio_class_t *self, int output) { int status; trio_custom_t *data; assert(VALID(self)); assert(VALID(self->location)); data = (trio_custom_t *)self->location; if (data->stream.out) { status = (data->stream.out)(data->closure, output); if (status >= 0) { self->actually.committed++; } else { if (self->error == 0) { self->error = TRIO_ERROR_RETURN(TRIO_ECUSTOM, -status); } } } self->processed++; } #endif /* TRIO_FEATURE_CLOSURE */ /************************************************************************* * TrioOutStreamString */ TRIO_PRIVATE void TrioOutStreamString TRIO_ARGS2((self, output), trio_class_t *self, int output) { char **buffer; assert(VALID(self)); assert(VALID(self->location)); buffer = (char **)self->location; **buffer = (char)output; (*buffer)++; self->processed++; self->actually.committed++; } /************************************************************************* * TrioOutStreamStringMax */ TRIO_PRIVATE void TrioOutStreamStringMax TRIO_ARGS2((self, output), trio_class_t *self, int output) { char **buffer; assert(VALID(self)); assert(VALID(self->location)); buffer = (char **)self->location; if (self->processed < self->max) { **buffer = (char)output; (*buffer)++; self->actually.committed++; } self->processed++; } /************************************************************************* * TrioOutStreamStringDynamic */ #if TRIO_FEATURE_DYNAMICSTRING TRIO_PRIVATE void TrioOutStreamStringDynamic TRIO_ARGS2((self, output), trio_class_t *self, int output) { assert(VALID(self)); assert(VALID(self->location)); if (self->error == 0) { trio_xstring_append_char((trio_string_t *)self->location, (char)output); self->actually.committed++; } /* The processed variable must always be increased */ self->processed++; } #endif /* TRIO_FEATURE_DYNAMICSTRING */ /************************************************************************* * TrioArrayGetter */ TRIO_PRIVATE trio_pointer_t TrioArrayGetter(trio_pointer_t context, int index, int type) { /* Utility function for the printfv family */ trio_pointer_t *argarray = (trio_pointer_t *)context; return argarray[index]; } /************************************************************************* * * Formatted printing functions * ************************************************************************/ /** @addtogroup Printf @{ */ /************************************************************************* * printf */ /** Print to standard output stream. @param format Formatting string. @param ... Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_STDIO TRIO_PUBLIC int trio_printf TRIO_VARGS2((format, va_alist), TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); TRIO_VA_START(args, format); status = TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_STDIO */ /** Print to standard output stream. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_STDIO TRIO_PUBLIC int trio_vprintf TRIO_ARGS2((format, args), TRIO_CONST char *format, va_list args) { assert(VALID(format)); return TrioFormat(stdout, 0, TrioOutStreamFile, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_STDIO */ /** Print to standard output stream. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_STDIO TRIO_PUBLIC int trio_printfv TRIO_ARGS2((format, args), TRIO_CONST char *format, trio_pointer_t * args) { static va_list unused; assert(VALID(format)); return TrioFormat(stdout, 0, TrioOutStreamFile, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_STDIO */ /************************************************************************* * fprintf */ /** Print to file. @param file File pointer. @param format Formatting string. @param ... Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_FILE TRIO_PUBLIC int trio_fprintf TRIO_VARGS3((file, format, va_alist), FILE *file, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(file)); assert(VALID(format)); TRIO_VA_START(args, format); status = TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_FILE */ /** Print to file. @param file File pointer. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_FILE TRIO_PUBLIC int trio_vfprintf TRIO_ARGS3((file, format, args), FILE *file, TRIO_CONST char *format, va_list args) { assert(VALID(file)); assert(VALID(format)); return TrioFormat(file, 0, TrioOutStreamFile, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_FILE */ /** Print to file. @param file File pointer. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_FILE TRIO_PUBLIC int trio_fprintfv TRIO_ARGS3((file, format, args), FILE *file, TRIO_CONST char *format, trio_pointer_t * args) { static va_list unused; assert(VALID(file)); assert(VALID(format)); return TrioFormat(file, 0, TrioOutStreamFile, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_FILE */ /************************************************************************* * dprintf */ /** Print to file descriptor. @param fd File descriptor. @param format Formatting string. @param ... Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_FD TRIO_PUBLIC int trio_dprintf TRIO_VARGS3((fd, format, va_alist), int fd, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); TRIO_VA_START(args, format); status = TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_FD */ /** Print to file descriptor. @param fd File descriptor. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_FD TRIO_PUBLIC int trio_vdprintf TRIO_ARGS3((fd, format, args), int fd, TRIO_CONST char *format, va_list args) { assert(VALID(format)); return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_FD */ /** Print to file descriptor. @param fd File descriptor. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_FD TRIO_PUBLIC int trio_dprintfv TRIO_ARGS3((fd, format, args), int fd, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; assert(VALID(format)); return TrioFormat(&fd, 0, TrioOutStreamFileDescriptor, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_FD */ /************************************************************************* * cprintf */ #if TRIO_FEATURE_CLOSURE TRIO_PUBLIC int trio_cprintf TRIO_VARGS4((stream, closure, format, va_alist), trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); TRIO_VA_START(args, format); data.stream.out = stream; data.closure = closure; status = TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_CLOSURE */ #if TRIO_FEATURE_CLOSURE TRIO_PUBLIC int trio_vcprintf TRIO_ARGS4((stream, closure, format, args), trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, va_list args) { trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); data.stream.out = stream; data.closure = closure; return TrioFormat(&data, 0, TrioOutStreamCustom, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_CLOSURE */ #if TRIO_FEATURE_CLOSURE TRIO_PUBLIC int trio_cprintfv TRIO_ARGS4((stream, closure, format, args), trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); data.stream.out = stream; data.closure = closure; return TrioFormat(&data, 0, TrioOutStreamCustom, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_CLOSURE */ #if TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC TRIO_PUBLIC int trio_cprintff TRIO_ARGS5((stream, closure, format, argfunc, context), trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_argfunc_t argfunc, trio_pointer_t context) { static va_list unused; trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); assert(VALID(argfunc)); data.stream.out = stream; data.closure = closure; return TrioFormat(&data, 0, TrioOutStreamCustom, format, unused, argfunc, (trio_pointer_t *)context); } #endif /* TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC */ /************************************************************************* * sprintf */ /** Print to string. @param buffer Output string. @param format Formatting string. @param ... Arguments. @return Number of printed characters. */ TRIO_PUBLIC int trio_sprintf TRIO_VARGS3((buffer, format, va_alist), char *buffer, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(buffer)); assert(VALID(format)); TRIO_VA_START(args, format); status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL, NULL); *buffer = NIL; /* Terminate with NIL character */ TRIO_VA_END(args); return status; } /** Print to string. @param buffer Output string. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ TRIO_PUBLIC int trio_vsprintf TRIO_ARGS3((buffer, format, args), char *buffer, TRIO_CONST char *format, va_list args) { int status; assert(VALID(buffer)); assert(VALID(format)); status = TrioFormat(&buffer, 0, TrioOutStreamString, format, args, NULL, NULL); *buffer = NIL; return status; } /** Print to string. @param buffer Output string. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ TRIO_PUBLIC int trio_sprintfv TRIO_ARGS3((buffer, format, args), char *buffer, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; int status; assert(VALID(buffer)); assert(VALID(format)); status = TrioFormat(&buffer, 0, TrioOutStreamString, format, unused, TrioArrayGetter, args); *buffer = NIL; return status; } /************************************************************************* * snprintf */ /** Print at most @p max characters to string. @param buffer Output string. @param max Maximum number of characters to print. @param format Formatting string. @param ... Arguments. @return Number of printed characters. */ TRIO_PUBLIC int trio_snprintf TRIO_VARGS4((buffer, max, format, va_alist), char *buffer, size_t max, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(buffer) || (max == 0)); assert(VALID(format)); TRIO_VA_START(args, format); status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, TrioOutStreamStringMax, format, args, NULL, NULL); if (max > 0) *buffer = NIL; TRIO_VA_END(args); return status; } /** Print at most @p max characters to string. @param buffer Output string. @param max Maximum number of characters to print. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ TRIO_PUBLIC int trio_vsnprintf TRIO_ARGS4((buffer, max, format, args), char *buffer, size_t max, TRIO_CONST char *format, va_list args) { int status; assert(VALID(buffer) || (max == 0)); assert(VALID(format)); status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, TrioOutStreamStringMax, format, args, NULL, NULL); if (max > 0) *buffer = NIL; return status; } /** Print at most @p max characters to string. @param buffer Output string. @param max Maximum number of characters to print. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ TRIO_PUBLIC int trio_snprintfv TRIO_ARGS4((buffer, max, format, args), char *buffer, size_t max, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; int status; assert(VALID(buffer) || (max == 0)); assert(VALID(format)); status = TrioFormat(&buffer, max > 0 ? max - 1 : 0, TrioOutStreamStringMax, format, unused, TrioArrayGetter, args); if (max > 0) *buffer = NIL; return status; } /************************************************************************* * snprintfcat * Appends the new string to the buffer string overwriting the '\0' * character at the end of buffer. */ #if TRIO_EXTENSION TRIO_PUBLIC int trio_snprintfcat TRIO_VARGS4((buffer, max, format, va_alist), char *buffer, size_t max, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; size_t buf_len; TRIO_VA_START(args, format); assert(VALID(buffer)); assert(VALID(format)); buf_len = trio_length(buffer); buffer = &buffer[buf_len]; status = TrioFormat(&buffer, max - 1 - buf_len, TrioOutStreamStringMax, format, args, NULL, NULL); TRIO_VA_END(args); *buffer = NIL; return status; } #endif #if TRIO_EXTENSION TRIO_PUBLIC int trio_vsnprintfcat TRIO_ARGS4((buffer, max, format, args), char *buffer, size_t max, TRIO_CONST char *format, va_list args) { int status; size_t buf_len; assert(VALID(buffer)); assert(VALID(format)); buf_len = trio_length(buffer); buffer = &buffer[buf_len]; status = TrioFormat(&buffer, max - 1 - buf_len, TrioOutStreamStringMax, format, args, NULL, NULL); *buffer = NIL; return status; } #endif /************************************************************************* * trio_aprintf */ #if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING TRIO_PUBLIC char * trio_aprintf TRIO_VARGS2((format, va_alist), TRIO_CONST char *format, TRIO_VA_DECL) { va_list args; trio_string_t *info; char *result = NULL; assert(VALID(format)); info = trio_xstring_duplicate(""); if (info) { TRIO_VA_START(args, format); (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, format, args, NULL, NULL); TRIO_VA_END(args); trio_string_terminate(info); result = trio_string_extract(info); trio_string_destroy(info); } return result; } #endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */ #if TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING TRIO_PUBLIC char * trio_vaprintf TRIO_ARGS2((format, args), TRIO_CONST char *format, va_list args) { trio_string_t *info; char *result = NULL; assert(VALID(format)); info = trio_xstring_duplicate(""); if (info) { (void)TrioFormat(info, 0, TrioOutStreamStringDynamic, format, args, NULL, NULL); trio_string_terminate(info); result = trio_string_extract(info); trio_string_destroy(info); } return result; } #endif /* TRIO_DEPRECATED && TRIO_FEATURE_DYNAMICSTRING */ /** Allocate and print to string. The memory allocated and returned by @p result must be freed by the calling application. @param result Output string. @param format Formatting string. @param ... Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_DYNAMICSTRING TRIO_PUBLIC int trio_asprintf TRIO_VARGS3((result, format, va_alist), char **result, TRIO_CONST char *format, TRIO_VA_DECL) { va_list args; int status; trio_string_t *info; assert(VALID(format)); *result = NULL; info = trio_xstring_duplicate(""); if (info == NULL) { status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); } else { TRIO_VA_START(args, format); status = TrioFormat(info, 0, TrioOutStreamStringDynamic, format, args, NULL, NULL); TRIO_VA_END(args); if (status >= 0) { trio_string_terminate(info); *result = trio_string_extract(info); } trio_string_destroy(info); } return status; } #endif /* TRIO_FEATURE_DYNAMICSTRING */ /** Allocate and print to string. The memory allocated and returned by @p result must be freed by the calling application. @param result Output string. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_DYNAMICSTRING TRIO_PUBLIC int trio_vasprintf TRIO_ARGS3((result, format, args), char **result, TRIO_CONST char *format, va_list args) { int status; trio_string_t *info; assert(VALID(format)); *result = NULL; info = trio_xstring_duplicate(""); if (info == NULL) { status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); } else { status = TrioFormat(info, 0, TrioOutStreamStringDynamic, format, args, NULL, NULL); if (status >= 0) { trio_string_terminate(info); *result = trio_string_extract(info); } trio_string_destroy(info); } return status; } #endif /* TRIO_FEATURE_DYNAMICSTRING */ /** Allocate and print to string. The memory allocated and returned by @p result must be freed by the calling application. @param result Output string. @param format Formatting string. @param args Arguments. @return Number of printed characters. */ #if TRIO_FEATURE_DYNAMICSTRING TRIO_PUBLIC int trio_asprintfv TRIO_ARGS3((result, format, args), char **result, TRIO_CONST char *format, trio_pointer_t * args) { static va_list unused; int status; trio_string_t *info; assert(VALID(format)); *result = NULL; info = trio_xstring_duplicate(""); if (info == NULL) { status = TRIO_ERROR_RETURN(TRIO_ENOMEM, 0); } else { status = TrioFormat(info, 0, TrioOutStreamStringDynamic, format, unused, TrioArrayGetter, args); if (status >= 0) { trio_string_terminate(info); *result = trio_string_extract(info); } trio_string_destroy(info); } return status; } #endif /* TRIO_FEATURE_DYNAMICSTRING */ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_printf.h" #endif /** @} End of Printf documentation module */ /************************************************************************* * * CALLBACK * ************************************************************************/ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_register.h" #endif /** @addtogroup UserDefined @{ */ #if TRIO_FEATURE_USER_DEFINED /************************************************************************* * trio_register */ /** Register new user-defined specifier. @param callback @param name @return Handle. */ TRIO_PUBLIC trio_pointer_t trio_register TRIO_ARGS2((callback, name), trio_callback_t callback, TRIO_CONST char *name) { trio_userdef_t *def; trio_userdef_t *prev = NULL; if (callback == NULL) return NULL; if (name) { /* Handle built-in namespaces */ if (name[0] == ':') { if (trio_equal(name, ":enter")) { internalEnterCriticalRegion = callback; } else if (trio_equal(name, ":leave")) { internalLeaveCriticalRegion = callback; } return NULL; } /* Bail out if namespace is too long */ if (trio_length(name) >= MAX_USER_NAME) return NULL; /* Bail out if namespace already is registered */ def = TrioFindNamespace(name, &prev); if (def) return NULL; } def = (trio_userdef_t *)TRIO_MALLOC(sizeof(trio_userdef_t)); if (def) { if (internalEnterCriticalRegion) (void)internalEnterCriticalRegion(NULL); if (name) { /* Link into internal list */ if (prev == NULL) internalUserDef = def; else prev->next = def; } /* Initialize */ def->callback = callback; def->name = (name == NULL) ? NULL : trio_duplicate(name); def->next = NULL; if (internalLeaveCriticalRegion) (void)internalLeaveCriticalRegion(NULL); } return (trio_pointer_t)def; } /** Unregister an existing user-defined specifier. @param handle */ TRIO_PUBLIC void trio_unregister TRIO_ARGS1((handle), trio_pointer_t handle) { trio_userdef_t *self = (trio_userdef_t *)handle; trio_userdef_t *def; trio_userdef_t *prev = NULL; assert(VALID(self)); if (self->name) { def = TrioFindNamespace(self->name, &prev); if (def) { if (internalEnterCriticalRegion) (void)internalEnterCriticalRegion(NULL); if (prev == NULL) internalUserDef = internalUserDef->next; else prev->next = def->next; if (internalLeaveCriticalRegion) (void)internalLeaveCriticalRegion(NULL); } trio_destroy(self->name); } TRIO_FREE(self); } /************************************************************************* * trio_get_format */ TRIO_PUBLIC TRIO_CONST char * trio_get_format TRIO_ARGS1((ref), trio_pointer_t ref) { #if TRIO_FEATURE_USER_DEFINED assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); #endif return (((trio_reference_t *)ref)->parameter->user_data); } /************************************************************************* * trio_get_argument */ TRIO_PUBLIC TRIO_CONST trio_pointer_t trio_get_argument TRIO_ARGS1((ref), trio_pointer_t ref) { #if TRIO_FEATURE_USER_DEFINED assert(((trio_reference_t *)ref)->parameter->type == FORMAT_USER_DEFINED); #endif return ((trio_reference_t *)ref)->parameter->data.pointer; } /************************************************************************* * trio_get_width / trio_set_width */ TRIO_PUBLIC int trio_get_width TRIO_ARGS1((ref), trio_pointer_t ref) { return ((trio_reference_t *)ref)->parameter->width; } TRIO_PUBLIC void trio_set_width TRIO_ARGS2((ref, width), trio_pointer_t ref, int width) { ((trio_reference_t *)ref)->parameter->width = width; } /************************************************************************* * trio_get_precision / trio_set_precision */ TRIO_PUBLIC int trio_get_precision TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->precision); } TRIO_PUBLIC void trio_set_precision TRIO_ARGS2((ref, precision), trio_pointer_t ref, int precision) { ((trio_reference_t *)ref)->parameter->precision = precision; } /************************************************************************* * trio_get_base / trio_set_base */ TRIO_PUBLIC int trio_get_base TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->base); } TRIO_PUBLIC void trio_set_base TRIO_ARGS2((ref, base), trio_pointer_t ref, int base) { ((trio_reference_t *)ref)->parameter->base = base; } /************************************************************************* * trio_get_long / trio_set_long */ TRIO_PUBLIC int trio_get_long TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONG) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_long TRIO_ARGS2((ref, is_long), trio_pointer_t ref, int is_long) { if (is_long) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONG; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONG; } /************************************************************************* * trio_get_longlong / trio_set_longlong */ TRIO_PUBLIC int trio_get_longlong TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUAD) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_longlong TRIO_ARGS2((ref, is_longlong), trio_pointer_t ref, int is_longlong) { if (is_longlong) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUAD; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUAD; } /************************************************************************* * trio_get_longdouble / trio_set_longdouble */ # if TRIO_FEATURE_FLOAT TRIO_PUBLIC int trio_get_longdouble TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LONGDOUBLE) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_longdouble TRIO_ARGS2((ref, is_longdouble), trio_pointer_t ref, int is_longdouble) { if (is_longdouble) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LONGDOUBLE; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LONGDOUBLE; } # endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * trio_get_short / trio_set_short */ TRIO_PUBLIC int trio_get_short TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORT) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_short TRIO_ARGS2((ref, is_short), trio_pointer_t ref, int is_short) { if (is_short) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORT; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORT; } /************************************************************************* * trio_get_shortshort / trio_set_shortshort */ TRIO_PUBLIC int trio_get_shortshort TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHORTSHORT) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_shortshort TRIO_ARGS2((ref, is_shortshort), trio_pointer_t ref, int is_shortshort) { if (is_shortshort) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHORTSHORT; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHORTSHORT; } /************************************************************************* * trio_get_alternative / trio_set_alternative */ TRIO_PUBLIC int trio_get_alternative TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_ALTERNATIVE) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_alternative TRIO_ARGS2((ref, is_alternative), trio_pointer_t ref, int is_alternative) { if (is_alternative) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_ALTERNATIVE; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_ALTERNATIVE; } /************************************************************************* * trio_get_alignment / trio_set_alignment */ TRIO_PUBLIC int trio_get_alignment TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_LEFTADJUST) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_alignment TRIO_ARGS2((ref, is_leftaligned), trio_pointer_t ref, int is_leftaligned) { if (is_leftaligned) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_LEFTADJUST; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_LEFTADJUST; } /************************************************************************* * trio_get_spacing /trio_set_spacing */ TRIO_PUBLIC int trio_get_spacing TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SPACE) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_spacing TRIO_ARGS2((ref, is_space), trio_pointer_t ref, int is_space) { if (is_space) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SPACE; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SPACE; } /************************************************************************* * trio_get_sign / trio_set_sign */ TRIO_PUBLIC int trio_get_sign TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SHOWSIGN) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_sign TRIO_ARGS2((ref, is_sign), trio_pointer_t ref, int is_sign) { if (is_sign) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SHOWSIGN; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SHOWSIGN; } /************************************************************************* * trio_get_padding / trio_set_padding */ TRIO_PUBLIC int trio_get_padding TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_NILPADDING) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_padding TRIO_ARGS2((ref, is_padding), trio_pointer_t ref, int is_padding) { if (is_padding) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_NILPADDING; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_NILPADDING; } /************************************************************************* * trio_get_quote / trio_set_quote */ # if TRIO_FEATURE_QUOTE TRIO_PUBLIC int trio_get_quote TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_QUOTE) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_quote TRIO_ARGS2((ref, is_quote), trio_pointer_t ref, int is_quote) { if (is_quote) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_QUOTE; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_QUOTE; } #endif /* TRIO_FEATURE_QUOTE */ /************************************************************************* * trio_get_upper / trio_set_upper */ TRIO_PUBLIC int trio_get_upper TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_UPPER) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_upper TRIO_ARGS2((ref, is_upper), trio_pointer_t ref, int is_upper) { if (is_upper) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_UPPER; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_UPPER; } /************************************************************************* * trio_get_largest / trio_set_largest */ #if TRIO_FEATURE_INTMAX_T TRIO_PUBLIC int trio_get_largest TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_INTMAX_T) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_largest TRIO_ARGS2((ref, is_largest), trio_pointer_t ref, int is_largest) { if (is_largest) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_INTMAX_T; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_INTMAX_T; } #endif /* TRIO_FEATURE_INTMAX_T */ /************************************************************************* * trio_get_ptrdiff / trio_set_ptrdiff */ #if TRIO_FEATURE_PTRDIFF_T TRIO_PUBLIC int trio_get_ptrdiff TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_PTRDIFF_T) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_ptrdiff TRIO_ARGS2((ref, is_ptrdiff), trio_pointer_t ref, int is_ptrdiff) { if (is_ptrdiff) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_PTRDIFF_T; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_PTRDIFF_T; } #endif /* TRIO_FEATURE_PTRDIFF_T */ /************************************************************************* * trio_get_size / trio_set_size */ #if TRIO_FEATURE_SIZE_T TRIO_PUBLIC int trio_get_size TRIO_ARGS1((ref), trio_pointer_t ref) { return (((trio_reference_t *)ref)->parameter->flags & FLAGS_SIZE_T) ? TRUE : FALSE; } TRIO_PUBLIC void trio_set_size TRIO_ARGS2((ref, is_size), trio_pointer_t ref, int is_size) { if (is_size) ((trio_reference_t *)ref)->parameter->flags |= FLAGS_SIZE_T; else ((trio_reference_t *)ref)->parameter->flags &= ~FLAGS_SIZE_T; } #endif /* TRIO_FEATURE_SIZE_T */ /************************************************************************* * trio_print_int */ TRIO_PUBLIC void trio_print_int TRIO_ARGS2((ref, number), trio_pointer_t ref, int number) { trio_reference_t *self = (trio_reference_t *)ref; TrioWriteNumber(self->data, (trio_uintmax_t)number, self->parameter->flags, self->parameter->width, self->parameter->precision, self->parameter->base); } /************************************************************************* * trio_print_uint */ TRIO_PUBLIC void trio_print_uint TRIO_ARGS2((ref, number), trio_pointer_t ref, unsigned int number) { trio_reference_t *self = (trio_reference_t *)ref; TrioWriteNumber(self->data, (trio_uintmax_t)number, self->parameter->flags | FLAGS_UNSIGNED, self->parameter->width, self->parameter->precision, self->parameter->base); } /************************************************************************* * trio_print_double */ #if TRIO_FEATURE_FLOAT TRIO_PUBLIC void trio_print_double TRIO_ARGS2((ref, number), trio_pointer_t ref, double number) { trio_reference_t *self = (trio_reference_t *)ref; TrioWriteDouble(self->data, number, self->parameter->flags, self->parameter->width, self->parameter->precision, self->parameter->base); } #endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * trio_print_string */ TRIO_PUBLIC void trio_print_string TRIO_ARGS2((ref, string), trio_pointer_t ref, TRIO_CONST char *string) { trio_reference_t *self = (trio_reference_t *)ref; TrioWriteString(self->data, string, self->parameter->flags, self->parameter->width, self->parameter->precision); } /************************************************************************* * trio_print_ref */ TRIO_PUBLIC int trio_print_ref TRIO_VARGS3((ref, format, va_alist), trio_pointer_t ref, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list arglist; assert(VALID(format)); TRIO_VA_START(arglist, format); status = TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL, NULL); TRIO_VA_END(arglist); return status; } /************************************************************************* * trio_vprint_ref */ TRIO_PUBLIC int trio_vprint_ref TRIO_ARGS3((ref, format, arglist), trio_pointer_t ref, TRIO_CONST char *format, va_list arglist) { assert(VALID(format)); return TrioFormatRef((trio_reference_t *)ref, format, arglist, NULL, NULL); } /************************************************************************* * trio_printv_ref */ TRIO_PUBLIC int trio_printv_ref TRIO_ARGS3((ref, format, argarray), trio_pointer_t ref, TRIO_CONST char *format, trio_pointer_t *argarray) { static va_list unused; assert(VALID(format)); return TrioFormatRef((trio_reference_t *)ref, format, unused, TrioArrayGetter, argarray); } #endif /************************************************************************* * trio_print_pointer */ TRIO_PUBLIC void trio_print_pointer TRIO_ARGS2((ref, pointer), trio_pointer_t ref, trio_pointer_t pointer) { trio_reference_t *self = (trio_reference_t *)ref; trio_flags_t flags; trio_uintmax_t number; if (NULL == pointer) { TRIO_CONST char *string = internalNullString; while (*string) self->data->OutStream(self->data, *string++); } else { /* * The subtraction of the null pointer is a workaround * to avoid a compiler warning. The performance overhead * is negligible (and likely to be removed by an * optimizing compiler). The (char *) casting is done * to please ANSI C++. */ number = (trio_uintmax_t)((char *)pointer - (char *)0); /* Shrink to size of pointer */ number &= (trio_uintmax_t)-1; flags = self->parameter->flags; flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING); TrioWriteNumber(self->data, number, flags, POINTER_WIDTH, NO_PRECISION, BASE_HEX); } } /** @} End of UserDefined documentation module */ /************************************************************************* * * LOCALES * ************************************************************************/ /************************************************************************* * trio_locale_set_decimal_point * * Decimal point can only be one character. The input argument is a * string to enable multibyte characters. At most MB_LEN_MAX characters * will be used. */ #if TRIO_FEATURE_LOCALE TRIO_PUBLIC void trio_locale_set_decimal_point TRIO_ARGS1((decimalPoint), char *decimalPoint) { #if defined(USE_LOCALE) if (NULL == internalLocaleValues) { TrioSetLocale(); } #endif internalDecimalPointLength = trio_length(decimalPoint); if (internalDecimalPointLength == 1) { internalDecimalPoint = *decimalPoint; } else { internalDecimalPoint = NIL; trio_copy_max(internalDecimalPointString, sizeof(internalDecimalPointString), decimalPoint); } } #endif /************************************************************************* * trio_locale_set_thousand_separator * * See trio_locale_set_decimal_point */ #if TRIO_FEATURE_LOCALE || TRIO_EXTENSION TRIO_PUBLIC void trio_locale_set_thousand_separator TRIO_ARGS1((thousandSeparator), char *thousandSeparator) { # if defined(USE_LOCALE) if (NULL == internalLocaleValues) { TrioSetLocale(); } # endif trio_copy_max(internalThousandSeparator, sizeof(internalThousandSeparator), thousandSeparator); internalThousandSeparatorLength = trio_length(internalThousandSeparator); } #endif /************************************************************************* * trio_locale_set_grouping * * Array of bytes. Reversed order. * * CHAR_MAX : No further grouping * 0 : Repeat last group for the remaining digits (not necessary * as C strings are zero-terminated) * n : Set current group to n * * Same order as the grouping attribute in LC_NUMERIC. */ #if TRIO_FEATURE_LOCALE || TRIO_EXTENSION TRIO_PUBLIC void trio_locale_set_grouping TRIO_ARGS1((grouping), char *grouping) { # if defined(USE_LOCALE) if (NULL == internalLocaleValues) { TrioSetLocale(); } # endif trio_copy_max(internalGrouping, sizeof(internalGrouping), grouping); } #endif /************************************************************************* * * SCANNING * ************************************************************************/ #if TRIO_FEATURE_SCANF /************************************************************************* * TrioSkipWhitespaces */ TRIO_PRIVATE int TrioSkipWhitespaces TRIO_ARGS1((self), trio_class_t *self) { int ch; ch = self->current; while (isspace(ch)) { self->InStream(self, &ch); } return ch; } /************************************************************************* * TrioGetCollation */ #if TRIO_EXTENSION TRIO_PRIVATE void TrioGetCollation(TRIO_NOARGS) { int i; int j; int k; char first[2]; char second[2]; /* This is computationally expensive */ first[1] = NIL; second[1] = NIL; for (i = 0; i < MAX_CHARACTER_CLASS; i++) { k = 0; first[0] = (char)i; for (j = 0; j < MAX_CHARACTER_CLASS; j++) { second[0] = (char)j; if (trio_equal_locale(first, second)) internalCollationArray[i][k++] = (char)j; } internalCollationArray[i][k] = NIL; } } #endif /************************************************************************* * TrioGetCharacterClass * * FIXME: * multibyte */ TRIO_PRIVATE int TrioGetCharacterClass TRIO_ARGS4((format, offsetPointer, flagsPointer, characterclass), TRIO_CONST char *format, int *offsetPointer, trio_flags_t *flagsPointer, int *characterclass) { int offset = *offsetPointer; int i; char ch; char range_begin; char range_end; *flagsPointer &= ~FLAGS_EXCLUDE; if (format[offset] == QUALIFIER_CIRCUMFLEX) { *flagsPointer |= FLAGS_EXCLUDE; offset++; } /* * If the ungroup character is at the beginning of the scanlist, * it will be part of the class, and a second ungroup character * must follow to end the group. */ if (format[offset] == SPECIFIER_UNGROUP) { characterclass[(int)SPECIFIER_UNGROUP]++; offset++; } /* * Minus is used to specify ranges. To include minus in the class, * it must be at the beginning of the list */ if (format[offset] == QUALIFIER_MINUS) { characterclass[(int)QUALIFIER_MINUS]++; offset++; } /* Collect characters */ for (ch = format[offset]; (ch != SPECIFIER_UNGROUP) && (ch != NIL); ch = format[++offset]) { switch (ch) { case QUALIFIER_MINUS: /* Scanlist ranges */ /* * Both C99 and UNIX98 describes ranges as implementation- * defined. * * We support the following behaviour (although this may * change as we become wiser) * - only increasing ranges, ie. [a-b] but not [b-a] * - transitive ranges, ie. [a-b-c] == [a-c] * - trailing minus, ie. [a-] is interpreted as an 'a' * and a '-' * - duplicates (although we can easily convert these * into errors) */ range_begin = format[offset - 1]; range_end = format[++offset]; if (range_end == SPECIFIER_UNGROUP) { /* Trailing minus is included */ characterclass[(int)ch]++; ch = range_end; break; /* for */ } if (range_end == NIL) return TRIO_ERROR_RETURN(TRIO_EINVAL, offset); if (range_begin > range_end) return TRIO_ERROR_RETURN(TRIO_ERANGE, offset); for (i = (int)range_begin; i <= (int)range_end; i++) characterclass[i]++; ch = range_end; break; #if TRIO_EXTENSION case SPECIFIER_GROUP: switch (format[offset + 1]) { case QUALIFIER_DOT: /* Collating symbol */ /* * FIXME: This will be easier to implement when multibyte * characters have been implemented. Until now, we ignore * this feature. */ for (i = offset + 2; ; i++) { if (format[i] == NIL) /* Error in syntax */ return -1; else if (format[i] == QUALIFIER_DOT) break; /* for */ } if (format[++i] != SPECIFIER_UNGROUP) return -1; offset = i; break; case QUALIFIER_EQUAL: /* Equivalence class expressions */ { unsigned int j; unsigned int k; if (internalCollationUnconverted) { /* Lazy evaluation of collation array */ TrioGetCollation(); internalCollationUnconverted = FALSE; } for (i = offset + 2; ; i++) { if (format[i] == NIL) /* Error in syntax */ return -1; else if (format[i] == QUALIFIER_EQUAL) break; /* for */ else { /* Mark any equivalent character */ k = (unsigned int)format[i]; for (j = 0; internalCollationArray[k][j] != NIL; j++) characterclass[(int)internalCollationArray[k][j]]++; } } if (format[++i] != SPECIFIER_UNGROUP) return -1; offset = i; } break; case QUALIFIER_COLON: /* Character class expressions */ if (trio_equal_max(CLASS_ALNUM, sizeof(CLASS_ALNUM) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isalnum(i)) characterclass[i]++; offset += sizeof(CLASS_ALNUM) - 1; } else if (trio_equal_max(CLASS_ALPHA, sizeof(CLASS_ALPHA) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isalpha(i)) characterclass[i]++; offset += sizeof(CLASS_ALPHA) - 1; } else if (trio_equal_max(CLASS_CNTRL, sizeof(CLASS_CNTRL) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (iscntrl(i)) characterclass[i]++; offset += sizeof(CLASS_CNTRL) - 1; } else if (trio_equal_max(CLASS_DIGIT, sizeof(CLASS_DIGIT) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isdigit(i)) characterclass[i]++; offset += sizeof(CLASS_DIGIT) - 1; } else if (trio_equal_max(CLASS_GRAPH, sizeof(CLASS_GRAPH) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isgraph(i)) characterclass[i]++; offset += sizeof(CLASS_GRAPH) - 1; } else if (trio_equal_max(CLASS_LOWER, sizeof(CLASS_LOWER) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (islower(i)) characterclass[i]++; offset += sizeof(CLASS_LOWER) - 1; } else if (trio_equal_max(CLASS_PRINT, sizeof(CLASS_PRINT) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isprint(i)) characterclass[i]++; offset += sizeof(CLASS_PRINT) - 1; } else if (trio_equal_max(CLASS_PUNCT, sizeof(CLASS_PUNCT) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (ispunct(i)) characterclass[i]++; offset += sizeof(CLASS_PUNCT) - 1; } else if (trio_equal_max(CLASS_SPACE, sizeof(CLASS_SPACE) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isspace(i)) characterclass[i]++; offset += sizeof(CLASS_SPACE) - 1; } else if (trio_equal_max(CLASS_UPPER, sizeof(CLASS_UPPER) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isupper(i)) characterclass[i]++; offset += sizeof(CLASS_UPPER) - 1; } else if (trio_equal_max(CLASS_XDIGIT, sizeof(CLASS_XDIGIT) - 1, &format[offset])) { for (i = 0; i < MAX_CHARACTER_CLASS; i++) if (isxdigit(i)) characterclass[i]++; offset += sizeof(CLASS_XDIGIT) - 1; } else { characterclass[(int)ch]++; } break; default: characterclass[(int)ch]++; break; } break; #endif /* TRIO_EXTENSION */ default: characterclass[(int)ch]++; break; } } return 0; } /************************************************************************* * TrioReadNumber * * We implement our own number conversion in preference of strtol and * strtoul, because we must handle 'long long' and thousand separators. */ TRIO_PRIVATE BOOLEAN_T TrioReadNumber TRIO_ARGS5((self, target, flags, width, base), trio_class_t *self, trio_uintmax_t *target, trio_flags_t flags, int width, int base) { trio_uintmax_t number = 0; int digit; int count; BOOLEAN_T isNegative = FALSE; BOOLEAN_T gotNumber = FALSE; int j; assert(VALID(self)); assert(VALID(self->InStream)); assert((base >= MIN_BASE && base <= MAX_BASE) || (base == NO_BASE)); if (internalDigitsUnconverted) { /* Lazy evaluation of digits array */ memset(internalDigitArray, -1, sizeof(internalDigitArray)); for (j = 0; j < (int)sizeof(internalDigitsLower) - 1; j++) { internalDigitArray[(int)internalDigitsLower[j]] = j; internalDigitArray[(int)internalDigitsUpper[j]] = j; } internalDigitsUnconverted = FALSE; } TrioSkipWhitespaces(self); /* Leading sign */ if (self->current == '+') { self->InStream(self, NULL); } else if (self->current == '-') { self->InStream(self, NULL); isNegative = TRUE; } count = self->processed; if (flags & FLAGS_ALTERNATIVE) { switch (base) { case NO_BASE: case BASE_OCTAL: case BASE_HEX: case BASE_BINARY: if (self->current == '0') { self->InStream(self, NULL); if (self->current) { if ((base == BASE_HEX) && (trio_to_upper(self->current) == 'X')) { self->InStream(self, NULL); } else if ((base == BASE_BINARY) && (trio_to_upper(self->current) == 'B')) { self->InStream(self, NULL); } } } else return FALSE; break; default: break; } } while (((width == NO_WIDTH) || (self->processed - count < width)) && (! ((self->current == EOF) || isspace(self->current)))) { if (isascii(self->current)) { digit = internalDigitArray[self->current]; /* Abort if digit is not allowed in the specified base */ if ((digit == -1) || (digit >= base)) break; } #if TRIO_FEATURE_QUOTE else if (flags & FLAGS_QUOTE) { /* Compare with thousands separator */ for (j = 0; internalThousandSeparator[j] && self->current; j++) { if (internalThousandSeparator[j] != self->current) break; self->InStream(self, NULL); } if (internalThousandSeparator[j]) break; /* Mismatch */ else continue; /* Match */ } #endif else break; number *= base; number += digit; gotNumber = TRUE; /* we need at least one digit */ self->InStream(self, NULL); } /* Was anything read at all? */ if (!gotNumber) return FALSE; if (target) *target = (isNegative) ? (trio_uintmax_t)(-((trio_intmax_t)number)) : number; return TRUE; } /************************************************************************* * TrioReadChar */ TRIO_PRIVATE int TrioReadChar TRIO_ARGS4((self, target, flags, width), trio_class_t *self, char *target, trio_flags_t flags, int width) { int i; char ch; trio_uintmax_t number; assert(VALID(self)); assert(VALID(self->InStream)); for (i = 0; (self->current != EOF) && (i < width); i++) { ch = (char)self->current; self->InStream(self, NULL); if ((flags & FLAGS_ALTERNATIVE) && (ch == CHAR_BACKSLASH)) { switch (self->current) { case '\\': ch = '\\'; break; case 'a': ch = '\007'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case 'v': ch = '\v'; break; default: if (isdigit(self->current)) { /* Read octal number */ if (!TrioReadNumber(self, &number, 0, 3, BASE_OCTAL)) return 0; ch = (char)number; } else if (trio_to_upper(self->current) == 'X') { /* Read hexadecimal number */ self->InStream(self, NULL); if (!TrioReadNumber(self, &number, 0, 2, BASE_HEX)) return 0; ch = (char)number; } else { ch = (char)self->current; } break; } } if (target) target[i] = ch; } return i + 1; } /************************************************************************* * TrioReadString */ TRIO_PRIVATE BOOLEAN_T TrioReadString TRIO_ARGS4((self, target, flags, width), trio_class_t *self, char *target, trio_flags_t flags, int width) { int i; assert(VALID(self)); assert(VALID(self->InStream)); TrioSkipWhitespaces(self); /* * Continue until end of string is reached, a whitespace is encountered, * or width is exceeded */ for (i = 0; ((width == NO_WIDTH) || (i < width)) && (! ((self->current == EOF) || isspace(self->current))); i++) { if (TrioReadChar(self, (target ? &target[i] : 0), flags, 1) == 0) break; /* for */ } if (target) target[i] = NIL; return TRUE; } /************************************************************************* * TrioReadWideChar */ #if TRIO_FEATURE_WIDECHAR TRIO_PRIVATE int TrioReadWideChar TRIO_ARGS4((self, target, flags, width), trio_class_t *self, trio_wchar_t *target, trio_flags_t flags, int width) { int i; int j; int size; int amount = 0; trio_wchar_t wch; char buffer[MB_LEN_MAX + 1]; assert(VALID(self)); assert(VALID(self->InStream)); for (i = 0; (self->current != EOF) && (i < width); i++) { if (isascii(self->current)) { if (TrioReadChar(self, buffer, flags, 1) == 0) return 0; buffer[1] = NIL; } else { /* * Collect a multibyte character, by enlarging buffer until * it contains a fully legal multibyte character, or the * buffer is full. */ j = 0; do { buffer[j++] = (char)self->current; buffer[j] = NIL; self->InStream(self, NULL); } while ((j < (int)sizeof(buffer)) && (mblen(buffer, (size_t)j) != j)); } if (target) { size = mbtowc(&wch, buffer, sizeof(buffer)); if (size > 0) target[i] = wch; } amount += size; self->InStream(self, NULL); } return amount; } #endif /* TRIO_FEATURE_WIDECHAR */ /************************************************************************* * TrioReadWideString */ #if TRIO_FEATURE_WIDECHAR TRIO_PRIVATE BOOLEAN_T TrioReadWideString TRIO_ARGS4((self, target, flags, width), trio_class_t *self, trio_wchar_t *target, trio_flags_t flags, int width) { int i; int size; assert(VALID(self)); assert(VALID(self->InStream)); TrioSkipWhitespaces(self); #if defined(TRIO_COMPILER_SUPPORTS_MULTIBYTE) /* Required by TrioReadWideChar */ (void)mblen(NULL, 0); #endif /* * Continue until end of string is reached, a whitespace is encountered, * or width is exceeded */ for (i = 0; ((width == NO_WIDTH) || (i < width)) && (! ((self->current == EOF) || isspace(self->current))); ) { size = TrioReadWideChar(self, &target[i], flags, 1); if (size == 0) break; /* for */ i += size; } if (target) target[i] = WCONST('\0'); return TRUE; } #endif /* TRIO_FEATURE_WIDECHAR */ /************************************************************************* * TrioReadGroup * * Reads non-empty character groups. * * FIXME: characterclass does not work with multibyte characters */ TRIO_PRIVATE BOOLEAN_T TrioReadGroup TRIO_ARGS5((self, target, characterclass, flags, width), trio_class_t *self, char *target, int *characterclass, trio_flags_t flags, int width) { int ch; int i; assert(VALID(self)); assert(VALID(self->InStream)); ch = self->current; for (i = 0; ((width == NO_WIDTH) || (i < width)) && (! ((ch == EOF) || (((flags & FLAGS_EXCLUDE) != 0) ^ (characterclass[ch] == 0)))); i++) { if (target) target[i] = (char)ch; self->InStream(self, &ch); } if (i == 0) return FALSE; /* Terminate the string if input saved */ if (target) target[i] = NIL; return TRUE; } /************************************************************************* * TrioReadDouble * * FIXME: * add long double * handle base */ #if TRIO_FEATURE_FLOAT TRIO_PRIVATE BOOLEAN_T TrioReadDouble TRIO_ARGS4((self, target, flags, width), trio_class_t *self, trio_pointer_t target, trio_flags_t flags, int width) { int ch; char doubleString[512]; int offset = 0; int start; # if TRIO_FEATURE_QUOTE int j; # endif BOOLEAN_T isHex = FALSE; trio_long_double_t infinity; doubleString[0] = 0; if ((width == NO_WIDTH) || (width > (int)sizeof(doubleString) - 1)) width = sizeof(doubleString) - 1; TrioSkipWhitespaces(self); /* * Read entire double number from stream. trio_to_double requires * a string as input, but InStream can be anything, so we have to * collect all characters. */ ch = self->current; if ((ch == '+') || (ch == '-')) { doubleString[offset++] = (char)ch; self->InStream(self, &ch); width--; } start = offset; switch (ch) { case 'n': case 'N': /* Not-a-number */ if (offset != 0) break; /* FALLTHROUGH */ case 'i': case 'I': /* Infinity */ while (isalpha(ch) && (offset - start < width)) { doubleString[offset++] = (char)ch; self->InStream(self, &ch); } doubleString[offset] = NIL; /* Case insensitive string comparison */ if (trio_equal(&doubleString[start], INFINITE_UPPER) || trio_equal(&doubleString[start], LONG_INFINITE_UPPER)) { infinity = ((start == 1) && (doubleString[0] == '-')) ? trio_ninf() : trio_pinf(); if (flags & FLAGS_LONGDOUBLE) { *((trio_long_double_t *)target) = infinity; } else if (flags & FLAGS_LONG) { *((double *)target) = infinity; } else { *((float *)target) = infinity; } return TRUE; } if (trio_equal(doubleString, NAN_UPPER)) { /* NaN must not have a preceeding + nor - */ if (flags & FLAGS_LONGDOUBLE) { *((trio_long_double_t *)target) = trio_nan(); } else if (flags & FLAGS_LONG) { *((double *)target) = trio_nan(); } else { *((float *)target) = trio_nan(); } return TRUE; } return FALSE; case '0': doubleString[offset++] = (char)ch; self->InStream(self, &ch); if (trio_to_upper(ch) == 'X') { isHex = TRUE; doubleString[offset++] = (char)ch; self->InStream(self, &ch); } break; default: break; } while ((ch != EOF) && (offset - start < width)) { /* Integer part */ if (isHex ? isxdigit(ch) : isdigit(ch)) { doubleString[offset++] = (char)ch; self->InStream(self, &ch); } # if TRIO_FEATURE_QUOTE else if (flags & FLAGS_QUOTE) { /* Compare with thousands separator */ for (j = 0; internalThousandSeparator[j] && self->current; j++) { if (internalThousandSeparator[j] != self->current) break; self->InStream(self, &ch); } if (internalThousandSeparator[j]) break; /* Mismatch */ else continue; /* Match */ } # endif else break; /* while */ } if (ch == '.') { /* Decimal part */ doubleString[offset++] = (char)ch; self->InStream(self, &ch); while ((isHex ? isxdigit(ch) : isdigit(ch)) && (offset - start < width)) { doubleString[offset++] = (char)ch; self->InStream(self, &ch); } } if (isHex ? (trio_to_upper(ch) == 'P') : (trio_to_upper(ch) == 'E')) { /* Exponent */ doubleString[offset++] = (char)ch; self->InStream(self, &ch); if ((ch == '+') || (ch == '-')) { doubleString[offset++] = (char)ch; self->InStream(self, &ch); } while (isdigit(ch) && (offset - start < width)) { doubleString[offset++] = (char)ch; self->InStream(self, &ch); } } if ((offset == start) || (*doubleString == NIL)) return FALSE; doubleString[offset] = 0; if (flags & FLAGS_LONGDOUBLE) { *((trio_long_double_t *)target) = trio_to_long_double(doubleString, NULL); } else if (flags & FLAGS_LONG) { *((double *)target) = trio_to_double(doubleString, NULL); } else { *((float *)target) = trio_to_float(doubleString, NULL); } return TRUE; } #endif /* TRIO_FEATURE_FLOAT */ /************************************************************************* * TrioReadPointer */ TRIO_PRIVATE BOOLEAN_T TrioReadPointer TRIO_ARGS3((self, target, flags), trio_class_t *self, trio_pointer_t *target, trio_flags_t flags) { trio_uintmax_t number; char buffer[sizeof(internalNullString)]; flags |= (FLAGS_UNSIGNED | FLAGS_ALTERNATIVE | FLAGS_NILPADDING); if (TrioReadNumber(self, &number, flags, POINTER_WIDTH, BASE_HEX)) { if (target) { #if defined(TRIO_COMPILER_GCC) || defined(TRIO_COMPILER_MIPSPRO) /* * The strange assignment of number is a workaround for a compiler * warning */ *target = &((char *)0)[number]; #else *target = (trio_pointer_t)number; #endif } return TRUE; } else if (TrioReadString(self, (flags & FLAGS_IGNORE) ? NULL : buffer, 0, sizeof(internalNullString) - 1)) { if (trio_equal_case(buffer, internalNullString)) { if (target) *target = NULL; return TRUE; } } return FALSE; } /************************************************************************* * TrioScanProcess */ TRIO_PRIVATE int TrioScanProcess TRIO_ARGS3((data, format, parameters), trio_class_t *data, TRIO_CONST char *format, trio_parameter_t *parameters) { int status; int assignment; int ch; int offset; /* Offset of format string */ int i; /* Offset of current parameter */ trio_flags_t flags; int width; int base; trio_pointer_t pointer; /* Return on empty format string */ if (format[0] == NIL) return 0; status = 0; assignment = 0; i = 0; offset = 0; data->InStream(data, &ch); for (;;) { /* Skip the parameter entries */ while (parameters[i].type == FORMAT_PARAMETER) { assert(i <= MAX_PARAMETERS); i++; } /* Compare non conversion-specifier part of format string */ while (offset < parameters[i].beginOffset) { if ((CHAR_IDENTIFIER == format[offset]) && (CHAR_IDENTIFIER == format[offset + 1])) { /* Two % in format matches one % in input stream */ if (CHAR_IDENTIFIER == ch) { data->InStream(data, &ch); offset += 2; continue; /* while format chars left */ } else { status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset); goto end; } } else /* Not an % identifier */ { if (isspace((int)format[offset])) { /* Whitespaces may match any amount of whitespaces */ ch = TrioSkipWhitespaces(data); } else if (ch == format[offset]) { data->InStream(data, &ch); } else { status = assignment; goto end; } offset++; } } if (parameters[i].type == FORMAT_SENTINEL) break; if ((EOF == ch) && (parameters[i].type != FORMAT_COUNT)) { status = (assignment > 0) ? assignment : EOF; goto end; } flags = parameters[i].flags; /* Find width */ width = parameters[i].width; if (flags & FLAGS_WIDTH_PARAMETER) { /* Get width from parameter list */ width = (int)parameters[width].data.number.as_signed; } /* Find base */ if (NO_BASE != parameters[i].baseSpecifier) { /* Base from specifier has priority */ base = parameters[i].baseSpecifier; } else if (flags & FLAGS_BASE_PARAMETER) { /* Get base from parameter list */ base = parameters[i].base; base = (int)parameters[base].data.number.as_signed; } else { /* Use base from format string */ base = parameters[i].base; } switch (parameters[i].type) { case FORMAT_INT: { trio_uintmax_t number; if (0 == base) base = BASE_DECIMAL; if (!TrioReadNumber(data, &number, flags, width, base)) { status = assignment; goto end; } if (!(flags & FLAGS_IGNORE)) { assignment++; pointer = parameters[i].data.pointer; #if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER if (flags & FLAGS_SIZE_T) *(size_t *)pointer = (size_t)number; else #endif #if TRIO_FEATURE_PTRDIFF_T if (flags & FLAGS_PTRDIFF_T) *(ptrdiff_t *)pointer = (ptrdiff_t)number; else #endif #if TRIO_FEATURE_INTMAX_T if (flags & FLAGS_INTMAX_T) *(trio_intmax_t *)pointer = (trio_intmax_t)number; else #endif if (flags & FLAGS_QUAD) *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)number; else if (flags & FLAGS_LONG) *(long int *)pointer = (long int)number; else if (flags & FLAGS_SHORT) *(short int *)pointer = (short int)number; else *(int *)pointer = (int)number; } } break; /* FORMAT_INT */ case FORMAT_STRING: #if TRIO_FEATURE_WIDECHAR if (flags & FLAGS_WIDECHAR) { if (!TrioReadWideString(data, (flags & FLAGS_IGNORE) ? NULL : parameters[i].data.wstring, flags, width)) { status = assignment; goto end; } } else #endif { if (!TrioReadString(data, (flags & FLAGS_IGNORE) ? NULL : parameters[i].data.string, flags, width)) { status = assignment; goto end; } } if (!(flags & FLAGS_IGNORE)) assignment++; break; /* FORMAT_STRING */ #if TRIO_FEATURE_FLOAT case FORMAT_DOUBLE: { if (flags & FLAGS_IGNORE) { pointer = NULL; } else { pointer = (flags & FLAGS_LONGDOUBLE) ? (trio_pointer_t)parameters[i].data.longdoublePointer : (trio_pointer_t)parameters[i].data.doublePointer; } if (!TrioReadDouble(data, pointer, flags, width)) { status = assignment; goto end; } if (!(flags & FLAGS_IGNORE)) { assignment++; } break; /* FORMAT_DOUBLE */ } #endif case FORMAT_GROUP: { int characterclass[MAX_CHARACTER_CLASS + 1]; /* Skip over modifiers */ while (format[offset] != SPECIFIER_GROUP) { offset++; } /* Skip over group specifier */ offset++; memset(characterclass, 0, sizeof(characterclass)); status = TrioGetCharacterClass(format, &offset, &flags, characterclass); if (status < 0) goto end; if (!TrioReadGroup(data, (flags & FLAGS_IGNORE) ? NULL : parameters[i].data.string, characterclass, flags, parameters[i].width)) { status = assignment; goto end; } if (!(flags & FLAGS_IGNORE)) assignment++; } break; /* FORMAT_GROUP */ case FORMAT_COUNT: pointer = parameters[i].data.pointer; if (NULL != pointer) { int count = data->processed; if (ch != EOF) count--; /* a character is read, but is not consumed yet */ #if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_SIZE_T_UPPER if (flags & FLAGS_SIZE_T) *(size_t *)pointer = (size_t)count; else #endif #if TRIO_FEATURE_PTRDIFF_T if (flags & FLAGS_PTRDIFF_T) *(ptrdiff_t *)pointer = (ptrdiff_t)count; else #endif #if TRIO_FEATURE_INTMAX_T if (flags & FLAGS_INTMAX_T) *(trio_intmax_t *)pointer = (trio_intmax_t)count; else #endif if (flags & FLAGS_QUAD) { *(trio_ulonglong_t *)pointer = (trio_ulonglong_t)count; } else if (flags & FLAGS_LONG) { *(long int *)pointer = (long int)count; } else if (flags & FLAGS_SHORT) { *(short int *)pointer = (short int)count; } else { *(int *)pointer = (int)count; } } break; /* FORMAT_COUNT */ case FORMAT_CHAR: #if TRIO_FEATURE_WIDECHAR if (flags & FLAGS_WIDECHAR) { if (TrioReadWideChar(data, (flags & FLAGS_IGNORE) ? NULL : parameters[i].data.wstring, flags, (width == NO_WIDTH) ? 1 : width) == 0) { status = assignment; goto end; } } else #endif { if (TrioReadChar(data, (flags & FLAGS_IGNORE) ? NULL : parameters[i].data.string, flags, (width == NO_WIDTH) ? 1 : width) == 0) { status = assignment; goto end; } } if (!(flags & FLAGS_IGNORE)) assignment++; break; /* FORMAT_CHAR */ case FORMAT_POINTER: if (!TrioReadPointer(data, (flags & FLAGS_IGNORE) ? NULL : (trio_pointer_t *)parameters[i].data.pointer, flags)) { status = assignment; goto end; } if (!(flags & FLAGS_IGNORE)) assignment++; break; /* FORMAT_POINTER */ case FORMAT_PARAMETER: break; /* FORMAT_PARAMETER */ default: status = TRIO_ERROR_RETURN(TRIO_EINVAL, offset); goto end; } ch = data->current; offset = parameters[i].endOffset; i++; } status = assignment; end: if (data->UndoStream) data->UndoStream(data); return status; } /************************************************************************* * TrioScan */ TRIO_PRIVATE int TrioScan TRIO_ARGS8((source, sourceSize, InStream, UndoStream, format, arglist, argfunc, argarray), trio_pointer_t source, size_t sourceSize, void (*InStream) TRIO_PROTO((trio_class_t *, int *)), void (*UndoStream) TRIO_PROTO((trio_class_t *)), TRIO_CONST char *format, va_list arglist, trio_argfunc_t argfunc, trio_pointer_t *argarray) { int status; trio_parameter_t parameters[MAX_PARAMETERS]; trio_class_t data; assert(VALID(InStream)); assert(VALID(format)); memset(&data, 0, sizeof(data)); data.InStream = InStream; data.UndoStream = UndoStream; data.location = (trio_pointer_t)source; data.max = sourceSize; data.error = 0; #if defined(USE_LOCALE) if (NULL == internalLocaleValues) { TrioSetLocale(); } #endif status = TrioParse(TYPE_SCAN, format, parameters, arglist, argfunc, argarray); if (status < 0) return status; status = TrioScanProcess(&data, format, parameters); if (data.error != 0) { status = data.error; } return status; } /************************************************************************* * TrioInStreamFile */ #if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO TRIO_PRIVATE void TrioInStreamFile TRIO_ARGS2((self, intPointer), trio_class_t *self, int *intPointer) { FILE *file = (FILE *)self->location; assert(VALID(self)); assert(VALID(file)); self->actually.cached = 0; /* The initial value of self->current is zero */ if (self->current == EOF) { self->error = (ferror(file)) ? TRIO_ERROR_RETURN(TRIO_ERRNO, 0) : TRIO_ERROR_RETURN(TRIO_EOF, 0); } else { self->processed++; self->actually.cached++; } self->current = fgetc(file); if (VALID(intPointer)) { *intPointer = self->current; } } #endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */ /************************************************************************* * TrioUndoStreamFile */ #if TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO TRIO_PRIVATE void TrioUndoStreamFile TRIO_ARGS1((self), trio_class_t *self) { FILE *file = (FILE *)self->location; assert(VALID(self)); assert(VALID(file)); if (self->actually.cached > 0) { assert(self->actually.cached == 1); self->current = ungetc(self->current, file); self->actually.cached = 0; } } #endif /* TRIO_FEATURE_FILE || TRIO_FEATURE_STDIO */ /************************************************************************* * TrioInStreamFileDescriptor */ #if TRIO_FEATURE_FD TRIO_PRIVATE void TrioInStreamFileDescriptor TRIO_ARGS2((self, intPointer), trio_class_t *self, int *intPointer) { int fd = *((int *)self->location); int size; unsigned char input; assert(VALID(self)); self->actually.cached = 0; size = read(fd, &input, sizeof(char)); if (size == -1) { self->error = TRIO_ERROR_RETURN(TRIO_ERRNO, 0); self->current = EOF; } else { self->current = (size == 0) ? EOF : input; } if (self->current != EOF) { self->actually.cached++; self->processed++; } if (VALID(intPointer)) { *intPointer = self->current; } } #endif /* TRIO_FEATURE_FD */ /************************************************************************* * TrioInStreamCustom */ #if TRIO_FEATURE_CLOSURE TRIO_PRIVATE void TrioInStreamCustom TRIO_ARGS2((self, intPointer), trio_class_t *self, int *intPointer) { trio_custom_t *data; assert(VALID(self)); assert(VALID(self->location)); self->actually.cached = 0; data = (trio_custom_t *)self->location; self->current = (data->stream.in == NULL) ? NIL : (data->stream.in)(data->closure); if (self->current == NIL) { self->current = EOF; } else { self->processed++; self->actually.cached++; } if (VALID(intPointer)) { *intPointer = self->current; } } #endif /* TRIO_FEATURE_CLOSURE */ /************************************************************************* * TrioInStreamString */ TRIO_PRIVATE void TrioInStreamString TRIO_ARGS2((self, intPointer), trio_class_t *self, int *intPointer) { unsigned char **buffer; assert(VALID(self)); assert(VALID(self->location)); self->actually.cached = 0; buffer = (unsigned char **)self->location; self->current = (*buffer)[0]; if (self->current == NIL) { self->current = EOF; } else { (*buffer)++; self->processed++; self->actually.cached++; } if (VALID(intPointer)) { *intPointer = self->current; } } /************************************************************************* * * Formatted scanning functions * ************************************************************************/ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_scanf.h" #endif /** @addtogroup Scanf @{ */ /************************************************************************* * scanf */ /** Scan characters from standard input stream. @param format Formatting string. @param ... Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_STDIO TRIO_PUBLIC int trio_scanf TRIO_VARGS2((format, va_alist), TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); TRIO_VA_START(args, format); status = TrioScan((trio_pointer_t)stdin, 0, TrioInStreamFile, TrioUndoStreamFile, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_STDIO */ /** Scan characters from standard input stream. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_STDIO TRIO_PUBLIC int trio_vscanf TRIO_ARGS2((format, args), TRIO_CONST char *format, va_list args) { assert(VALID(format)); return TrioScan((trio_pointer_t)stdin, 0, TrioInStreamFile, TrioUndoStreamFile, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_STDIO */ /** Scan characters from standard input stream. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_STDIO TRIO_PUBLIC int trio_scanfv TRIO_ARGS2((format, args), TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; assert(VALID(format)); return TrioScan((trio_pointer_t)stdin, 0, TrioInStreamFile, TrioUndoStreamFile, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_STDIO */ /************************************************************************* * fscanf */ /** Scan characters from file. @param file File pointer. @param format Formatting string. @param ... Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_FILE TRIO_PUBLIC int trio_fscanf TRIO_VARGS3((file, format, va_alist), FILE *file, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(file)); assert(VALID(format)); TRIO_VA_START(args, format); status = TrioScan((trio_pointer_t)file, 0, TrioInStreamFile, TrioUndoStreamFile, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_FILE */ /** Scan characters from file. @param file File pointer. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_FILE TRIO_PUBLIC int trio_vfscanf TRIO_ARGS3((file, format, args), FILE *file, TRIO_CONST char *format, va_list args) { assert(VALID(file)); assert(VALID(format)); return TrioScan((trio_pointer_t)file, 0, TrioInStreamFile, TrioUndoStreamFile, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_FILE */ /** Scan characters from file. @param file File pointer. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_FILE TRIO_PUBLIC int trio_fscanfv TRIO_ARGS3((file, format, args), FILE *file, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; assert(VALID(file)); assert(VALID(format)); return TrioScan((trio_pointer_t)file, 0, TrioInStreamFile, TrioUndoStreamFile, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_FILE */ /************************************************************************* * dscanf */ /** Scan characters from file descriptor. @param fd File descriptor. @param format Formatting string. @param ... Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_FD TRIO_PUBLIC int trio_dscanf TRIO_VARGS3((fd, format, va_alist), int fd, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(format)); TRIO_VA_START(args, format); status = TrioScan((trio_pointer_t)&fd, 0, TrioInStreamFileDescriptor, NULL, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_FD */ /** Scan characters from file descriptor. @param fd File descriptor. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_FD TRIO_PUBLIC int trio_vdscanf TRIO_ARGS3((fd, format, args), int fd, TRIO_CONST char *format, va_list args) { assert(VALID(format)); return TrioScan((trio_pointer_t)&fd, 0, TrioInStreamFileDescriptor, NULL, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_FD */ /** Scan characters from file descriptor. @param fd File descriptor. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ #if TRIO_FEATURE_FD TRIO_PUBLIC int trio_dscanfv TRIO_ARGS3((fd, format, args), int fd, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; assert(VALID(format)); return TrioScan((trio_pointer_t)&fd, 0, TrioInStreamFileDescriptor, NULL, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_FD */ /************************************************************************* * cscanf */ #if TRIO_FEATURE_CLOSURE TRIO_PUBLIC int trio_cscanf TRIO_VARGS4((stream, closure, format, va_alist), trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); TRIO_VA_START(args, format); data.stream.in = stream; data.closure = closure; status = TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL, NULL); TRIO_VA_END(args); return status; } #endif /* TRIO_FEATURE_CLOSURE */ #if TRIO_FEATURE_CLOSURE TRIO_PUBLIC int trio_vcscanf TRIO_ARGS4((stream, closure, format, args), trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, va_list args) { trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); data.stream.in = stream; data.closure = closure; return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, args, NULL, NULL); } #endif /* TRIO_FEATURE_CLOSURE */ #if TRIO_FEATURE_CLOSURE TRIO_PUBLIC int trio_cscanfv TRIO_ARGS4((stream, closure, format, args), trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); data.stream.in = stream; data.closure = closure; return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_CLOSURE */ #if TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC TRIO_PUBLIC int trio_cscanff TRIO_ARGS5((stream, closure, format, argfunc, context), trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_argfunc_t argfunc, trio_pointer_t context) { static va_list unused; trio_custom_t data; assert(VALID(stream)); assert(VALID(format)); assert(VALID(argfunc)); data.stream.in = stream; data.closure = closure; return TrioScan(&data, 0, TrioInStreamCustom, NULL, format, unused, argfunc, (trio_pointer_t *)context); } #endif /* TRIO_FEATURE_CLOSURE && TRIO_FEATURE_ARGFUNC */ /************************************************************************* * sscanf */ /** Scan characters from string. @param buffer Input string. @param format Formatting string. @param ... Arguments. @return Number of scanned characters. */ TRIO_PUBLIC int trio_sscanf TRIO_VARGS3((buffer, format, va_alist), TRIO_CONST char *buffer, TRIO_CONST char *format, TRIO_VA_DECL) { int status; va_list args; assert(VALID(buffer)); assert(VALID(format)); TRIO_VA_START(args, format); status = TrioScan((trio_pointer_t)&buffer, 0, TrioInStreamString, NULL, format, args, NULL, NULL); TRIO_VA_END(args); return status; } /** Scan characters from string. @param buffer Input string. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ TRIO_PUBLIC int trio_vsscanf TRIO_ARGS3((buffer, format, args), TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args) { assert(VALID(buffer)); assert(VALID(format)); return TrioScan((trio_pointer_t)&buffer, 0, TrioInStreamString, NULL, format, args, NULL, NULL); } /** Scan characters from string. @param buffer Input string. @param format Formatting string. @param args Arguments. @return Number of scanned characters. */ TRIO_PUBLIC int trio_sscanfv TRIO_ARGS3((buffer, format, args), TRIO_CONST char *buffer, TRIO_CONST char *format, trio_pointer_t *args) { static va_list unused; assert(VALID(buffer)); assert(VALID(format)); return TrioScan((trio_pointer_t)&buffer, 0, TrioInStreamString, NULL, format, unused, TrioArrayGetter, args); } #endif /* TRIO_FEATURE_SCANF */ /** @} End of Scanf documentation module */ /************************************************************************* * trio_strerror */ TRIO_PUBLIC TRIO_CONST char * trio_strerror TRIO_ARGS1((errorcode), int errorcode) { #if TRIO_FEATURE_STRERR /* Textual versions of the error codes */ switch (TRIO_ERROR_CODE(errorcode)) { case TRIO_EOF: return "End of file"; case TRIO_EINVAL: return "Invalid argument"; case TRIO_ETOOMANY: return "Too many arguments"; case TRIO_EDBLREF: return "Double reference"; case TRIO_EGAP: return "Reference gap"; case TRIO_ENOMEM: return "Out of memory"; case TRIO_ERANGE: return "Invalid range"; case TRIO_ECUSTOM: return "Custom error"; default: return "Unknown"; } #else return "Unknown"; #endif } ================================================ FILE: src/trio/trio.h ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************* * * http://ctrio.sourceforge.net/ * ************************************************************************/ #ifndef TRIO_TRIO_H #define TRIO_TRIO_H #if !defined(WITHOUT_TRIO) /* * Use autoconf defines if present. Packages using trio must define * HAVE_CONFIG_H as a compiler option themselves. */ #if defined(HAVE_CONFIG_H) # include #endif #include "triop.h" #include #ifdef __cplusplus extern "C" { #endif /* * Error codes. * * Remember to add a textual description to trio_strerror. */ enum { TRIO_EOF = 1, TRIO_EINVAL = 2, TRIO_ETOOMANY = 3, TRIO_EDBLREF = 4, TRIO_EGAP = 5, TRIO_ENOMEM = 6, TRIO_ERANGE = 7, TRIO_ERRNO = 8, TRIO_ECUSTOM = 9 }; /* Error macros */ #define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF) #define TRIO_ERROR_POSITION(x) ((-(x)) >> 8) #define TRIO_ERROR_NAME(x) trio_strerror(x) /* Argument function types */ enum { TRIO_TYPE_POINTER = 1, TRIO_TYPE_CHAR = 2, TRIO_TYPE_SHORT = 3, TRIO_TYPE_INT = 4, TRIO_TYPE_LONG = 5, TRIO_TYPE_ULONGLONG = 6, TRIO_TYPE_UINTMAX = 7, TRIO_TYPE_PTRDIFF = 8, TRIO_TYPE_SIZE = 9, TRIO_TYPE_PCHAR = 10, TRIO_TYPE_PWCHAR = 11, TRIO_TYPE_FLOAT = 12, TRIO_TYPE_DOUBLE = 13, TRIO_TYPE_LONGDOUBLE = 14 }; typedef trio_pointer_t (*trio_argfunc_t) TRIO_PROTO((trio_pointer_t, int, int)); typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int)); typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t)); TRIO_CONST char *trio_strerror TRIO_PROTO((int)); /************************************************************************* * Print Functions */ #if defined(TRIO_COMPILER_GCC) && !TRIO_EXTENSION # define TRIO_PROTO_PRINTF(x,a) TRIO_PROTO(x) __attribute__ ((format (gnu_printf, a, a+1))) # define TRIO_PROTO_SCANF(x,a) TRIO_PROTO(x) __attribute__ ((format (gnu_scanf, a, a+1))) #else # define TRIO_PROTO_PRINTF(x,a) TRIO_PROTO(x) # define TRIO_PROTO_SCANF(x,a) TRIO_PROTO(x) #endif int trio_printf TRIO_PROTO_PRINTF((TRIO_CONST char *format, ...), 1); int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); int trio_printfv TRIO_PROTO((TRIO_CONST char *format, trio_pointer_t *args)); int trio_fprintf TRIO_PROTO_PRINTF((FILE *file, TRIO_CONST char *format, ...), 2); int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, trio_pointer_t *args)); int trio_dprintf TRIO_PROTO_PRINTF((int fd, TRIO_CONST char *format, ...), 2); int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, trio_pointer_t *args)); int trio_cprintf TRIO_PROTO_PRINTF((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, ...), 3); int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, va_list args)); int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_pointer_t *args)); int trio_cprintff TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_argfunc_t func, trio_pointer_t context)); int trio_sprintf TRIO_PROTO_PRINTF((char *buffer, TRIO_CONST char *format, ...), 2); int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args)); int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, trio_pointer_t *args)); int trio_snprintf TRIO_PROTO_PRINTF((char *buffer, size_t max, TRIO_CONST char *format, ...), 3); int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, va_list args)); int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, trio_pointer_t *args)); int trio_snprintfcat TRIO_PROTO_PRINTF((char *buffer, size_t max, TRIO_CONST char *format, ...), 3); int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, va_list args)); #if defined(TRIO_DEPRECATED) char *trio_aprintf TRIO_PROTO_PRINTF((TRIO_CONST char *format, ...), 1); char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); #endif int trio_asprintf TRIO_PROTO_PRINTF((char **ret, TRIO_CONST char *format, ...), 2); int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args)); int trio_asprintfv TRIO_PROTO((char **result, TRIO_CONST char *format, trio_pointer_t * args)); /************************************************************************* * Scan Functions */ int trio_scanf TRIO_PROTO_SCANF((TRIO_CONST char *format, ...), 1); int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args)); int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args)); int trio_fscanf TRIO_PROTO_SCANF((FILE *file, TRIO_CONST char *format, ...), 2); int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); int trio_dscanf TRIO_PROTO_SCANF((int fd, TRIO_CONST char *format, ...), 2); int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); int trio_cscanf TRIO_PROTO_SCANF((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, ...), 3); int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, va_list args)); int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, void **args)); int trio_cscanff TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, trio_argfunc_t func, trio_pointer_t context)); int trio_sscanf TRIO_PROTO_SCANF((TRIO_CONST char *buffer, TRIO_CONST char *format, ...), 2); int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args)); int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args)); /************************************************************************* * Locale Functions */ void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint)); void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator)); void trio_locale_set_grouping TRIO_PROTO((char *grouping)); /************************************************************************* * Renaming */ #ifdef TRIO_REPLACE_STDIO /* Replace the functions */ #ifndef HAVE_PRINTF # undef printf # define printf trio_printf #endif #ifndef HAVE_VPRINTF # undef vprintf # define vprintf trio_vprintf #endif #ifndef HAVE_FPRINTF # undef fprintf # define fprintf trio_fprintf #endif #ifndef HAVE_VFPRINTF # undef vfprintf # define vfprintf trio_vfprintf #endif #ifndef HAVE_SPRINTF # undef sprintf # define sprintf trio_sprintf #endif #ifndef HAVE_VSPRINTF # undef vsprintf # define vsprintf trio_vsprintf #endif #ifndef HAVE_SNPRINTF # undef snprintf # define snprintf trio_snprintf #endif #ifndef HAVE_VSNPRINTF # undef vsnprintf # define vsnprintf trio_vsnprintf #endif #ifndef HAVE_SCANF # undef scanf # define scanf trio_scanf #endif #ifndef HAVE_VSCANF # undef vscanf # define vscanf trio_vscanf #endif #ifndef HAVE_FSCANF # undef fscanf # define fscanf trio_fscanf #endif #ifndef HAVE_VFSCANF # undef vfscanf # define vfscanf trio_vfscanf #endif #ifndef HAVE_SSCANF # undef sscanf # define sscanf trio_sscanf #endif #ifndef HAVE_VSSCANF # undef vsscanf # define vsscanf trio_vsscanf #endif /* These aren't stdio functions, but we make them look similar */ #undef dprintf #define dprintf trio_dprintf #undef vdprintf #define vdprintf trio_vdprintf #undef aprintf #define aprintf trio_aprintf #undef vaprintf #define vaprintf trio_vaprintf #undef asprintf #define asprintf trio_asprintf #undef vasprintf #define vasprintf trio_vasprintf #undef dscanf #define dscanf trio_dscanf #undef vdscanf #define vdscanf trio_vdscanf #endif #ifdef __cplusplus } /* extern "C" */ #endif #endif /* WITHOUT_TRIO */ #endif /* TRIO_TRIO_H */ ================================================ FILE: src/trio/triodef.h ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 2001 Bjorn Reese * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ #ifndef TRIO_TRIODEF_H #define TRIO_TRIODEF_H /************************************************************************* * Compiler support detection */ #if defined(__GNUC__) # define TRIO_COMPILER_GCC #endif #if defined(__SUNPRO_CC) # define TRIO_COMPILER_SUNPRO __SUNPRO_CC #else # if defined(__SUNPRO_C) # define TRIO_COMPILER_SUNPRO __SUNPRO_C # endif #endif #if defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__) # define TRIO_COMPILER_XLC #else # if defined(_AIX) && !defined(__GNUC__) # define TRIO_COMPILER_XLC /* Workaround for old xlc */ # endif #endif #if defined(__DECC) || defined(__DECCXX) # define TRIO_COMPILER_DECC #else # if defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__) # define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */ # endif #endif #if defined(__HP_aCC) || defined(__HP_cc) # define TRIO_COMPILER_HP #endif #if defined(sgi) || defined(__sgi) # define TRIO_COMPILER_MIPSPRO #endif #if defined(_MSC_VER) # define TRIO_COMPILER_MSVC #endif #if defined(__BORLANDC__) # define TRIO_COMPILER_BCB #endif /************************************************************************* * Platform support detection */ #if defined(VMS) || defined(__VMS) # define TRIO_PLATFORM_VMS #endif #if defined(unix) || defined(__unix) || defined(__unix__) # define TRIO_PLATFORM_UNIX #endif #if defined(TRIO_COMPILER_XLC) || defined(_AIX) # define TRIO_PLATFORM_UNIX #endif #if defined(TRIO_COMPILER_DECC) || defined(__osf___) # if !defined(TRIO_PLATFORM_VMS) # define TRIO_PLATFORM_UNIX # endif #endif #if defined(__NetBSD__) # define TRIO_PLATFORM_UNIX #endif #if defined(__Lynx__) # define TRIO_PLATFORM_UNIX # define TRIO_PLATFORM_LYNX #endif #if defined(__APPLE__) && defined(__MACH__) # define TRIO_PLATFORM_UNIX #endif #if defined(__QNX__) # define TRIO_PLATFORM_UNIX # define TRIO_PLATFORM_QNX #endif #if defined(__CYGWIN__) # define TRIO_PLATFORM_UNIX #endif #if defined(AMIGA) && defined(TRIO_COMPILER_GCC) # define TRIO_PLATFORM_UNIX #endif #if defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32) # define TRIO_PLATFORM_WIN32 #endif #if defined(_WIN32_WCE) # define TRIO_PLATFORM_WINCE #endif #if defined(mpeix) || defined(__mpexl) # define TRIO_PLATFORM_MPEIX #endif #if defined(_AIX) # define TRIO_PLATFORM_AIX #endif #if defined(__hpux) # define TRIO_PLATFORM_HPUX #endif #if defined(sun) || defined(__sun__) # if defined(__SVR4) || defined(__svr4__) # define TRIO_PLATFORM_SOLARIS # else # define TRIO_PLATFORM_SUNOS # endif #endif #if defined(__powerpc) || defined(__powerpc__) || defined(_ARCH_PPC) # define TRIO_CPU_POWERPC #endif #if defined(__sparc) || defined(__sparc__) # define TRIO_CPU_SPARC #endif #if defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH__) # define TRIO_CPU_SYSTEMZ #endif /************************************************************************* * Standards support detection */ #if defined(__STDC__) \ || defined(_MSC_EXTENSIONS) \ || defined(TRIO_COMPILER_BCB) # define PREDEF_STANDARD_C89 #endif #if defined(__STDC_VERSION__) # define PREDEF_STANDARD_C90 #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L) # define PREDEF_STANDARD_C94 #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define PREDEF_STANDARD_C99 #endif #if defined(TRIO_COMPILER_SUNPRO) && (TRIO_COMPILER_SUNPRO >= 0x420) # if !defined(PREDEF_STANDARD_C94) # define PREDEF_STANDARD_C94 # endif #endif #if defined(__cplusplus) # define PREDEF_STANDARD_CXX #endif #if defined(__cplusplus) && (__cplusplus >= 199711L) # define PREDEF_STANDARD_CXX89 #endif #if defined(TRIO_PLATFORM_UNIX) # include #endif #if defined(_POSIX_VERSION) # define PREDEF_STANDARD_POSIX _POSIX_VERSION # if (_POSIX_VERSION >= 199506L) # define PREDEF_STANDARD_POSIX_1996 # endif #endif #if (_XOPEN_VERSION - 0 >= 3) || defined(_XOPEN_XPG3) # define PREDEF_STANDARD_XPG3 #endif #if (_XOPEN_VERSION - 0 >= 4) || defined(_XOPEN_XPG4) # define PREDEF_STANDARD_XPG4 #endif #if (_XOPEN_VERSION - 0 > 4) \ || (defined(_XOPEN_UNIX) && (_XOPEN_VERSION - 0 == 4)) # define PREDEF_STANDARD_UNIX95 #endif #if (_XOPEN_VERSION - 0 >= 500) # define PREDEF_STANDARD_UNIX98 #endif #if (_XOPEN_VERSION - 0 >= 600) # define PREDEF_STANDARD_UNIX03 #endif /************************************************************************* * Generic defines */ #if !defined(TRIO_PUBLIC) /* Based on http://gcc.gnu.org/wiki/Visibility */ # if defined(TRIO_PLATFORM_WIN32) || defined (__CYGWIN__) # if defined(BUILDING_DLL) # if defined(TRIO_COMPILER_GCC) # define TRIO_PUBLIC __attribute__ ((dllexport)) # else # define TRIO_PUBLIC __declspec(dllexport) # endif # else # if defined(TRIO_COMPILER_GCC) # define TRIO_PUBLIC __attribute__ ((dllimport)) # else # define TRIO_PUBLIC __declspec(dllimport) # endif # endif # else # if defined(TRIO_COMPILER_GCC) && __GNUC__ >= 4 # define TRIO_PUBLIC __attribute__ ((visibility ("default"))) # define TRIO_PRIVATE __attribute__ ((visibility ("hidden"))) # else # define TRIO_PUBLIC # endif # endif #endif #if !defined(TRIO_PRIVATE) # define TRIO_PRIVATE static #endif #if !(defined(PREDEF_STANDARD_C89) || defined(PREDEF_STANDARD_CXX)) # define TRIO_COMPILER_ANCIENT #endif #if defined(TRIO_COMPILER_ANCIENT) # define TRIO_CONST # define TRIO_VOLATILE # define TRIO_SIGNED typedef double trio_long_double_t; typedef char * trio_pointer_t; # define TRIO_SUFFIX_LONG(x) x # define TRIO_PROTO(x) () # define TRIO_NOARGS # define TRIO_ARGS1(list,a1) list a1; # define TRIO_ARGS2(list,a1,a2) list a1; a2; # define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3; # define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4; # define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5; # define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6; # define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) list a1; a2; a3; a4; a5; a6; a7; # define TRIO_ARGS8(list,a1,a2,a3,a4,a5,a6,a7,a8) list a1; a2; a3; a4; a5; a6; a7; a8; # define TRIO_VARGS2(list,a1,a2) list a1; a2 # define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3 # define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4 # define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5 # define TRIO_VA_DECL va_dcl # define TRIO_VA_START(x,y) va_start(x) # define TRIO_VA_END(x) va_end(x) #else /* ANSI C */ # define TRIO_CONST const # define TRIO_VOLATILE volatile # define TRIO_SIGNED signed typedef long double trio_long_double_t; typedef void * trio_pointer_t; # define TRIO_SUFFIX_LONG(x) x ## L # define TRIO_PROTO(x) x # define TRIO_NOARGS void # define TRIO_ARGS1(list,a1) (a1) # define TRIO_ARGS2(list,a1,a2) (a1,a2) # define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3) # define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4) # define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5) # define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6) # define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) (a1,a2,a3,a4,a5,a6,a7) # define TRIO_ARGS8(list,a1,a2,a3,a4,a5,a6,a7,a8) (a1,a2,a3,a4,a5,a6,a7,a8) # define TRIO_VARGS2 TRIO_ARGS2 # define TRIO_VARGS3 TRIO_ARGS3 # define TRIO_VARGS4 TRIO_ARGS4 # define TRIO_VARGS5 TRIO_ARGS5 # define TRIO_VA_DECL ... # define TRIO_VA_START(x,y) va_start(x,y) # define TRIO_VA_END(x) va_end(x) #endif #if defined(PREDEF_STANDARD_C99) || defined(PREDEF_STANDARD_CXX) # define TRIO_INLINE inline #else # if defined(TRIO_COMPILER_GCC) # define TRIO_INLINE __inline__ # endif # if defined(TRIO_COMPILER_MSVC) # define TRIO_INLINE _inline # endif # if defined(TRIO_COMPILER_BCB) # define TRIO_INLINE __inline # endif #endif #if !defined(TRIO_INLINE) # define TRIO_INLINE #endif /************************************************************************* * Workarounds */ #if defined(TRIO_PLATFORM_VMS) /* * Computations done with constants at compile time can trigger these * even when compiling with IEEE enabled. */ # pragma message disable (UNDERFLOW, FLOATOVERFL) # if (__CRTL_VER < 80210001) /* * Although the compiler supports C99 language constructs, the C * run-time library does not contain all C99 functions. */ # if defined(PREDEF_STANDARD_C99) # undef PREDEF_STANDARD_C99 # endif # endif #endif /* * Not all preprocessors supports the LL token. */ #if defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) #else # define TRIO_COMPILER_SUPPORTS_LL #endif #if defined(__CYGWIN__) /* * Cygwin defines the macros for hosted C99, but does not support certain * long double math functions. */ # include # define TRIO_CYGWIN_VERSION_API CYGWIN_VERSION_API_MAJOR * 1000 + \ CYGWIN_VERSION_API_MINOR /* * Please change the version number below when the Cygwin API supports * long double math functions (powl, fmodl, etc.) */ # if TRIO_CYGWIN_VERSION_API < 99999999 # define TRIO_NO_FLOORL 1 # define TRIO_NO_CEILL 1 # define TRIO_NO_POWL 1 # define TRIO_NO_FMODL 1 # define TRIO_NO_LOG10L 1 # endif #endif # if defined(TRIO_CPU_POWERPC) || defined(TRIO_CPU_SPARC) || defined(TRIO_CPU_SYSTEMZ) # define TRIO_DOUBLE_DOUBLE # endif #endif /* TRIO_TRIODEF_H */ ================================================ FILE: src/trio/trionan.c ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 2001 Bjorn Reese * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************ * * Functions to handle special quantities in floating-point numbers * (that is, NaNs and infinity). They provide the capability to detect * and fabricate special quantities. * * Although written to be as portable as possible, it can never be * guaranteed to work on all platforms, as not all hardware supports * special quantities. * * The approach used here (approximately) is to: * * 1. Use C99 functionality when available. * 2. Use IEEE 754 bit-patterns if possible. * 3. Use platform-specific techniques. * ************************************************************************/ /************************************************************************* * Include files */ #include "triodef.h" #include "trionan.h" #include #include #include #if !defined(TRIO_PLATFORM_SYMBIAN) # include #endif #if defined(TRIO_PLATFORM_UNIX) # include #endif #if defined(TRIO_COMPILER_DECC) # include #endif #include #if defined(TRIO_DOCUMENTATION) # include "doc/doc_nan.h" #endif /** @addtogroup SpecialQuantities @{ */ /************************************************************************* * Definitions */ #if !defined(TRIO_PUBLIC_NAN) # define TRIO_PUBLIC_NAN TRIO_PUBLIC #endif #if !defined(TRIO_PRIVATE_NAN) # define TRIO_PRIVATE_NAN TRIO_PRIVATE #endif #if !defined(TRIO_INLINE_NAN) # define TRIO_INLINE_NAN TRIO_INLINE #endif #define TRIO_TRUE (1 == 1) #define TRIO_FALSE (0 == 1) /* * We must enable IEEE floating-point on Alpha */ #if defined(__alpha) && !defined(_IEEE_FP) # if defined(TRIO_COMPILER_DECC) # if defined(TRIO_PLATFORM_VMS) # error "Must be compiled with option /IEEE_MODE=UNDERFLOW_TO_ZERO/FLOAT=IEEE" # else # if !defined(_CFE) # error "Must be compiled with option -ieee" # endif # endif # else # if defined(TRIO_COMPILER_GCC) # error "Must be compiled with option -mieee" # endif # endif #endif /* __alpha && ! _IEEE_FP */ /* * In ANSI/IEEE 754-1985 64-bits double format numbers have the * following properties (amoungst others) * * o FLT_RADIX == 2: binary encoding * o DBL_MAX_EXP == 1024: 11 bits exponent, where one bit is used * to indicate special numbers (e.g. NaN and Infinity), so the * maximum exponent is 10 bits wide (2^10 == 1024). * o DBL_MANT_DIG == 53: The mantissa is 52 bits wide, but because * numbers are normalized the initial binary 1 is represented * implicitly (the so-called "hidden bit"), which leaves us with * the ability to represent 53 bits wide mantissa. */ #if defined(__STDC_IEC_559__) # define TRIO_IEEE_754 #else # if (FLT_RADIX - 0 == 2) && (DBL_MAX_EXP - 0 == 1024) && (DBL_MANT_DIG - 0 == 53) # define TRIO_IEEE_754 # endif #endif /* * Determine which fpclassify_and_sign() function to use. */ #if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT) # if defined(PREDEF_STANDARD_C99) && defined(fpclassify) # define TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT # else # if defined(TRIO_COMPILER_DECC) # define TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT # else # if defined(TRIO_COMPILER_VISUALC) || defined(TRIO_COMPILER_BORLAND) # define TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT # else # if defined(TRIO_COMPILER_HP) && defined(FP_PLUS_NORM) # define TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT # else # if defined(TRIO_COMPILER_XLC) && defined(FP_PLUS_NORM) # define TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT # else # define TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT # endif # endif # endif # endif # endif #endif /* * Determine how to generate negative zero. */ #if defined(TRIO_FUNC_NZERO) # if defined(TRIO_IEEE_754) # define TRIO_NZERO_IEEE_754 # else # define TRIO_NZERO_FALLBACK # endif #endif /* * Determine how to generate positive infinity. */ #if defined(TRIO_FUNC_PINF) # if defined(INFINITY) && defined(__STDC_IEC_559__) # define TRIO_PINF_C99_MACRO # else # if defined(TRIO_IEEE_754) # define TRIO_PINF_IEEE_754 # else # define TRIO_PINF_FALLBACK # endif # endif #endif /* * Determine how to generate NaN. */ #if defined(TRIO_FUNC_NAN) # if defined(PREDEF_STANDARD_C99) && !defined(TRIO_COMPILER_DECC) # define TRIO_NAN_C99_FUNCTION # else # if defined(NAN) && defined(__STDC_IEC_559__) # define TRIO_NAN_C99_MACRO # else # if defined(TRIO_IEEE_754) # define TRIO_NAN_IEEE_754 # else # define TRIO_NAN_FALLBACK # endif # endif # endif #endif /* * Resolve internal dependencies. */ #if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT) # define TRIO_FUNC_INTERNAL_ISNAN # define TRIO_FUNC_INTERNAL_ISINF # if defined(TRIO_IEEE_754) # define TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY # define TRIO_FUNC_INTERNAL_IS_NEGATIVE # endif #endif #if defined(TRIO_NZERO_IEEE_754) \ || defined(TRIO_PINF_IEEE_754) \ || defined(TRIO_NAN_IEEE_754) # define TRIO_FUNC_INTERNAL_MAKE_DOUBLE #endif #if defined(TRIO_FUNC_INTERNAL_ISNAN) # if defined(PREDEF_STANDARD_XPG3) # define TRIO_INTERNAL_ISNAN_XPG3 # else # if defined(TRIO_IEEE_754) # define TRIO_INTERNAL_ISNAN_IEEE_754 # else # define TRIO_INTERNAL_ISNAN_FALLBACK # endif # endif #endif #if defined(TRIO_FUNC_INTERNAL_ISINF) # if defined(TRIO_IEEE_754) # define TRIO_INTERNAL_ISINF_IEEE_754 # else # define TRIO_INTERNAL_ISINF_FALLBACK # endif #endif /************************************************************************* * Constants */ #if !defined(TRIO_EMBED_NAN) static TRIO_CONST char rcsid[] = "@(#)$Id$"; #endif #if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE) \ || defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) \ || defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE) /* * Endian-agnostic indexing macro. * * The value of internalEndianMagic, when converted into a 64-bit * integer, becomes 0x0706050403020100 (we could have used a 64-bit * integer value instead of a double, but not all platforms supports * that type). The value is automatically encoded with the correct * endianess by the compiler, which means that we can support any * kind of endianess. The individual bytes are then used as an index * for the IEEE 754 bit-patterns and masks. */ #define TRIO_DOUBLE_INDEX(x) (((unsigned char *)&internalEndianMagic)[7-(x)]) static TRIO_CONST double internalEndianMagic = 7.949928895127363e-275; #endif #if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) /* Mask for the exponent */ static TRIO_CONST unsigned char ieee_754_exponent_mask[] = { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Mask for the mantissa */ static TRIO_CONST unsigned char ieee_754_mantissa_mask[] = { 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #endif #if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE) /* Mask for the sign bit */ static TRIO_CONST unsigned char ieee_754_sign_mask[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #if defined(TRIO_NZERO_IEEE_754) /* Bit-pattern for negative zero */ static TRIO_CONST unsigned char ieee_754_negzero_array[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #if defined(TRIO_PINF_IEEE_754) /* Bit-pattern for infinity */ static TRIO_CONST unsigned char ieee_754_infinity_array[] = { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif #if defined(TRIO_NAN_IEEE_754) /* Bit-pattern for quiet NaN */ static TRIO_CONST unsigned char ieee_754_qnan_array[] = { 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif /************************************************************************* * Internal functions */ /* * */ #if defined(TRIO_PLATFORM_UNIX) && defined(TRIO_INTERNAL_ISNAN_FALLBACK) /* Assume that if SA_SIGINFO is defined, then sigaction() and * 'struct sigaction' are also properly defined on this platform. */ #ifndef TRIO_USE_SIGACTION # ifdef SA_SIGINFO # define TRIO_USE_SIGACTION 1 # else # define TRIO_USE_SIGACTION 0 # endif #endif # if TRIO_USE_SIGACTION typedef struct sigaction signal_handler_t; # else typedef void (*signal_handler_t) TRIO_PROTO((int)); # endif /* * internal_ignore_signal_handler */ TRIO_PRIVATE_NAN signal_handler_t internal_ignore_signal_handler TRIO_ARGS1((signum), int signum) { # if TRIO_USE_SIGACTION signal_handler_t old_handler, new_handler; memset(&new_handler, '\0', sizeof(new_handler)); new_handler.sa_handler = SIG_IGN; new_handler.sa_flags = SA_RESTART; sigaction(signum, &new_handler, &old_handler); return old_handler; # else return signal(signum, SIG_IGN); # endif } /* * internal_restore_signal_handler */ TRIO_PRIVATE_NAN void internal_restore_signal_handler TRIO_ARGS2((signum, handler), int signum, signal_handler_t handler) { # if TRIO_USE_SIGACTION sigaction(signum, &handler, NULL); # else signal(signum, handler); # endif } #endif /* * internal_make_double */ #if defined(TRIO_FUNC_INTERNAL_MAKE_DOUBLE) TRIO_PRIVATE_NAN double internal_make_double TRIO_ARGS1((values), TRIO_CONST unsigned char *values) { TRIO_VOLATILE double result; int i; for (i = 0; i < (int)sizeof(double); i++) { ((TRIO_VOLATILE unsigned char *)&result)[TRIO_DOUBLE_INDEX(i)] = values[i]; } return result; } #endif /* * internal_is_special_quantity */ #if defined(TRIO_FUNC_INTERNAL_IS_SPECIAL_QUANTITY) TRIO_PRIVATE_NAN int internal_is_special_quantity TRIO_ARGS2((number, has_mantissa), double number, int *has_mantissa) { unsigned int i; unsigned char current; int is_special_quantity = TRIO_TRUE; *has_mantissa = 0; for (i = 0; i < (unsigned int)sizeof(double); i++) { current = ((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)]; is_special_quantity &= ((current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i]); *has_mantissa |= (current & ieee_754_mantissa_mask[i]); } return is_special_quantity; } #endif /* * internal_is_negative */ #if defined(TRIO_FUNC_INTERNAL_IS_NEGATIVE) TRIO_PRIVATE_NAN int internal_is_negative TRIO_ARGS1((number), double number) { unsigned int i; int is_negative = TRIO_FALSE; for (i = 0; i < (unsigned int)sizeof(double); i++) { is_negative |= (((unsigned char *)&number)[TRIO_DOUBLE_INDEX(i)] & ieee_754_sign_mask[i]); } return is_negative; } #endif #if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT) TRIO_PRIVATE_NAN TRIO_INLINE_NAN int c99_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, int *is_negative) { *is_negative = signbit(number); switch (fpclassify(number)) { case FP_NAN: return TRIO_FP_NAN; case FP_INFINITE: return TRIO_FP_INFINITE; case FP_SUBNORMAL: return TRIO_FP_SUBNORMAL; case FP_ZERO: return TRIO_FP_ZERO; default: return TRIO_FP_NORMAL; } } #endif /* TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT */ #if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT) TRIO_PRIVATE_NAN TRIO_INLINE_NAN int decc_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, int *is_negative) { switch (fp_class(number)) { case FP_QNAN: case FP_SNAN: *is_negative = TRIO_FALSE; /* NaN has no sign */ return TRIO_FP_NAN; case FP_POS_INF: *is_negative = TRIO_FALSE; return TRIO_FP_INFINITE; case FP_NEG_INF: *is_negative = TRIO_TRUE; return TRIO_FP_INFINITE; case FP_POS_DENORM: *is_negative = TRIO_FALSE; return TRIO_FP_SUBNORMAL; case FP_NEG_DENORM: *is_negative = TRIO_TRUE; return TRIO_FP_SUBNORMAL; case FP_POS_ZERO: *is_negative = TRIO_FALSE; return TRIO_FP_ZERO; case FP_NEG_ZERO: *is_negative = TRIO_TRUE; return TRIO_FP_ZERO; case FP_POS_NORM: *is_negative = TRIO_FALSE; return TRIO_FP_NORMAL; case FP_NEG_NORM: *is_negative = TRIO_TRUE; return TRIO_FP_NORMAL; default: *is_negative = (number < 0.0); return TRIO_FP_NORMAL; } } #endif /* TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT */ #if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT) TRIO_PRIVATE_NAN int ms_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, int *is_negative) { int result; # if defined(TRIO_COMPILER_BORLAND) /* * The floating-point precision may be changed by the Borland _fpclass() * function, so we have to save and restore the floating-point control mask. */ unsigned int mask; /* Remember the old mask */ mask = _control87(0, 0); # endif switch (_fpclass(number)) { case _FPCLASS_QNAN: case _FPCLASS_SNAN: *is_negative = TRIO_FALSE; /* NaN has no sign */ result = TRIO_FP_NAN; break; case _FPCLASS_PINF: *is_negative = TRIO_FALSE; result = TRIO_FP_INFINITE; break; case _FPCLASS_NINF: *is_negative = TRIO_TRUE; result = TRIO_FP_INFINITE; break; case _FPCLASS_PD: *is_negative = TRIO_FALSE; result = TRIO_FP_SUBNORMAL; break; case _FPCLASS_ND: *is_negative = TRIO_TRUE; result = TRIO_FP_SUBNORMAL; break; case _FPCLASS_PZ: *is_negative = TRIO_FALSE; result = TRIO_FP_ZERO; break; case _FPCLASS_NZ: *is_negative = TRIO_TRUE; result = TRIO_FP_ZERO; break; case _FPCLASS_PN: *is_negative = TRIO_FALSE; result = TRIO_FP_NORMAL; break; case _FPCLASS_NN: *is_negative = TRIO_TRUE; result = TRIO_FP_NORMAL; break; default: *is_negative = (number < 0.0); result = TRIO_FP_NORMAL; break; } # if defined(TRIO_COMPILER_BORLAND) /* Restore the old precision */ (void)_control87(mask, MCW_PC); # endif return result; } #endif /* TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT */ #if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT) TRIO_PRIVATE_NAN TRIO_INLINE_NAN int hp_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, int *is_negative) { /* * HP-UX 9.x and 10.x have an fpclassify() function, that is different * from the C99 fpclassify() macro supported on HP-UX 11.x. */ switch (fpclassify(number)) { case FP_QNAN: case FP_SNAN: *is_negative = TRIO_FALSE; /* NaN has no sign */ return TRIO_FP_NAN; case FP_PLUS_INF: *is_negative = TRIO_FALSE; return TRIO_FP_INFINITE; case FP_MINUS_INF: *is_negative = TRIO_TRUE; return TRIO_FP_INFINITE; case FP_PLUS_DENORM: *is_negative = TRIO_FALSE; return TRIO_FP_SUBNORMAL; case FP_MINUS_DENORM: *is_negative = TRIO_TRUE; return TRIO_FP_SUBNORMAL; case FP_PLUS_ZERO: *is_negative = TRIO_FALSE; return TRIO_FP_ZERO; case FP_MINUS_ZERO: *is_negative = TRIO_TRUE; return TRIO_FP_ZERO; case FP_PLUS_NORM: *is_negative = TRIO_FALSE; return TRIO_FP_NORMAL; case FP_MINUS_NORM: *is_negative = TRIO_TRUE; return TRIO_FP_NORMAL; default: *is_negative = (number < 0.0); return TRIO_FP_NORMAL; } } #endif /* TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT */ #if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT) TRIO_PRIVATE_NAN TRIO_INLINE_NAN int xlc_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, int *is_negative) { /* * AIX has class() for C, and _class() for C++ */ # if defined(__cplusplus) # define AIX_CLASS(n) _class(n) # else # define AIX_CLASS(n) class(n) # endif switch (AIX_CLASS(number)) { case FP_QNAN: case FP_SNAN: *is_negative = TRIO_FALSE; /* NaN has no sign */ return TRIO_FP_NAN; case FP_PLUS_INF: *is_negative = TRIO_FALSE; return TRIO_FP_INFINITE; case FP_MINUS_INF: *is_negative = TRIO_TRUE; return TRIO_FP_INFINITE; case FP_PLUS_DENORM: *is_negative = TRIO_FALSE; return TRIO_FP_SUBNORMAL; case FP_MINUS_DENORM: *is_negative = TRIO_TRUE; return TRIO_FP_SUBNORMAL; case FP_PLUS_ZERO: *is_negative = TRIO_FALSE; return TRIO_FP_ZERO; case FP_MINUS_ZERO: *is_negative = TRIO_TRUE; return TRIO_FP_ZERO; case FP_PLUS_NORM: *is_negative = TRIO_FALSE; return TRIO_FP_NORMAL; case FP_MINUS_NORM: *is_negative = TRIO_TRUE; return TRIO_FP_NORMAL; default: *is_negative = (number < 0.0); return TRIO_FP_NORMAL; } } #endif /* TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT */ #if defined(TRIO_FUNC_INTERNAL_ISNAN) TRIO_PRIVATE_NAN TRIO_INLINE int internal_isnan TRIO_ARGS1((number), double number) { # if defined(TRIO_INTERNAL_ISNAN_XPG3) || defined(TRIO_PLATFORM_SYMBIAN) /* * XPG3 defines isnan() as a function. */ return isnan(number); # endif # if defined(TRIO_INTERNAL_ISNAN_IEEE_754) /* * Examine IEEE 754 bit-pattern. A NaN must have a special exponent * pattern, and a non-empty mantissa. */ int has_mantissa; int is_special_quantity; is_special_quantity = internal_is_special_quantity(number, &has_mantissa); return (is_special_quantity && has_mantissa); # endif # if defined(TRIO_INTERNAL_ISNAN_FALLBACK) /* * Fallback solution */ int status; double integral, fraction; # if defined(TRIO_PLATFORM_UNIX) signal_handler_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); # endif status = (/* * NaN is the only number which does not compare to itself */ ((TRIO_VOLATILE double)number != (TRIO_VOLATILE double)number) || /* * Fallback solution if NaN compares to NaN */ ((number != 0.0) && (fraction = modf(number, &integral), integral == fraction))); # if defined(TRIO_PLATFORM_UNIX) internal_restore_signal_handler(SIGFPR, sigfpe_handler); # endif return status; # endif } #endif /* TRIO_FUNC_INTERNAL_ISNAN */ #if defined(TRIO_FUNC_INTERNAL_ISINF) TRIO_PRIVATE_NAN TRIO_INLINE int internal_isinf TRIO_ARGS1((number), double number) { # if defined(TRIO_PLATFORM_SYMBIAN) return isinf(number); # endif # if defined(TRIO_INTERNAL_ISINF_IEEE_754) /* * Examine IEEE 754 bit-pattern. Infinity must have a special exponent * pattern, and an empty mantissa. */ int has_mantissa; int is_special_quantity; is_special_quantity = internal_is_special_quantity(number, &has_mantissa); return (is_special_quantity && !has_mantissa) ? ((number < 0.0) ? -1 : 1) : 0; # endif # if defined(TRIO_INTERNAL_ISINF_FALLBACK) /* * Fallback solution. */ int status; # if defined(TRIO_PLATFORM_UNIX) signal_handler_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); # endif double infinity = trio_pinf(); status = ((number == infinity) ? 1 : ((number == -infinity) ? -1 : 0)); # if defined(TRIO_PLATFORM_UNIX) internal_restore_signal_handler(SIGFPE, sigfpe_handler); # endif return status; # endif } #endif /* TRIO_FUNC_INTERNAL_ISINF */ /************************************************************************* * Public functions */ #if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT) TRIO_PUBLIC_NAN int trio_fpclassify_and_signbit TRIO_ARGS2((number, is_negative), double number, int *is_negative) { /* The TRIO_FUNC_xxx_FPCLASSIFY_AND_SIGNBIT macros are mutually exclusive */ #if defined(TRIO_FUNC_C99_FPCLASSIFY_AND_SIGNBIT) return c99_fpclassify_and_signbit(number, is_negative); #endif #if defined(TRIO_FUNC_DECC_FPCLASSIFY_AND_SIGNBIT) return decc_fpclassify_and_signbit(number, is_negative); #endif #if defined(TRIO_FUNC_MS_FPCLASSIFY_AND_SIGNBIT) return ms_fpclassify_and_signbit(number, is_negative); #endif #if defined(TRIO_FUNC_HP_FPCLASSIFY_AND_SIGNBIT) return hp_fpclassify_and_signbit(number, is_negative); #endif #if defined(TRIO_FUNC_XLC_FPCLASSIFY_AND_SIGNBIT) return xlc_fpclassify_and_signbit(number, is_negative); #endif #if defined(TRIO_FUNC_INTERNAL_FPCLASSIFY_AND_SIGNBIT) /* * Fallback solution. */ int rc; if (number == 0.0) { /* * In IEEE 754 the sign of zero is ignored in comparisons, so we * have to handle this as a special case by examining the sign bit * directly. */ # if defined(TRIO_IEEE_754) *is_negative = internal_is_negative(number); # else *is_negative = TRIO_FALSE; /* FIXME */ # endif return TRIO_FP_ZERO; } if (internal_isnan(number)) { *is_negative = TRIO_FALSE; return TRIO_FP_NAN; } rc = internal_isinf(number); if (rc != 0) { *is_negative = (rc == -1); return TRIO_FP_INFINITE; } if ((number > 0.0) && (number < DBL_MIN)) { *is_negative = TRIO_FALSE; return TRIO_FP_SUBNORMAL; } if ((number < 0.0) && (number > -DBL_MIN)) { *is_negative = TRIO_TRUE; return TRIO_FP_SUBNORMAL; } *is_negative = (number < 0.0); return TRIO_FP_NORMAL; #endif } #endif /** Check for NaN. @param number An arbitrary floating-point number. @return Boolean value indicating whether or not the number is a NaN. */ #if defined(TRIO_FUNC_ISNAN) TRIO_PUBLIC_NAN int trio_isnan TRIO_ARGS1((number), double number) { int dummy; return (trio_fpclassify_and_signbit(number, &dummy) == TRIO_FP_NAN); } #endif /** Check for infinity. @param number An arbitrary floating-point number. @return 1 if positive infinity, -1 if negative infinity, 0 otherwise. */ #if defined(TRIO_FUNC_ISINF) TRIO_PUBLIC_NAN int trio_isinf TRIO_ARGS1((number), double number) { int is_negative; if (trio_fpclassify_and_signbit(number, &is_negative) == TRIO_FP_INFINITE) { return (is_negative) ? -1 : 1; } else { return 0; } } #endif /** Check for finity. @param number An arbitrary floating-point number. @return Boolean value indicating whether or not the number is a finite. */ #if defined(TRIO_FUNC_ISFINITE) TRIO_PUBLIC_NAN int trio_isfinite TRIO_ARGS1((number), double number) { int dummy; switch (trio_fpclassify_and_signbit(number, &dummy)) { case TRIO_FP_INFINITE: case TRIO_FP_NAN: return 0; default: return 1; } } #endif /** Examine the sign of a number. @param number An arbitrary floating-point number. @return Boolean value indicating whether or not the number has the sign bit set (i.e. is negative). */ #if defined(TRIO_FUNC_SIGNBIT) TRIO_PUBLIC_NAN int trio_signbit TRIO_ARGS1((number), double number) { int is_negative; (void)trio_fpclassify_and_signbit(number, &is_negative); return is_negative; } #endif /** Examine the class of a number. @param number An arbitrary floating-point number. @return Enumerable value indicating the class of @p number */ #if defined(TRIO_FUNC_FPCLASSIFY) TRIO_PUBLIC_NAN int trio_fpclassify TRIO_ARGS1((number), double number) { int dummy; return trio_fpclassify_and_signbit(number, &dummy); } #endif /** Generate negative zero. @return Floating-point representation of negative zero. */ #if defined(TRIO_FUNC_NZERO) TRIO_PUBLIC_NAN double trio_nzero(TRIO_NOARGS) { # if defined(TRIO_NZERO_IEEE_754) return internal_make_double(ieee_754_negzero_array); # endif # if defined(TRIO_NZERO_FALLBACK) TRIO_VOLATILE double zero = 0.0; return -zero; # endif } #endif /** Generate positive infinity. @return Floating-point representation of positive infinity. */ #if defined(TRIO_FUNC_PINF) TRIO_PUBLIC_NAN double trio_pinf(TRIO_NOARGS) { /* Cache the result */ static double pinf_value = 0.0; if (pinf_value == 0.0) { # if defined(TRIO_PINF_C99_MACRO) pinf_value = (double)INFINITY; # endif # if defined(TRIO_PINF_IEEE_754) pinf_value = internal_make_double(ieee_754_infinity_array); # endif # if defined(TRIO_PINF_FALLBACK) /* * If HUGE_VAL is different from DBL_MAX, then HUGE_VAL is used * as infinity. Otherwise we have to resort to an overflow * operation to generate infinity. */ # if defined(TRIO_PLATFORM_UNIX) signal_handler_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); # endif pinf_value = HUGE_VAL; if (HUGE_VAL == DBL_MAX) { /* Force overflow */ pinf_value += HUGE_VAL; } # if defined(TRIO_PLATFORM_UNIX) internal_restore_signal_handler(SIGFPE, sigfpe_handler); # endif # endif } return pinf_value; } #endif /** Generate negative infinity. @return Floating-point value of negative infinity. */ #if defined(TRIO_FUNC_NINF) TRIO_PUBLIC_NAN double trio_ninf(TRIO_NOARGS) { static double ninf_value = 0.0; if (ninf_value == 0.0) { /* * Negative infinity is calculated by negating positive infinity, * which can be done because it is legal to do calculations on * infinity (for example, 1 / infinity == 0). */ ninf_value = -trio_pinf(); } return ninf_value; } #endif /** Generate NaN. @return Floating-point representation of NaN. */ #if defined(TRIO_FUNC_NAN) TRIO_PUBLIC_NAN double trio_nan(TRIO_NOARGS) { /* Cache the result */ static double nan_value = 0.0; if (nan_value == 0.0) { # if defined(TRIO_NAN_C99_FUNCTION) || defined(TRIO_PLATFORM_SYMBIAN) nan_value = nan(""); # endif # if defined(TRIO_NAN_C99_MACRO) nan_value = (double)NAN; # endif # if defined(TRIO_NAN_IEEE_754) nan_value = internal_make_double(ieee_754_qnan_array); # endif # if defined(TRIO_NAN_FALLBACK) /* * There are several ways to generate NaN. The one used here is * to divide infinity by infinity. I would have preferred to add * negative infinity to positive infinity, but that yields wrong * result (infinity) on FreeBSD. * * This may fail if the hardware does not support NaN, or if * the Invalid Operation floating-point exception is unmasked. */ # if defined(TRIO_PLATFORM_UNIX) signal_handle_t sigfpe_handler = internal_ignore_signal_handler(SIGFPE); # endif nan_value = trio_pinf() / trio_pinf(); # if defined(TRIO_PLATFORM_UNIX) internal_restore_signal_handler(SIGFPE, sigfpe_handler); # endif # endif } return nan_value; } #endif /** @} SpecialQuantities */ /************************************************************************* * For test purposes. * * Add the following compiler option to include this test code. * * Unix : -DSTANDALONE * VMS : /DEFINE=(STANDALONE) */ #if defined(STANDALONE) # include static TRIO_CONST char * getClassification TRIO_ARGS1((type), int type) { switch (type) { case TRIO_FP_INFINITE: return "FP_INFINITE"; case TRIO_FP_NAN: return "FP_NAN"; case TRIO_FP_NORMAL: return "FP_NORMAL"; case TRIO_FP_SUBNORMAL: return "FP_SUBNORMAL"; case TRIO_FP_ZERO: return "FP_ZERO"; default: return "FP_UNKNOWN"; } } static void print_class TRIO_ARGS2((prefix, number), TRIO_CONST char *prefix, double number) { printf("%-6s: %s %-15s %g\n", prefix, trio_signbit(number) ? "-" : "+", getClassification(trio_fpclassify(number)), number); } int main(TRIO_NOARGS) { double my_nan; double my_pinf; double my_ninf; # if defined(TRIO_PLATFORM_UNIX) signal_handler_t signal_handler; # endif my_nan = trio_nan(); my_pinf = trio_pinf(); my_ninf = trio_ninf(); print_class("Nan", my_nan); print_class("PInf", my_pinf); print_class("NInf", my_ninf); print_class("PZero", 0.0); print_class("NZero", -0.0); print_class("PNorm", 1.0); print_class("NNorm", -1.0); print_class("PSub", 1.01e-307 - 1.00e-307); print_class("NSub", 1.00e-307 - 1.01e-307); printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", my_nan, ((unsigned char *)&my_nan)[0], ((unsigned char *)&my_nan)[1], ((unsigned char *)&my_nan)[2], ((unsigned char *)&my_nan)[3], ((unsigned char *)&my_nan)[4], ((unsigned char *)&my_nan)[5], ((unsigned char *)&my_nan)[6], ((unsigned char *)&my_nan)[7], trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan)); printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", my_pinf, ((unsigned char *)&my_pinf)[0], ((unsigned char *)&my_pinf)[1], ((unsigned char *)&my_pinf)[2], ((unsigned char *)&my_pinf)[3], ((unsigned char *)&my_pinf)[4], ((unsigned char *)&my_pinf)[5], ((unsigned char *)&my_pinf)[6], ((unsigned char *)&my_pinf)[7], trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf)); printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", my_ninf, ((unsigned char *)&my_ninf)[0], ((unsigned char *)&my_ninf)[1], ((unsigned char *)&my_ninf)[2], ((unsigned char *)&my_ninf)[3], ((unsigned char *)&my_ninf)[4], ((unsigned char *)&my_ninf)[5], ((unsigned char *)&my_ninf)[6], ((unsigned char *)&my_ninf)[7], trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf)); # if defined(TRIO_PLATFORM_UNIX) signal_handler = internal_ignore_signal_handler(SIGFPE); # endif my_pinf = DBL_MAX + DBL_MAX; my_ninf = -my_pinf; my_nan = my_pinf / my_pinf; # if defined(TRIO_PLATFORM_UNIX) internal_restore_signal_handler(SIGFPE, signal_handler); # endif printf("NaN : %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", my_nan, ((unsigned char *)&my_nan)[0], ((unsigned char *)&my_nan)[1], ((unsigned char *)&my_nan)[2], ((unsigned char *)&my_nan)[3], ((unsigned char *)&my_nan)[4], ((unsigned char *)&my_nan)[5], ((unsigned char *)&my_nan)[6], ((unsigned char *)&my_nan)[7], trio_isnan(my_nan), trio_isinf(my_nan), trio_isfinite(my_nan)); printf("PInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", my_pinf, ((unsigned char *)&my_pinf)[0], ((unsigned char *)&my_pinf)[1], ((unsigned char *)&my_pinf)[2], ((unsigned char *)&my_pinf)[3], ((unsigned char *)&my_pinf)[4], ((unsigned char *)&my_pinf)[5], ((unsigned char *)&my_pinf)[6], ((unsigned char *)&my_pinf)[7], trio_isnan(my_pinf), trio_isinf(my_pinf), trio_isfinite(my_pinf)); printf("NInf: %4g 0x%02x%02x%02x%02x%02x%02x%02x%02x (%2d, %2d, %2d)\n", my_ninf, ((unsigned char *)&my_ninf)[0], ((unsigned char *)&my_ninf)[1], ((unsigned char *)&my_ninf)[2], ((unsigned char *)&my_ninf)[3], ((unsigned char *)&my_ninf)[4], ((unsigned char *)&my_ninf)[5], ((unsigned char *)&my_ninf)[6], ((unsigned char *)&my_ninf)[7], trio_isnan(my_ninf), trio_isinf(my_ninf), trio_isfinite(my_ninf)); return 0; } #endif ================================================ FILE: src/trio/trionan.h ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 2001 Bjorn Reese * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ #ifndef TRIO_TRIONAN_H #define TRIO_TRIONAN_H #include "triodef.h" #ifdef __cplusplus extern "C" { #endif #if !defined(TRIO_PUBLIC_NAN) # if !defined(TRIO_PUBLIC) # define TRIO_PUBLIC # endif # define TRIO_PUBLIC_NAN TRIO_PUBLIC #endif enum { TRIO_FP_INFINITE, TRIO_FP_NAN, TRIO_FP_NORMAL, TRIO_FP_SUBNORMAL, TRIO_FP_ZERO }; /************************************************************************* * Dependencies */ #if defined(TRIO_EMBED_NAN) /* * The application that trionan is embedded in must define which functions * it uses. * * The following resolves internal dependencies. */ # if defined(TRIO_FUNC_ISNAN) \ || defined(TRIO_FUNC_ISINF) # if !defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT) # define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT # endif # endif # if defined(TRIO_FUNC_NAN) # if !defined(TRIO_FUNC_PINF) # define TRIO_FUNC_PINF # endif # endif # if defined(TRIO_FUNC_NINF) # if !defined(TRIO_FUNC_PINF) # define TRIO_FUNC_PINF # endif # endif # if !defined(TRIO_INLINE_NAN) # define TRIO_INLINE_NAN # endif #else /* * When trionan is not embedded all all functions are defined. */ # define TRIO_FUNC_NAN # define TRIO_FUNC_PINF # define TRIO_FUNC_NINF # define TRIO_FUNC_NZERO # define TRIO_FUNC_ISNAN # define TRIO_FUNC_ISINF # define TRIO_FUNC_ISFINITE # define TRIO_FUNC_SIGNBIT # define TRIO_FUNC_FPCLASSIFY # define TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT #endif /************************************************************************* * Functions */ /* * Return NaN (Not-a-Number). */ #if defined(TRIO_FUNC_NAN) TRIO_PUBLIC_NAN double trio_nan TRIO_PROTO((void)); #endif /* * Return positive infinity. */ #if defined(TRIO_FUNC_PINF) TRIO_PUBLIC_NAN double trio_pinf TRIO_PROTO((void)); #endif /* * Return negative infinity. */ #if defined(TRIO_FUNC_NINF) TRIO_PUBLIC_NAN double trio_ninf TRIO_PROTO((void)); #endif /* * Return negative zero. */ #if defined(TRIO_FUNC_NZERO) TRIO_PUBLIC_NAN double trio_nzero TRIO_PROTO((TRIO_NOARGS)); #endif /* * If number is a NaN return non-zero, otherwise return zero. */ #if defined(TRIO_FUNC_ISNAN) TRIO_PUBLIC_NAN int trio_isnan TRIO_PROTO((double number)); #endif /* * If number is positive infinity return 1, if number is negative * infinity return -1, otherwise return 0. */ #if defined(TRIO_FUNC_ISINF) TRIO_PUBLIC_NAN int trio_isinf TRIO_PROTO((double number)); #endif /* * If number is finite return non-zero, otherwise return zero. */ #if defined(TRIO_FUNC_ISFINITE) TRIO_PUBLIC_NAN int trio_isfinite TRIO_PROTO((double number)); #endif #if defined(TRIO_FUNC_SIGNBIT) TRIO_PUBLIC_NAN int trio_signbit TRIO_PROTO((double number)); #endif #if defined(TRIO_FUNC_FPCLASSIFY) TRIO_PUBLIC_NAN int trio_fpclassify TRIO_PROTO((double number)); #endif #if defined(TRIO_FUNC_FPCLASSIFY_AND_SIGNBIT) TRIO_PUBLIC_NAN int trio_fpclassify_and_signbit TRIO_PROTO((double number, int *is_negative)); #endif #ifdef __cplusplus } #endif #endif /* TRIO_TRIONAN_H */ ================================================ FILE: src/trio/triop.h ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 2000 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************ * * Private functions, types, etc. used for callback functions. * * The ref pointer is an opaque type and should remain as such. * Private data must only be accessible through the getter and * setter functions. * ************************************************************************/ #ifndef TRIO_TRIOP_H #define TRIO_TRIOP_H #include "triodef.h" #include #if defined(TRIO_COMPILER_ANCIENT) # include #else # include #endif #ifdef __cplusplus extern "C" { #endif /************************************************************************* * Supported standards */ /* * TRIO_C99 (=0 or =1) * * Define this to 0 to disable C99 format specifier extensions, or * define to 1 to enable them. The format specifiers that are * disabled by this switch are labelled with [C99] in the format * specifier documentation. */ #if !defined(TRIO_C99) # define TRIO_C99 1 #endif /* * TRIO_BSD (=0 or =1) * * Define this to 0 to disable BSD format specifier extensions, or * define to 1 to enable them. The format specifiers that are * disabled by this switch are labelled with [BSD] in the format * specifier documentation. */ #if !defined(TRIO_BSD) # define TRIO_BSD 1 #endif /* * TRIO_GNU (=0 or =1) * * Define this to 0 to disable GNU format specifier extensions, or * define to 1 to enable them. The format specifiers that are * disabled by this switch are labelled with [GNU] in the format * specifier documentation. */ #if !defined(TRIO_GNU) # define TRIO_GNU 1 #endif /* * TRIO_MISC (=0 or =1) * * Define this to 0 to disable miscellaneous format specifier * extensions, or define to 1 to enable them. The format specifiers * that are disabled by this switch are labelled with [MISC] in the * format specifier documentation. */ #if !defined(TRIO_MISC) # define TRIO_MISC 1 #endif /* * TRIO_UNIX98 (=0 or =1) * * Define this to 0 to disable UNIX98 format specifier extensions, * or define to 1 to enable them. The format specifiers that are * disabled by this switch are labelled with [UNIX98] in the format * specifier documentation. */ #if !defined(TRIO_UNIX98) # define TRIO_UNIX98 1 #endif /* * TRIO_MICROSOFT (=0 or =1) * * Define this to 0 to disable Microsoft Visual C format specifier * extensions, or define to 1 to enable them. The format specifiers * that are disabled by this switch are labelled with [MSVC] in the * format specifier documentation. */ #if !defined(TRIO_MICROSOFT) # define TRIO_MICROSOFT 1 #endif /* * TRIO_EXTENSION (=0 or =1) * * Define this to 0 to disable Trio-specific extensions, or define * to 1 to enable them. This has two effects: it controls whether * or not the Trio user-defined formating mechanism * (trio_register() etc) is supported, and it enables or disables * Trio's own format specifier extensions. The format specifiers * that are disabled by this switch are labelled with [TRIO] in * the format specifier documentation. */ #if !defined(TRIO_EXTENSION) # define TRIO_EXTENSION 1 #endif /* * TRIO_DEPRECATED (=0 or =1) * * Define this to 0 to disable deprecated functionality, or define * to 1 to enable them. */ #if !defined(TRIO_DEPRECATED) # define TRIO_DEPRECATED 1 #endif /************************************************************************* * Features */ #if defined(TRIO_SNPRINTF_ONLY) # define TRIO_FEATURE_SCANF 0 # define TRIO_FEATURE_FILE 0 # define TRIO_FEATURE_STDIO 0 # define TRIO_FEATURE_FD 0 # define TRIO_FEATURE_DYNAMICSTRING 0 # define TRIO_FEATURE_CLOSURE 0 # define TRIO_FEATURE_ARGFUNC 0 # define TRIO_FEATURE_STRERR 0 # define TRIO_FEATURE_LOCALE 0 # define TRIO_EMBED_NAN 1 # define TRIO_EMBED_STRING 1 #endif /* * TRIO_FEATURE_SCANF (=0 or =1) * * Define this to 0 to disable all the scanf() variants, or define to 1 * to enable them. */ #if !defined(TRIO_FEATURE_SCANF) # define TRIO_FEATURE_SCANF 1 #endif /* * TRIO_FEATURE_FILE (=0 or =1) * * Define this to 0 to disable compilation of the trio_fprintf() and * trio_fscanf() family of functions, or define to 1 to enable them. * * This may be useful on an embedded platform with no filesystem. * Note that trio_printf() uses fwrite to write to stdout, so if you * do not have an implementation of fwrite() at all then you must also * define TRIO_FEATURE_STDIO to 0. */ #if !defined(TRIO_FEATURE_FILE) # define TRIO_FEATURE_FILE 1 #endif /* * TRIO_FEATURE_STDIO (=0 or =1) * * Define this to 0 to disable compilation of the trio_printf() and * trio_scanf() family of functions, or define to 1 to enable them. * * This may be useful on an embedded platform with no standard I/O. */ #if !defined(TRIO_FEATURE_STDIO) # define TRIO_FEATURE_STDIO 1 #endif /* * TRIO_FEATURE_FD (=0 or =1) * * Define this to 0 to disable compilation of the trio_dprintf() and * trio_dscanf() family of functions, or define to 1 to enable them. * * This may be useful on an embedded platform with no filesystem, or on * a platform that supports file I/O using FILE* but not using raw file * descriptors. */ #if !defined(TRIO_FEATURE_FD) # define TRIO_FEATURE_FD 1 #endif /* * TRIO_FEATURE_DYNAMICSTRING (=0 or =1) * * Define this to 0 to disable compilation of the trio_aprintf() * family of functions, or define to 1 to enable them. * * If you define both this and TRIO_MINIMAL to 0, then Trio will never * call malloc or free. */ #if !defined(TRIO_FEATURE_DYNAMICSTRING) # define TRIO_FEATURE_DYNAMICSTRING 1 #endif /* * TRIO_FEATURE_CLOSURE (=0 or =1) * * Define this to 0 to disable compilation of the trio_cprintf() and * trio_cscanf() family of functions, or define to 1 to enable them. * * These functions are rarely needed. This saves a (small) amount of code. */ #if !defined(TRIO_FEATURE_CLOSURE) # define TRIO_FEATURE_CLOSURE 1 #endif /* * TRIO_FEATURE_ARGFUNC (=0 or =1) * * Define this to 0 to disable compilation of trio_cprintff() and * trio_cscanff() functions and related code (might have a tiny * performance gain), or define to 1 to enable them. * * This functionality is needed only if you have to fetch the arguments using * a pull model instead of passing them all at once (for example if you plan * to plug the library into a script interpreter or validate the types). * * Only the closure family of functions are available with this interface, * because if you need this, you usually provide custom input/output * handling too (and so this forces TRIO_FEATURE_CLOSURE to enabled). */ #if !defined(TRIO_FEATURE_ARGFUNC) # define TRIO_FEATURE_ARGFUNC 1 #endif #if TRIO_FEATURE_ARGFUNC # undef TRIO_FEATURE_CLOSURE # define TRIO_FEATURE_CLOSURE 1 #endif /* * TRIO_FEATURE_ERRORCODE (=0 or =1) * * Define this to 0 to return -1 from the print and scan function on * error, or define to 1 to return a negative number with debugging * information as part of the return code. * * If enabled, the return code will be a negative number, which encodes * an error code and an error location. These can be decoded with the * TRIO_ERROR_CODE and TRIO_ERROR_POSITION macros. */ #if defined(TRIO_ERRORS) # define TRIO_FEATURE_ERRORCODE TRIO_ERRORS #endif #if !defined(TRIO_FEATURE_ERRORCODE) # define TRIO_FEATURE_ERRORCODE 1 #endif /* * TRIO_FEATURE_STRERR (=0 or =1) * * Define this to 0 if you do not use trio_strerror(), or define to 1 if * you do use it. * * This saves a (small) amount of code. */ #if !defined(TRIO_FEATURE_STRERR) # define TRIO_FEATURE_STRERR 1 #endif /* * TRIO_FEATURE_FLOAT (=0 or =1) * * Define this to 0 to disable all floating-point support, or define * to 1 to enable it. * * This is useful in restricted embedded platforms that do not support * floating-point. Obviously you cannot use floating-point format * specifiers if you define this. * * Do not compile trionan.c if you disable this. */ #if !defined(TRIO_FEATURE_FLOAT) # define TRIO_FEATURE_FLOAT 1 #endif /* * TRIO_FEATURE_LOCALE (=0 or =1) * * Define this to 0 to disable customized locale support, or define * to 1 to enable it. * * This saves a (small) amount of code. */ #if !defined(TRIO_FEATURE_LOCALE) # define TRIO_FEATURE_LOCALE 1 #endif /* * TRIO_MINIMAL * * Define this to disable building the public trionan.h and triostr.h. * If you define this, then you must not compile trionan.c and triostr.c * separately. */ #if defined(TRIO_MINIMAL) # if !defined(TRIO_EMBED_NAN) # define TRIO_EMBED_NAN # endif # if !defined(TRIO_EMBED_STRING) # define TRIO_EMBED_STRING # endif #endif /* Does not work yet. Do not enable */ #ifndef TRIO_FEATURE_WIDECHAR # define TRIO_FEATURE_WIDECHAR 0 #endif /************************************************************************* * Mapping standards to internal features */ #if !defined(TRIO_FEATURE_HEXFLOAT) # define TRIO_FEATURE_HEXFLOAT (TRIO_C99 && TRIO_FEATURE_FLOAT) #endif #if !defined(TRIO_FEATURE_LONGDOUBLE) # define TRIO_FEATURE_LONGDOUBLE TRIO_FEATURE_FLOAT #endif #if !defined(TRIO_FEATURE_ERRNO) # define TRIO_FEATURE_ERRNO TRIO_GNU #endif #if !defined(TRIO_FEATURE_QUAD) # define TRIO_FEATURE_QUAD (TRIO_BSD || TRIO_GNU) #endif #if !defined(TRIO_FEATURE_SIZE_T) # define TRIO_FEATURE_SIZE_T TRIO_C99 #endif #if !defined(TRIO_FEATURE_SIZE_T_UPPER) # define TRIO_FEATURE_SIZE_T_UPPER TRIO_GNU #endif #if !defined(TRIO_FEATURE_PTRDIFF_T) # define TRIO_FEATURE_PTRDIFF_T TRIO_C99 #endif #if !defined(TRIO_FEATURE_INTMAX_T) # define TRIO_FEATURE_INTMAX_T TRIO_C99 #endif #if !defined(TRIO_FEATURE_FIXED_SIZE) # define TRIO_FEATURE_FIXED_SIZE TRIO_MICROSOFT #endif #if !defined(TRIO_FEATURE_POSITIONAL) # define TRIO_FEATURE_POSITIONAL TRIO_UNIX98 #endif #if !defined(TRIO_FEATURE_USER_DEFINED) # define TRIO_FEATURE_USER_DEFINED TRIO_EXTENSION #endif #if !defined(TRIO_FEATURE_BINARY) # define TRIO_FEATURE_BINARY TRIO_EXTENSION #endif #if !defined(TRIO_FEATURE_QUOTE) # define TRIO_FEATURE_QUOTE TRIO_EXTENSION #endif #if !defined(TRIO_FEATURE_STICKY) # define TRIO_FEATURE_STICKY TRIO_EXTENSION #endif #if !defined(TRIO_FEATURE_VARSIZE) # define TRIO_FEATURE_VARSIZE TRIO_EXTENSION #endif #if !defined(TRIO_FEATURE_ROUNDING) # define TRIO_FEATURE_ROUNDING TRIO_EXTENSION #endif /************************************************************************* * Memory handling */ #ifndef TRIO_MALLOC # define TRIO_MALLOC(n) malloc(n) #endif #ifndef TRIO_REALLOC # define TRIO_REALLOC(x,n) realloc((x),(n)) #endif #ifndef TRIO_FREE # define TRIO_FREE(x) free(x) #endif /************************************************************************* * User-defined specifiers */ typedef int (*trio_callback_t) TRIO_PROTO((trio_pointer_t)); trio_pointer_t trio_register TRIO_PROTO((trio_callback_t callback, const char *name)); void trio_unregister TRIO_PROTO((trio_pointer_t handle)); TRIO_CONST char *trio_get_format TRIO_PROTO((trio_pointer_t ref)); TRIO_CONST trio_pointer_t trio_get_argument TRIO_PROTO((trio_pointer_t ref)); /* Modifiers */ int trio_get_width TRIO_PROTO((trio_pointer_t ref)); void trio_set_width TRIO_PROTO((trio_pointer_t ref, int width)); int trio_get_precision TRIO_PROTO((trio_pointer_t ref)); void trio_set_precision TRIO_PROTO((trio_pointer_t ref, int precision)); int trio_get_base TRIO_PROTO((trio_pointer_t ref)); void trio_set_base TRIO_PROTO((trio_pointer_t ref, int base)); int trio_get_padding TRIO_PROTO((trio_pointer_t ref)); void trio_set_padding TRIO_PROTO((trio_pointer_t ref, int is_padding)); int trio_get_short TRIO_PROTO((trio_pointer_t ref)); /* h */ void trio_set_shortshort TRIO_PROTO((trio_pointer_t ref, int is_shortshort)); int trio_get_shortshort TRIO_PROTO((trio_pointer_t ref)); /* hh */ void trio_set_short TRIO_PROTO((trio_pointer_t ref, int is_short)); int trio_get_long TRIO_PROTO((trio_pointer_t ref)); /* l */ void trio_set_long TRIO_PROTO((trio_pointer_t ref, int is_long)); int trio_get_longlong TRIO_PROTO((trio_pointer_t ref)); /* ll */ void trio_set_longlong TRIO_PROTO((trio_pointer_t ref, int is_longlong)); int trio_get_longdouble TRIO_PROTO((trio_pointer_t ref)); /* L */ void trio_set_longdouble TRIO_PROTO((trio_pointer_t ref, int is_longdouble)); int trio_get_alternative TRIO_PROTO((trio_pointer_t ref)); /* # */ void trio_set_alternative TRIO_PROTO((trio_pointer_t ref, int is_alternative)); int trio_get_alignment TRIO_PROTO((trio_pointer_t ref)); /* - */ void trio_set_alignment TRIO_PROTO((trio_pointer_t ref, int is_leftaligned)); int trio_get_spacing TRIO_PROTO((trio_pointer_t ref)); /* (space) */ void trio_set_spacing TRIO_PROTO((trio_pointer_t ref, int is_space)); int trio_get_sign TRIO_PROTO((trio_pointer_t ref)); /* + */ void trio_set_sign TRIO_PROTO((trio_pointer_t ref, int is_showsign)); #if TRIO_FEATURE_QUOTE int trio_get_quote TRIO_PROTO((trio_pointer_t ref)); /* ' */ void trio_set_quote TRIO_PROTO((trio_pointer_t ref, int is_quote)); #endif int trio_get_upper TRIO_PROTO((trio_pointer_t ref)); void trio_set_upper TRIO_PROTO((trio_pointer_t ref, int is_upper)); #if TRIO_FEATURE_INTMAX_T int trio_get_largest TRIO_PROTO((trio_pointer_t ref)); /* j */ void trio_set_largest TRIO_PROTO((trio_pointer_t ref, int is_largest)); #endif #if TRIO_FEATURE_PTRDIFF_T int trio_get_ptrdiff TRIO_PROTO((trio_pointer_t ref)); /* t */ void trio_set_ptrdiff TRIO_PROTO((trio_pointer_t ref, int is_ptrdiff)); #endif #if TRIO_FEATURE_SIZE_T int trio_get_size TRIO_PROTO((trio_pointer_t ref)); /* z / Z */ void trio_set_size TRIO_PROTO((trio_pointer_t ref, int is_size)); #endif /* Printing */ int trio_print_ref TRIO_PROTO((trio_pointer_t ref, const char *format, ...)); int trio_vprint_ref TRIO_PROTO((trio_pointer_t ref, const char *format, va_list args)); int trio_printv_ref TRIO_PROTO((trio_pointer_t ref, const char *format, trio_pointer_t *args)); void trio_print_int TRIO_PROTO((trio_pointer_t ref, int number)); void trio_print_uint TRIO_PROTO((trio_pointer_t ref, unsigned int number)); /* void trio_print_long TRIO_PROTO((trio_pointer_t ref, long number)); */ /* void trio_print_ulong TRIO_PROTO((trio_pointer_t ref, unsigned long number)); */ void trio_print_double TRIO_PROTO((trio_pointer_t ref, double number)); void trio_print_string TRIO_PROTO((trio_pointer_t ref, TRIO_CONST char *string)); void trio_print_pointer TRIO_PROTO((trio_pointer_t ref, trio_pointer_t pointer)); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* TRIO_TRIOP_H */ ================================================ FILE: src/trio/triostr.c ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ /************************************************************************* * Include files */ #if defined(HAVE_CONFIG_H) # include #endif #include #include #include #include #include "triodef.h" #include "triostr.h" #if defined(TRIO_FUNC_TO_LONG_DOUBLE) # define USE_MATH #endif #if defined(USE_MATH) # include #endif /************************************************************************* * Definitions */ #if !defined(TRIO_PUBLIC_STRING) # define TRIO_PUBLIC_STRING TRIO_PUBLIC #endif #if !defined(TRIO_PRIVATE_STRING) # define TRIO_PRIVATE_STRING TRIO_PRIVATE #endif #if !defined(NULL) # define NULL 0 #endif #if !defined(NIL) # define NIL ((char)0) #endif #if !defined(FALSE) # define FALSE (1 == 0) # define TRUE (! FALSE) #endif #if !defined(BOOLEAN_T) # define BOOLEAN_T int #endif #if defined(USE_MATH) # if defined(PREDEF_STANDARD_C99) # if defined(TRIO_COMPILER_DECC) # if (TRIO_COMPILER_DECC - 0 > 80000000) /* * The OSF/1 runtime that comes with the DECC compiler does not support * hexfloats conversion. */ # define USE_STRTOD # define USE_STRTOF # endif # else # define USE_STRTOD # define USE_STRTOF # endif # else # if defined(TRIO_COMPILER_VISUALC) # define USE_STRTOD # endif #endif #endif #if defined(TRIO_PLATFORM_UNIX) # if defined(PREDEF_STANDARD_UNIX95) # define USE_STRCASECMP # define USE_STRNCASECMP # endif # if defined(TRIO_PLATFORM_SUNOS) # define USE_SYS_ERRLIST # else # define USE_STRERROR # endif # if defined(TRIO_PLATFORM_QNX) # define strcasecmp(x,y) stricmp(x,y) # define strncasecmp(x,y,n) strnicmp(x,y,n) # endif #endif #if defined(TRIO_PLATFORM_WIN32) # define USE_STRCASECMP # if defined(TRIO_PLATFORM_WINCE) # define strcasecmp(x,y) _stricmp(x,y) # else # define strcasecmp(x,y) strcmpi(x,y) # endif #endif #if !defined(HAVE_CONFIG_H) # if !(defined(TRIO_PLATFORM_SUNOS)) # define HAVE_TOLOWER # define HAVE_TOUPPER # endif #endif #if defined(USE_MATH) && !defined(TRIO_NO_POWL) # if !defined(HAVE_POWL) # if defined(PREDEF_STANDARD_C99) \ || defined(PREDEF_STANDARD_UNIX03) # define HAVE_POWL # else # if defined(TRIO_COMPILER_VISUALC) # if defined(powl) # define HAVE_POWL # endif # endif # endif # endif #endif #if defined(HAVE_POWL) # define trio_powl(x,y) powl((x),(y)) #else # define trio_powl(x,y) pow((double)(x),(double)(y)) #endif #if defined(TRIO_FUNC_TO_UPPER) \ || (defined(TRIO_FUNC_EQUAL) && !defined(USE_STRCASECMP)) \ || (defined(TRIO_FUNC_EQUAL_MAX) && !defined(USE_STRNCASECMP)) \ || defined(TRIO_FUNC_MATCH) \ || defined(TRIO_FUNC_TO_LONG_DOUBLE) \ || defined(TRIO_FUNC_UPPER) # define TRIO_FUNC_INTERNAL_TO_UPPER #endif /************************************************************************* * Structures */ struct _trio_string_t { char *content; size_t length; size_t allocated; }; /************************************************************************* * Constants */ #if !defined(TRIO_EMBED_STRING) static TRIO_CONST char rcsid[] = "@(#)$Id$"; #endif /************************************************************************* * Static String Functions */ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_static.h" #endif /** @addtogroup StaticStrings @{ */ /* * internal_duplicate_max */ #if defined(TRIO_FUNC_DUPLICATE) \ || defined(TRIO_FUNC_DUPLICATE_MAX) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PRIVATE_STRING char * internal_duplicate_max TRIO_ARGS2((source, size), TRIO_CONST char *source, size_t size) { char *target; assert(source); /* Make room for string plus a terminating zero */ size++; target = trio_create(size); if (target) { trio_copy_max(target, size, source); } return target; } #endif /* * internal_string_alloc */ #if defined(TRIO_FUNC_STRING_CREATE) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PRIVATE_STRING trio_string_t * internal_string_alloc(TRIO_NOARGS) { trio_string_t *self; self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t)); if (self) { self->content = NULL; self->length = 0; self->allocated = 0; } return self; } #endif /* * internal_string_grow * * The size of the string will be increased by 'delta' characters. If * 'delta' is zero, the size will be doubled. */ #if defined(TRIO_FUNC_STRING_CREATE) \ || defined(TRIO_FUNC_STRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND_CHAR) TRIO_PRIVATE_STRING BOOLEAN_T internal_string_grow TRIO_ARGS2((self, delta), trio_string_t *self, size_t delta) { BOOLEAN_T status = FALSE; char *new_content; size_t new_size; new_size = (delta == 0) ? ( (self->allocated == 0) ? 1 : self->allocated * 2 ) : self->allocated + delta; new_content = (char *)TRIO_REALLOC(self->content, new_size); if (new_content) { self->content = new_content; self->allocated = new_size; status = TRUE; } return status; } #endif /* * internal_string_grow_to * * The size of the string will be increased to 'length' plus one characters. * If 'length' is less than the original size, the original size will be * used (that is, the size of the string is never decreased). */ #if defined(TRIO_FUNC_STRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND_MAX) TRIO_PRIVATE_STRING BOOLEAN_T internal_string_grow_to TRIO_ARGS2((self, length), trio_string_t *self, size_t length) { length++; /* Room for terminating zero */ return (self->allocated < length) ? internal_string_grow(self, length - self->allocated) : TRUE; } #endif #if defined(TRIO_FUNC_INTERNAL_TO_UPPER) TRIO_PRIVATE_STRING int internal_to_upper TRIO_ARGS1((source), int source) { # if defined(HAVE_TOUPPER) return toupper(source); # else /* Does not handle locales or non-contiguous alphabetic characters */ return ((source >= (int)'a') && (source <= (int)'z')) ? source - 'a' + 'A' : source; # endif } #endif /** Create new string. @param size Size of new string. @return Pointer to string, or NULL if allocation failed. */ #if defined(TRIO_FUNC_CREATE) TRIO_PUBLIC_STRING char * trio_create TRIO_ARGS1((size), size_t size) { return (char *)TRIO_MALLOC(size); } #endif /** Destroy string. @param string String to be freed. */ #if defined(TRIO_FUNC_DESTROY) TRIO_PUBLIC_STRING void trio_destroy TRIO_ARGS1((string), char *string) { if (string) { TRIO_FREE(string); } } #endif /** Count the number of characters in a string. @param string String to measure. @return Number of characters in @p string. */ #if defined(TRIO_FUNC_LENGTH) TRIO_PUBLIC_STRING size_t trio_length TRIO_ARGS1((string), TRIO_CONST char *string) { return strlen(string); } #endif /** Count at most @p max characters in a string. @param string String to measure. @param max Maximum number of characters to count. @return The maximum value of @p max and number of characters in @p string. */ #if defined(TRIO_FUNC_LENGTH_MAX) TRIO_PUBLIC_STRING size_t trio_length_max TRIO_ARGS2((string, max), TRIO_CONST char *string, size_t max) { size_t i; for (i = 0; i < max; ++i) { if (string[i] == 0) break; } return i; } #endif /** Append @p source at the end of @p target. @param target Target string. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chunk with sufficient room to contain the @p target string and @p source string. @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_APPEND) TRIO_PUBLIC_STRING int trio_append TRIO_ARGS2((target, source), char *target, TRIO_CONST char *source) { assert(target); assert(source); return (strcat(target, source) != NULL); } #endif /** Append at most @p max characters from @p source to @p target. @param target Target string. @param max Maximum number of characters to append. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chuck with sufficient room to contain the @p target string and the @p source string (at most @p max characters). @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_APPEND_MAX) TRIO_PUBLIC_STRING int trio_append_max TRIO_ARGS3((target, max, source), char *target, size_t max, TRIO_CONST char *source) { size_t length; assert(target); assert(source); length = trio_length(target); if (max > length) { strncat(target, source, max - length - 1); } return TRUE; } #endif /** Determine if a string contains a substring. @param string String to be searched. @param substring String to be found. @return Boolean value indicating success or failure. */ #if defined(TRIO_FUNC_CONTAINS) TRIO_PUBLIC_STRING int trio_contains TRIO_ARGS2((string, substring), TRIO_CONST char *string, TRIO_CONST char *substring) { assert(string); assert(substring); return (0 != strstr(string, substring)); } #endif /** Copy @p source to @p target. @param target Target string. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chunk with sufficient room to contain the @p source string. @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_COPY) TRIO_PUBLIC_STRING int trio_copy TRIO_ARGS2((target, source), char *target, TRIO_CONST char *source) { assert(target); assert(source); (void)strcpy(target, source); return TRUE; } #endif /** Copy at most @p max - 1 characters from @p source to @p target. @param target Target string. @param max Maximum number of characters to append (one of which is a NUL terminator). In other words @p source must point to at least @p max - 1 bytes, but @p target must point to at least @p max bytes. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chunk with sufficient room to contain the @p source string and a NUL terminator (at most @p max bytes total). @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_COPY_MAX) TRIO_PUBLIC_STRING int trio_copy_max TRIO_ARGS3((target, max, source), char *target, size_t max, TRIO_CONST char *source) { assert(target); assert(source); assert(max > 0); /* Includes != 0 */ (void)strncpy(target, source, max - 1); target[max - 1] = (char)0; return TRUE; } #endif /** Duplicate @p source. @param source Source string. @return A copy of the @p source string. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_DUPLICATE) TRIO_PUBLIC_STRING char * trio_duplicate TRIO_ARGS1((source), TRIO_CONST char *source) { return internal_duplicate_max(source, trio_length(source)); } #endif /** Duplicate at most @p max characters of @p source. @param source Source string. @param max Maximum number of characters to duplicate. @return A copy of the @p source string. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_DUPLICATE_MAX) TRIO_PUBLIC_STRING char * trio_duplicate_max TRIO_ARGS2((source, max), TRIO_CONST char *source, size_t max) { size_t length; assert(source); assert(max > 0); length = trio_length(source); if (length > max) { length = max; } return internal_duplicate_max(source, length); } #endif /** Compare if two strings are equal. @param first First string. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-insensitive comparison. */ #if defined(TRIO_FUNC_EQUAL) TRIO_PUBLIC_STRING int trio_equal TRIO_ARGS2((first, second), TRIO_CONST char *first, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { # if defined(USE_STRCASECMP) return (0 == strcasecmp(first, second)); # else while ((*first != NIL) && (*second != NIL)) { if (internal_to_upper(*first) != internal_to_upper(*second)) { break; } first++; second++; } return ((*first == NIL) && (*second == NIL)); # endif } return FALSE; } #endif /** Compare if two strings are equal. @param first First string. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-sensitive comparison. */ #if defined(TRIO_FUNC_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_equal_case TRIO_ARGS2((first, second), TRIO_CONST char *first, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { return (0 == strcmp(first, second)); } return FALSE; } #endif /** Compare if two strings up until the first @p max characters are equal. @param first First string. @param max Maximum number of characters to compare. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-sensitive comparison. */ #if defined(TRIO_FUNC_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_equal_case_max TRIO_ARGS3((first, max, second), TRIO_CONST char *first, size_t max, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { return (0 == strncmp(first, second, max)); } return FALSE; } #endif /** Compare if two strings are equal. @param first First string. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Collating characters are considered equal. */ #if defined(TRIO_FUNC_EQUAL_LOCALE) TRIO_PUBLIC_STRING int trio_equal_locale TRIO_ARGS2((first, second), TRIO_CONST char *first, TRIO_CONST char *second) { assert(first); assert(second); # if defined(LC_COLLATE) return (strcoll(first, second) == 0); # else return trio_equal(first, second); # endif } #endif /** Compare if two strings up until the first @p max characters are equal. @param first First string. @param max Maximum number of characters to compare. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-insensitive comparison. */ #if defined(TRIO_FUNC_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_equal_max TRIO_ARGS3((first, max, second), TRIO_CONST char *first, size_t max, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { # if defined(USE_STRNCASECMP) return (0 == strncasecmp(first, second, max)); # else /* Not adequately tested yet */ size_t cnt = 0; while ((*first != NIL) && (*second != NIL) && (cnt <= max)) { if (internal_to_upper(*first) != internal_to_upper(*second)) { break; } first++; second++; cnt++; } return ((cnt == max) || ((*first == NIL) && (*second == NIL))); # endif } return FALSE; } #endif /** Provide a textual description of an error code (errno). @param error_number Error number. @return Textual description of @p error_number. */ #if defined(TRIO_FUNC_ERROR) TRIO_PUBLIC_STRING TRIO_CONST char * trio_error TRIO_ARGS1((error_number), int error_number) { # if defined(USE_STRERROR) return strerror(error_number); # else # if defined(USE_SYS_ERRLIST) extern char *sys_errlist[]; extern int sys_nerr; return ((error_number < 0) || (error_number >= sys_nerr)) ? "unknown" : sys_errlist[error_number]; # else return "unknown"; # endif # endif } #endif /** Format the date/time according to @p format. @param target Target string. @param max Maximum number of characters to format. @param format Formatting string. @param datetime Date/time structure. @return Number of formatted characters. The formatting string accepts the same specifiers as the standard C function strftime. */ #if defined(TRIO_FUNC_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_format_date_max TRIO_ARGS4((target, max, format, datetime), char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime) { assert(target); assert(format); assert(datetime); assert(max > 0); return strftime(target, max, format, datetime); } #endif /** Calculate a hash value for a string. @param string String to be calculated on. @param type Hash function. @return Calculated hash value. @p type can be one of the following @li @c TRIO_HASH_PLAIN Plain hash function. */ #if defined(TRIO_FUNC_HASH) TRIO_PUBLIC_STRING unsigned long trio_hash TRIO_ARGS2((string, type), TRIO_CONST char *string, int type) { unsigned long value = 0L; char ch; assert(string); switch (type) { case TRIO_HASH_PLAIN: while ( (ch = *string++) != NIL ) { value *= 31; value += (unsigned long)ch; } break; default: assert(FALSE); break; } return value; } #endif /** Find first occurrence of a character in a string. @param string String to be searched. @param character Character to be found. @return A pointer to the found character, or NULL if character was not found. */ #if defined(TRIO_FUNC_INDEX) TRIO_PUBLIC_STRING char * trio_index TRIO_ARGS2((string, character), TRIO_CONST char *string, int character) { assert(string); return strchr(string, character); } #endif /** Find last occurrence of a character in a string. @param string String to be searched. @param character Character to be found. @return A pointer to the found character, or NULL if character was not found. */ #if defined(TRIO_FUNC_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_index_last TRIO_ARGS2((string, character), TRIO_CONST char *string, int character) { assert(string); return strchr(string, character); } #endif /** Convert the alphabetic letters in the string to lower-case. @param target String to be converted. @return Number of processed characters (converted or not). */ #if defined(TRIO_FUNC_LOWER) TRIO_PUBLIC_STRING int trio_lower TRIO_ARGS1((target), char *target) { assert(target); return trio_span_function(target, target, trio_to_lower); } #endif /** Compare two strings using wildcards. @param string String to be searched. @param pattern Pattern, including wildcards, to search for. @return Boolean value indicating success or failure. Case-insensitive comparison. The following wildcards can be used @li @c * Match any number of characters. @li @c ? Match a single character. */ #if defined(TRIO_FUNC_MATCH) TRIO_PUBLIC_STRING int trio_match TRIO_ARGS2((string, pattern), TRIO_CONST char *string, TRIO_CONST char *pattern) { assert(string); assert(pattern); for (; ('*' != *pattern); ++pattern, ++string) { if (NIL == *string) { return (NIL == *pattern); } if ((internal_to_upper((int)*string) != internal_to_upper((int)*pattern)) && ('?' != *pattern)) { return FALSE; } } /* two-line patch to prevent *too* much recursiveness: */ while ('*' == pattern[1]) pattern++; do { if ( trio_match(string, &pattern[1]) ) { return TRUE; } } while (*string++); return FALSE; } #endif /** Compare two strings using wildcards. @param string String to be searched. @param pattern Pattern, including wildcards, to search for. @return Boolean value indicating success or failure. Case-sensitive comparison. The following wildcards can be used @li @c * Match any number of characters. @li @c ? Match a single character. */ #if defined(TRIO_FUNC_MATCH_CASE) TRIO_PUBLIC_STRING int trio_match_case TRIO_ARGS2((string, pattern), TRIO_CONST char *string, TRIO_CONST char *pattern) { assert(string); assert(pattern); for (; ('*' != *pattern); ++pattern, ++string) { if (NIL == *string) { return (NIL == *pattern); } if ((*string != *pattern) && ('?' != *pattern)) { return FALSE; } } /* two-line patch to prevent *too* much recursiveness: */ while ('*' == pattern[1]) pattern++; do { if ( trio_match_case(string, &pattern[1]) ) { return TRUE; } } while (*string++); return FALSE; } #endif /** Execute a function on each character in string. @param target Target string. @param source Source string. @param Function Function to be executed. @return Number of processed characters. */ #if defined(TRIO_FUNC_SPAN_FUNCTION) TRIO_PUBLIC_STRING size_t trio_span_function TRIO_ARGS3((target, source, Function), char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int))) { size_t count = 0; assert(target); assert(source); assert(Function); while (*source != NIL) { *target++ = Function(*source++); count++; } return count; } #endif /** Search for a substring in a string. @param string String to be searched. @param substring String to be found. @return Pointer to first occurrence of @p substring in @p string, or NULL if no match was found. */ #if defined(TRIO_FUNC_SUBSTRING) TRIO_PUBLIC_STRING char * trio_substring TRIO_ARGS2((string, substring), TRIO_CONST char *string, TRIO_CONST char *substring) { assert(string); assert(substring); return strstr(string, substring); } #endif /** Search for a substring in the first @p max characters of a string. @param string String to be searched. @param max Maximum characters to be searched. @param substring String to be found. @return Pointer to first occurrence of @p substring in @p string, or NULL if no match was found. */ #if defined(TRIO_FUNC_SUBSTRING_MAX) TRIO_PUBLIC_STRING char * trio_substring_max TRIO_ARGS3((string, max, substring), TRIO_CONST char *string, size_t max, TRIO_CONST char *substring) { size_t count; size_t size; char *result = NULL; assert(string); assert(substring); size = trio_length(substring); if (size <= max) { for (count = 0; count <= max - size; count++) { if (trio_equal_max(substring, size, &string[count])) { result = (char *)&string[count]; break; } } } return result; } #endif /** Tokenize string. @param string String to be tokenized. @param delimiters String containing list of delimiting characters. @return Start of new token. @warning @p string will be destroyed. */ #if defined(TRIO_FUNC_TOKENIZE) TRIO_PUBLIC_STRING char * trio_tokenize TRIO_ARGS2((string, delimiters), char *string, TRIO_CONST char *delimiters) { assert(delimiters); return strtok(string, delimiters); } #endif /** Convert string to floating-point number. @param source String to be converted. @param endp Pointer to end of the converted string. @return A floating-point number. The following Extended Backus-Naur form is used @verbatim double ::= [ ] ( | | ) [ [ ] ] number ::= 1*( ) digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) exponential ::= ( 'e' | 'E' ) sign ::= ( '-' | '+' ) decimal_point ::= '.' @endverbatim */ #if defined(TRIO_FUNC_TO_LONG_DOUBLE) /* FIXME: Add EBNF for hex-floats */ TRIO_PUBLIC_STRING trio_long_double_t trio_to_long_double TRIO_ARGS2((source, endp), TRIO_CONST char *source, char **endp) { # if defined(USE_STRTOLD) return strtold(source, endp); # else int isNegative = FALSE; int isExponentNegative = FALSE; trio_long_double_t integer = 0.0; trio_long_double_t fraction = 0.0; unsigned long exponent = 0; trio_long_double_t base; trio_long_double_t fracdiv = 1.0; trio_long_double_t value = 0.0; /* First try hex-floats */ if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) { base = 16.0; source += 2; while (isxdigit((int)*source)) { integer *= base; integer += (isdigit((int)*source) ? (*source - '0') : 10 + (internal_to_upper((int)*source) - 'A')); source++; } if (*source == '.') { source++; while (isxdigit((int)*source)) { fracdiv /= base; fraction += fracdiv * (isdigit((int)*source) ? (*source - '0') : 10 + (internal_to_upper((int)*source) - 'A')); source++; } if ((*source == 'p') || (*source == 'P')) { source++; if ((*source == '+') || (*source == '-')) { isExponentNegative = (*source == '-'); source++; } while (isdigit((int)*source)) { exponent *= 10; exponent += (*source - '0'); source++; } } } /* For later use with exponent */ base = 2.0; } else /* Then try normal decimal floats */ { base = 10.0; isNegative = (*source == '-'); /* Skip sign */ if ((*source == '+') || (*source == '-')) source++; /* Integer part */ while (isdigit((int)*source)) { integer *= base; integer += (*source - '0'); source++; } if (*source == '.') { source++; /* skip decimal point */ while (isdigit((int)*source)) { fracdiv /= base; fraction += (*source - '0') * fracdiv; source++; } } if ((*source == 'e') || (*source == 'E') # if TRIO_MICROSOFT || (*source == 'd') || (*source == 'D') # endif ) { source++; /* Skip exponential indicator */ isExponentNegative = (*source == '-'); if ((*source == '+') || (*source == '-')) source++; while (isdigit((int)*source)) { exponent *= (int)base; exponent += (*source - '0'); source++; } } } value = integer + fraction; if (exponent != 0) { if (isExponentNegative) value /= trio_powl(base, (trio_long_double_t)exponent); else value *= trio_powl(base, (trio_long_double_t)exponent); } if (isNegative) value = -value; if (endp) *endp = (char *)source; return value; # endif } #endif /** Convert string to floating-point number. @param source String to be converted. @param endp Pointer to end of the converted string. @return A floating-point number. See @ref trio_to_long_double. */ #if defined(TRIO_FUNC_TO_DOUBLE) TRIO_PUBLIC_STRING double trio_to_double TRIO_ARGS2((source, endp), TRIO_CONST char *source, char **endp) { #if defined(USE_STRTOD) return strtod(source, endp); #else return (double)trio_to_long_double(source, endp); #endif } #endif /** Convert string to floating-point number. @param source String to be converted. @param endp Pointer to end of the converted string. @return A floating-point number. See @ref trio_to_long_double. */ #if defined(TRIO_FUNC_TO_FLOAT) TRIO_PUBLIC_STRING float trio_to_float TRIO_ARGS2((source, endp), TRIO_CONST char *source, char **endp) { # if defined(USE_STRTOF) return strtof(source, endp); # else return (float)trio_to_long_double(source, endp); # endif } #endif /** Convert string to signed integer. @param string String to be converted. @param endp Pointer to end of converted string. @param base Radix number of number. */ #if defined(TRIO_FUNC_TO_LONG) TRIO_PUBLIC_STRING long trio_to_long TRIO_ARGS3((string, endp, base), TRIO_CONST char *string, char **endp, int base) { assert(string); assert((base >= 2) && (base <= 36)); return strtol(string, endp, base); } #endif /** Convert one alphabetic letter to lower-case. @param source The letter to be converted. @return The converted letter. */ #if defined(TRIO_FUNC_TO_LOWER) TRIO_PUBLIC_STRING int trio_to_lower TRIO_ARGS1((source), int source) { # if defined(HAVE_TOLOWER) return tolower(source); # else /* Does not handle locales or non-contiguous alphabetic characters */ return ((source >= (int)'A') && (source <= (int)'Z')) ? source - 'A' + 'a' : source; # endif } #endif /** Convert string to unsigned integer. @param string String to be converted. @param endp Pointer to end of converted string. @param base Radix number of number. */ #if defined(TRIO_FUNC_TO_UNSIGNED_LONG) TRIO_PUBLIC_STRING unsigned long trio_to_unsigned_long TRIO_ARGS3((string, endp, base), TRIO_CONST char *string, char **endp, int base) { assert(string); assert((base >= 2) && (base <= 36)); return strtoul(string, endp, base); } #endif /** Convert one alphabetic letter to upper-case. @param source The letter to be converted. @return The converted letter. */ #if defined(TRIO_FUNC_TO_UPPER) TRIO_PUBLIC_STRING int trio_to_upper TRIO_ARGS1((source), int source) { return internal_to_upper(source); } #endif /** Convert the alphabetic letters in the string to upper-case. @param target The string to be converted. @return The number of processed characters (converted or not). */ #if defined(TRIO_FUNC_UPPER) TRIO_PUBLIC_STRING int trio_upper TRIO_ARGS1((target), char *target) { assert(target); return trio_span_function(target, target, internal_to_upper); } #endif /** @} End of StaticStrings */ /************************************************************************* * Dynamic String Functions */ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_dynamic.h" #endif /** @addtogroup DynamicStrings @{ */ /** Create a new dynamic string. @param initial_size Initial size of the buffer. @return Newly allocated dynamic string, or NULL if memory allocation failed. */ #if defined(TRIO_FUNC_STRING_CREATE) TRIO_PUBLIC_STRING trio_string_t * trio_string_create TRIO_ARGS1((initial_size), int initial_size) { trio_string_t *self; self = internal_string_alloc(); if (self) { if (internal_string_grow(self, (size_t)((initial_size > 0) ? initial_size : 1))) { self->content[0] = (char)0; self->allocated = initial_size; } else { trio_string_destroy(self); self = NULL; } } return self; } #endif /** Deallocate the dynamic string and its contents. @param self Dynamic string */ #if defined(TRIO_FUNC_STRING_DESTROY) TRIO_PUBLIC_STRING void trio_string_destroy TRIO_ARGS1((self), trio_string_t *self) { assert(self); if (self) { trio_destroy(self->content); TRIO_FREE(self); } } #endif /** Get a pointer to the content. @param self Dynamic string. @param offset Offset into content. @return Pointer to the content. @p Offset can be zero, positive, or negative. If @p offset is zero, then the start of the content will be returned. If @p offset is positive, then a pointer to @p offset number of characters from the beginning of the content is returned. If @p offset is negative, then a pointer to @p offset number of characters from the ending of the string, starting at the terminating zero, is returned. */ #if defined(TRIO_FUNC_STRING_GET) TRIO_PUBLIC_STRING char * trio_string_get TRIO_ARGS2((self, offset), trio_string_t *self, int offset) { char *result = NULL; assert(self); if (self->content != NULL) { if (self->length == 0) { (void)trio_string_length(self); } if (offset >= 0) { if (offset > (int)self->length) { offset = self->length; } } else { offset += self->length + 1; if (offset < 0) { offset = 0; } } result = &(self->content[offset]); } return result; } #endif /** Extract the content. @param self Dynamic String @return Content of dynamic string. The content is removed from the dynamic string. This enables destruction of the dynamic string without deallocation of the content. */ #if defined(TRIO_FUNC_STRING_EXTRACT) TRIO_PUBLIC_STRING char * trio_string_extract TRIO_ARGS1((self), trio_string_t *self) { char *result; assert(self); result = self->content; /* FIXME: Allocate new empty buffer? */ self->content = NULL; self->length = self->allocated = 0; return result; } #endif /** Set the content of the dynamic string. @param self Dynamic String @param buffer The new content. Sets the content of the dynamic string to a copy @p buffer. An existing content will be deallocated first, if necessary. @remark This function will make a copy of @p buffer. You are responsible for deallocating @p buffer yourself. */ #if defined(TRIO_FUNC_XSTRING_SET) TRIO_PUBLIC_STRING void trio_xstring_set TRIO_ARGS2((self, buffer), trio_string_t *self, char *buffer) { assert(self); trio_destroy(self->content); self->content = trio_duplicate(buffer); } #endif /* * trio_string_size */ #if defined(TRIO_FUNC_STRING_SIZE) TRIO_PUBLIC_STRING int trio_string_size TRIO_ARGS1((self), trio_string_t *self) { assert(self); return self->allocated; } #endif /* * trio_string_terminate */ #if defined(TRIO_FUNC_STRING_TERMINATE) TRIO_PUBLIC_STRING void trio_string_terminate TRIO_ARGS1((self), trio_string_t *self) { trio_xstring_append_char(self, 0); } #endif /** Append the second string to the first. @param self Dynamic string to be modified. @param other Dynamic string to copy from. @return Boolean value indicating success or failure. */ #if defined(TRIO_FUNC_STRING_APPEND) TRIO_PUBLIC_STRING int trio_string_append TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { size_t length; assert(self); assert(other); length = self->length + other->length; if (!internal_string_grow_to(self, length)) goto error; trio_copy(&self->content[self->length], other->content); self->length = length; return TRUE; error: return FALSE; } #endif /* * trio_xstring_append */ #if defined(TRIO_FUNC_XSTRING_APPEND) TRIO_PUBLIC_STRING int trio_xstring_append TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { size_t length; assert(self); assert(other); length = self->length + trio_length(other); if (!internal_string_grow_to(self, length)) goto error; trio_copy(&self->content[self->length], other); self->length = length; return TRUE; error: return FALSE; } #endif /* * trio_xstring_append_char */ #if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) TRIO_PUBLIC_STRING int trio_xstring_append_char TRIO_ARGS2((self, character), trio_string_t *self, char character) { assert(self); if ((int)self->length >= trio_string_size(self)) { if (!internal_string_grow(self, 0)) goto error; } self->content[self->length] = character; self->length++; return TRUE; error: return FALSE; } #endif /* * trio_xstring_append_max */ #if defined(TRIO_FUNC_XSTRING_APPEND_MAX) TRIO_PUBLIC_STRING int trio_xstring_append_max TRIO_ARGS3((self, other, max), trio_string_t *self, TRIO_CONST char *other, size_t max) { size_t length; assert(self); assert(other); length = self->length + trio_length_max(other, max); if (!internal_string_grow_to(self, length)) goto error; /* * Pass max + 1 since trio_copy_max copies one character less than * this from the source to make room for a terminating zero. */ trio_copy_max(&self->content[self->length], max + 1, other); self->length = length; return TRUE; error: return FALSE; } #endif /** Search for the first occurrence of second parameter in the first. @param self Dynamic string to be modified. @param other Dynamic string to copy from. @return Boolean value indicating success or failure. */ #if defined(TRIO_FUNC_STRING_CONTAINS) TRIO_PUBLIC_STRING int trio_string_contains TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); return trio_contains(self->content, other->content); } #endif /* * trio_xstring_contains */ #if defined(TRIO_FUNC_XSTRING_CONTAINS) TRIO_PUBLIC_STRING int trio_xstring_contains TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); return trio_contains(self->content, other); } #endif /* * trio_string_copy */ #if defined(TRIO_FUNC_STRING_COPY) TRIO_PUBLIC_STRING int trio_string_copy TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); self->length = 0; return trio_string_append(self, other); } #endif /* * trio_xstring_copy */ #if defined(TRIO_FUNC_XSTRING_COPY) TRIO_PUBLIC_STRING int trio_xstring_copy TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); self->length = 0; return trio_xstring_append(self, other); } #endif /* * trio_string_duplicate */ #if defined(TRIO_FUNC_STRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_string_duplicate TRIO_ARGS1((other), trio_string_t *other) { trio_string_t *self; assert(other); self = internal_string_alloc(); if (self) { self->content = internal_duplicate_max(other->content, other->length); if (self->content) { self->length = other->length; self->allocated = self->length + 1; } else { self->length = self->allocated = 0; } } return self; } #endif /* * trio_xstring_duplicate */ #if defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_xstring_duplicate TRIO_ARGS1((other), TRIO_CONST char *other) { trio_string_t *self; assert(other); self = internal_string_alloc(); if (self) { self->content = internal_duplicate_max(other, trio_length(other)); if (self->content) { self->length = trio_length(self->content); self->allocated = self->length + 1; } else { self->length = self->allocated = 0; } } return self; } #endif /* * trio_string_equal */ #if defined(TRIO_FUNC_STRING_EQUAL) TRIO_PUBLIC_STRING int trio_string_equal TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); return trio_equal(self->content, other->content); } #endif /* * trio_xstring_equal */ #if defined(TRIO_FUNC_XSTRING_EQUAL) TRIO_PUBLIC_STRING int trio_xstring_equal TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); return trio_equal(self->content, other); } #endif /* * trio_string_equal_max */ #if defined(TRIO_FUNC_STRING_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_string_equal_max TRIO_ARGS3((self, max, other), trio_string_t *self, size_t max, trio_string_t *other) { assert(self); assert(other); return trio_equal_max(self->content, max, other->content); } #endif /* * trio_xstring_equal_max */ #if defined(TRIO_FUNC_XSTRING_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_xstring_equal_max TRIO_ARGS3((self, max, other), trio_string_t *self, size_t max, TRIO_CONST char *other) { assert(self); assert(other); return trio_equal_max(self->content, max, other); } #endif /* * trio_string_equal_case */ #if defined(TRIO_FUNC_STRING_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_string_equal_case TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); return trio_equal_case(self->content, other->content); } #endif /* * trio_xstring_equal_case */ #if defined(TRIO_FUNC_XSTRING_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_xstring_equal_case TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); return trio_equal_case(self->content, other); } #endif /* * trio_string_equal_case_max */ #if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_string_equal_case_max TRIO_ARGS3((self, max, other), trio_string_t *self, size_t max, trio_string_t *other) { assert(self); assert(other); return trio_equal_case_max(self->content, max, other->content); } #endif /* * trio_xstring_equal_case_max */ #if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_xstring_equal_case_max TRIO_ARGS3((self, max, other), trio_string_t *self, size_t max, TRIO_CONST char *other) { assert(self); assert(other); return trio_equal_case_max(self->content, max, other); } #endif /* * trio_string_format_data_max */ #if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_string_format_date_max TRIO_ARGS4((self, max, format, datetime), trio_string_t *self, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime) { assert(self); return trio_format_date_max(self->content, max, format, datetime); } #endif /* * trio_string_index */ #if defined(TRIO_FUNC_STRING_INDEX) TRIO_PUBLIC_STRING char * trio_string_index TRIO_ARGS2((self, character), trio_string_t *self, int character) { assert(self); return trio_index(self->content, character); } #endif /* * trio_string_index_last */ #if defined(TRIO_FUNC_STRING_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_string_index_last TRIO_ARGS2((self, character), trio_string_t *self, int character) { assert(self); return trio_index_last(self->content, character); } #endif /* * trio_string_length */ #if defined(TRIO_FUNC_STRING_LENGTH) TRIO_PUBLIC_STRING int trio_string_length TRIO_ARGS1((self), trio_string_t *self) { assert(self); if (self->length == 0) { self->length = trio_length(self->content); } return self->length; } #endif /* * trio_string_lower */ #if defined(TRIO_FUNC_STRING_LOWER) TRIO_PUBLIC_STRING int trio_string_lower TRIO_ARGS1((self), trio_string_t *self) { assert(self); return trio_lower(self->content); } #endif /* * trio_string_match */ #if defined(TRIO_FUNC_STRING_MATCH) TRIO_PUBLIC_STRING int trio_string_match TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); return trio_match(self->content, other->content); } #endif /* * trio_xstring_match */ #if defined(TRIO_FUNC_XSTRING_MATCH) TRIO_PUBLIC_STRING int trio_xstring_match TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); return trio_match(self->content, other); } #endif /* * trio_string_match_case */ #if defined(TRIO_FUNC_STRING_MATCH_CASE) TRIO_PUBLIC_STRING int trio_string_match_case TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); return trio_match_case(self->content, other->content); } #endif /* * trio_xstring_match_case */ #if defined(TRIO_FUNC_XSTRING_MATCH_CASE) TRIO_PUBLIC_STRING int trio_xstring_match_case TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); return trio_match_case(self->content, other); } #endif /* * trio_string_substring */ #if defined(TRIO_FUNC_STRING_SUBSTRING) TRIO_PUBLIC_STRING char * trio_string_substring TRIO_ARGS2((self, other), trio_string_t *self, trio_string_t *other) { assert(self); assert(other); return trio_substring(self->content, other->content); } #endif /* * trio_xstring_substring */ #if defined(TRIO_FUNC_XSTRING_SUBSTRING) TRIO_PUBLIC_STRING char * trio_xstring_substring TRIO_ARGS2((self, other), trio_string_t *self, TRIO_CONST char *other) { assert(self); assert(other); return trio_substring(self->content, other); } #endif /* * trio_string_upper */ #if defined(TRIO_FUNC_STRING_UPPER) TRIO_PUBLIC_STRING int trio_string_upper TRIO_ARGS1((self), trio_string_t *self) { assert(self); return trio_upper(self->content); } #endif /** @} End of DynamicStrings */ ================================================ FILE: src/trio/triostr.h ================================================ /************************************************************************* * * $Id$ * * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ #ifndef TRIO_TRIOSTR_H #define TRIO_TRIOSTR_H /* * Documentation is located in triostr.c */ #include #include #include #include #include "triodef.h" #include "triop.h" #ifdef __cplusplus extern "C" { #endif enum { TRIO_HASH_NONE = 0, TRIO_HASH_PLAIN, TRIO_HASH_TWOSIGNED }; #if !defined(TRIO_PUBLIC_STRING) # if !defined(TRIO_PUBLIC) # define TRIO_PUBLIC # endif # define TRIO_PUBLIC_STRING TRIO_PUBLIC #endif /************************************************************************* * Dependencies */ #if defined(TRIO_EMBED_STRING) /* * The application that triostr is embedded in must define which functions * it uses. * * The following resolves internal dependencies. */ # if defined(TRIO_FUNC_XSTRING_SET) # if !defined(TRIO_FUNC_DUPLICATE) # define TRIO_FUNC_DUPLICATE # endif # endif # if defined(TRIO_FUNC_DUPLICATE) \ || defined(TRIO_FUNC_DUPLICATE_MAX) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE) # if !defined(TRIO_FUNC_CREATE) # define TRIO_FUNC_CREATE # endif # if !defined(TRIO_FUNC_COPY_MAX) # define TRIO_FUNC_COPY_MAX # endif # endif # if defined(TRIO_FUNC_STRING_CREATE) # if !defined(TRIO_FUNC_STRING_DESTROY) # define TRIO_FUNC_STRING_DESTROY # endif # endif # if defined(TRIO_FUNC_STRING_DESTROY) \ || defined(TRIO_FUNC_XSTRING_SET) # if !defined(TRIO_FUNC_DESTROY) # define TRIO_FUNC_DESTROY # endif # endif # if defined(TRIO_FUNC_EQUAL_LOCALE) \ || defined(TRIO_FUNC_STRING_EQUAL) \ || defined(TRIO_FUNC_XSTRING_EQUAL) # if !defined(TRIO_FUNC_EQUAL) # define TRIO_FUNC_EQUAL # endif # endif # if defined(TRIO_FUNC_EQUAL_CASE) \ || defined(TRIO_FUNC_STRING_EQUAL_CASE) \ || defined(TRIO_FUNC_XSTRING_EQUAL_CASE) # if !defined(TRIO_FUNC_EQUAL_CASE) # define TRIO_FUNC_EQUAL_CASE # endif # endif # if defined(TRIO_FUNC_SUBSTRING_MAX) \ || defined(TRIO_FUNC_STRING_EQUAL_MAX) \ || defined(TRIO_FUNC_XSTRING_EQUAL_MAX) # if !defined(TRIO_FUNC_EQUAL_MAX) # define TRIO_FUNC_EQUAL_MAX # endif # endif # if defined(TRIO_FUNC_TO_DOUBLE) \ || defined(TRIO_FUNC_TO_FLOAT) # if !defined(TRIO_FUNC_TO_LONG_DOUBLE) # define TRIO_FUNC_TO_LONG_DOUBLE # endif # if !defined(TRIO_FUNC_TO_FLOAT) # define TRIO_FUNC_TO_FLOAT # endif # endif # if defined(TRIO_FUNC_STRING_TERMINATE) # if !defined(TRIO_FUNC_XSTRING_APPEND_CHAR) # define TRIO_FUNC_XSTRING_APPEND_CHAR # endif # endif # if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) # if !defined(TRIO_FUNC_STRING_SIZE) # define TRIO_FUNC_STRING_SIZE # endif # endif #else /* * When triostr is not embedded all functions are defined. */ # define TRIO_FUNC_APPEND # define TRIO_FUNC_APPEND_MAX # define TRIO_FUNC_CONTAINS # define TRIO_FUNC_COPY # define TRIO_FUNC_COPY_MAX # define TRIO_FUNC_CREATE # define TRIO_FUNC_DESTROY # define TRIO_FUNC_DUPLICATE # define TRIO_FUNC_DUPLICATE_MAX # define TRIO_FUNC_EQUAL # define TRIO_FUNC_EQUAL_CASE # define TRIO_FUNC_EQUAL_CASE_MAX # define TRIO_FUNC_EQUAL_LOCALE # define TRIO_FUNC_EQUAL_MAX # define TRIO_FUNC_ERROR # if !defined(TRIO_PLATFORM_WINCE) # define TRIO_FUNC_FORMAT_DATE_MAX # endif # define TRIO_FUNC_HASH # define TRIO_FUNC_INDEX # define TRIO_FUNC_INDEX_LAST # define TRIO_FUNC_LENGTH # define TRIO_FUNC_LENGTH_MAX # define TRIO_FUNC_LOWER # define TRIO_FUNC_MATCH # define TRIO_FUNC_MATCH_CASE # define TRIO_FUNC_SPAN_FUNCTION # define TRIO_FUNC_SUBSTRING # define TRIO_FUNC_SUBSTRING_MAX # define TRIO_FUNC_TO_DOUBLE # define TRIO_FUNC_TO_FLOAT # define TRIO_FUNC_TO_LONG # define TRIO_FUNC_TO_LONG_DOUBLE # define TRIO_FUNC_TO_LOWER # define TRIO_FUNC_TO_UNSIGNED_LONG # define TRIO_FUNC_TO_UPPER # define TRIO_FUNC_TOKENIZE # define TRIO_FUNC_UPPER # define TRIO_FUNC_STRING_APPEND # define TRIO_FUNC_STRING_CONTAINS # define TRIO_FUNC_STRING_COPY # define TRIO_FUNC_STRING_CREATE # define TRIO_FUNC_STRING_DESTROY # define TRIO_FUNC_STRING_DUPLICATE # define TRIO_FUNC_STRING_EQUAL # define TRIO_FUNC_STRING_EQUAL_CASE # define TRIO_FUNC_STRING_EQUAL_CASE_MAX # define TRIO_FUNC_STRING_EQUAL_MAX # define TRIO_FUNC_STRING_EXTRACT # if !defined(TRIO_PLATFORM_WINCE) # define TRIO_FUNC_STRING_FORMAT_DATE_MAX # endif # define TRIO_FUNC_STRING_GET # define TRIO_FUNC_STRING_INDEX # define TRIO_FUNC_STRING_INDEX_LAST # define TRIO_FUNC_STRING_LENGTH # define TRIO_FUNC_STRING_LOWER # define TRIO_FUNC_STRING_MATCH # define TRIO_FUNC_STRING_MATCH_CASE # define TRIO_FUNC_STRING_SIZE # define TRIO_FUNC_STRING_SUBSTRING # define TRIO_FUNC_STRING_TERMINATE # define TRIO_FUNC_STRING_UPPER # define TRIO_FUNC_XSTRING_APPEND # define TRIO_FUNC_XSTRING_APPEND_CHAR # define TRIO_FUNC_XSTRING_APPEND_MAX # define TRIO_FUNC_XSTRING_CONTAINS # define TRIO_FUNC_XSTRING_COPY # define TRIO_FUNC_XSTRING_DUPLICATE # define TRIO_FUNC_XSTRING_EQUAL # define TRIO_FUNC_XSTRING_EQUAL_CASE # define TRIO_FUNC_XSTRING_EQUAL_CASE_MAX # define TRIO_FUNC_XSTRING_EQUAL_MAX # define TRIO_FUNC_XSTRING_MATCH # define TRIO_FUNC_XSTRING_MATCH_CASE # define TRIO_FUNC_XSTRING_SET # define TRIO_FUNC_XSTRING_SUBSTRING #endif /************************************************************************* * String functions */ #if defined(TRIO_FUNC_APPEND) TRIO_PUBLIC_STRING int trio_append TRIO_PROTO((char *target, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_APPEND_MAX) TRIO_PUBLIC_STRING int trio_append_max TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_CONTAINS) TRIO_PUBLIC_STRING int trio_contains TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring)); #endif #if defined(TRIO_FUNC_COPY) TRIO_PUBLIC_STRING int trio_copy TRIO_PROTO((char *target, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_COPY_MAX) TRIO_PUBLIC_STRING int trio_copy_max TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_CREATE) TRIO_PUBLIC_STRING char * trio_create TRIO_PROTO((size_t size)); #endif #if defined(TRIO_FUNC_DESTROY) TRIO_PUBLIC_STRING void trio_destroy TRIO_PROTO((char *string)); #endif #if defined(TRIO_FUNC_DUPLICATE) TRIO_PUBLIC_STRING char * trio_duplicate TRIO_PROTO((TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_DUPLICATE_MAX) TRIO_PUBLIC_STRING char * trio_duplicate_max TRIO_PROTO((TRIO_CONST char *source, size_t max)); #endif #if defined(TRIO_FUNC_EQUAL) TRIO_PUBLIC_STRING int trio_equal TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_equal_case TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_equal_case_max TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_LOCALE) TRIO_PUBLIC_STRING int trio_equal_locale TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_equal_max TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_ERROR) TRIO_PUBLIC_STRING TRIO_CONST char * trio_error TRIO_PROTO((int)); #endif #if defined(TRIO_FUNC_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime)); #endif #if defined(TRIO_FUNC_HASH) TRIO_PUBLIC_STRING unsigned long trio_hash TRIO_PROTO((TRIO_CONST char *string, int type)); #endif #if defined(TRIO_FUNC_INDEX) TRIO_PUBLIC_STRING char * trio_index TRIO_PROTO((TRIO_CONST char *string, int character)); #endif #if defined(TRIO_FUNC_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_index_last TRIO_PROTO((TRIO_CONST char *string, int character)); #endif #if defined(TRIO_FUNC_LENGTH) TRIO_PUBLIC_STRING size_t trio_length TRIO_PROTO((TRIO_CONST char *string)); #endif #if defined(TRIO_FUNC_LENGTH_MAX) TRIO_PUBLIC_STRING size_t trio_length_max TRIO_PROTO((TRIO_CONST char *string, size_t max)); #endif #if defined(TRIO_FUNC_LOWER) TRIO_PUBLIC_STRING int trio_lower TRIO_PROTO((char *target)); #endif #if defined(TRIO_FUNC_MATCH) TRIO_PUBLIC_STRING int trio_match TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern)); #endif #if defined(TRIO_FUNC_MATCH_CASE) TRIO_PUBLIC_STRING int trio_match_case TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern)); #endif #if defined(TRIO_FUNC_SPAN_FUNCTION) TRIO_PUBLIC_STRING size_t trio_span_function TRIO_PROTO((char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int)))); #endif #if defined(TRIO_FUNC_SUBSTRING) TRIO_PUBLIC_STRING char * trio_substring TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring)); #endif #if defined(TRIO_FUNC_SUBSTRING_MAX) TRIO_PUBLIC_STRING char * trio_substring_max TRIO_PROTO((TRIO_CONST char *string, size_t max, TRIO_CONST char *substring)); #endif #if defined(TRIO_FUNC_TO_DOUBLE) TRIO_PUBLIC_STRING double trio_to_double TRIO_PROTO((TRIO_CONST char *source, char **endp)); #endif #if defined(TRIO_FUNC_TO_FLOAT) TRIO_PUBLIC_STRING float trio_to_float TRIO_PROTO((TRIO_CONST char *source, char **endp)); #endif #if defined(TRIO_FUNC_TO_LONG) TRIO_PUBLIC_STRING long trio_to_long TRIO_PROTO((TRIO_CONST char *source, char **endp, int base)); #endif #if defined(TRIO_FUNC_TO_LOWER) TRIO_PUBLIC_STRING int trio_to_lower TRIO_PROTO((int source)); #endif #if defined(TRIO_FUNC_TO_LONG_DOUBLE) TRIO_PUBLIC_STRING trio_long_double_t trio_to_long_double TRIO_PROTO((TRIO_CONST char *source, char **endp)); #endif #if defined(TRIO_FUNC_TO_UNSIGNED_LONG) TRIO_PUBLIC_STRING unsigned long trio_to_unsigned_long TRIO_PROTO((TRIO_CONST char *source, char **endp, int base)); #endif #if defined(TRIO_FUNC_TO_UPPER) TRIO_PUBLIC_STRING int trio_to_upper TRIO_PROTO((int source)); #endif #if defined(TRIO_FUNC_TOKENIZE) TRIO_PUBLIC_STRING char * trio_tokenize TRIO_PROTO((char *string, TRIO_CONST char *delimiters)); #endif #if defined(TRIO_FUNC_UPPER) TRIO_PUBLIC_STRING int trio_upper TRIO_PROTO((char *target)); #endif /************************************************************************* * Dynamic string functions */ /* * Opaque type for dynamic strings */ typedef struct _trio_string_t trio_string_t; #if defined(TRIO_FUNC_STRING_APPEND) TRIO_PUBLIC_STRING int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_CONTAINS) TRIO_PUBLIC_STRING int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_COPY) TRIO_PUBLIC_STRING int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_CREATE) TRIO_PUBLIC_STRING trio_string_t * trio_string_create TRIO_PROTO((int initial_size)); #endif #if defined(TRIO_FUNC_STRING_DESTROY) TRIO_PUBLIC_STRING void trio_string_destroy TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_string_duplicate TRIO_PROTO((trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EQUAL) TRIO_PUBLIC_STRING int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second)); #endif #if defined(TRIO_FUNC_STRING_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EXTRACT) TRIO_PUBLIC_STRING char * trio_string_extract TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime)); #endif #if defined(TRIO_FUNC_STRING_GET) TRIO_PUBLIC_STRING char * trio_string_get TRIO_PROTO((trio_string_t *self, int offset)); #endif #if defined(TRIO_FUNC_STRING_INDEX) TRIO_PUBLIC_STRING char * trio_string_index TRIO_PROTO((trio_string_t *self, int character)); #endif #if defined(TRIO_FUNC_STRING_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_string_index_last TRIO_PROTO((trio_string_t *self, int character)); #endif #if defined(TRIO_FUNC_STRING_LENGTH) TRIO_PUBLIC_STRING int trio_string_length TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_LOWER) TRIO_PUBLIC_STRING int trio_string_lower TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_MATCH) TRIO_PUBLIC_STRING int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_MATCH_CASE) TRIO_PUBLIC_STRING int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_SIZE) TRIO_PUBLIC_STRING int trio_string_size TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_SUBSTRING) TRIO_PUBLIC_STRING char * trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_TERMINATE) TRIO_PUBLIC_STRING void trio_string_terminate TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_UPPER) TRIO_PUBLIC_STRING int trio_string_upper TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_XSTRING_APPEND) TRIO_PUBLIC_STRING int trio_xstring_append TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) TRIO_PUBLIC_STRING int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character)); #endif #if defined(TRIO_FUNC_XSTRING_APPEND_MAX) TRIO_PUBLIC_STRING int trio_xstring_append_max TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other, size_t max)); #endif #if defined(TRIO_FUNC_XSTRING_CONTAINS) TRIO_PUBLIC_STRING int trio_xstring_contains TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_COPY) TRIO_PUBLIC_STRING int trio_xstring_copy TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_xstring_duplicate TRIO_PROTO((TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL) TRIO_PUBLIC_STRING int trio_xstring_equal TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_MATCH) TRIO_PUBLIC_STRING int trio_xstring_match TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_MATCH_CASE) TRIO_PUBLIC_STRING int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_SET) TRIO_PUBLIC_STRING void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer)); #endif #if defined(TRIO_FUNC_XSTRING_SUBSTRING) TRIO_PUBLIC_STRING char * trio_xstring_substring TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #ifdef __cplusplus } #endif #endif /* TRIO_TRIOSTR_H */ ================================================ FILE: src/txt2html.c ================================================ /* ** Copyright (C) 1997, Peter McCluskey (pcm@rahul.net) ** Based fairly closely on Seth Golub's txt2html.pl, Revision: 1.24 ** (http://www.cs.wustl.edu/~seth/txt2html/) */ #include "hypermail.h" #include "proto.h" #include "setup.h" #include "print.h" #include "finelink.h" #include "txt2html.h" #include #include #include static int short_line_length = 40; static int preformat_whitespace_min = 5; static int preformat_vertical_chars_min = 3; static int preformat_repeated_chars_min = 14; static int preformat_repeated_carets_min = 5; static char preformat_dots[MAXLINE]; static char preformat_carets[MAXLINE]; static int par_indent = 2; static int preformat_trigger_lines = 2; static int endpreformat_trigger_lines = 2; static int hrule_min = 4; static int min_caps_length = 3; static char caps_tag[MAXLINE] = "strong"; static int tab_width = 8; static int indent_width = 2; static int unhyphenation = 1; static char *unhyphenated_word; static int in_pre_block; static int insig; static int islist; static int is_blank_prev; static int inquote; static int was_quote_prefix; static int quote_num = 0; static int was_break; static int was_hrule; static int prior_was_hrule; static int was_par; static int was_caps; static int was_header; static int prev_line_length; static int prev_indent; #define OL 1 #define UL 2 #define MAXLISTNESTING 8 static int listnum; static int list[MAXLISTNESTING]; static char list_indent[MAXLINE]; static char list_prefix[MAXLISTNESTING][MAXLINE]; static char *chomp(char *line) { /* sort of replaces rmcr() */ int l = strlen(line); if (l > 0 && line[l - 1] == '\n') line[l - 1] = 0; return line; } static int convert_to_hrule(const char *line) { int count_hrule_chars = 0; while (*line && isspace(*line)) ++line; while (*line == '-' || *line == '_' || *line == '~' || *line == '=' || *line == '*') { if (!count_hrule_chars || *line == line[-1]) ++count_hrule_chars; else return 0; ++line; } while (isspace(*line)) ++line; return (!*line && count_hrule_chars >= hrule_min); } /* check for vertically aligned non-alphanumeric chars */ static int find_vertical_repeats(const struct body *bp) { int i; if (!bp->next) { return 0; } i = (isquote(bp->line) ? strlen(get_quote_prefix()) : 0); if (i > strlen(bp->line)) return 0; for (; i < MAXLINE; ++i) { int j; const struct body *bp2 = bp->next; if (!bp->line[i] || i > strlen(bp2->line) || !bp2->line[i]) { return 0; } for (j = 1; bp2; ++j) { if (i >= strlen(bp2->line) || bp->line[i] != bp2->line[i] || !ispunct(bp->line[i])) break; bp2 = bp2->next; } if (j >= preformat_vertical_chars_min) { return j; } } return 0; } static int find_repetition(const struct body *bp) { const char *line = bp->line; int i = 0; while (line[i]) { int count_repeated_chars = 0; while (line[i + 1] == line[i]) { if (++count_repeated_chars > preformat_repeated_chars_min) { while (isspace(line[i])) ++i; /* if trailing whitespace, return 0 */ if (!line[i]) return find_vertical_repeats(bp); return 1; } ++i; } ++i; } return find_vertical_repeats(bp); } static int has_many_carets(const char *line) { return strstr(line, preformat_carets) != NULL; } /* Returns true if line is considered to be preformatted */ static int is_preformatted(const char *line) { int count_whitespace = 0; if (strstr(line, preformat_dots)) return 1; while (*line) { if (isspace(*line)) { if (*line == '\t') count_whitespace += tab_width - (count_whitespace % tab_width); else ++count_whitespace; if (count_whitespace >= preformat_whitespace_min) { while (isspace(*line)) { ++line; if (!*line) /* was trailing whitespace */ return 0; } return 1; } } else count_whitespace = 0; ++line; } return 0; } /* * What, if anything, identifies this line as something that should start a new *
  • ? */ static void listprefix(char *line, struct Push *number, struct Push *prefix, struct Push *rawprefix) { const char *p; int is_prefix = 0; for (p = line; isspace(*p); ++p); if (isalnum(*p)) { const char *p2 = p; if (isdigit(*p2)) while (isdigit(*++p2)); else ++p2; if (*p2 != '.' && *p2 != ')' && *p2 != ']' && *p2 != ':') return; if (!isspace(*++p2)) return; while (isspace(*p2)) ++p2; if (!isprint(*p2)) return; is_prefix = 1; } if (*p == '-' || *p == '=' || *p == '*' || (*p == 'o' && !is_prefix)) { const char *p2 = p; while (*++p2 == *p); if (!isspace(*p2)) return; while (isspace(*p2)) ++p2; if (!isprint(*p2)) return; is_prefix = 1; } if (!is_prefix) return; if (isalnum(*p) && !(*p == 'o' && isspace(p[1]))) { if (isdigit(*p)) do PushByte(number, *p++); while (isdigit(*p)); else PushByte(number, *p++); PushByte(prefix, *p++); PushNString(rawprefix, line, p - line); } else { if (*p == '-' || *p == 'o' || *p == '=' || *p == '*') { PushNString(rawprefix, line, p - line); PushNString(prefix, line, p - line); while (*p == '-' || *p == 'o' || *p == '=' || *p == '*') { PushByte(rawprefix, *p); PushByte(prefix, *p++); } } PushByte(number, 0); /* make sure it has empty string, not null pointer */ } } static void set_list_indent(int n) { assert(n * indent_width < MAXLINE - 1); /* shouldn't be a problem unless MAXLISTNESTING ~ MAXLINE */ memset(list_indent, ' ', n * indent_width); list_indent[n * indent_width] = 0; } static int startlist(FILE *fp, const char *number, const char *prefix, const char *rawprefix) { strcpy(list_prefix[listnum], prefix); /* AUDIT biege: does it fit? */ if (*number) { /* It doesn't start with 1,a,A. Let's not screw with it. */ if ((*number != '1') && (*number != 'a') && (*number != 'A')) return 0; fprintf(fp, "\n%s
      \n", list_indent); list[listnum] = OL; } else { fprintf(fp, "\n%s
        \n", list_indent); list[listnum] = UL; } if (listnum < MAXLISTNESTING) list[++listnum] = 0; set_list_indent(listnum); return 1; } static void endlist(FILE *fp, int n) { /* End N lists */ for (; n > 0; n--, listnum--) { set_list_indent(listnum - 1); if (list[listnum - 1] == UL) { fprintf(fp, "\n%s
      \n", list_indent); } else if (list[listnum - 1] == OL) { fprintf(fp, "\n%s
    \n", list_indent); } else { snprintf(errmsg, sizeof(errmsg), "Encountered list of unknown type %d\n", list[listnum - 1]); progerr(errmsg); } } islist = (listnum != 0); } static char *continuelist(FILE *fp, char *line) { char *p = line; if (list[listnum - 1] == UL) { while (*p && isspace(*p)) ++p; if (*p != '-' && *p != '=' && *p != 'o' && *p != '*') return line; ++p; while (*p == p[-1] && (*p == '-' || *p == '=' || *p == 'o' || *p == '*')) ++p; while (*p && isspace(*p)) ++p; fprintf(fp, "%s
  • ", list_indent); return --p; } if (list[listnum - 1] == OL) { while (*p && isspace(*p)) ++p; if (!isalnum(*p)) return line; if (isalpha(*p)) ++p; else while (isdigit(*p)) ++p; if (!*p) return line; ++p; while (*p && isspace(*p)) ++p; fprintf(fp, "%s
  • ", list_indent); return --p; } return line; } static char *liststuff(FILE *fp, char *line, int line_indent) { int i, j; const char *p; int len; char *prefix; char *rawprefix; char *number; struct Push prefix_buf; struct Push rawprefix_buf; struct Push number_buf; struct Push prefix_alternate; int total_prefix_count = 0; INIT_PUSH(prefix_buf); INIT_PUSH(rawprefix_buf); INIT_PUSH(number_buf); INIT_PUSH(prefix_alternate); listprefix(line, &number_buf, &prefix_buf, &rawprefix_buf); if (!prefix_buf.len) { if (!is_blank_prev) return line; /* inside a list item */ /* This ain't no list. We'll want to end all of them. */ if (listnum) endlist(fp, listnum); return line; } number = PUSH_STRING(number_buf); prefix = PUSH_STRING(prefix_buf); rawprefix = PUSH_STRING(rawprefix_buf); /* If numbers with more than one digit grow to the left instead of */ /* to the right, the prefix will shrink and we'll fail to match the */ /* right list. We need to account for this. */ if ((len = strlen(number)) > 1) { for (i = 0; i < len - 1; ++i) PushByte(&prefix_alternate, ' '); PushString(&prefix_alternate, prefix); } else PushByte(&prefix_alternate, 0); /* Maybe we're going back up to a previous list */ for (i = listnum - 1; (i >= 0) && strcmp(prefix, list_prefix[i]); --i) { if (len > 1 && !strcmp(PUSH_STRING(prefix_alternate), list_prefix[i])) break; } free(PUSH_STRING(prefix_alternate)); /* Measure the indent from where the text starts, not where the */ /* prefix starts. This won't screw anything up, and if we don't do */ /* it, the next line might appear to be indented relative to this */ /* line, and get tagged as a new paragraph. */ p = line; while (isspace(*p)) { total_prefix_count++; p++; } j = total_prefix_count; while (isalnum(*p) || *p == '-' || *p == '=' || *p == '*') { total_prefix_count++; p++; } if (total_prefix_count && total_prefix_count != j) { /* found a prefix */ total_prefix_count++; p++; while (*p && isspace(*p)) { total_prefix_count++; p++; } } /* Of course, we only use it if it really turns out to be a list. */ ++i; if ((i > 0) && (i != listnum)) { endlist(fp, listnum - i); } else if (!listnum || (i != listnum)) { if ((line_indent > 0) || is_blank_prev || was_break || was_header || prior_was_hrule) islist |= startlist(fp, number, prefix, rawprefix); else { free(prefix); free(rawprefix); free(number); return line; /* We have something like this: "- foo" which usually turns out not to be a list. */ } } else line_indent = total_prefix_count; if (islist) line = continuelist(fp, line); if (islist) line_indent = total_prefix_count; free(prefix); free(rawprefix); free(number); return line; } static int iscaps(const char *line) { int count_uppercase = 0; int found_enough_uppercase = 0; while (*line) { if (islower(*line) || *line == '<') return 0; if (isupper(*line)) { if (++count_uppercase >= min_caps_length) found_enough_uppercase = 1; } else count_uppercase = 0; ++line; } return found_enough_uppercase; } static char *unhyphenate1(struct Push *uwbuf, const char *next_line, char *line, int len) { struct Push buffer; while (*next_line && isalpha(*next_line)) PushByte(uwbuf, *next_line++); if (*next_line == '-') /* something like 'one-of-a-kind'? */ return line; while (*next_line && strchr(")}].,:;'\">", *next_line)) PushByte(uwbuf, *next_line++); /* include any punct with word */ if (isupper(PUSH_STRING(*uwbuf)[0]) && islower((PUSH_STRING(*uwbuf))[1])) return line; /* capitalization probably means separate word */ INIT_PUSH(buffer); PushNString(&buffer, line, len - 2); PushString(&buffer, PUSH_STRING(*uwbuf)); /* concatenate 2 parts of word */ PushByte(&buffer, '\n'); RETURN_PUSH(buffer); } static char *unhyphenate(char *line, const char *next_line) { struct Push uwbuf; char *buffer; int len = strlen(line); const char *p = line + strlen(line) - 3; /* look before the final '-\n' */ if (strlen(line) < 3 || !isalpha(*p)) return line; /* doesn't look like hyphenated word */ while (p > line && isalpha(*p)) --p; if (p == line || *p == '-') return line; /* too long to be word or something like 'one-of-a-kind' */ while (*next_line && isspace(*next_line)) ++next_line; if (!isalpha(*next_line)) return line; INIT_PUSH(uwbuf); buffer = unhyphenate1(&uwbuf, next_line, line, len); if (unhyphenated_word) free(unhyphenated_word); unhyphenated_word = PUSH_STRING(uwbuf); return buffer; } static char *unhyphenate_2nd_line(char *line) { struct Push buffer; char *next_part = unhyphenated_word; INIT_PUSH(buffer); while (*line && isspace(*line)) PushByte(&buffer, *line++); while (*next_part++) ++line; /* skip over part that was moved to prior line */ PushString(&buffer, line); free(unhyphenated_word); unhyphenated_word = NULL; RETURN_PUSH(buffer); } /* char *id, char *subject, int msgnum, char *inreply, const char *dir, */ void txt2html(FILE *fp, struct emailinfo *email, const struct body *bp, bool replace_quoted, int maybe_reply) { int is_caps_line = 0; int is_blank_line = 1; int line_indent = 0; const char *p; const char *next_line = bp->next ? bp->next->line : ""; char *line = strsav(bp->line); if (unhyphenated_word) { char *new_line = unhyphenate_2nd_line(line); free(line); line = new_line; } for (p = line; *p; ++p) { if (!isspace(*p)) { is_blank_line = 0; break; } if (*p == '\t') line_indent += tab_width - (line_indent % tab_width); else ++line_indent; } if (in_pre_block > 1 && !isquote(line)) { --in_pre_block; } else if (in_pre_block && preformat_trigger_lines != 0 && !is_preformatted(line) && !insig && !is_blank_line && !find_repetition(bp) && !has_many_carets(line) && !has_many_carets(next_line) && (endpreformat_trigger_lines == 1 || !is_preformatted(next_line))) { in_pre_block = 0; fprintf(fp, "\n"); } if (!in_pre_block && convert_to_hrule(line)) { fprintf(fp, "
    \n"); line[0] = 0; was_hrule = 1; } if (!in_pre_block && !is_blank_line) { char *new_line = liststuff(fp, line, line_indent); if (new_line != line) { /* new_line points to middle of line */ int i; for (i = 0; new_line[i] && line[i]; ++i) line[i] = new_line[i]; line[i] = new_line[i]; } } if (!in_pre_block && !islist && endpreformat_trigger_lines != 0 && !isquote(line) && !was_hrule && (preformat_trigger_lines == 0 || is_sig_start(line) || find_repetition(bp) || has_many_carets(line) || has_many_carets(next_line) || (is_preformatted(line) && (preformat_trigger_lines == 1 || is_preformatted(next_line))))) { fprintf(fp, "
    \n");
    	in_pre_block = find_repetition(bp);	/* set #lines from find_vertical_repeats */
    	if (!in_pre_block)
    	    in_pre_block = 1;
    	if (is_sig_start(line))
    	    insig = 1;
        }
    	if (!is_blank_line && !in_pre_block && !was_break && !was_caps && !was_hrule && !was_par && !islist && (is_blank_prev || (line_indent > prev_indent + par_indent))) {
    	fprintf(fp, "

    \n"); was_par = 1; } if (!islist && !in_pre_block && !is_blank_line && !inquote && !is_blank_prev && prev_line_length < short_line_length && !was_hrule && !was_par && !islist && !was_break) { fprintf(fp, "
    \n"); was_break = 1; } if (unhyphenation && !is_blank_line && !in_pre_block && !inquote && !was_break && strlen(line) >= 2 && line[strlen(line) - 2] == '-') { char *new_line = unhyphenate(line, next_line); if (new_line != line) { free(line); line = new_line; } } if ((is_caps_line = (!in_pre_block && iscaps(line))) != 0) fprintf(fp, "<%s>", caps_tag); if (isquote(line)) { if (!was_quote_prefix && !was_break && !was_par && !was_hrule) { fprintf(fp, "
    \n"); was_break = 1; } if (!set_linkquotes) { fprintf(fp, "", find_quote_class(line)); ConvURLs(fp, chomp(line), email->msgid, email->subject, email->charset); fprintf(fp, "
    \n"); } else if (handle_quoted_text(fp, email, bp, line, inquote, quote_num, replace_quoted, maybe_reply)) { ++quote_num; inquote = 1; } if (!inquote) was_break = 1; was_quote_prefix = 1; } else if (line[0] != '\0') { char *sp; if (in_pre_block || insig || islist) sp = line; else sp = print_leading_whitespace(fp, line); ConvURLs(fp, chomp(sp), email->msgid, email->subject, email->charset); fprintf(fp, "\n"); } if (is_caps_line) fprintf(fp, "\n", caps_tag); is_blank_prev = is_blank_line; if (!isquote(line)) inquote = was_quote_prefix = 0; prior_was_hrule = was_hrule; if (!is_blank_line) { was_hrule = 0; if (!was_quote_prefix || !isquote(next_line)) was_break = 0; was_par = 0; was_caps = is_caps_line; was_header = 0; prev_line_length = strlen(line); prev_indent = line_indent; } free(line); } void init_txt2html() { in_pre_block = 0; insig = 0; islist = 0; listnum = 0; is_blank_prev = 0; inquote = 0; was_quote_prefix = 0; was_break = 0; was_hrule = 0; prior_was_hrule = 0; was_par = 0; was_header = 1; memset(preformat_dots, ' ', preformat_whitespace_min); preformat_dots[preformat_whitespace_min] = 0; memset(preformat_carets, '^', preformat_repeated_carets_min); preformat_carets[preformat_repeated_carets_min] = 0; prev_line_length = 0; prev_indent = 0; quote_num = 0; unhyphenated_word = NULL; } void end_txt2html(FILE *fp) { if (islist) endlist(fp, listnum); /* End all lists */ if (in_pre_block) fprintf(fp, "

    \n"); if (unhyphenated_word) { free(unhyphenated_word); unhyphenated_word = NULL; } #if DEBUG_HTML printcomment(fp, "end_txt2html", ""); #endif } ================================================ FILE: src/txt2html.h ================================================ void txt2html(FILE *, struct emailinfo *, const struct body *, bool, int); void init_txt2html(void); void end_txt2html(FILE *fp); ================================================ FILE: src/uconvert.h ================================================ #ifndef __UCONVERT_H #define __UCONVERT_H /* ** This file lists the convertions between a given charset space and the Unicode one. */ /* JK: Taken from the Amaya source code (Amaya/thotlib/unicode/uconvert.c) */ /* Windows Latin 1 Code Page */ int WIN1252CP [] = { 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; #define WIN1252CP_length sizeof(WIN1252CP) / sizeof(int) #endif /* __UCONVERT_H */ ================================================ FILE: src/uudecode.c ================================================ /* ** This file was written by Daniel Stenberg. ** Parts of it were stolen from the BSD uudecode command. */ /* ** Copyright (c) 1983 Regents of the University of California. ** All rights reserved. ** ** 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. ** 3. Neither the name of the University 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 REGENTS 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 REGENTS 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 "hypermail.h" #include "setup.h" #include "uudecode.h" #ifdef HAVE_SYS_PARAM_H #include #endif /* sco/isc */ #ifndef MAXPATHLEN #ifdef PATH_MAX #define MAXPATHLEN PATH_MAX #else #define MAXPATHLEN 1024 #endif #endif #define DEC(c) (((c) - ' ') & 077) /* single character decode */ #define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) /* ** uudecode returns non-zero on error */ int uudecode(FILE *input, /* get file data from (if needed) */ char *iptr, /* input string from where we are right now */ char *output, /* write result to, must be at least 80 bytes */ int *length, /* output size */ struct Push *init) { /* set to non-zero when initing */ register int n; register char ch, *p; int mode; char buf[MAXPATHLEN] = { 0 }; char scanfstring[MAXPATHLEN] = { 0 }; int outlen = 0; if (length) *length = 0; /* in case we abort early */ if (init) { /* search for header line */ /* AUDIT biege: BOF in buf! */ sprintf(scanfstring, "begin %%o %%%us", sizeof(buf) - 1); while (2 != sscanf(iptr, scanfstring, &mode, buf)) { if (!fgets(buf, MAXPATHLEN, input)) { return 2; } PushString(init, buf); iptr = buf + set_ietf_mbox; } #if 0 fprintf(stderr, "FIRST %s", iptr); #endif /* ignore file mode */ /* ignore file name too for now */ } else { /* for each input line */ p = iptr; /* first, just make sure this isn't the end line: */ if (!strcmp(buf, "end") || !strcmp(buf, "end\n") || !strcmp(buf, "end\r\n")) { /* muu->state = UU_HASENDED; */ if (length) *length = 0; return 0; } n = DEC(*p); for (++p; (n > 0) && (outlen < 80); p += 4, n -= 3) { if (n >= 3) { if (!(IS_DEC(*p) && IS_DEC(*(p + 1)) && IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) return 33; ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; output[outlen++] = ch; ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; output[outlen++] = ch; ch = DEC(p[2]) << 6 | DEC(p[3]); output[outlen++] = ch; } else { if (n >= 1) { if (!(IS_DEC(*p) && IS_DEC(*(p + 1)))) return 34; ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; output[outlen++] = ch; } if (n >= 2) { if (!(IS_DEC(*(p + 1)) && IS_DEC(*(p + 2)))) return 35; ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; output[outlen++] = ch; } if (n >= 3) { if (!(IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) return 36; ch = DEC(p[2]) << 6 | DEC(p[3]); output[outlen++] = ch; } } } } if (output) output[outlen] = 0; /* zero terminate */ if (length) *length = outlen; /* send back size */ return 0; } ================================================ FILE: src/uudecode.h ================================================ /* ** uudecode.c function */ int uudecode(FILE *, char *, char *, int *, struct Push *); ================================================ FILE: tests/README ================================================ Testing Hypermail: ================== This directory is here for you to use in testing hypermail locally. It is useful for testing new hypermail distributions and features without impacting your production facilities. You will find the following files in this directory: test-footer.hyp - HTML footer template file test-index.hyp - Index pages template file test-msg.hyp - Message pages template file test.rc - Test configuration file testhm - Script to run test command lines diff_hypermail_archives.pl - Script to show diffs between two archives To test hypermail: - Copy a mailbox you have to a local file named "testmail" - Edit the test-footer.hyp, test-index.hyp and test-msg.hyp template configuration files as appropritate for you needs. - Edit the test.rc and assure it is configured as you wish. - Verify that testhm is running the proper command line for the testing you are doing. - Type "testhm" This will generate an archive under a newly created "testdir/" directory. Check it out with your favorite browser. When you are done testing, - remove the testdir directory, - remove the testmail file. ================================================ FILE: tests/diff_hypermail_archives.pl ================================================ #!/usr/bin/perl # diff_hypermail_archives # # Compare two directories with archives produced by Hypermail. # Intended primarily to test changes to Hypermail. # # Originally written by Peter McCluskey (pcm@rahul.net). # Rewritten and extended by Jose Kahan (jose.kahan@w3.org). # # TODO: If more portability is needed, try switch the sytem # diff and grep to File::Compare # https://perldoc.perl.org/File/Compare.html use strict; use warnings; use File::Find; use FindBin '$Script'; use Cwd qw( abs_path ); use Getopt::Std; ## ## configurable options ## # path to diff command our $diff_cmd = "/usr/bin/diff"; # path to grep command our $grep_cmd= "/bin/grep"; ## ## End of configurable options ## ## ## Global variables ## # don't print progress messages our $quiet; # print a "." for each processed file our $show_progress; # enable to print extra messages our $debug; # ignore all content below the footer trailer our $ignore_footer; # hash with filenames|dirnames that must be ignored our @ignore_files_regex; # hash with text that must be ignored in the diff output our @ignore_text_regex; # thw two dirs that need to be compared our $dir1; our $dir2; # global difference counter (we consider them errors) our $errors = 0; # attachmed dir prefix, hard-coded into hypermail our $attachment_dir_prefix = "att-"; # archive generated by hypermail generated text blurb our $hmail_generated_by_text = q(This archive was generated by ); # returns the line number of the footer or of the generated_by hypermail # blurb if found sub get_hypermail_generated_by_lines { my $filename = shift; my $counter = 0; my $expected_counter = ($ignore_footer) ? 1 : 2; my %generated_by_lines; my $needle = $ignore_footer ? $footer_trailer : $hmail_generated_by_text; my @grep_args = ($grep_cmd, $ignore_footer ? "-A0" : "-A1", "-n", $needle, $filename); open (my $fh, "-|", @grep_args) || die("cannot @grep_args\n"); while (my $line = <$fh>) { if ($line =~ m/^\d+-?:\ ?/) { my $line_nb = (split /:/, $line)[0]; $line_nb =~ s/-$//; $generated_by_lines{$line_nb} = 1; $counter++; } } close ($fh); return ($counter == $expected_counter) ? \%generated_by_lines : {}; } # get_hypermail_generated_by_lines # checks if the filenames exist in both directories and the type sub compare_filenames { my ($filename1, $filename2) = @_; my $res = 0; if (!-e $filename2) { $errors++; $res = -1; print "\n" if $show_progress; print "[$errors] $filename2 does not exist\n" unless $quiet; } elsif (-d $filename1) { if (!-d $filename2) { print "\n" if $show_progress; print "[$errors] $filename2 is not a directory\n" unless $quiet; $errors++; } $res = -1; } return $res; } # compare_filenames # filter out files we're not interested in sub filter_filenames { my $filename = shift; my $res = 0; foreach my $regex (@ignore_files_regex) { if ($filename =~ m/$regex/) { $res = 1; print "$filename is ignored per regex: " . $regex . "\n" if $debug && !$quiet; last; } } return $res; } # filter_filenames # filter out text lines we're not interested in # returns true if both strings match the same regex sub filter_regex { my ($text1, $text2) = @_; my $res = 0; foreach my $regex (@ignore_text_regex) { if ($text1 =~ m/$regex/ && $text2 =~ m/$regex/) { $res = 1; print "$text1 is ignored per regex: " . $regex . "\n" if $debug && !$quiet; last; } } return $res; } # filter_regex sub store_diffs { my ($header, $diff_file1, $diff_file2) = @_; my $diff = ""; # also compare files and regex text, add + 1 to error if added # do the same at the end of the while if not yet done if (defined $header && $header ne "") { $diff = $diff . $header . "\n"; if (defined $diff_file1 && $diff_file1 ne "") { $diff = $diff . $diff_file1; } if (defined $diff_file2 && $diff_file2 ne "") { $diff = $diff . "---\n" . $diff_file2; } } return $diff; } # store_diffs # does a diff on existing directories, files, and file content sub diff_files_complete { my $file = $_; my $filename1 = $File::Find::name; my $filename2 = $filename1; $filename2 =~ s/$dir1/$dir2/; my $generated_by_lines; my $footer_line; my $diffs = ""; my $local_errors = 0; print "." if $show_progress; if (filter_filenames ($filename1) || compare_filenames ($filename1, $filename2)) { return; } my $is_attachment_dir = $filename1 =~ m#/$attachment_dir_prefix#; if (!$is_attachment_dir) { if ($filename1 =~ m/\.html$/) { $generated_by_lines = get_hypermail_generated_by_lines ($filename1); if ($ignore_footer) { $footer_line = (keys %{ $generated_by_lines } )[0]; } } } print "comparing $filename1\n" if $debug; my @diff_args = ($diff_cmd, $filename1, $filename2); open (my $fh, "-|", @diff_args) || die("cannot diff $filename1 $filename2\n"); my $header; my $diff_file1; my $diff_file2; my $skip = 1; my $filter_diff_content = 0; while (my $line = <$fh>) { chomp $line; if ($line eq "") { next; } # for hypermail generated messages and indexes, if the diff # finds the the generated_by blurb, we assume that the only # things that changed are the version number and/or the # generation date. We ignore the rest of the diff output at # this point. if ($line =~ /^\d/) { # store previous diff. # also compare files and regex text, add + 1 to error if added # do the same at the end of the while if not yet done if (!$skip) { if (!$filter_diff_content || !filter_regex ($diff_file1, $diff_file2)) { $diffs .= store_diffs ($header, $diff_file1, $diff_file2); $local_errors++; } } $skip = $filter_diff_content = 0; $header = $line; $diff_file1 = $diff_file2 = ""; if ($line =~ /\d+c\d+/) { if (!$is_attachment_dir) { my ($ln_1, $ln_2) = split /c/, $line; # if we have diffs in a series of sequential lines my ($ln_1_1, $ln_1_2) = split /,/, $ln_1; my ($ln_2_1, $ln_2_2) = split /,/, $ln_2; if (defined $generated_by_lines && %{ $generated_by_lines } && (defined $ln_1_2 && defined $ln_2_2 && ($ln_1_2 - $ln_1_1) == ($ln_2_2 - $ln_2_1)) || (defined $ln_1_1 && !defined $ln_1_2 && defined $ln_2_1 && !defined $ln_2_2)) { if ($ignore_footer && ($ln_1_1 >= $footer_line)) { $skip = 1; last; } elsif ((!defined $ln_1_2 && $$generated_by_lines{$ln_1_1}) || (defined $ln_1_2 && $$generated_by_lines{$ln_1_1} && $$generated_by_lines{$ln_1_2})) { $skip = 1; last; } else { $filter_diff_content = 1; } } } } } else { if ($line =~ /^/) { $diff_file2 = $line . "\n"; } } } close ($fh); # store last diff. if (!$skip) { if (!$filter_diff_content || !filter_regex ($diff_file1, $diff_file2)) { $diffs .= store_diffs ($header, $diff_file1, $diff_file2); $local_errors++; } } if ($local_errors > 0 && !$quiet) { $errors++; print "\n" if $show_progress; print "[$errors] $filename1\n[$errors] $filename2: found $local_errors difference" . ($local_errors == 1 ? "" : "s") . "\n"; print "$diffs\n"; } } # diff_files_complete # only does a diff to see if the same directories and files exist. # Ignores content differences. sub diff_files_dir { my $filename1 = $File::Find::name; my $filename2 = $filename1; $filename2 =~ s/$dir1/$dir2/; print "." if $show_progress; if (!filter_filenames ($filename1)) { compare_filenames ($filename1, $filename2); } return; } # diff_files_dir sub process_options { my %options=(); getopts("qhfpdi:r:", \%options); $dir1 = $ARGV[0]; $dir2 = $ARGV[1]; if (defined $options{d}) { $debug = 1; } if (defined $options{q}) { $quiet = 1; } if (defined $options{p} && !$quiet && !$debug) { $show_progress = 1; } if (defined $options{f}) { $ignore_footer = 1; } if (defined $options{h} || !defined $dir1 || !defined $dir2) { die ("\nUsage: $Script [-q -h -i foo:bar] dir1 dir2\n" . "\t-q quiet mode\n" . "\t-p show processing progress\n" . "\t-h help prints this message\n" . "\t-f ignore all content below the footer trailer comment\n" . "\t-i list of colon separated regex corresponding to directories/filenames to ignore\n" . "\t-r list of colon separated regex corresponding to text that should be ignored in diff reports\n" . "\tdir1, dir2 paths to the two directories to compare\n\n"); } # remove trailing / if given $dir1 = abs_path ($dir1); $dir2 = abs_path ($dir2); if (!defined $dir1 || !-d $dir1) { die ("$ARGV[0] is not a directory\n"); } if (!defined $dir2 || !-d $dir2) { die ("$ARGV[1] is not a directory\n"); } if (defined $options{i}) { @ignore_files_regex = split (/:/, $options{i}); } if (defined $options{r}) { @ignore_text_regex = split (/:/, $options{r}); } } # process_options # main { # read command-line options process_options(); my %find_options = ('follow' => 1, 'wanted' => \&diff_files_complete, ); print "\n" unless $quiet; print "comparing $dir1 against $dir2\n" unless $quiet; print "\n" if $debug && !$quiet; find(\%find_options, $dir1); # do the opposite diff too, to make sure we are not generating new files print "\n\n" if $show_progress || $debug; print "comparing $dir2 filenames against $dir1\n" unless $quiet; ($dir1, $dir2) = ($dir2, $dir1); $find_options{wanted} = \&diff_files_dir; find(\%find_options, $dir1); print "\n" if $show_progress; print "\n" unless $quiet; if ($errors) { print "=> $dir1 and $dir2 dirs differ: $errors file", $errors > 1 ? "s are" : " is", " different\n\n" unless $quiet; } else { print "=> Archives are identical\n\n" unless $quiet; } exit (($errors == 0) ? 0 : -1); } # main ================================================ FILE: tests/mboxes/1msg.mbox ================================================ From Daniel.Stenberg@sth.frontec.se Fri Jul 24 09:06 CDT 1998 Received: from latour.sth.frontec.se (pc252.frontec.se [193.13.194.252]) by landfield.com (8.9.0/8.9.0) with ESMTP id JAA02673 for ; Fri, 24 Jul 1998 09:06:22 -0500 (CDT) Received: from metal (metal.sth1.frontec.se [193.12.206.10]) by latour.sth.frontec.se (8.8.0/8.6.6) with SMTP id QAA03785 for ; Fri, 24 Jul 1998 16:03:20 +0200 (MET DST) Date: Fri, 24 Jul 1998 16:03:18 +0200 (MET DST) From: Daniel Stenberg X-Sender: dast@metal To: Kent Landfield Subject: hypermail *FIXED* Message-ID: MIME-Version: 1.0 Content-Type: MULTIPART/MIXED; BOUNDARY="-559023410-851401618-901288998=:17635" X-Lines: 2420 Content-Length: 146654 Status: OR ---559023410-851401618-901288998=:17635 Content-Type: TEXT/PLAIN; charset="US-ASCII" X-Sun-Content-Length: 432 Hi I'm sorry I caused those problems. I'm sending you the only two files I changed to get your test mail archive to get processed successfully. Clearly, I was just lucky my first implementation worked on my examples. Just get back if there's anything more I can do before the new beta release! -- Daniel Stenberg - http://www.fts.frontec.se/~dast ech`echo xiun|tr nu oc|sed 'sx\([sx]\)\([xoi]\)xo un\2\1 is xg'`ol ---559023410-851401618-901288998=:17635 Content-Type: TEXT/PLAIN; charset="US-ASCII"; name="parse.c" Content-Transfer-Encoding: BASE64 Content-ID: Content-Disposition: attachment; filename="parse.c" X-Sun-Content-Length: 92053 LyogDQoqKiBDb3B5cmlnaHQgKEMpIDE5OTQsIDE5OTUgRW50ZXJwcmlzZSBJ bnRlZ3JhdGlvbiBUZWNobm9sb2dpZXMgQ29ycC4NCioqICAgICAgICAgVmVy aUZvbmUgSW5jLi9IZXdsZXR0LVBhY2thcmQuIEFsbCBSaWdodHMgUmVzZXJ2 ZWQuDQoqKiBLZXZpbiBIdWdoZXMsIGtldkBrZXZjb20uY29tIDMvMTEvOTQN CioqIEtlbnQgTGFuZGZpZWxkLCBrZW50QGxhbmRmaWVsZC5jb20gNC82Lzk3 DQoqKiANCioqIFRoaXMgcHJvZ3JhbSBhbmQgbGlicmFyeSBpcyBmcmVlIHNv ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgDQoqKiBt b2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgKExpYnJhcnkp IEdlbmVyYWwgUHVibGljIExpY2Vuc2UgDQoqKiBhcyBwdWJsaXNoZWQgYnkg dGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24g MiANCioqIG9mIHRoZSBMaWNlbnNlLCBvciBhbnkgbGF0ZXIgdmVyc2lvbi4g DQoqKiANCioqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUg aG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCANCioqIGJ1dCBXSVRIT1VU IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJh bnR5IG9mIA0KKiogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEg UEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIA0KKiogR05VIChMaWJyYXJ5 KSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuIA0K KiogDQoqKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRo ZSBHTlUgKExpYnJhcnkpIEdlbmVyYWwgUHVibGljIExpY2Vuc2UNCioqIGFs b25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBG cmVlIFNvZnR3YXJlIA0KKiogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxl IFBsYWNlIC0gU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3LCBV U0EgDQoqLw0KDQojaW5jbHVkZSA8c3lzL3R5cGVzLmg+DQojaW5jbHVkZSA8 c3lzL3N0YXQuaD4NCiNpbmNsdWRlIDxmY250bC5oPg0KDQojaW5jbHVkZSAi aHlwZXJtYWlsLmgiDQojaW5jbHVkZSA8Y3R5cGUuaD4NCiNpbmNsdWRlIDxl cnJuby5oPg0KDQojZGVmaW5lIFBBVEhfU0VQQVJBVE9SICcvJw0KDQp0eXBl ZGVmIGVudW0gew0KICAgIEVOQ09ERV9OT1JNQUwsDQogICAgRU5DT0RFX1FQ LCAgICAgLyogcXVvdGVkIHByaW50YWJsZSAqLw0KDQogICAgRU5DT0RFX01V TFRJTElORUQsIC8qIHRoaXMgaXMgbm90IGEgcmVhbCB0eXBlLCBidXQganVz dCBhIHNlcGFyYXRvciBzaG93aW5nICAgICAgICAgICAgICAgICAgICAgICAg ICB0aGF0IHRoZSB0eXBlcyBiZWxvdyBhcmUgZW5jb2RlZCBpbiBhIHdheSB0 aGF0IG1ha2VzDQogICAgICAgICAgICAgICAgICAgICAgICAgIG9uZSBsaW5l IGluIHRoZSBpbmRhdGEgbWF5IGJlY29tZSBvbmUgb3IgbW9yZSBsaW5lcw0K ICAgICAgICAgICAgICAgICAgICAgICAgICBpbiB0aGUgb3V0ZGF0YSAqLw0K DQogICAgRU5DT0RFX0JBU0U2NCwgLyogYmFzZTY0ICovDQogICAgRU5DT0RF X1VVRU5DT0RFLCAvKiB3ZWxsLCBpdCBzZWVtcyB0aGVyZSBleGlzdCBzb21l IGtpbmQgb2Ygc2VtaS1zdGFuZGFyZA0KICAgICAgICAgICAgICAgICAgICAg ICAgZm9yIHV1LWVuY29kZWQgYXR0YWNobWVudHMuICovDQogDQogICAgRU5D T0RFX1VOS05PV04gLyogbXVzdCBiZSB0aGUgbGFzdCBvbmUgKi8NCn0gRW5j b2RlVHlwZTsNCg0KdHlwZWRlZiBlbnVtIHsNCiAgICBDT05URU5UX1RFWFQs ICAgLyogbm9ybWFsIG1haWxzIGFyZSB0ZXh0IGJhc2VkIGRlZmF1bHQgKi8N CiAgICBDT05URU5UX0JJTkFSWSwgLyogdGhpcyBraW5kIHdlIHN0b3JlIHNl cGFyYXRlbHkgYW5kIGhyZWYgdG8gKi8NCiAgICBDT05URU5UX0hUTUwsICAg LyogdGhpcyBpcyBodG1sIGZvcm1hdGVkIHRleHQgKi8NCiAgICBDT05URU5U X0lHTk9SRSwgLyogZG9uJ3QgY2FyZSBhYm91dCB0aGlzIGNvbnRlbnQgKi8N Cg0KICAgIENPTlRFTlRfVU5LTk9XTiAvKiBtdXN0IGJlIHRoZSBsYXN0IG9u ZSAqLw0KfSBDb250ZW50VHlwZTsNCg0KDQppbnQgaWdub3JlY29udGVudChj aGFyICp0eXBlKQ0Kew0KICAgcmV0dXJuIChpbmxpc3QoaWdub3JlX3R5cGVz LCB0eXBlKSk7DQp9DQoNCmludCBpbmxpbmVjb250ZW50KGNoYXIgKnR5cGUp DQp7DQogICByZXR1cm4gKGlubGlzdChpbmxpbmVfdHlwZXMsIHR5cGUpKTsN Cn0NCg0KaW50IHByZWZlcmVkY29udGVudChjaGFyICp0eXBlKQ0Kew0KICAv KiBXZSBsZXQgcGxhaW4gdGV4dCByZW1haW4gUFJFRkVSRUQgYXQgYWxsIHRp bWVzICovDQogIGlmKCFzdHJjYXNlY21wKCJ0ZXh0L3BsYWluIiwgdHlwZSkp DQogICAgcmV0dXJuOw0KDQogIGlmKHByZWZlcmVkX3R5cGVzKSB7DQogICAg cmV0dXJuIChpbmxpc3QocHJlZmVyZWRfdHlwZXMsIHR5cGUpKTsNCiAgfQ0K ICByZXR1cm4gMDsNCn0NCg0KY2hhciAqdG1wbmFtZShjaGFyICpkaXIsIGNo YXIgKnBmeCkNCnsNCiAgICBpbnQgc3ZlcnJubzsNCiAgICBjaGFyICpmLCAq bmFtZTsNCiAgICBzdGF0aWMgY250ciA9IDA7DQoNCiAgICBjaGFyICpta3Rl bXAoY2hhciAqdGVtcGxhdGUpOw0KDQogICAgaWYgKChuYW1lID0gbWFsbG9j KE1BWExJTkUpKSA9PSBOVUxMKQ0KICAgICAgICAgIHJldHVybihOVUxMKTsN Cg0KICAgIHNwcmludGYobmFtZSwgIiVzLyVzJWRYWFhYWFgiLCBkaXIsIHBm eCwgY250cisrKTsNCg0KICAgIGlmICgoZiA9IG1rdGVtcChuYW1lKSkgIT0g TlVMTCkNCiAgICAgICAgcmV0dXJuKGYpOw0KDQogICAgc3ZlcnJubyA9IGVy cm5vOw0KICAgIGZyZWUobmFtZSk7DQogICAgZXJybm8gPSBzdmVycm5vOw0K ICAgIHJldHVybihOVUxMKTsNCn0NCg0KLyoNCioqIENyb3NzLWluZGV4ZXMg LSBhZGRzIHRvIGEgbGlzdCBvZiByZXBsaWVzLiBJZiBhIG1lc3NhZ2UgaXMg YSByZXBseSB0bw0KKiogYW5vdGhlciwgdGhlIG51bWJlciBvZiB0aGUgbWVz c2dlIGl0J3MgcmVwbHlpbmcgdG8gaXMgYWRkZWQgdG8gdGhlIGxpc3QuDQoq KiBUaGlzIGxpc3QgaXMgc2VhcmNoZWQgdXBvbiBwcmludGluZy4NCiovDQoN CnZvaWQgY3Jvc3NpbmRleCgpDQp7DQogICAgaW50IG51bSwgc3RhdHVzLCBt YXliZXJlcGx5Ow0KICAgIGNoYXIgbmFtZVtOQU1FU1RSTEVOXSwgc3ViamVj dFtTVUJKU1RSTEVOXSwgZW1haWxbTUFJTFNUUkxFTl0sDQogICAgICAgIGlu cmVwbHlbUkVQWVNUUkxFTl0sIGRhdGVbREFURVNUUkxFTl0sIGZyb21kYXRl W0RBVEVTVFJMRU5dLA0KICAgICAgICBtc2dpZFtNU0dEU1RSTEVOXTsNCg0K ICAgIG51bSA9IDA7DQogICAgcmVwbHlsaXN0ID0gTlVMTDsNCg0KICAgIHdo aWxlIChoYXNobnVtbG9va3VwKG51bSxuYW1lLGVtYWlsLHN1YmplY3QsaW5y ZXBseSxkYXRlLGZyb21kYXRlLG1zZ2lkKSAhPSBOVUxMKSB7DQogICAgICAg IGlmIChpbnJlcGx5WzBdICE9ICdcMCcpIHsNCiAgICAgICAgICAgIHN0YXR1 cyA9IGhhc2hyZXBseW51bWxvb2t1cChpbnJlcGx5LCAmbWF5YmVyZXBseSk7 DQogICAgICAgICAgICBpZiAoc3RhdHVzICE9IC0xKQ0KICAgICAgICAgICAg ICAgIHJlcGx5bGlzdCA9IChzdHJ1Y3QgcmVwbHkgKikNCiAgICAgICAgICAg ICAgICBhZGRyZXBseShyZXBseWxpc3Qsc3RhdHVzLG51bSxuYW1lLHN1Ympl Y3QsbWF5YmVyZXBseSk7DQogICAgICAgIH0NCiAgICAgICAgbnVtKys7DQog ICAgfQ0KfQ0KDQovKiANCioqIFJlY3Vyc2l2ZWx5IGNoZWNrcyBmb3IgcmVw bGllcyB0byByZXBsaWVzIHRvIGEgbWVzc2FnZSwgZXRjLg0KKiogUmVwbGll cyBhcmUgYWRkZWQgdG8gdGhlIHRocmVhZCBsaXN0Lg0KKi8NCg0Kdm9pZCBj cm9zc2luZGV4dGhyZWFkMihpbnQgbnVtKQ0Kew0KICAgIHN0cnVjdCByZXBs eSAqcnA7DQoNCiAgICBmb3IgKHJwID0gcmVwbHlsaXN0OyBycCAhPSBOVUxM OyBycCA9IHJwLT5uZXh0KSB7DQogICAgICAgIGlmIChycC0+bXNnbnVtID09 IG51bSkgew0KICAgICAgICAgICAgdGhyZWFkbGlzdCA9IChzdHJ1Y3QgcmVw bHkgKilhZGRyZXBseSh0aHJlYWRsaXN0LCBycC0+ZnJvbW1zZ251bSwgDQog ICAgICAgICAgICAgICAgICAgICAgICAgICBudW0sIHJwLT5uYW1lLCBycC0+ c3ViamVjdCwgMCk7DQogICAgICAgICAgICBwcmludGVkbGlzdCA9IChzdHJ1 Y3QgcHJpbnRlZCAqKQ0KICAgICAgICAgICAgICAgICAgICAgICAgbWFya2Fz cHJpbnRlZChwcmludGVkdGhyZWFkbGlzdCwgcnAtPmZyb21tc2dudW0pOw0K ICAgICAgICAgICAgY3Jvc3NpbmRleHRocmVhZDIocnAtPmZyb21tc2dudW0p Ow0KICAgICAgICB9DQogICAgfQ0KfQ0KDQoNCi8qDQoqKiBGaXJzdCwgcHJp bnQgb3V0IHRoZSB0aHJlYWRzIGluIG9yZGVyIGJ5IGRhdGUuLi4NCioqIEVh Y2ggbWVzc2FnZSBudW1iZXIgaXMgYXBwZW5kZWQgdG8gYSB0aHJlYWQgbGlz dC4gVGhyZWFkcyBhbmQgaW5kaXZpZHVhbA0KKiogbWVzc2FnZXMgYXJlIHNl cGFyYXRlZCBieSBhIC0xLg0KKi8NCg0Kdm9pZCBjcm9zc2luZGV4dGhyZWFk MShzdHJ1Y3QgaGVhZGVyICpocCkNCnsNCiAgICBpbnQgaGFzcmVwbHk7DQog ICAgc3RydWN0IHJlcGx5ICpycDsNCg0KICAgIGlmIChocCAhPSBOVUxMKSB7 DQogICAgICAgIGNyb3NzaW5kZXh0aHJlYWQxKGhwLT5sZWZ0KTsNCg0KICAg ICAgICBmb3IgKGhhc3JlcGx5ID0gMCwgcnAgPSByZXBseWxpc3Q7IHJwICE9 IE5VTEw7IHJwID0gcnAtPm5leHQpIHsNCiAgICAgICAgICAgICBpZiAocnAt PmZyb21tc2dudW0gPT0gaHAtPm1zZ251bSkgew0KICAgICAgICAgICAgICAg ICBoYXNyZXBseSA9IDE7DQogICAgICAgICAgICAgICAgIGJyZWFrOw0KICAg ICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIGlmICghaGFzcmVw bHkgJiYgIXdhc3ByaW50ZWQocHJpbnRlZHRocmVhZGxpc3QsIGhwLT5tc2du dW0pKSB7DQogICAgICAgICAgICB0aHJlYWRsaXN0ID0gKHN0cnVjdCByZXBs eSAqKQ0KICAgICAgICAgICAgICBhZGRyZXBseSh0aHJlYWRsaXN0LGhwLT5t c2dudW0saHAtPm1zZ251bSxocC0+bmFtZSxocC0+c3ViamVjdCwwKTsNCiAg ICAgICAgICAgIGNyb3NzaW5kZXh0aHJlYWQyKGhwLT5tc2dudW0pOw0KICAg ICAgICAgICAgICB0aHJlYWRsaXN0ID0gKHN0cnVjdCByZXBseSAqKWFkZHJl cGx5KHRocmVhZGxpc3QsLTEsLTEsIiAiLCIgIiwwKTsNCiAgICAgICAgfQ0K DQogICAgICAgIGNyb3NzaW5kZXh0aHJlYWQxKGhwLT5yaWdodCk7DQogICAg fQ0KfQ0KDQovKg0KKiogR3JhYnMgdGhlIGRhdGUgc3RyaW5nIGZyb20gYSBE YXRlOiBoZWFkZXIuDQoqLw0KDQpjaGFyICpnZXRtYWlsZGF0ZShjaGFyICps aW5lKQ0Kew0KICAgIGludCBpOw0KICAgIGludCBsZW47DQogICAgY2hhciAq YzsNCiAgICBzdGF0aWMgY2hhciBkYXRlW0RBVEVTVFJMRU5dOw0KDQogICAg YyA9IChjaGFyICopIHN0cmNocihsaW5lLCAnOicpOw0KICAgIGlmICgoKihj ICsgMSkgJiYgKihjICsgMSkgPT0gJ1xuJykgfHwgKCooYyArIDIpICYmICoo YyArIDIpID09ICdcbicpKSB7DQogICAgICAgIHN0cmNweShkYXRlLCBOT0RB VEUpOw0KICAgICAgICByZXR1cm4gZGF0ZTsNCiAgICB9DQogICAgYyArPSAy Ow0KICAgIHdoaWxlICgqYyA9PSAnICcgfHwgKmMgPT0gJ1x0JykNCiAgICAg ICAgYysrOw0KICAgIGZvciAoaSA9IDAsIGxlbiA9IERBVEVTVFJMRU4tMTsg KmMgJiYgKmMgIT0gJ1xuJyAmJiBpIDwgbGVuOyBjKyspDQogICAgICAgIGRh dGVbaSsrXSA9ICpjOw0KICAgIGRhdGVbaV0gPSAnXDAnOw0KDQogICAgcmV0 dXJuIGRhdGU7DQp9DQoNCi8qDQoqKiBHcmFicyB0aGUgZGF0ZSBzdHJpbmcg ZnJvbSBhIEZyb20gYXJ0aWNsZSBzZXBhcmF0b3IuDQoqLw0KDQpjaGFyICpn ZXRmcm9tZGF0ZShjaGFyICpsaW5lKQ0Kew0KICAgIHN0YXRpYyBjaGFyIHRt cGRhdGVbREFURVNUUkxFTl07DQogICAgaW50IGk7DQogICAgaW50IGxlbjsN CiAgICBjaGFyICpjID0gTlVMTDsNCg0KICAgIGZvciAoaSA9IDA7IGRheXNb aV0gIT0gTlVMTCAmJiANCiAgICAgICAgKChjID0gKGNoYXIgKikgc3Ryc3Ry KGxpbmUsIGRheXNbaV0pKSA9PSBOVUxMKTsgaSsrKQ0KICAgICAgICA7DQog ICAgaWYgKGRheXNbaV0gPT0gTlVMTCkNCiAgICAgICAgdG1wZGF0ZVswXSA9 ICdcMCc7DQogICAgZWxzZSB7DQogICAgICAgIGZvciAoaSA9IDAsIGxlbiA9 IERBVEVTVFJMRU4tMTsgKmMgJiYgKmMgIT0gJ1xuJyAmJiBpIDwgbGVuOyBj KyspDQogICAgICAgICAgICAgdG1wZGF0ZVtpKytdID0gKmM7DQoNCiAgICAg ICAgdG1wZGF0ZVtpXSA9ICdcMCc7DQoNCiAgICAgICAgaWYgKHRtcGRhdGVb MTZdICE9ICc6Jykgew0KICAgICAgICAgICAgICAgIHRtcGRhdGVbMTZdID0g JzonOw0KICAgICAgICAgICAgICAgIHRtcGRhdGVbMTddID0gJzAnOw0KICAg ICAgICAgICAgICAgIHRtcGRhdGVbMThdID0gJzAnOw0KICAgICAgICAgICAg ICAgIHRtcGRhdGVbMTldID0gJyAnOw0KICAgICAgICAgICAgICAgIHRtcGRh dGVbMjBdID0gdGhpc3llYXJbMF07DQogICAgICAgICAgICAgICAgdG1wZGF0 ZVsyMV0gPSB0aGlzeWVhclsxXTsNCiAgICAgICAgICAgICAgICB0bXBkYXRl WzIyXSA9IHRoaXN5ZWFyWzJdOw0KICAgICAgICAgICAgICAgIHRtcGRhdGVb MjNdID0gdGhpc3llYXJbM107DQogICAgICAgICAgICAgICAgdG1wZGF0ZVsy NF0gPSAnXDAnOw0KICAgICAgICB9DQogICAgICAgIHNwcmludGYodG1wZGF0 ZSwgIiVzICVzIiwgdG1wZGF0ZSwgdGltZXpvbmVzdHIpOw0KICAgICAgICBy ZXR1cm4gdG1wZGF0ZTsNCiAgICB9DQoNCiAgICByZXR1cm4gdG1wZGF0ZTsN Cn0NCg0KDQovKg0KKiogR3JhYnMgdGhlIG5hbWUgYW5kIGVtYWlsIGFkZHJl c3MgZnJvbSBhIEZyb206IGhlYWRlci4NCioqIFRoaXMgY291bGQgZ2V0IHRy aWNreTsgSSd2ZSB0cmllZCB0byBrZWVwIGl0IHNpbXBsZS4NCioqIFNob3Vs ZCBiZSBhYmxlIHRvIGhhbmRsZSBhbGwgdGhlIGFkZHJlc3NlcyBiZWxvdzoN CioqDQoqKiAgIEZyb206IHVzZXIgICAgICAgICAgICAgICAgICAgW25vIEBd DQoqKiAgIEZyb206IGtlbnQgKEtlbnQgTGFuZGZpZWxkKSAgW25vIEAgLSB3 aXRoIGNvbW1lbnRdDQoqKiAgIEZyb206IDx1c2VyQG5vZGUuZG9tYWluPiAg ICAgW25vIHRleHQgbmFtZSwgdXNlIGVtYWlsIGFzIHRleHQgbmFtZV0NCioq ICAgRnJvbTogS2VudCBMYW5kZmllbGQgPGtlbnQ+ICBbdGV4dCBuYW1lIGJ1 dCBubyBAXQ0KKiogICBGcm9tOiAoa2VudCkgICAgICAgICAgICAgICAgIFtj b21tZW50IC0gbm8gZW1haWwgYWRkcmVzc10NCioqICAgRnJvbTogIiIgPGtl bnQ+ICAgICAgICAgICAgICBbZW1haWwgYWRkcmVzcyBidXQgbnVsbCBjb21t ZW50XQ0KKiogICBGcm9tOiAgICAgICAgICAgICAgICAgICAgICAgIFtibGFu ayBGcm9tOiBsaW5lXQ0KKiogICBGcm9tOiB1dS5uZXQha2VudCAgICAgICAg ICAgIFt1dWNwIGFkZHJlc3NlcyAtIG5vIGNvbW1lbnRdDQoqKiAgIEZyb206 IHV1Lm5ldCFrZW50IChrZW50KSAgICAgW3V1Y3AgYWRkcmVzc2VzIC0gd2l0 aCBjb21tZW50XQ0KKiogICBGcm9tOiAiKEpvZSBCbG9nZ3MpIiA8am9lQGFu b3JnLmNvbT4gDQoqKiAgIEZyb206ICJSb3kgVC4gRmllbGRpbmciIDxmaWVs ZGluZ0BraXdpLmljcy51Y2kuZWR1Pg0KKiogICBGcm9tOiBrZW50QGxvY2Fs aG9zdA0KKiogICBGcm9tOiBrZW50QHV1Lm5ldCAoS2VudCBMYW5kZmllbGQp DQoqKiAgIEZyb206IChHZW9yZ2UgQnVyZ3lhbikgPGdidXJneWFuQGN5YmVy Y29uLmNvbT4NCioqICAgRnJvbTogPGdidXJneWFuQGN5YmVyY29uLmNvbT4g KEdlb3JnZSBCdXJneWFuKSANCioqICAgRnJvbTogICAgICAgICAgICAgIEtl bnQgQi4gTGFuZGZpZWxkIDxrZW50QGxhbmRmaWVsZC5jb20+DQoqKiAgIEZy b206ICAgICAgSU4lImZla2V0ZStyZXBseUBjMi5uZXQiIDI2LUpBTi0xOTk3 IDEzOjI4OjU1LjM2DQoqKiAgIEZyb206ICAgICAgSU4lInZpY3JpY0BwYW5p eC5jb20iICAiVmlja2kgUmljaG1hbiIgMTMtQVVHLTE5OTYgMTA6NTQ6MzMu MzgNCioqICAgRnJvbTogICAgICBVUzJSTUM6OiJsd3YyNkBjYXMub3JnIiAi TGFycnkgVy4gVmlyZGVuLCB4MjQ4NyIgMjItT0NULTE5OTQgMDk6NDQ6MjEu NDQNCioqICAgRnJvbTogICAgICAgICAgTWFpbCBEZWxpdmVyeSBTdWJzeXN0 ZW0gPHBvc3RtYXN0ZXJAaWdjLmFwYy5vcmc+DQoqKiAgIEZyb206ICAgICAg ICAgIFNlbGYgPGVoYXNicm91Y2s+DQoqKiAgIEZyb206ICAgICAgICAgYWRh bUBlZGVuLmFwYW5hLm9yZy5hdSAoQWRhbSBGcmV5KQ0KKiogICBGcm9tOiAg ICAgICAgZmFxc2VydkBwZW5ndWluLWx1c3QubWl0LmVkdQ0KKiogICBGcm9t OiAgICBuYzA1NDhAZnJlZWJzZC5uZXRjb20uY29tIChNYXJrIEhpdHRpbmdl cikNCioqICAgRnJvbTogIi0gUGFtIEdyZWVuZSwgb25lIG9mIHRoZSAqLmFu c3dlcnMgbW9kZXJhdG9ycyIgPHBncmVlbmVATUlULkVEVT4NCioqICAgRnJv bTogIkZlbGFuIHNoZW5hIFRob3JvbidlZHJhcyIgPGZlbGFuQG5ldGNvbS5j b20+DQoqKiAgIEZyb206IERhdmlkIE11aXIgU2hhcm5vZmYgPG11aXJAaWRp b20uY29tPg0KKiogICBGcm9tOiBBLkouRG9oZXJ0eUByZWFkaW5nLmFjLnVr IChBbmR5IERvaGVydHkpDQoqKiAgIEZyb206IEpvcmRhbiBIdWJiYXJkICAg ICAgICAgICAgICAgICAgICAgICAgPGpraEB2ZWN0b3IuZWlrb24uZS10ZWNo bmlrLnR1LW11ZW5jaGVuLmRlPg0KKiogICBGcm9tOiBaWFBBTiVTTEFDVk0u QklUTkVUQE1JVFZNQS5NSVQuRURVDQoqKiAgIEZyb206IGFmcyFwaXohYWxm QHV1NS5wc2kuY29tIChBbGYgdGhlIFBvZXQpDQoqKiAgIEZyb206IGFuc3dl cnNAY3AudG4udHVkZWxmdC5ubCAoIk1vZGVyYXRvciAqLmFuc3dlcnMiKQ0K KiogICBGcm9tOiBtZHclbWVyZW5ndWVAbWVyZW5ndWUub2l0LnVuYy5lZHUg KE1hdHQgV2Vsc2gpDQoqKiAgIEZyb206IGJnb2ZmZUB3aGFsZS5zdC51c20u ZWR1IChXaWxsaWFtIEwuIEdvZmZlKQ0KKi8NCg0Kdm9pZCBnZXRuYW1lKGNo YXIgKmxpbmUsIGNoYXIgKm5hbWUsIGNoYXIgKmVtYWlsKQ0Kew0KICAgIGlu dCBpOw0KICAgIGludCBsZW47DQogICAgY2hhciAqYzsNCg0KICAgIGxlbiA9 IE1BSUxTVFJMRU4tMTsNCg0KICAgIC8qDQogICAgKiogWmVyb291dCBkYXRh Lg0KICAgICovDQogICAgemVyb19vdXQoZW1haWwsIE1BSUxTVFJMRU4pOw0K ICAgIHplcm9fb3V0KG5hbWUsIE5BTUVTVFJMRU4pOw0KDQogICAgLyogRU1h aWwgUHJvY2Vzc2luZyBGaXJzdDoNCiAgICAqKiBGaXJzdCwgaXMgdGhlcmUg YW4gJ0AnIHNpZ24gd2UgY2FuIHVzZSBhcyBhbiBhbmNob3IgPw0KICAgICov DQogICAgaWYgKChjID0gKGNoYXIgKikgc3RyY2hyKGxpbmUsICdAJykpID09 IE5VTEwpIHsNCiAgICAgICAgLyogDQogICAgICAgICoqIE5vICdAJyBzaWdu IGhlcmUgc28gLi4uDQogICAgICAgICovDQogICAgICAgIGlmIChzdHJjaHIo bGluZSwgJygnKSkgeyAgICAgICAvKiBGcm9tOiBib2IgKFRoZSBCaWcgR3V5 KSAqLw0KICAgICAgICAgICAgYyA9IChjaGFyICopIHN0cmNocihsaW5lLCAn OicpICsgMTsNCiAgICAgICAgICAgIHdoaWxlICgqYyA9PSAnICcgfHwgKmMg PT0gJ1x0JykNCiAgICAgICAgICAgICAgICBjKys7DQogICAgICAgICAgICBm b3IgKGkgPSAwOyAqYyAmJiAqYyAhPSAnKCcgJiYgKmMgIT0gJyAnICYmIA0K ICAgICAgICAgICAgICAgICAqYyAhPSAnXHQnICYmICpjICE9ICdcbicgJiYg aSA8IGxlbjsgYysrKQ0KICAgICAgICAgICAgICAgIGVtYWlsW2krK10gPSAq YzsNCiAgICAgICAgICAgIGVtYWlsW2ldID0gJ1wwJzsNCiAgICAgICAgfQ0K ICAgICAgICBlbHNlIGlmICgoYyA9IChjaGFyICopIHN0cmNocihsaW5lLCAn PCcpKSkgeyAgLyogRnJvbTogPGtlbnQ+ICovDQogICAgICAgICAgICBjKys7 DQogICAgICAgICAgICBmb3IgKGkgPSAwOyAqYyAmJiAqYyAhPSAnPicgJiYg KmMgIT0gJyAnICYmIA0KICAgICAgICAgICAgICAgICAqYyAhPSAnXHQnICYm ICpjICE9ICdcbicgJiYgaSA8IGxlbjsgYysrKQ0KICAgICAgICAgICAgICAg IGVtYWlsW2krK10gPSAqYzsNCiAgICAgICAgICAgIGVtYWlsW2ldID0gJ1ww JzsNCiAgICAgICAgfQ0KICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgIC8q IA0KICAgICAgICAgICAgKiogICAgLSBjaGVjayB0byBzZWUgaWYgdGhlIEZy b206IGxpbmUgaXMgYmxhbmssICh0YWtlbiBjYXJlIG9mKQ0KICAgICAgICAg ICAgKiogICAgLSBjaGVjayBpZiBGcm9tOiB1dS5uZXQha2VudCBmb3JtYXR0 ZWQgbGluZQ0KICAgICAgICAgICAgKiogICAgLSBjaGVjayBpZiAiRnJvbTog a2VudCIgZm9ybWF0dGVkIGxpbmUNCiAgICAgICAgICAgICovDQogICAgICAg ICAgICBjID0gKGNoYXIgKikgc3RyY2hyKGxpbmUsICc6JykgKyAxOw0KICAg ICAgICAgICAgd2hpbGUgKCpjID09ICcgJyB8fCAqYyA9PSAnXHQnKQ0KICAg ICAgICAgICAgICAgICAgIGMrKzsNCiAgICAgICAgICAgIGZvciAoaSA9IDA7 ICpjICYmICpjICE9ICcgJyAmJiAqYyAhPSAnXHQnICYmIA0KICAgICAgICAg ICAgICAgICpjICE9ICdcbicgJiYgKmMgIT0gJywnICYmIGkgPCBsZW47IGMr KykNCiAgICAgICAgICAgICAgICAgZW1haWxbaSsrXSA9ICpjOw0KICAgICAg ICAgICAgZW1haWxbaV0gPSAnXDAnOw0KDQogICAgICAgIH0NCg0KICAgICAg ICBpZiAoZW1haWxbMF0gPT0gJ1wwJykgLyogV2FzIGl0IGEganVuayBGcm9t IGxpbmUgPyAqLw0KICAgICAgICAgICAgc3RyY3B5KGVtYWlsLCBOT0VNQUlM KTsNCg0KICAgICAgICBlbHNlIGlmICh1c2VfZG9tYWluYWRkcikgeyANCiAg ICAgICAgICAgIC8qDQogICAgICAgICAgICAqKiBjaGVjayBpZiBzaXRlIGRv bWFpbml6ZXMgYWRkcmVzc2VzIA0KICAgICAgICAgICAgKiogYnV0IGRvbid0 IG1vZGlmeSB1dWNwIGFkZHJlc3Nlcw0KICAgICAgICAgICAgKi8NCiAgICAg ICAgICAgIGlmICgoYyA9IChjaGFyICopIHN0cmNocihlbWFpbCwgJyEnKSkg PT0gTlVMTCkgew0KICAgICAgICAgICAgICAgIHN0cmNhdChlbWFpbCwgIkAi KTsNCiAgICAgICAgICAgICAgICBzdHJjYXQoZW1haWwsIGRvbWFpbmFkZHIp Ow0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KICAgIGVsc2Ug ew0KICAgICAgICB3aGlsZSAoKmMgIT0gJyAnICYmICpjICE9ICdcdCcgJiYg KmMgIT0gJzwnICYmICpjICE9ICciJykNCiAgICAgICAgICAgIGMtLTsNCiAg ICAgICAgYysrOw0KICAgICAgICBmb3IgKGkgPSAwOyAqYyAmJiAqYyAhPSAn PicgJiYgKmMgIT0gJyAnICYmICpjICE9ICdcdCcgJiYNCiAgICAgICAgICAg ICAqYyAhPSAnIicgJiYgKmMgIT0gJ1xuJyAmJiBpIDwgbGVuOyBjKyspDQog ICAgICAgICAgICBlbWFpbFtpKytdID0gKmM7DQogICAgICAgIGVtYWlsW2ld ID0gJ1wwJzsNCiAgICB9DQoNCiAgICAvKg0KICAgICoqIE5BTUUgUHJvY2Vz c2luZyAtIEJveSBhcmUgdGhlcmUgYSBidW5jaCBvZiBmdW5reSBmb3JtYXRz IGhlcmUuDQogICAgKiogICAgICAgICAgICAgICAgICAgTm8gcHJvbWlzZXMu Li4gSSdsbCBkbyBteSBiZXN0LiBMZXQgbWUga25vdw0KICAgICoqICAgICAg ICAgICAgICAgICAgIHdoYXQgSSBtaXNzZWQuLi4NCiAgICAqLw0KICAgIGlm IChzdHJjaHIobGluZSwgJygnKSkgew0KICAgICAgICBjID0gKGNoYXIgKikg c3RyY2hyKGxpbmUsICcoJykgKyAxOw0KICAgICAgICBpZiAoKmMgPT0gJyIn KSAvKiBpcyB0aGVyZSBhIGNvbW1lbnQgaW4gdGhlIGNvbW1lbnQgPyAqLw0K ICAgICAgICAgICAgIGMrKzsNCiAgICB9DQogICAgZWxzZSBpZiAoc3RyY2hy KGxpbmUsICc8JykpIHsNCiAgICAgICAgYyA9IChjaGFyICopIHN0cmNocihs aW5lLCAnOicpICsgMTsNCiAgICAgICAgd2hpbGUgKCpjID09ICcgJyB8fCAq YyA9PSAnXHQnIHx8ICpjID09ICdcIicpDQogICAgICAgICAgICBjKys7DQog ICAgfQ0KICAgIGVsc2Ugew0KICAgICAgICAvKg0KICAgICAgICAqKiBJcyB0 aGVyZSBhbiBlbWFpbCBhZGRyZXNzIGF2YWlsYWJsZSANCiAgICAgICAgKiog dGhhdCB3ZSBjYW4gdXNlIGZvciB0aGUgbmFtZSA/DQogICAgICAgICovDQog ICAgICAgIGlmICghc3RyY21wKGVtYWlsLCBOT0VNQUlMKSkgICAgLyogTm8g Ki8NCiAgICAgICAgICAgIHN0cmNweShuYW1lLCBOT05BTUUpOw0KICAgICAg ICBlbHNlIHsNCiAgICAgICAgICAgIGMgPSBlbWFpbCtzdHJsZW4oZW1haWwp IC0gMTsNCiAgICAgICAgICAgIHdoaWxlIChpc3NwYWNlKCpjKSkgKmMtLSA9 ICdcMCc7DQogICAgICAgICAgICBzdHJjcHkobmFtZSwgZW1haWwpOyAgICAg ICAgLyogWWVzICovDQogICAgICAgIH0NCiAgICAgICAgcmV0dXJuOw0KICAg IH0NCg0KICAgIGZvciAoaSA9IDAsIGxlbiA9IE5BTUVTVFJMRU4tMTsgKmMg JiYgKmMgIT0gJzwnICYmICpjICE9ICdcIicgJiYgKmMgIT0gJyknICYmICpj ICE9ICcoJyAmJiAqYyAhPSAnXG4nICYmIGkgPCBsZW47IGMrKykNCiAgICAg ICAgbmFtZVtpKytdID0gKmM7DQoNCiAgICBpZiAoKmMgPT0gJzwnIHx8ICpj ID09ICcoJykNCiAgICAgICAgbmFtZVstLWldID0gJ1wwJzsNCiAgICBlbHNl DQogICAgICAgIG5hbWVbaV0gPSAnXDAnOw0KDQogICAgDQogICAgLyogQmFp bGluZyBhbmQgdGFraW5nIHRoZSBlYXN5IHdheSBvdXQuLi4gKi8NCg0KICAg IGlmIChuYW1lWzBdID09ICdcMCcpIHsNCiAgICAgICAgaWYgKGVtYWlsWzBd ID09ICdcMCcpDQogICAgICAgICAgICBzdHJjcHkobmFtZSwgTk9OQU1FKTsN CiAgICAgICAgZWxzZQ0KICAgICAgICAgICAgc3RyY3B5KG5hbWUsIGVtYWls KTsNCiAgICB9DQoNCiAgICAgLyogbmVlZCB0byBzdHJpcCBzcGFjZXMgb2Zm IHRoZSBlbmQgb2YgDQogICAgICoqIHRoZSBlbWFpbCBhbmQgbmFtZSBzdHJp bmdzIA0KICAgICAqLw0KDQogICAgIGMgPSBlbWFpbCtzdHJsZW4oZW1haWwp IC0gMTsNCiAgICAgd2hpbGUgKGlzc3BhY2UoKmMpKSAqYy0tID0gJ1wwJzsN CiAgICAgYyA9IG5hbWUrc3RybGVuKG5hbWUpIC0gMTsNCiAgICAgd2hpbGUg KGlzc3BhY2UoKmMpKSAqYy0tID0gJ1wwJzsNCn0NCg0KLyogDQoqKiBHcmFi cyB0aGUgbWVzc2FnZSBJRCwgbGlrZSA8Li4uPiBmcm9tIHRoZSBNZXNzYWdl LUlEOiBoZWFkZXIuDQoqLw0KDQoNCmNoYXIgKmdldGlkKGNoYXIgKmxpbmUp DQp7DQogICAgaW50IGk7DQogICAgaW50IGxlbjsNCiAgICBjaGFyICpjOw0K ICAgIHN0YXRpYyBjaGFyIG1zZ2lkW01TR0RTVFJMRU5dOw0KIA0KICAgIGlm ICgoY2hhciAqKXN0cmNocihsaW5lLCAnPCcpID09IE5VTEwpIHsNCiAgICAg ICAgLyogYm96byBhbGVydCENCiAgICAgICAgKiogICBtc2ctaWQgPSAiPCIg YWRkci1zcGVjICI+IiANCiAgICAgICAgKiogdHJ5IHRvIHJlY292ZXIgYXMg YmVzdCB3ZSBjYW4NCiAgICAgICAgKi8NCiAgICAgICAgYyA9IChjaGFyICop IHN0cmNocihsaW5lLCAnOicpICsgMTsgLyogd2Uga25vdyB0aGlzIGV4aXN0 cyEgKi8NCg0KICAgICAgICAvKiBza2lwIHNwYWNlcyBiZWZvcmUgbWVzc2Fn ZSBJRCAqLw0KICAgICAgICB3aGlsZSAoKmMgJiYgKCpjID09ICcgJyB8fCAq YyA9PSAnXHQnKSkgYysrOyANCiAgICB9DQogICAgZWxzZSANCiAgICAgICAg YyA9IChjaGFyICopIHN0cmNocihsaW5lLCAnPCcpICsgMTsNCg0KICAgIGZv ciAoaSA9IDAsIGxlbiA9IE1TR0RTVFJMRU4gLTE7ICpjICYmICpjICE9ICc+ JyAmJiAqYyAhPSAnXG4nICYmIGkgPCBsZW47IGMrKykgew0KICAgICAgICBp ZiAoKmMgPT0gJ1xcJykNCiAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAg ICBtc2dpZFtpKytdID0gKmM7DQogICAgfQ0KDQogICAgbXNnaWRbaV0gPSAn XDAnOw0KDQogICAgaWYgKHN0cmxlbihtc2dpZCkgPT0gMCkgDQogICAgICAg IHN0cmNweShtc2dpZCwgIkJPWk8iKTsNCg0KICAgIHJldHVybiBtc2dpZDsN Cn0NCg0KDQovKg0KKiogR3JhYnMgdGhlIHN1YmplY3QgZnJvbSB0aGUgU3Vi amVjdDogaGVhZGVyLg0KKi8NCg0KY2hhciAqZ2V0c3ViamVjdChjaGFyICps aW5lKQ0Kew0KICAgIGludCBpOw0KICAgIGludCBsZW47DQogICAgY2hhciAq YzsNCiAgICBzdGF0aWMgY2hhciBzdWJqZWN0W1NVQkpTVFJMRU5dOw0KDQog ICAgYyA9IChjaGFyICopIHN0cmNocihsaW5lLCAnOicpICsgMjsNCiAgICB3 aGlsZSAoaXNzcGFjZSgqYykpDQogICAgICAgICBjKys7DQogICAgZm9yIChp ID0gMCwgbGVuID0gU1VCSlNUUkxFTiAtMTsgKmMgJiYgKmMgIT0gJ1xuJyAm JiBpIDwgbGVuOyBjKyspDQogICAgICAgICBzdWJqZWN0W2krK10gPSAqYzsN Cg0KICAgIHN1YmplY3RbaV0gPSAnXDAnOw0KDQogICAgLyogc3RyaXAgdHJh aWxpbmcgc3BhY2VzICovDQoNCg0KICAgIGZvciAoaS0tOyBpID49IDAgJiYg aXNzcGFjZShzdWJqZWN0W2ldKTsgaS0tKQ0KICAgICAgICAgc3ViamVjdFtp XSA9ICdcMCc7DQoNCiAgICAvKg0KICAgICoqIEZpeCBmb3IgRXhjaGFuZ2Ug YnVnIHRoYXQgcHV0cyAiRlc6IiBpbiBmcm9udCBvZiBmb3J3YXJkZWQgDQog ICAgKiogbWVzc2FnZXMgd2hpY2ggYXJlIHN1YnN0aXR1dGVkIGJ5IEV4Y2hh bmdlIGZvciAiUkU6IiBvbiByZXBsaWVzDQogICAgKi8NCg0KICAgIGlmICgh c3RybmNtcChzdWJqZWN0LCAiRlc6IiwgMykpIHsNCiAgICAgICAgc3ViamVj dFswXSA9ICdSJzsNCiAgICAgICAgc3ViamVjdFsxXSA9ICdlJzsNCiAgICB9 ICAgDQoNCiAgICBpZiAoc3ViamVjdFswXSA9PSAgJ1wwJyB8fCBpc3NwYWNl KHN1YmplY3RbMF0pIHx8IHN1YmplY3RbMF0gPT0gJ1xuJyB8fCANCiAgICAg ICAgIXN0cmNhc2VjbXAoc3ViamVjdCwgIlJlOiIpIHx8ICFzdHJjYXNlY21w KHN1YmplY3QsICJSZVsyXToiKSkNCiAgICAgICAgc3RyY3B5KHN1YmplY3Qs IE5PU1VCSkVDVCk7DQoNCiAgICByZXR1cm4gc3ViamVjdDsNCn0NCg0KLyoN CioqIEdyYWJzIHRoZSBtZXNzYWdlIElELCBvciBkYXRlLCBmcm9tIHRoZSBJ bi1yZXBseS10bzogaGVhZGVyLg0KKioNCioqIE1heWJlIEknbSBjb25mdXNl ZCBidXQuLi4uDQoqKiAgICAgV2hhdCBlaXRoZXIgPyBTaG91bGQgaXQgbm90 IGJlIGNvbnNpc3RlbnQgYW5kIGNob29zZSB0byByZXR1cm4gDQoqKiAgICAg b25lICh0aGUgbXNnaWQpIGFzIHRoZSBkZWZhdWx0IGFuZCBmYWxsIGJhY2sg dG8gZGF0ZSB3aGVuIGEgDQoqKiAgICAgbXNnaWQgY2Fubm90IGJlIGZvdW5k ID8NCioqDQoqKiBXaG8ga25vd3Mgd2hhdCBvdGhlciBmb3JtYXRzIGFyZSBv dXQgdGhlcmUuLi4NCioqDQoqKiBJbi1SZXBseS1UbzogPDFERDlCODU0RTI3 QGV2ZXJldHQucGl0dC5jYy5uYy51cz4NCioqIEluLVJlcGx5LVRvOiA8MTk5 NzA5MTgxNjQ1Lk1BQTAyMDk3QG1haWwuY2xhcmsubmV0PiBmcm9tICJNYXJj dXMgSi4gUmFudW0iIGF0IFNlcCAxOCwgOTcgMTI6NDE6NDAgcG0NCioqIElu LVJlcGx5LVRvOiA8MTk5NzA5MTgxNjQ1Lk1BQTAyMDk3QG1haWwuY2xhcmsu bmV0PiBmcm9tIA0KKiogSW4tUmVwbHktVG86ICJMLiBEZXR3ZWlsZXIiJ3Mg bWVzc2FnZSBvZiBGcmksIDA0IEZlYiA5NCAyMjo1MToyMiAtMDcwMCA8MTk5 NDAyMDUwNTUxLldBQTE2MTg5QGxvbmdzLmxhbmNlLmNvbG9zdGF0ZS5lZHU+ DQoqKg0KKiogVGhpcyByb3V0aW5lIGlzIGJ1Z2d5IGFuZCB0aGUgZml4IGlz IHRvIGFkZCBhIHJlYWRsaW5lIHJvdXRpbmUgdGhhdCANCioqIGNvbmNhdGVu YXRlcyBjb250aW51YXRpb24gbGluZXMgaW50byBhIHNpbmdsZSBsaW5lIGFu ZCBjb2xsYXBzZXMgDQoqKiB3aGl0ZXNwYWNlLiBUaGUgbWVzc2FnZSBpZCBz aG91bGQgYWx3YXlzIGJlIHJldHVybmVkIGZvciB0aHJlYWRpbmcgDQoqKiBw dXJwb3Nlcy4gTWl4aW5nIG1lc3NhZ2UtaWRzIGFuZCBkYXRlcyBqdXN0IGRv ZXMgbm90IGFsbG93IGZvciBwcm9wZXIgDQoqKiB0aHJlYWRpbmcgbG9va3Vw cy4NCiovDQogDQpjaGFyICpnZXRyZXBseShjaGFyICpsaW5lKQ0Kew0KICAg IGludCBpOw0KICAgIGludCByZXBseWxlbjsNCiAgICBpbnQgbWxlbjsNCiAg ICBjaGFyICpjOw0KICAgIGNoYXIgKm07DQogICAgc3RhdGljIGNoYXIgcmVw bHlbUkVQWVNUUkxFTl07DQoNCiAgICByZXBseWxlbiA9IFJFUFlTVFJMRU4g LTE7DQogICAgbWxlbiA9IE1TR0RTVFJMRU4gLTE7DQoNCiAgICAvKiBDaGVj ayBmb3IgYmxhbmsgbGluZSAqLw0KDQogICAgLyogDQogICAgKiogQ2hlY2sg Zm9yIGxpbmUgd2l0aCAiIGZyb20gIiBhbmQgIiBhdCAiLiAgRm9ybWF0IG9m IHRoZSBsaW5lIGlzIA0KICAgICoqICAgICA8bXNnaWQ+IGZyb20gInF1b3Rl ZCB1c2VyIG5hbWUiIGF0IGRhdGUtc3RyaW5nDQogICAgKi8NCg0KICAgIGlm ICgoY2hhciAqKSBzdHJzdHIobGluZSwgIiBmcm9tICIpICE9IE5VTEwpIHsN CiAgICAgICAgaWYgKCgoY2hhciAqKSBzdHJzdHIobGluZSwgIiBhdCAiKSkg IT0gTlVMTCkgew0KICAgICAgICAgICAgaWYgKChtID0gKGNoYXIgKikgc3Ry Y2hyKGxpbmUsICc8JykpICE9IE5VTEwpIHsNCiAgICAgICAgICAgICAgICBm b3IgKG0rKywgaSA9IDA7ICptICYmICptICE9ICc+JyAmJiAqbSAhPSAnXG4n ICYmIGkgPCByZXBseWxlbjsgbSsrKQ0KICAgICAgICAgICAgICAgICAgICAg cmVwbHlbaSsrXSA9ICptOw0KICAgICAgICAgICAgICAgIHJlcGx5W2ldID0g J1wwJzsNCiAgICAgICAgICAgICAgICByZXR1cm4ocmVwbHkpOw0KICAgICAg ICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgLyogDQogICAgICAgICoq IElmIG5vICdhdCcgdGhlIGxpbmUgbWF5IGJlIGEgY29udGludWVkIGxpbmUg b3IgYSB0cnVuY2F0ZWQgbGluZS4NCiAgICAgICAgKiogQm90aCB3aWxsIGJl IHBpY2tlZCB1cCBsYXRlci4NCiAgICAgICAgKi8NCiAgICB9DQoNCiAgICAv KiANCiAgICAqKiBDaGVjayBmb3IgbGluZSB3aXRoICIgbWVzc2FnZSBvZiAi LiAgRm9ybWF0IG9mIHRoZSBsaW5lIGlzIA0KICAgICoqICAgICAicXVvdGVk IHVzZXIgbmFtZSIncyBtZXNzYWdlIG9mIGRhdGUtc3RyaW5nIDxtc2dpZD4N CiAgICAqLw0KDQogICAgaWYgKChjID0gKGNoYXIgKikgc3Ryc3RyKGxpbmUs ICJtZXNzYWdlIG9mICIpKSAhPSBOVUxMKSB7DQogICAgICAgIC8qDQogICAg ICAgICoqIENoZWNrIHRvIHNlZSBpZiB0aGVyZSBpcyBhIG1lc3NhZ2UgSUQg b24gdGhlIGxpbmUuIA0KICAgICAgICAqKiBJZiBub3QgdGhpcyBpcyBhIGNv bnRpbnVlZCBsaW5lIGFuZCB3aGVuIHlvdSBhZGQgYSByZWFkbGluZSgpDQog ICAgICAgICoqIGZ1bmN0aW9uIHRoYXQgY29uY2F0ZW5hdGVzIGNvbnRpbnVh dGlvbiBsaW5lcyBjb2xsYXBzaW5nDQogICAgICAgICoqIHdoaXRlIHNwYWNl LCB5b3UgbWlnaHQgd2FudCB0byByZXZpc2l0IHRoaXMuLi4NCiAgICAgICAg Ki8NCg0KICAgICAgICBpZiAoKG0gPSAoY2hhciAqKSBzdHJjaHIobGluZSwg JzwnKSkgIT0gTlVMTCkgew0KICAgICAgICAgICAgIGZvciAobSsrLCBpID0g MDsgKm0gJiYgKm0gIT0gJz4nICYmICptICE9ICdcbicgJiYgaSA8IHJlcGx5 bGVuOyBtKyspDQogICAgICAgICAgICAgICAgICByZXBseVtpKytdID0gKm07 DQogICAgICAgICAgICAgcmVwbHlbaV0gPSAnXDAnOw0KICAgICAgICAgICAg IHJldHVybihyZXBseSk7DQogICAgICAgIH0NCiAgDQogICAgICAgIC8qIE5v cGUuLi4gR28gZm9yIHRoZSBEYXRlIGluZm8uLi4gQnVnLi4uKi8NCiAgICAg ICAgYyArPSAxMTsNCiAgICAgICAgd2hpbGUgKGlzc3BhY2UoKmMpKQ0KICAg ICAgICAgICAgYysrOw0KICAgICAgICBpZiAoKmMgPT0gJyInKSANCiAgICAg ICAgICAgIGMrKzsNCg0KICAgICAgICBmb3IgKGkgPSAwOyAqYyAmJiAqYyAh PSAnLicgJiYgKmMgIT0gJ1xuJyAmJiBpIDwgcmVwbHlsZW47IGMrKykNCiAg ICAgICAgICAgICByZXBseVtpKytdID0gKmM7DQogICAgICAgIHJlcGx5W2ld ID0gJ1wwJzsNCiAgICAgICAgcmV0dXJuKHJlcGx5KTsNCiAgICB9DQoNCiAg ICBpZiAoKGMgPSAoY2hhciAqKSBzdHJzdHIobGluZSwgImRhdGVkOiAiKSkg IT0gTlVMTCkgew0KICAgICAgICBjICs9IDc7DQogICAgICAgIGZvciAoaSA9 IDA7ICpjICYmICpjICE9ICcuJyAmJiAqYyAhPSAnXG4nICYmIGkgPCByZXBs eWxlbjsgYysrKQ0KICAgICAgICAgICAgIHJlcGx5W2krK10gPSAqYzsNCiAg ICAgICAgcmVwbHlbaV0gPSAnXDAnOw0KICAgICAgICByZXR1cm4ocmVwbHkp Ow0KICAgIH0NCiANCiAgICBpZiAoKGMgPSAoY2hhciAqKSBzdHJzdHIobGlu ZSwgImRhdGVkICIpKSAhPSBOVUxMKSB7DQogICAgICAgIGMgKz0gNjsNCiAg ICAgICAgZm9yIChpID0gMDsgKmMgJiYgKmMgIT0gJy4nICYmICpjICE9ICdc bicgJiYgaSA8IHJlcGx5bGVuOyBjKyspDQogICAgICAgICAgICAgcmVwbHlb aSsrXSA9ICpjOw0KICAgICAgICByZXBseVtpXSA9ICdcMCc7DQogICAgICAg IHJldHVybihyZXBseSk7DQogICAgfQ0KDQogICAgaWYgKChjID0gKGNoYXIg Kikgc3RyY2hyKGxpbmUsICc8JykpICE9IE5VTEwgKSB7DQogICAgICAgIGMr KzsNCiAgICAgICAgZm9yIChpID0gMDsgKmMgJiYgKmMgIT0gJz4nICYmICpj ICE9ICdcbicgJiYgaSA8IG1sZW47IGMrKykgew0KICAgICAgICAgICAgIGlm ICgqYyA9PSAnXFwnKQ0KICAgICAgICAgICAgICAgICBjb250aW51ZTsNCiAg ICAgICAgICAgICByZXBseVtpKytdID0gKmM7DQogICAgICAgIH0NCiAgICAg ICAgcmVwbHlbaV0gPSAnXDAnOw0KICAgICAgICByZXR1cm4ocmVwbHkpOw0K ICAgIH0NCiANCiAgICBpZiAoKGMgPSAoY2hhciAqKSBzdHJzdHIobGluZSwg InNhZ2Ugb2YgIikpICE9IE5VTEwpIHsNCiAgICAgICAgYyArPSA4Ow0KICAg ICAgICBpZiAoKmMgPT0gJ1wiJykNCiAgICAgICAgICAgIGMrKzsNCg0KICAg ICAgICBmb3IgKGkgPSAwOyAqYyAmJiAqYyAhPSAnLicgJiYgKmMgIT0gJ1xu JyAmJiANCiAgICAgICAgICAgICAqYyAhPSAnZicgJiYgaSA8IHJlcGx5bGVu OyBjKyspDQogICAgICAgICAgICAgcmVwbHlbaSsrXSA9ICpjOw0KICAgICAg ICByZXBseVtpXSA9ICdcMCc7DQoNCiAgICAgICAgaWYgKCpjID09ICdmJykN CiAgICAgICAgICAgIHJlcGx5Wy0taV0gPSAnXDAnOw0KICAgICAgICByZXR1 cm4ocmVwbHkpOw0KICAgIH0NCiANCiAgICByZXBseVswXSA9ICdcMCc7DQog ICAgcmV0dXJuKHJlcGx5KTsNCn0NCg0KLyoNCioqIFJGQyAyMDQ3IGRlZmlu ZXMgTUlNRSBleHRlbnNpb25zIGZvciBtYWlsIGhlYWRlcnMuDQoqKg0KKiog VGhpcyBmdW5jdGlvbiBkZWNvZGVzIHRoYXQgaW50byBiaW5hcnkvOGJpdCBk YXRhLg0KKioNCioqIEV4YW1wbGU6DQoqKiAgID0/aXNvLTg4NTktMT9xP0kn bV9jYWxsZWRfPz0gPT9pc28tODg1OS0xP3E/RGFuaWVsPz0NCioqDQoqKiBT aG91bGQgcmVzdWx0IGluICJJJ20gY2FsbGVkIERhbmllbCIsIGJ1dDoNCioq DQoqKiAgID0/aXNvLTg4NTktMT9xP0knbV9jYWxsZWQ/PSBEYW5pZWwNCioq DQoqKiBTaG91bGQgcmVzdWx0IGluICJJJ20gY2FsbGVkIERhbmllbCIgdG9v Lg0KKioNCioqIFJldHVybnMgdGhlIG5ld2x5IGFsbGNhdGVkIHN0cmluZywg b3IgdGhlIHByZXZpb3VzIGlmIG5vdGhpbmcgY2hhbmdlZCANCiovDQoNCnN0 YXRpYyBjaGFyICptZGVjb2RlUkZDMjA0NyggY2hhciAqc3RyaW5nLCBpbnQg bGVuZ3RoICkNCnsNCiAgICBjaGFyICppcHRyID0gc3RyaW5nOw0KICAgIGNo YXIgKm9sZHB0cjsNCiAgICBjaGFyICpzdG9yYWdlPW1hbGxvYyhsZW5ndGgr MSk7DQogIA0KICAgIGNoYXIgKm91dHB1dCA9IHN0b3JhZ2U7DQogIA0KICAg IGNoYXIgY2hhcnNldFsxMjldOw0KICAgIGNoYXIgZW5jb2RpbmdbMzNdOw0K ICAgIGNoYXIgYmx1cmJbMTI5XTsNCiAgICBjaGFyIGVxdWFsOw0KICAgIGlu dCB2YWx1ZTsNCiAgDQogICAgY2hhciBkaWRhbnl0aGluZz1GQUxTRTsNCg0K ICAgIHdoaWxlICgqaXB0cikgew0KICAgICAgICBpZiAoIXN0cm5jbXAoaXB0 ciwgIj0/IiwgMikgJiYNCiAgICAgICAgICAgICg0ID09IHNzY2FuZihpcHRy KzIsICIlMTI4W14/XT8lMzJbXj9dPyUxMjhbXj9dPyVjIiwNCiAgICAgICAg ICAgICAgICAgICAgICAgIGNoYXJzZXQsIGVuY29kaW5nLCBibHVyYiwgJmVx dWFsKSkgJiYNCiAgICAgICAgICAgICgnPScgPT0gZXF1YWwpKSB7DQogICAg ICAgICAgICAvKiBUaGlzIGlzIGEgZnVsbCwgdmFsaWQgJ2VuY29kZWQtd29y ZCcuIERlY29kZSEgKi8NCiAgICAgICAgICAgIGNoYXIgKnB0cj1ibHVyYjsN CiAgDQogICAgICAgICAgICBkaWRhbnl0aGluZz1UUlVFOyAvKiB5ZXMsIHdl IGRlY29kZSBzb21ldGhpbmcgKi8NCiAgDQogICAgICAgICAgICAvKiB3ZSBj b3VsZCd2ZSBkb25lIHRoaXMgd2l0aCBhICVuIGluIHRoZSBzc2NhbmYsIGJ1 dCB3ZSBrbm93IGFsbA0KICAgICAgICAgICAgICAgc3NjYW5mcyBkb24ndCBn cm9rIHRoYXQgKi8NCg0KICAgICAgICAgICAgaXB0ciArPSAyKyBzdHJsZW4o Y2hhcnNldCkgKyAxICsgc3RybGVuKGVuY29kaW5nKSArIDEgKyBzdHJsZW4o Ymx1cmIpICsgMjsNCiAgDQogICAgICAgICAgICBpZiAoIXN0cmNhc2VjbXAo InEiLCBlbmNvZGluZykpIHsNCiAgICAgICAgICAgICAgIC8qIHF1b3RlZCBw cmludGFibGUgZGVjb2RpbmcgKi8NCiAgDQogICAgICAgICAgICAgICAgZm9y ICggOyAqcHRyOyBwdHIrKyApIHsNCiAgICAgICAgICAgICAgICAgICAgc3dp dGNoICggKnB0ciApIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Ug Jz0nOg0KICAgICAgICAgICAgICAgICAgICAgICAgICBzc2NhbmYoIHB0cisx LCAiJTAyWCIsICZ2YWx1ZSApOw0KICAgICAgICAgICAgICAgICAgICAgICAg ICAqb3V0cHV0KysgPSB2YWx1ZTsNCiAgICAgICAgICAgICAgICAgICAgICAg ICAgcHRyICs9IDI7DQogICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFr Ow0KICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnXyc6DQogICAgICAg ICAgICAgICAgICAgICAgICAgICpvdXRwdXQrKyA9ICcgJzsNCiAgICAgICAg ICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAg ICAgICBkZWZhdWx0Og0KICAgICAgICAgICAgICAgICAgICAgICAgICAqb3V0 cHV0KysgPSAqcHRyOw0KICAgICAgICAgICAgICAgICAgICAgICAgICBicmVh azsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0N CiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2UgaWYgKCFzdHJjYXNl Y21wKCJiIiwgZW5jb2RpbmcpKSB7DQogICAgICAgICAgICAgICAgLyogYmFz ZTY0IGRlY29kaW5nICovDQogICAgICAgICAgICAgICAgaW50IGxlbmd0aDsN CiAgICAgICAgICAgICAgICBiYXNlNjREZWNvZGUocHRyLCBvdXRwdXQsICZs ZW5ndGgpOw0KICAgICAgICAgICAgICAgIG91dHB1dCArPSBsZW5ndGgtMTsN CiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAg ICAgICAgIC8qIHVuc3VwcG9ydGVkIGVuY29kaW5nIHR5cGUgKi8NCiAgICAg ICAgICAgICAgICBzdHJjcHkob3V0cHV0LCAiPHVua25vd24+Iik7DQogICAg ICAgICAgICAgICAgb3V0cHV0ICs9IDk7DQogICAgICAgICAgICB9DQogIA0K ICAgICAgICAgICAgb2xkcHRyID0gaXB0cjsgLyogc2F2ZSBzdGFydCBwb3Np dGlvbiAqLw0KICANCiAgICAgICAgICAgIHdoaWxlICgqaXB0ciAmJiBpc3Nw YWNlKCppcHRyKSkNCiAgICAgICAgICAgICAgICAgIGlwdHIrKzsgLyogcGFz cyBhbGwgd2hpdGVzcGFjZXMgKi8NCiAgDQogICAgICAgICAgICAvKiBpZiB0 aGlzIGlzIGFuIGVuY29kZWQgd29yZCBoZXJlLCB3ZSBzaG91bGQgc2tpcCB0 aGUgcGFzc2VkDQogICAgICAgICAgICAgICB3aGl0ZXNwYWNlcy4gSWYgaXQg aXNuJ3QgYW4gZW5jb2RlZC13b3JkLCB3ZSBzaG91bGQgaW5jbHVkZSB0aGUN CiAgICAgICAgICAgICAgIHdoaXRlc3BhY2VzIGluIHRoZSBvdXRwdXQuICov DQoNCiAgICAgICAgICAgIGlmICghc3RybmNtcChpcHRyLCAiPT8iLCAyKSAm Jg0KICAgICAgICAgICAgICAgICg0ID09IHNzY2FuZihpcHRyKzIsICIlMTI4 W14/XT8lMzJbXj9dPyUxMjhbXj9dPyVjIiwNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIGNoYXJzZXQsIGVuY29kaW5nLCBibHVyYiwgJmVxdWFs KSkgJiYNCiAgICAgICAgICAgICAgICAoJz0nID09IGVxdWFsKSkgew0KICAg ICAgICAgICAgICAgIGNvbnRpbnVlOyAvKiB0aGlzIElTIGFuIGVuY29kZWQt d29yZCwgY29udGludWUgZnJvbSBoZXJlICovDQogICAgICAgICAgICB9DQog ICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgIC8qIHRoaXMgSVMgTk9U IGFuIGVuY29kZWQtd29yZCwgbW92ZSBiYWNrIHRvIHRoZSBmaXJzdCB3aGl0 ZXNwYWNlICovDQogICAgICAgICAgICAgIGlwdHIgPSBvbGRwdHI7DQogICAg ICAgIH0NCiAgICAgICAgZWxzZQ0KICAgICAgICAgICAgKm91dHB1dCsrID0g KmlwdHIrKzsgICANCiAgICB9DQogICAgKm91dHB1dD0wOw0KICANCiAgICBp ZiAoZGlkYW55dGhpbmcpIHsNCiAgICAgICAgLyogdGhpcyBjaGVjayBwcmV2 ZW50cyB1bm5lY2Nlc3Nhcnkgc3Ryc2F2KCkgY2FsbHMgaWYgbm90IG5lZWRl ZCAqLw0KICAgICAgICBmcmVlKHN0cmluZyk7IC8qIGZyZWUgb2xkIG1lbW9y eSAqLw0KICANCiNpZiAwDQogICAgICAgIC8qIGRlYnVnIGRpc3BsYXkgKi8N CiAgICAgICAgcHJpbnRmKCJORVc6ICVzXG4iLCBzdG9yYWdlKTsNCiAgDQog ICAgICAgIHsgIA0KICAgICAgICAgICAgdW5zaWduZWQgY2hhciAqZjsNCiAg ICAgICAgICAgIHB1dHMoIk5FVzoiKTsNCiAgICAgICAgICAgIGZvciAoZj1z dG9yYWdlOyBmPG91dHB1dDsgZisrKSB7DQogICAgICAgICAgICAgICAgaWYg KGlzZ3JhcGgoKmYpKQ0KICAgICAgICAgICAgICAgICAgIHByaW50ZigiJWMi LCAqZik7DQogICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAg ICAgIHByaW50ZigiJTAyWCIsICh1bnNpZ25lZCBjaGFyKSpmKTsNCiAgICAg ICAgICAgIH0NCiAgICAgICAgICAgIHB1dHMoIiIpOw0KICAgICAgICB9ICAN CiNlbmRpZg0KICAgICAgICByZXR1cm4gc3RvcmFnZTsgLyogcmV0dXJuIG5l dyAqLw0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgIGZyZWUgKHN0b3JhZ2Up Ow0KICAgICAgcmV0dXJuIHN0cmluZzsNCiAgICB9DQp9DQoNCi8qDQoqKiBE ZWNvZGUgdGhpcyBbdmlydHVhbF0gUXVvdGVkLVByaW50YWJsZSBsaW5lIGFz IGRlZmluZWQgYnkgUkZDMjA0NS4NCioqIFdyaXR0ZW4gYnkgRGFuaWVsLlN0 ZW5iZXJnQHN0aC5mcm9udGVjLnNlDQoqLw0KDQpzdGF0aWMgdm9pZCBtZGVj b2RlUVAoRklMRSAqZmlsZSwgY2hhciAqaW5wdXQsIGNoYXIgKipyZXN1bHQs IGludCAqbGVuZ3RoKQ0Kew0KICAgIGludCBvdXRjb3VudD0wOw0KICAgIGNo YXIgKmJ1ZmZlcj1pbnB1dDsNCiAgICB1bnNpZ25lZCBjaGFyIGluY2hhcjsN CiAgICBjaGFyICpvdXRwdXQ7DQoNCiAgICBpbnQgbGVuPXN0cmxlbihpbnB1 dCk7ICANCiAgICBvdXRwdXQ9c3Ryc2F2KGlucHV0KTsNCg0KI2RlZmluZSBR UF9FTkxBUkdFX1NURVAgNTEyDQoNCiAgICB3aGlsZSAoKGluY2hhciA9ICpp bnB1dCkgIT0gJ1wwJykgew0KDQogICAgICAgIGlmIChvdXRjb3VudD49bGVu LTEpIHsNCiAgICAgICAgICAgIC8qIHdlIG5lZWQgdG8gZW5sYXJnZSB0aGUg ZGVzdGluYXRpb24gYXJlYSEgKi8NCiAgICAgICAgICAgIGNoYXIgKm5ld3Ag PSByZWFsbG9jKG91dHB1dCwgbGVuK1FQX0VOTEFSR0VfU1RFUCk7DQogICAg ICAgICAgICBpZiAobmV3cCkgew0KICAgICAgICAgICAgICAgIG91dHB1dCA9 IG5ld3A7DQogICAgICAgICAgICAgICAgbGVuICs9IFFQX0VOTEFSR0VfU1RF UDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2UNCiAgICAgICAg ICAgICAgICBicmVhazsNCiAgICAgICAgfQ0KDQogICAgICAgIGlucHV0Kys7 DQogICAgICAgIGlmICgnPScgPT0gaW5jaGFyKSB7DQogICAgICAgICAgICBp bnQgdmFsdWU7DQogICAgICAgICAgICBpZiAoJ1xuJz09ICppbnB1dCkgew0K ICAgICAgICAgICAgICAgIGlmICghZmdldHMoYnVmZmVyLCBNQVhMSU5FLCBm aWxlKSkNCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAg ICAgICAgaW5wdXQgPSBidWZmZXI7DQogICAgICAgICAgICAgICAgY29udGlu dWU7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlIGlmICgnPScg PT0gKmlucHV0KSB7DQogICAgICAgICAgICAgICAgaW5jaGFyPSc9JzsNCiAg ICAgICAgICAgICAgICBpbnB1dCsrOyAvKiBwYXNzIHRoaXMgKi8NCiAgICAg ICAgICAgIH0NCiAgICAgICAgICAgIGVsc2UgaWYgKGlzeGRpZ2l0KCppbnB1 dCkpIHsNCiAgICAgICAgICAgICAgICBzc2NhbmYoaW5wdXQsICIlMDJYIiwg JnZhbHVlKTsNCiAgICAgICAgICAgICAgICBpbmNoYXIgPSAodW5zaWduZWQg Y2hhcil2YWx1ZTsNCiAgICAgICAgICAgICAgICBpbnB1dCs9MjsgLyogcGFz cyB0aGUgdHdvIGxldHRlcnMgKi8NCiAgICAgICAgICAgIH0NCiAgICAgICAg ICAgIGVsc2UNCiAgICAgICAgICAgICAgICBpbmNoYXI9Jz0nOw0KICAgICAg ICB9DQogICAgICAgIG91dHB1dFtvdXRjb3VudCsrXSA9IGluY2hhcjsNCiAg ICB9DQogICAgb3V0cHV0W291dGNvdW50XT0wOyAvKiB6ZXJvIHRlcm1pbmF0 ZSAqLw0KDQogICAgKnJlc3VsdCA9IG91dHB1dDsNCiAgICAqbGVuZ3RoID0g b3V0Y291bnQ7DQp9DQoNCi8qDQoqKiBQYXJzaW5nLi4udGhlIGhlYXJ0IG9m IEh5cGVybWFpbCENCioqIFRoaXMgbG9hZHMgaW4gdGhlIGFydGljbGVzIGZy b20gc3RkaW4gb3IgYSBtYWlsYm94LCBhZGRpbmcgdGhlIHJpZ2h0DQoqKiBm aWVsZCB2YXJpYWJsZXMgdG8gdGhlIHJpZ2h0IHN0cnVjdHVyZXMuIElmIHJl YWRvbmUgaXMgc2V0LCBpdCB3aWxsDQoqKiB0aGluayBhbnl0aGluZyBpdCBy ZWFkcyBpbiBpcyBvbmUgYXJ0aWNsZSBvbmx5Lg0KKi8NCg0Kdm9pZCBsb2Fk aGVhZGVycyhjaGFyICptYm94LCBpbnQgdXNlX3N0ZGluLCBpbnQgcmVhZG9u ZSwgY2hhciAqZGlyKQ0Kew0KICAgIEZJTEUgKmZwOw0KICAgIGNoYXIgbmFt ZVtOQU1FU1RSTEVOXSwgZW1haWxbTUFJTFNUUkxFTl0sIGRhdGVbREFURVNU UkxFTl0sDQogICAgICAgIG1zZ2lkW01TR0RTVFJMRU5dLCBzdWJqZWN0W1NV QkpTVFJMRU5dLCBpbnJlcGx5W1JFUFlTVFJMRU5dLA0KICAgICAgICBsaW5l W01BWExJTkVdLCB0bXBmcm9tW01BWExJTkVdLCBmcm9tZGF0ZVtEQVRFU1RS TEVOXSwNCiAgICAgICAgb2xkbGluZVtNQVhMSU5FXSwgKmNwOw0KICAgIGlu dCBudW0sIGlzaW5oZWFkZXIsIGhhc3N1YmplY3QsIGhhc2RhdGU7DQojaWYg MA0KICAgIGludCB3YXNpbnJlcGx5Ow0KI2VuZGlmDQoNCiAgICAvKiAtLSB2 YXJpYWJsZXMgZm9yIHRoZSBtdWx0aXBhcnQvYWx0ZXJuYXRpdmUgcGFyc2Vy IC0tICovDQogICAgc3RydWN0IGJvZHkgKm9yaWdicD1OVUxMOyAvKiBzdG9y ZSB0aGUgb3JpZ2luYWwgYnAgKi8NCiAgICBzdHJ1Y3QgYm9keSAqb3JpZ2xw PU5VTEw7IC8qIC4uLiBhbmQgdGhlIG9yaWdpbmFsIGxwICovDQogICAgc3Ry dWN0IGJvZHkgKmZpcnN0YnA9TlVMTDsgLyogdXNlIHRoaXMgZm9yIHRoZSBm aXJzdCBwYXJ0ICovDQogICAgY2hhciBhbHRlcm5hdGl2ZXBhcnNlcj1GQUxT RTsgLyogc2V0IHdoZW4gaW5zaWRlIGFsdGVybmF0aXZlIHBhcnNlcg0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGUgKi8NCg0K ICAgIC8qIC0tIGVuZCBvZiBhbHRlcm5hdGl2ZSBwYXJzZXIgdmFyaWFibGVz IC0tICovDQoNCiAgICBzdHJ1Y3QgYm9keSAqYnA7DQogICAgc3RydWN0IGJv ZHkgKmxwPU5VTEw7IC8qIHRoZSBsYXN0IHBvaW50ZXIsIHBvaW50cyB0byB0 aGUgbGFzdCBub2RlIGluIHRoZQ0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBib2R5IGxpc3QuIEluaXRpYWxseSBzZXQgdG8gTlVMTCBzaW5jZSB3 ZSBoYXZlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbmUgYXQg dGhlIG1vbWVudC4gKi8NCg0KICAgIHN0cnVjdCBib2R5ICpoZWFkcD1OVUxM OyAvKiBzdG9yZWQgcG9pbnRlciB0byB0aGUgcG9pbnQgd2hlcmUgd2UgbGFz dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FubmVkIHRo ZSBoZWFkZXJzIG9mIHRoaXMgbWFpbC4gKi8NCg0KICAgIGNoYXIgTWltZV9C ID0gRkFMU0U7DQoNCiAgICBjaGFyIGJvdW5kYnVmZmVyWzEyOF09IiI7DQoN CiAgICAvKiBUaGlzIHZhcmlhYmxlIGlzIHVzZWQgdG8gc3RvcmUgYSBzdGFj ayBvZiBib3VuZGFyeSBzZXBhcmF0b3JzIGluIGNhc2VzDQogICAgICAgd2l0 aCBtaW1lZCBtYWlscyBpbnNpZGUgbWltZWQgbWFpbHMgKi8NCiAgICBzdHJ1 Y3QgYm91bmRhcnkgKmJvdW5kcD1OVUxMOw0KDQogICAgLyogVGhpcyB2YXJp YWJsZSBpcyBzZXQgVFJVRSBpZiB3ZSBoYXZlIHJlYWQgYSBwYXJ0aWFsIGxp bmUgb2ZmIGENCiAgICAgICBtdWx0aWxpbmUtZW5jb2RlZCBsaW5lLCBhbmQg dGhlIG5leHQgbGluZSB3ZSByZWFkIGlzIHN1cHBvc2VkIHRvIGdldA0KICAg ICAgIGFwcGVuZGVkIHRvIHRoZSBwcmV2aW91cyBvbmUgKi8NCiAgICBjaGFy IG11bHRpbGluZW5vZW5kPUZBTFNFOw0KDQogICAgLyogVGhpcyB2YXJpYWJs ZSBpcyBzZXQgdG8gZXh0cmEgZmxhZ3MgdGhhdCB0aGUgYWRkYm9keSgpIGNh bGxzIHNob3VsZCBPUg0KICAgICAgIGluIHRoZSBmbGFnIHBhcmFtZXRlciAq Lw0KICAgIGludCBib2R5ZmxhZ3M9MDsNCg0KICAgIGNoYXIgKmJpbm5hbWU9 TlVMTDsgLyogZmlsZSBuYW1lIHRvIHN0b3JlIGJpbmFyeSBhdHRhY2htZW50 cyBpbiAqLw0KICAgIGludCBiaW5maWxlPS0xOw0KDQogICAgRW5jb2RlVHlw ZSBkZWNvZGU9RU5DT0RFX05PUk1BTDsNCiAgICBDb250ZW50VHlwZSBjb250 ZW50PUNPTlRFTlRfVEVYVDsNCiAgDQogICAgaWYgKCFzdHJjYXNlY21wKG1i b3gsICJOT05FIikgfHwgdXNlX3N0ZGluKQ0KICAgICAgICBmcCA9IHN0ZGlu Ow0KICAgIGVsc2Ugew0KICAgICAgICBpZiAoKGZwID0gZm9wZW4obWJveCwg InIiKSkgPT0gTlVMTCkgew0KICAgICAgICAgICAgc3ByaW50ZihlcnJtc2cs ICJDb3VsZG4ndCBvcGVuIG1haWwgYXJjaGl2ZSBcIiVzXCIuIiwgbWJveCk7 DQogICAgICAgICAgICBwcm9nZXJyKE5VTEwpOw0KICAgICAgICB9DQogICAg fQ0KICANCiAgICBpZiAocmVhZG9uZSkNCiAgICAgICAgbnVtID0gYmlnbnVt Ow0KICAgIGVsc2UNCiAgICAgICAgbnVtID0gMDsNCg0KICAgIGhhc3N1Ympl Y3QgPSAwOw0KICAgIGhhc2RhdGUgPSAwOw0KI2lmIDANCiAgICB3YXNpbnJl cGx5ID0gMDsNCiNlbmRpZg0KICAgIGlzaW5oZWFkZXIgPSAxOw0KICAgIHN0 cmNweShzdWJqZWN0LCBOT1NVQkpFQ1QpOw0KICAgIGlucmVwbHlbMF0gPSAn XDAnOw0KICAgIHRtcGZyb21bMF0gPSAnXDAnOw0KICAgIG9sZGxpbmVbMF0g PSAnXDAnOw0KICAgIG1zZ2lkWzBdID0gJ1wwJzsNCiAgICBicCA9IE5VTEw7 DQoNCiAgICBpZiAoIXJlYWRvbmUpIHsNCiAgICAgICAgcmVwbHlsaXN0ID0g TlVMTDsNCiAgICAgICAgc3ViamVjdGxpc3QgPSBOVUxMOw0KICAgICAgICBh dXRob3JsaXN0ID0gTlVMTDsNCiAgICAgICAgZGF0ZWxpc3QgPSBOVUxMOw0K ICAgIH0NCg0KICAgIGlmIChzaG93cHJvZ3Jlc3MgJiYgcmVhZG9uZSkNCiAg ICAgICAgcHJpbnRmKCJSZWFkaW5nIG5ldyBoZWFkZXIuLi5cbiIpOw0KDQog ICAgaWYgKHNob3dwcm9ncmVzcyAmJiAhcmVhZG9uZSkgew0KICAgICAgICBp ZiAoIXN0cmNhc2VjbXAobWJveCwgIk5PTkUiKSB8fCB1c2Vfc3RkaW4pDQog ICAgICAgICAgICBwcmludGYoIkxvYWRpbmcgbWFpbGJveC4uLiAgICAiKTsN CiAgICAgICAgZWxzZQ0KICAgICAgICAgICAgcHJpbnRmKCJMb2FkaW5nIG1h aWxib3ggXCIlc1wiLi4uICAgICIsIG1ib3gpOw0KICAgIH0NCiAgICB3aGls ZSAoZmdldHMobGluZSwgTUFYTElORSwgZnApICE9IE5VTEwpIHsNCiAgICAg ICAgaWYgKGlzaW5oZWFkZXIpIHsNCiAgICAgICAgICAgIGlmICghc3RybmNh c2VjbXAobGluZSwgIkZyb20gIiwgNSkpDQogICAgICAgICAgICAgICAgc3Ry Y3B5bWF4KGZyb21kYXRlLCAoY2hhciAqKSBnZXRmcm9tZGF0ZShsaW5lKSwg REFURVNUUkxFTik7DQogICAgICAgICAgICAvKiBjaGVjayBmb3IgTUlNRSAq Lw0KICAgICAgICAgICAgZWxzZSBpZiAoIXN0cm5jYXNlY21wKCBsaW5lLCAi TUlNRS1WZXJzaW9uOiIsIDEzKSkNCiAgICAgICAgICAgICAgICBNaW1lX0Ig PSBUUlVFOw0KI2lmIDANCi8qIERhbmllbCdzIG5vdGU6IGp1c3QgKndoYXQq IGlzIHRoaXMgaGFjayBkb2luZz8gKi8NCi8qIEtlbnQncyBub3RlOiBTYWQg YXR0ZW1wdCBhdCBkZXRlcm1pbmcgYSBjb250aW51YXRpb24gbGluZSA/ICov DQogICAgICAgICAgICBlbHNlIGlmICgoIXN0cm5jbXAobGluZSwgIiAgICAi LCA0KSB8fCBsaW5lWzBdID09ICdcdCcpICYmDQogICAgICAgICAgICAgICAg c3RyY2hyKGxpbmUsICc8JykgJiYgc3RyY2hyKGxpbmUsICc+JykgJiYNCiAg ICAgICAgICAgICAgICBzdHJjaHIobGluZSwgJ0AnKSAmJiB3YXNpbnJlcGx5 KSB7DQogICAgICAgICAgICAgICAgYnAgPSAoc3RydWN0IGJvZHkgKikgYWRk Ym9keShicCwgJmxwLCBsaW5lLCAwKTsNCiAgICAgICAgICAgICAgICBzdHJj cHltYXgoaW5yZXBseSwgKGNoYXIgKikgZ2V0cmVwbHkobGluZSksIFJFUFlT VFJMRU4pOw0KICAgICAgICAgICAgICAgIHdhc2lucmVwbHkgPSAwOw0KICAg ICAgICAgICAgfQ0KI2VuZGlmDQogICAgICAgICAgICBlbHNlIGlmIChpc3Nw YWNlKGxpbmVbMF0pICYmICgnXG4nICE9IGxpbmVbMF0pICkgew0KICAgICAg ICAgICAgICAgIC8qDQogICAgICAgICAgICAgICAgKiogc2luY2UgdGhpcyBi ZWdpbnMgd2l0aCBhIHdoaXRlc3BhY2UsIGl0IG1lYW5zIHRoZSANCiAgICAg ICAgICAgICAgICAqKiBwcmV2aW91cyBsaW5lIGlzIGNvbnRpbnVlZCBvbiB0 aGlzIGxpbmUsIGxlYXZlIG9ubHkgDQogICAgICAgICAgICAgICAgKiogb25l IHNwYWNlIGNoYXJhY3RlciBhbmQgZ28hIA0KICAgICAgICAgICAgICAgICov DQogICAgICAgICAgICAgICAgY2hhciAqcHRyPWxpbmU7DQogICAgICAgICAg ICAgICAgd2hpbGUgKGlzc3BhY2UoKnB0cikpDQogICAgICAgICAgICAgICAg ICAgICBwdHIrKzsNCiAgICAgICAgICAgICAgICBwdHItLTsgLyogbGVhdmUg b25lIHNwYWNlICovDQogICAgICAgICAgICAgICAgKnB0cj0nICc7IC8qIG1h a2UgaXQgYSB0cnVlIHNwYWNlLCBubyB0YWJzIGhlcmUhICovDQojaWYgMA0K ICAgICAgICAgICAgICAgIGRlY29kZVJGQzIwNDcocHRyKzEsIE1BWExJTkUt KHB0cisyLWxpbmUpKTsNCiNlbmRpZg0KICAgICAgICAgICAgICAgIGJwID0g KHN0cnVjdCBib2R5ICopIGFkZGJvZHkoYnAsICZscCwgcHRyLA0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk9EWV9DT05USU5V RXxCT0RZX0hFQURFUnxib2R5ZmxhZ3MpOw0KICAgICAgICAgICAgfQ0KICAN CiAgICAgICAgICAgIGVsc2UgaWYgKGxpbmVbMF0gPT0gJ1xuJykgew0KICAg ICAgICAgICAgICAgIHN0cnVjdCBib2R5ICpoZWFkOw0KDQogICAgICAgICAg ICAgICAgY2hhciBzYXZlYWx0ZXJuYXRpdmU7DQoNCiAgICAgICAgICAgICAg ICAvKiANCiAgICAgICAgICAgICAgICAqKiB3ZSBtYXJrIHRoaXMgYXMgYSBo ZWFkZXItbGluZSwgYW5kIHdlIHVzZSBpdCB0byANCiAgICAgICAgICAgICAg ICAqKiB0cmFjayBlbmQtb2YtaGVhZGVyIGRpc3BsYXlzIA0KICAgICAgICAg ICAgICAgICovDQogICAgICAgICAgICAgICAgYnAgPSAoc3RydWN0IGJvZHkg KikgYWRkYm9keShicCwgJmxwLCBsaW5lLCANCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgQk9EWV9IRUFERVJ8Ym9keWZsYWdzKTsN CiAgICAgICAgICAgICAgICBpc2luaGVhZGVyLS07DQoNCiAgICAgICAgICAg ICAgICAvKg0KICAgICAgICAgICAgICAgICoqIFRoaXMgc2lnbmFscyB1cyB0 aGF0IHdlIGFyZSBubyBsb25nZXIgaW4gdGhlIGhlYWRlciwgDQogICAgICAg ICAgICAgICAgKiogbGV0J3MgZmlsbCBpbiBhbGwgdGhvc2UgZmllbGRzIHdl IGFyZSBpbnRlcmVzdGVkIGluLiANCiAgICAgICAgICAgICAgICAqKiBQYXJz ZSB0aGUgaGVhZGVycyB1cCB0byBub3cgYW5kIGNvcHkgdG8gdGhlIHRhcmdl dCANCiAgICAgICAgICAgICAgICAqKiB2YXJpYWJsZXMgDQogICAgICAgICAg ICAgICAgKi8NCiAgDQogICAgICAgICAgICAgICAgZm9yIChoZWFkID0gYnA7 IGhlYWQ7IGhlYWQ9aGVhZC0+bmV4dCkgew0KICAgICAgICAgICAgICAgICAg ICBpZiAoaGVhZC0+aGVhZGVyICYmICFoZWFkLT5kZW1pbWVkICYmIE1pbWVf Qikgew0KICAgICAgICAgICAgICAgICAgICAgICBoZWFkLT5saW5lID0gbWRl Y29kZVJGQzIwNDcoaGVhZC0+bGluZSwNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmxlbihoZWFkLT5s aW5lKSk7DQogICAgICAgICAgICAgICAgICAgICAgIGhlYWQtPmRlbWltZWQ9 VFJVRTsgLyogZG9uJ3QgZG8gdGhpcyBhZ2FpbiAqLw0KICAgICAgICAgICAg ICAgICAgICB9DQogIA0KICAgICAgICAgICAgICAgICAgICBpZiAoaGVhZC0+ YXR0YWNoZWQpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7 DQogICAgICAgICAgICAgICAgICAgIH0NCiAgDQogICAgICAgICAgICAgICAg ICAgIGlmICghc3RybmNhc2VjbXAoaGVhZC0+bGluZSwgIkRhdGU6IiwgNSkp IHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmNweW1heChkYXRlLCAo Y2hhciAqKWdldG1haWxkYXRlKGhlYWQtPmxpbmUpLCANCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIERBVEVTVFJMRU4pOw0KICAgICAg ICAgICAgICAgICAgICAgICAgaGFzZGF0ZSA9IDE7DQogICAgICAgICAgICAg ICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIXN0cm5j YXNlY21wKGhlYWQtPmxpbmUsICJGcm9tOiIsIDUpKSB7DQogICAgICAgICAg ICAgICAgICAgICAgICBnZXRuYW1lKGhlYWQtPmxpbmUsIG5hbWUsIGVtYWls KTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAg ICBlbHNlIGlmICghc3RybmNhc2VjbXAoaGVhZC0+bGluZSwgIk1lc3NhZ2Ut SWQ6IiwgMTEpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICBzdHJjcHlt YXgobXNnaWQsKGNoYXIgKilnZXRpZChoZWFkLT5saW5lKSxNU0dEU1RSTEVO KTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAg ICBlbHNlIGlmICghc3RybmNhc2VjbXAoaGVhZC0+bGluZSwgIlN1YmplY3Q6 IiwgOCkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmNweW1heChz dWJqZWN0LChjaGFyICopZ2V0c3ViamVjdChoZWFkLT5saW5lKSwgDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1VCSlNUUkxFTik7DQog ICAgICAgICAgICAgICAgICAgICAgICBoYXNzdWJqZWN0ID0gMTsNCiAgICAg ICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICBlbHNlIGlm ICghc3RybmNhc2VjbXAoaGVhZC0+bGluZSwgIkluLVJlcGx5LVRvOiIsIDEy KSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgc3RyY3B5bWF4KGlucmVw bHksKGNoYXIgKilnZXRyZXBseShoZWFkLT5saW5lKSwgDQogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgUkVQWVNUUkxFTik7DQogICAgICAg ICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAo IXN0cm5jYXNlY21wKGhlYWQtPmxpbmUsICJSZWZlcmVuY2VzOiIsIDExKSkg ew0KICAgICAgICAgICAgICAgICAgICAgICAgLyoNCiAgICAgICAgICAgICAg ICAgICAgICAgICoqIEFkZGluZyB0aHJlYWRpbmcgY2FwYWJpbGl0eSBmb3Ig dGhlICJSZWZlcmVuY2VzIiANCiAgICAgICAgICAgICAgICAgICAgICAgICoq IGhlYWRlciwgYWxhIFJGQyA4MjIsIHVzZWQgb25seSBmb3IgbWVzc2FnZXMg dGhhdCANCiAgICAgICAgICAgICAgICAgICAgICAgICoqIGhhdmUgIlJlZmVy ZW5jZXMiIGJ1dCBkbyBub3QgaGF2ZSBhbiAiSW4tcmVwbHktdG8iDQogICAg ICAgICAgICAgICAgICAgICAgICAqKiBmaWVsZC4gVGhpcyBpcyBwYXJ0aWNh bGx5IGEgY29uY2Vzc2lvbiBmb3IgTmV0c2NhcGUncw0KICAgICAgICAgICAg ICAgICAgICAgICAgKiogZW1haWwgY29tcG9zZXIsIHdoaWNoIGVycm9uZW91 c2x5IHVzZXMgIlJlZmVyZW5jZXMiICAgICAgICAgICAgICAgICAgICAgICAg ICoqIHdoZW4gaXQgc2hvdWxkIHVzZSAiSW4tcmVwbHktdG8iLiANCiAgICAg ICAgICAgICAgICAgICAgICAgICovDQogICAgICAgICAgICAgICAgICAgICAg ICBpZiAoISppbnJlcGx5KQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAg IHN0cmNweW1heChpbnJlcGx5LChjaGFyICopZ2V0aWQoaGVhZC0+bGluZSks IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSRVBZ U1RSTEVOKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg ICAgIH0NCg0KICAgICAgICAgICAgICAgIGlmICghaGVhZHApDQogICAgICAg ICAgICAgICAgICAgIGhlYWRwPWJwOw0KDQogICAgICAgICAgICAgICAgc2F2 ZWFsdGVybmF0aXZlID0gRkFMU0U7DQogICAgICAgICAgICAgICAgDQogICAg ICAgICAgICAgICAgZm9yIChoZWFkID0gaGVhZHA7IGhlYWQ7IGhlYWQ9aGVh ZC0+bmV4dCkgew0KICAgICAgICAgICAgICAgICAgICBpZiAoIXN0cm5jYXNl Y21wKCBoZWFkLT5saW5lLCAiQ29udGVudC1UeXBlOiIsIDEzKSkgew0KICAg ICAgICAgICAgICAgICAgICAgICBjaGFyICpwdHI9aGVhZC0+bGluZSsxMzsN CiAgICAgICAgICAgICAgICAgICAgICAgY2hhciAqYm91bmRhcnk7DQogICAg ICAgICAgICAgICAgICAgICAgIGNoYXIgdHlwZVsxMjldOw0KI2RlZmluZSBE SVNQX0hSRUYgMQ0KI2RlZmluZSBESVNQX0lNRyAgMg0KI2RlZmluZSBESVNQ X0lHTk9SRSAzDQogICAgICAgICAgICAgICAgICAgICAgIC8qIGRlZmF1bHQg aXMgaHJlZiB0byB0aGUgYXR0YWNobWVudDogKi8NCiAgICAgICAgICAgICAg ICAgICAgICAgY2hhciBkaXNwb3NpdGlvbj1ESVNQX0hSRUY7DQoNCiAgICAg ICAgICAgICAgICAgICAgICAgd2hpbGUgKGlzc3BhY2UoKnB0cikpDQogICAg ICAgICAgICAgICAgICAgICAgICAgICBwdHIrKzsNCg0KICAgICAgICAgICAg ICAgICAgICAgICBzc2NhbmYocHRyLCAiJTEyOFteO10iLCB0eXBlKTsNCiAg ICAgICAgICAgICAgICAgICAgICAgaWYgKChjcCA9IHN0cmNocih0eXBlLCAn XG4nKSkgIT0gTlVMTCkgDQogICAgICAgICAgICAgICAgICAgICAgICAgKmNw ID0gJ1wwJzsgLyogcm0gbmV3bGluZXMgKi8NCg0KICAgICAgICAgICAgICAg ICAgICAgICBpZihhbHRlcm5hdGl2ZXBhcnNlcikgew0KICAgICAgICAgICAg ICAgICAgICAgICAgIC8qIFdlIGFyZSBwYXJzaW5nIGFsdGVybmF0aXZlcy4u LiAqLw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgaWYocHJlZmVyZWRj b250ZW50KHR5cGUpICkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAg LyogLi4uIHRoaXMgaXMgYSBwcmVmZXJlZCB0eXBlLCB3ZSB3YW50IHRvIHN0 b3JlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzIFtpbnN0 ZWFkIG9mIHRoZSBlYXJsaWVyIG9uZV0uICovDQogICAgICAgICAgICAgICAg ICAgICAgICAgICBzdHJ1Y3QgYm9keSAqbmV4dDsNCiNpZiAwDQogICAgICAg ICAgICAgICAgICAgICAgICAgICBwcmludGYoIiVzIGlzIG1vcmUgZnVuIHRo YW4gdGhlIHByZXZpb3VzIG9uZVxuIiwNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICB0eXBlKTsNCiNlbmRpZg0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgd2hpbGUoYnApIHsNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgbmV4dD1icC0+bmV4dDsNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgZnJlZShicC0+bGluZSk7DQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgIGZyZWUoYnApOw0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBicD1uZXh0Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZHAgPSBOVUxMOw0KICAg ICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAg ICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIC4u LmFuZCB0aGlzIHR5cGUgaXMgbm90IGEgcHJlZmVyZWQgb25lLiBUaHVzLCB3 ZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICogc2hhbGwgaWdub3Jl IGl0IGNvbXBsZXRlbHkhICovDQogICAgICAgICAgICAgICAgICAgICAgICAg ICBkaXNwb3NpdGlvbiA9IERJU1BfSUdOT1JFOw0KICAgICAgICAgICAgICAg ICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAg ICAgICAgICAgICAgICAgICBpZiggKERJU1BfSUdOT1JFPT1kaXNwb3NpdGlv bikgfHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZWNvbnRl bnQodHlwZSkgKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgLyogZG9u J3Qgc2F2ZSB0aGlzICovDQogICAgICAgICAgICAgICAgICAgICAgICAgZGlz cG9zaXRpb24gPSBESVNQX0lHTk9SRTsNCiAgICAgICAgICAgICAgICAgICAg ICAgICBjb250ZW50ID0gQ09OVEVOVF9JR05PUkU7DQogICAgICAgICAgICAg ICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAo IXN0cm5jYXNlY21wKHR5cGUsICJ0ZXh0IiwgNCkpIHsNCiAgICAgICAgICAg ICAgICAgICAgICAgICAvKiANCiAgICAgICAgICAgICAgICAgICAgICAgICAg KiogdGV4dCBmb2xsb3dzLCBpZ25vcmUgdGhpcyANCiAgICAgICAgICAgICAg ICAgICAgICAgICAgKi8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgLyog ZGVmYXVsdCBpcyBqdXN0IHBsYWluIDcvOCBiaXQgKi8NCiAgICAgICAgICAg ICAgICAgICAgICAgICAgZGVjb2RlID0gRU5DT0RFX05PUk1BTDsNCg0KICAg ICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXN0cm5jYXNlY21wKCZ0eXBl WzRdLCAiL2h0bWwiLCA1KSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIGNvbnRlbnQgPSBDT05URU5UX0hUTUw7DQogICAgICAgICAgICAgICAg ICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IGNvbnRlbnQgPSBDT05URU5UX1RFWFQ7DQogICAgICAgICAgICAgICAgICAg ICAgICAgIGNvbnRpbnVlOw0KICAgICAgICAgICAgICAgICAgICAgICB9DQog ICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFzdHJuY2FzZWNtcCh0 eXBlLCAibWVzc2FnZS9yZmM4MjIiLCAxNCkpIHsNCiAgICAgICAgICAgICAg ICAgICAgICAgICAgIC8qIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAg KiogSGVyZSBjb21lcyBhbiBhdHRhY2hlZCBtYWlsISBUaGlzIGNhbiBiZSB1 Z2x5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICoqIHNpbmNlIHRo ZSBhdHRhY2hlZCBtYWlsIG1heSB2ZXJ5IHdlbGwgaXRzZWxmIA0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgKiogY29udGFpbiBhdHRhY2hlZCBiaW5h cmllcywgb3Igd2h5IG5vdCBhbm90aGVyIA0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgKiogYXR0YWNoZWQgbWFpbD8gOi0pDQogICAgICAgICAgICAg ICAgICAgICAgICAgICAqKg0KICAgICAgICAgICAgICAgICAgICAgICAgICAg KiogV2UgbmVlZCB0byBzdG9yZSB0aGUgY3VycmVudCBib3VuZGFyeSBzZXBh cmF0b3IgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAqKiBpbiBvcmRl ciB0byBnZXQgaXQgYmFjayB3aGVuIHdlJ3JlIGRvbmUgcGFyc2luZyANCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICoqIHRoaXMgcGFydGljdWxhciBt YWlsLCBzaW5jZSBlYWNoIGF0dGFjaGVkIG1haWwgDQogICAgICAgICAgICAg ICAgICAgICAgICAgICAqKiB3aWxsIGhhdmUgaXRzIG93biBib3VuZGFyeSBz ZXBhcmF0b3IgdGhhdCAqbWlnaHQqICAgICAgICAgICAgICAgICAgICAgICAg ICAgKiogYmUgdXNlZC4gIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAg Ki8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJwID0gKHN0cnVjdCBi b2R5ICopIGFkZGJvZHkoYnAsICZscCwNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAiPFA+PFNUUk9ORz5hdHRhY2hlZCBtYWlsIGZvbGxvd3M6 PC9TVFJPTkc+PEhSPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgQk9EWV9IVE1MSVpFRCB8IGJvZHlmbGFncyk7DQogICAgICAgICAgICAg ICAgICAgICAgICAgICBib2R5ZmxhZ3MgfD0gQk9EWV9BVFRBQ0hFRDsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgIGlzaW5oZWFkZXIgPSAyOw0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7DQogICAgICAgICAg ICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBp ZiAoc3RybmNhc2VjbXAodHlwZSwgIm11bHRpcGFydC8iLCAxMCkpIHsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgIC8qIA0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgKiogVGhpcyBpcyBub3QgYSBtdWx0aXBhcnQgYW5kIG5v dCB0ZXh0IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgKi8NCiAgICAg ICAgICAgICAgICAgICAgICAgICAgIGNoYXIgYXR0YWNobmFtZVsxMjldOw0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhciBjaGVja3BhdGhbMjU2 XTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXIgKm5hbWU7DQog ICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFyICpmaWxlID0gTlVMTDsN CiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXIgbmFtZWlzdW5pcT1G QUxTRTsNCiAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0g KGNoYXIgKilzdHJzdHIocHRyLCAibmFtZT0iKTsNCiAgICAgICAgICAgICAg ICAgICAgICAgICAgIGlmIChuYW1lKSB7DQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgc3NjYW5mKG5hbWUrNiwgIiUxMjhbXlwiXSIsIGF0dGFj aG5hbWUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUg PSBhdHRhY2huYW1lOw0KDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgLyogQ2hlY2sgaWYgd2UgY2FuIHVzZSB0aGlzIGF0dGFjaGVkIG5hbWUg Zm9yDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Rvcmlu ZzogKi8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihzdHJs ZW4obmFtZSkgKyBzdHJsZW4oZGlyKSA8PSAyNTQpIHsNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIC8qIHllcywgd2UgaGF2ZSByb29tIGlu IG91ciBhcnJheSAqLw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgc3RydWN0IHN0YXQgZmlsZWluZm87DQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBjaGFyIGFsdGVyWzJdPSIiOw0KICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgaW50IGNvdW50ZXI9J2EnOw0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZWlzdW5pcT1UUlVFOw0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8gew0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKGNoZWNrcGF0 aCwgIiVzLyVzJXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIGRpciwgYWx0ZXIsIG5hbWUpOw0KICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAvKiBsb29wIHdoaWxlIHRoZSBmaWxl IGV4aXN0IGFuZCB0cnkgYSBmZXcNCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgYWx0ZXJuYXRpdmUgZmlsZSBuYW1lcyBiZWZvcmUg Z2l2aW5nIHVwICovDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIGlmKGNvdW50ZXI+PSd6Jykgew0KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIC8qIHdlIGRpZG4ndCBmaW5kIGEgdW5pcXVlIGZp bGUgbmFtZSAqLw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIG5hbWVpc3VuaXE9RkFMU0U7DQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgc3ByaW50ZihhbHRlciwgIiVjIiwgY291bnRlcisrKTsNCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gd2hpbGUoMCA9PSBsc3Rh dChjaGVja3BhdGgsICZmaWxlaW5mbykpOw0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KDQoNCiAgICAg ICAgICAgICAgICAgICAgICAgICAgIGlmKERJU1BfSUdOT1JFICE9IGRpc3Bv c2l0aW9uKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIA0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKiBTYXZpbmcgb2YgdGhl IGF0dGFjaG1lbnRzIGlzIGJlaW5nIGRvbmUgaW5saW5lICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgKiogYXMgdGhleSBhcmUgZW5jb3VudGVyZWQu IFRoZSBkaXJlY3RvcmllcyBtdXN0IA0KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAqKiBleGlzdCBmaXJzdC4uLg0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAqLw0KICANCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgaWYoIW5hbWVpc3VuaXEpDQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgLyogZ2V0IGEgcmFuZG9tIG5hbWUgKi8NCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICBiaW5uYW1lID0gdG1wbmFtZShkaXIsICJiaW4i KTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQ0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGJpbm5hbWUgPSBjaGVja3BhdGg7 DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJpbm5hbWUp IHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaW5maWxlPW9w ZW4oYmlubmFtZSwgT19XUk9OTFl8T19DUkVBVCwgZmlsZW1vZGUpOw0KDQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoLTEgIT0gYmluZmls ZSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2htb2Qo YmlubmFtZSwgZmlsZW1vZGUpOw0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgaWYoc2hvd3Byb2dyZXNzKQ0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICBwcmludGYoIlxuQ3JlYXRlZCBmaWxlICVzIHdp dGggbW9kZSAlb1xuIiwgYmlubmFtZSwgZmlsZW1vZGUpOw0KICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIH0NCg0KI2lmIDENCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICBmaWxlPShjaGFyICopc3RycmNocihiaW5u YW1lLCBQQVRIX1NFUEFSQVRPUik7DQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgaWYgKGZpbGUpDQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICBmaWxlKys7IC8qIHBhc3MgdGhlIHNlcGFyYXRvciAqLw0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIGZpbGU9YmlubmFtZTsNCiNlbHNlDQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZSA9YmlubmFtZTsN CiNlbmRpZg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCBpbmxpbmVjb250ZW50KHR5 cGUpICkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIGlm IHdlIGtub3cgb3VyIGJyb3dzZXJzIGNhbiBzaG93IHRoaXMNCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlIG9mIGNvbnRleHQgYXMt aXMsIHdlIG1ha2UgYSA8aW1nPiB0YWcNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBpbnN0ZWFkIG9mIDxhIGhyZWY+ISAqLw0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3Bvc2l0aW9uID0gRElTUF9J TUc7DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRm KGxpbmUsICIlczxJTUcgU1JDPVwiJXNcIiBBTFQ9XCIlc1wiPiIsDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2hvd2hyID8g IjxIUj5cbiIgOiAiIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBmaWxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgbmFtZSA/IG5hbWUgOiAicGljdHVyZSIpOw0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIHNwcmludGYobGluZSwgIiVzPFVMPlxuPExJPiVzIGF0dGFjaG1lbnQ6 IDxBIEhSRUY9XCIlc1wiPiVzPC9BPlxuPC9VTD5cbiIsDQogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2hvd2hyID8gIjxIUj5c biIgOiAiIiksIHR5cGUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgZmlsZSA/IGZpbGUgOiAiPHZvaWQ+IiwgDQogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID8gbmFtZSA6 ICJzdG9yZWQiKTsNCiAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg IH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnAgPSAoc3RydWN0 IGJvZHkgKikgYWRkYm9keShicCwgJmxwLCBsaW5lLA0KICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IEJPRFlfSFRNTElaRUR8Ym9keWZsYWdzKTsNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgc3ByaW50ZihhdHRhY2huYW1lLCAiPCEtLSBhdHRhY2ht ZW50PVwiJS44MHNcIiAtLT5cbiIsDQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgZmlsZSk7DQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgIGJwID0gKHN0cnVjdCBib2R5ICopIGFkZGJvZHkoYnAsICZscCwg YXR0YWNobmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBCT0RZX0hUTUxJWkVEfGJvZHlm bGFncyk7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgfQ0KICANCiAgICAgICAgICAgICAgICAg ICAgICAgICAgIGlmKERJU1BfSUdOT1JFID09IGRpc3Bvc2l0aW9uKSB7DQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBDT05URU5U X0lHTk9SRTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAg ICAgICAgICAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBpZiAoYmlubmFtZSAmJiAoYmluZmlsZSE9LTEpKQ0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBDT05U RU5UX0JJTkFSWTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxz ZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBD T05URU5UX1VOS05PV047DQogICAgICAgICAgICAgICAgICAgICAgICAgICB9 DQogICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5hbWVpc3VuaXEg JiYgYmlubmFtZSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJl ZShiaW5uYW1lKTsNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgY29udGludWU7DQogICAgICAgICAgICAgICAgICAgICAgIH0N CiAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAg ICAgICAgICAgICAgLyoNCiAgICAgICAgICAgICAgICAgICAgICAgICAqKiBG aW5kIHRoZSBmaXJzdCBib3VuZGFyeSBzZXBhcmF0b3IgDQogICAgICAgICAg ICAgICAgICAgICAgICAgKi8NCiAgICAgICAgICAgDQogICAgICAgICAgICAg ICAgICAgICAgICAgYm91bmRhcnk9c3RyY2FzZXN0cihwdHIsICJib3VuZGFy eT0iKTsNCiAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAg ICAgaWYgKGJvdW5kYXJ5KSB7DQogICAgICAgICAgICAgICAgICAgICAgICAg ICBib3VuZGFyeT0oY2hhciAqKXN0cmNocihib3VuZGFyeSwgJz0nKTsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChib3VuZGFyeSkgew0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBib3VuZGFyeSsrOw0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaXNzcGFjZSgqYm91bmRh cnkpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kYXJ5 Kys7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnXCInID09 ICpib3VuZGFyeSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IHNzY2FuZigrK2JvdW5kYXJ5LCAiJVteXCJdIiwgYm91bmRidWZmZXIpOw0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgc3NjYW5mKGJvdW5kYXJ5LCAiJXMiLCBib3VuZGJ1ZmZl cik7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kYXJ5ID0g Ym91bmRidWZmZXI7DQogICAgICAgICAgICAgICAgICAgICAgICAgICB9DQog ICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAg ICAgICAgICAgIHdoaWxlIChmZ2V0cyhsaW5lLCBNQVhMSU5FLCBmcCkpIHsN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzdHJuY21wKGxp bmUsICItLSIsIDIpICYmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAhc3RybmNtcChsaW5lKzIsIGJvdW5kYnVmZmVyLCANCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmxlbihib3Vu ZGJ1ZmZlcikpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg YnJlYWs7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAg ICAgICAgICAgICAgICAgICAgICAgIH0NCiAgDQogICAgICAgICAgICAgICAg ICAgICAgICAgICAvKiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICoq IFRoaXMgc3RvcmVzIHRoZSBib3VuZGFyeSBzdHJpbmcgaW4gYSBzdGFjayAN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICoqIG9mIHN0cmluZ3M6IA0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgKi8NCiAgICAgICAgICAgICAg ICAgICAgICAgICAgIGJvdW5kcCA9IGJvdW5kKGJvdW5kcCwgYm91bmRidWZm ZXIpOw0KICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIHByaW50 Zigic2V0IG5ldyBib3VuZGFyeTogJXNcbiIsIGJvdW5kcC0+bGluZSk7ICov DQogIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgLyoNCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICoqIFdlIHNldCBvdXJzZWx2ZXMsICJiYWNr IGluIGhlYWRlciIgc2luY2UgdGhlcmUgaXMgICAgICAgICAgICAgICAgICAg ICAgICAgICAqKiBnb25uYSBjb21lIE1JTUUgaGVhZGVycyBub3cgYWZ0ZXIg dGhlIHNlcGFyYXRvcg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgKi8N CiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzaW5oZWFkZXIgPSAxOw0K DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIERhbmllbCBTdGVu YmVyZyBzdGFydGVkIGFkZGluZyB0aGUNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAqICJtdWx0aXBhcnQvYWx0ZXJuYXRpdmUiIHBhcnNlciAxM3Ro IG9mIEp1bHkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIDE5OTgh ICBXZSBjaGVjayBpZiB0aGlzIGlzIGEgJ211bHRpcGFydC8NCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAqIGFsdGVybmF0aXZlJyBoZWFkZXIsIGlu IHdoaWNoIGNhc2Ugd2UgbmVlZCB0bw0KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICogdHJlYXQgaXQgdmVyeSBzcGVjaWFsLiAgKi8NCg0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgaWYoIXN0cm5jYXNlY21wKCZwdHJbMTBd LCAiYWx0ZXJuYXRpdmUiLCAxMSkpIHsNCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgLyogSXQgKmlzKiBhbiBhbHRlcm5hdGl2ZSBzZXNzaW9uISAg QWx0ZXJuYXRpdmUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICog bWVhbnMgdGhlcmUgd2lsbCBiZSBYIHBhcnRzIHdpdGggdGhlIHNhbWUgdGV4 dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiB1c2luZyBkaWZm ZXJlbnQgY29udGVudC10eXBlcy4gV2UgYXJlIHN1cHBvc2VkDQogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAqIHRvIHRha2UgdGhlIG1vc3QgcHJl ZmVyZWQgZm9ybWF0IG9mIHRoZSBvbmVzDQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAqIHVzZWQgYW5kIG9ubHkgb3V0cHV0IHRoYXQgb25lLiBN SU1FIGRlZmluZXMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICog dGhlIG9yZGVyIG9mIHRoZSB0ZXh0cyB0byBzdGFydCB3aXRoIHB1cmUgdGV4 dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBhbmQgdGhlbiBj b250aW51ZSB3aXRoIG1vcmUgYW5kIG1vcmUgb2JzY3VyZQ0KICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgKiBmb3JtYXRzLiAod2VsbCwgaXQgZG9l c24ndCB1c2UgdGhvc2UgdGVybXMgYnV0DQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAqIHRoYXQncyB3aGF0IGl0IG1lYW5zISA7LSkpICovDQoN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogSG93ICJ3ZSIgYXJl IGdvbm5hIGRlYWwgd2l0aCB0aGVtOg0KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgKg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBX ZSBjcmVhdGUgYSAic3BhcmUiIGxpbmtlZCBsaXN0IGJvZHkgZm9yIHRoZQ0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiB2ZXJ5IGZpcnN0IHBh cnQuIFNpbmNlIHRoZSBmaXJzdCBwYXJ0IGlzDQogICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAqIGRlZmluZWQgdG8gYmUgdGhlIG1vc3QgcmVhZGFi bGUsIHdlIHNhdmUgdGhhdA0KICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgKiBpbiBjYXNlIG5vIGNvbnRlbnQtdHlwZSBwcmVzZW50IGlzIHByZWZl cmVkIQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKg0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgKiBXZSBza2lwIGFsbCBwYXJ0cyB0 aGF0IGFyZSBub3QgcHJlZmVyZWQuIEFsbA0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgKiBwcmVmZXJlZCBwYXJ0cyBmb3VuZCB3aWxsIHJlcGxh Y2UgdGhlIGZpcnN0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAq IG9uZSB0aGF0IGlzIHNhdmVkLiBXaGVuIHdlIHJlYWNoIHRoZSBlbmQgb2YN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogdGhlIGFsdGVybmF0 aXZlcywgd2Ugd2lsbCB1c2UgdGhlIGxhc3Qgc2F2ZWQNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICogb25lIGFzIHByZWZlcmVkLg0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgKiAqLw0KDQogICAgICAgICAgICAg ICAgICAgICAgICAgICAgIHNhdmVhbHRlcm5hdGl2ZSA9IFRSVUU7DQojaWYg MA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludGYoIlNBVkVB TFRFUk5BVElWRTogeWVzXG4iKTsNCiNlbmRpZiAgICAgICAgICAgDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAg ICAgICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgIGJvdW5kYXJ5ID0gTlVMTDsNCiAgICAgICAgICAgICAgICAg ICAgICAgfQ0KICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAg ICAgICBlbHNlIGlmICghc3RybmNhc2VjbXAoaGVhZC0+bGluZSwgIkNvbnRl bnQtVHJhbnNmZXItRW5jb2Rpbmc6IiwgMjYpKSB7DQogICAgICAgICAgICAg ICAgICAgICAgIGNoYXIgKnB0cj1oZWFkLT5saW5lKzI2Ow0KICANCiAgICAg ICAgICAgICAgICAgICAgICAgd2hpbGUgKGlzc3BhY2UoKnB0cikpDQogICAg ICAgICAgICAgICAgICAgICAgICAgICBwdHIrKzsNCiAgICAgICAgICAgICAg ICAgICAgICAgaWYgKCFzdHJuY2FzZWNtcChwdHIsICJRVU9URUQtUFJJTlRB QkxFIiwgMTYpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNv ZGUgPSBFTkNPREVfUVA7DQogICAgICAgICAgICAgICAgICAgICAgIH0NCiAg ICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIXN0cm5jYXNlY21wKHB0 ciwgIkJBU0U2NCIsIDYpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAg ICBkZWNvZGUgPSBFTkNPREVfQkFTRTY0Ow0KICAgICAgICAgICAgICAgICAg ICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFzdHJu Y2FzZWNtcChwdHIsICI4QklUIiwgNCkpIHsNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgIGRlY29kZSA9IEVOQ09ERV9OT1JNQUw7DQogICAgICAgICAg ICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBp ZiAoIXN0cm5jYXNlY21wKHB0ciwgIjdCSVQiLCA0KSkgew0KICAgICAgICAg ICAgICAgICAgICAgICAgICAgZGVjb2RlID0gRU5DT0RFX05PUk1BTDsNCiAg ICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAg ICBlbHNlIGlmICghc3RybmNhc2VjbXAocHRyLCAieC11dWUiLCA1KSkgew0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjb2RlID0gRU5DT0RFX1VV RU5DT0RFOw0KICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1 dWRlY29kZShmcCwgbGluZSwgbGluZSwgTlVMTCwgVFJVRSkpDQogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgLyoNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAqKiBvaCBnZWUsIHdlIGZhaWxlZCB0aGlzIGlzIGNo YW9zICovDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7 DQogICAgICAgICAgICAgICAgICAgICAgIH0gIA0KICAgICAgICAgICAgICAg ICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC8q IHRoaXMgaXMgYW4gdW5rbm93biBmb3JtYXQsIHdlIHVzZSBkZWZhdWx0IGRl Y29kaW5nICovDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFyIGNv ZGVbNjRdOw0KICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNzY2Fu ZihwdHIsICIlNjNzIiwgY29kZSk7DQogICAgICAgICAgICAgICAgICAgICAg ICAgICBzcHJpbnRmKGxpbmUsICIgKCclcycgZW5jb2RpbmcgaXMgbm90IHN1 cHBvcnRlZCwgc3RvcmVkIGFzLWlzKVxuIiwgY29kZSk7DQogIA0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgYnAgPSAoc3RydWN0IGJvZHkgKikgYWRk Ym9keShicCwgJmxwLCBsaW5lLA0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgQk9EWV9IVE1MSVpFRHxib2R5ZmxhZ3Mp Ow0KICAgICAgICAgICAgICAgICAgICAgIH0gIA0KICAgICAgICAgICAgICAg ICAgfQ0KICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgIGlmIChzYXZl YWx0ZXJuYXRpdmUpIHsNCiAgICAgICAgICAgICAgICAgIC8qIGxldCdzIHJl bWVtYmVyICdicCcgYW5kICdscCcgKi8NCg0KICAgICAgICAgICAgICAgICAg b3JpZ2JwPWJwOw0KICAgICAgICAgICAgICAgICAgb3JpZ2xwPWxwOw0KDQog ICAgICAgICAgICAgICAgICBmaXJzdGJwPU5VTEw7IC8qIHJlc2V0IHRoaXMg Ki8NCiAgICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlcGFyc2VyID0gVFJV RTsNCg0KICAgICAgICAgICAgICAgICAgLyogcmVzdGFydCBvbiBhIG5ldyBs aXN0OiAqLw0KICAgICAgICAgICAgICAgICAgbHA9YnA9TlVMTDsNCiAgICAg ICAgICAgICAgfQ0KICAgICAgICAgICAgICBoZWFkcCA9IGxwOyAvKiBzdGFy dCBhdCB0aGlzIHBvaW50IG5leHQgdGltZSAqLw0KICAgICAgICAgIH0NCiAg ICAgICAgICBlbHNlIHsNCiNpZiAwDQogICAgICAgICAgICAgIGRlY29kZVJG QzIwNDcobGluZSwgTUFYTElORSk7DQojZW5kaWYNCiAgICAgICAgICAgICAg YnAgPSAoc3RydWN0IGJvZHkgKikgYWRkYm9keShicCwgJmxwLCBsaW5lLCBC T0RZX0hFQURFUnxib2R5ZmxhZ3MpOw0KICAgICAgICAgICAgfQ0KICAgICAg ICB9DQogICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgaWYgKCFzdHJuY21w KGxpbmUsICJGcm9tICIsIDUpICYmIChvbGRsaW5lWzBdPT0nXG4nKSkgew0K ICAgICAgICAgICAgICAgIGlmIChyZWFkb25lKQ0KICAgICAgICAgICAgICAg ICAgICBjb250aW51ZTsNCiAgICAgICAgICAgICAgICBpZiAoc3Ryc3RyKG9s ZGxpbmUsICJGb3J3YXJkZWQgbWVzc2FnZToiKSkgew0KICAgICAgICAgICAg ICAgICAgICBvbGRsaW5lWzBdID0gJ1wwJzsNCiAgICAgICAgICAgICAgICAg ICAgY29udGludWU7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg ICAgIGlzaW5oZWFkZXIgPSAxOw0KI2lmIDANCiAgICAgICAgICAgICAgICB3 YXNpbnJlcGx5ID0gMDsNCiNlbmRpZg0KICAgICAgICAgICAgICAgIGlmICgh aGFzc3ViamVjdCkNCiAgICAgICAgICAgICAgICAgICAgc3RyY3B5KHN1Ympl Y3QsIE5PU1VCSkVDVCk7DQogICAgICAgICAgICAgICAgZWxzZQ0KICAgICAg ICAgICAgICAgICAgICBoYXNzdWJqZWN0ID0gMTsNCiAgDQogICAgICAgICAg ICAgICAgaWYgKCFoYXNkYXRlKQ0KICAgICAgICAgICAgICAgICAgICBzdHJj cHkoZGF0ZSwgTk9EQVRFKTsNCiAgICAgICAgICAgICAgICBlbHNlDQogICAg ICAgICAgICAgICAgICAgIGhhc2RhdGUgPSAxOw0KICANCiAgICAgICAgICAg ICAgICBpZiAoaW5yZXBseVswXSA9PSAnXDAnKQ0KICAgICAgICAgICAgICAg ICAgICBvbmV1bnJlKGlucmVwbHksIHN1YmplY3QpOw0KICANCiAgICAgICAg ICAgICAgICB3aGlsZSAocm1sYXN0bGluZXMoYnApKTsNCiAgICAgICAgICAg ICAgICBhZGRoYXNoKG51bSxkYXRlLG5hbWUsZW1haWwsbXNnaWQsc3ViamVj dCxpbnJlcGx5LGZyb21kYXRlLGJwKTsgICAgICAgICAgICAgICAgYXV0aG9y bGlzdCA9IChzdHJ1Y3QgaGVhZGVyICopDQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgYWRkaGVhZGVyKGF1dGhvcmxpc3QsIG51bSwgbmFtZSwgc3Vi amVjdCwgZGF0ZSwgMSk7ICAgICAgICAgICAgICAgIHN1YmplY3RsaXN0ID0g KHN0cnVjdCBoZWFkZXIgKikNCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICBhZGRoZWFkZXIoc3ViamVjdGxpc3QsbnVtLG5hbWUsdW5yZShzdWJqZWN0 KSxkYXRlLDApOw0KICAgICAgICAgICAgICAgIGRhdGVsaXN0ID0gKHN0cnVj dCBoZWFkZXIgKikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRo ZWFkZXIoZGF0ZWxpc3QsIG51bSwgbmFtZSwgc3ViamVjdCwgZnJvbWRhdGUs IDIpOw0KICAgICAgICAgICAgICAgIHN0cmNweW1heChmcm9tZGF0ZSwgKGNo YXIgKikgZ2V0ZnJvbWRhdGUobGluZSksIERBVEVTVFJMRU4pOw0KICAgICAg ICAgICAgDQogICAgICAgICAgICAgICAgYnAgPSBOVUxMOw0KICAgICAgICAg ICAgICAgIG51bSsrOw0KICAgICAgICAgICAgICAgIGJvZHlmbGFncz0wOyAv KiByZXNldCBzdGF0ZSBmbGFncyAqLw0KICAgICANCiAgICAgICAgICAgICAg ICAvKiBnbyBiYWNrIHRvIGRlZmF1bHQgbW9kZTogKi8NCiAgICAgICAgICAg ICAgICBjb250ZW50ID0gQ09OVEVOVF9URVhUOw0KICAgICAgICAgICAgICAg IGRlY29kZSA9IEVOQ09ERV9OT1JNQUw7DQogICAgICAgICAgICAgICAgTWlt ZV9CID0gRkFMU0U7DQogICAgICAgICAgICAgICAgaGVhZHAgPSBOVUxMOyAN CiAgICAgDQogICAgICAgICAgICAgICAgaWYgKCEobnVtICUgMTApICYmIHNo b3dwcm9ncmVzcyAmJiAhcmVhZG9uZSkgew0KICAgICAgICAgICAgICAgICAg ICBwcmludGYoIlxiXGJcYlxiJTRkIiwgbnVtKTsNCiAgICAgICAgICAgICAg ICAgICAgZmZsdXNoKHN0ZG91dCk7DQogICAgICAgICAgICAgICAgfQ0KICAg ICAgICAgICAgICAgIGlucmVwbHlbMF0gPSAnXDAnOw0KICAgICAgICAgICAg fQ0KICAgICAgICAgICAgZWxzZSB7IC8qIGRlY29kZSBNSU1FIGNvbXBsaWVu dCBnaWJiZXJpc2ggKi8NCiAgICAgICAgICAgICAgICBjaGFyIG5ld2J1ZmZl cltNQVhMSU5FXTsNCiAgICAgICAgICAgICAgICBjaGFyICpkYXRhOw0KICAg ICAgICAgICAgICAgIGludCBkYXRhbGVuPS0xOyAvKiAtMSBtZWFucyB1c2Ug c3RybGVuIHRvIGdldCBsZW5ndGggKi8NCiAgICANCiAgICAgICAgICAgICAg ICBpZiAoTWltZV9CKSB7DQogICAgICAgICAgICAgICAgICAgIGlmIChib3Vu ZHAgJiYNCiAgICAgICAgICAgICAgICAgICAgICAgICFzdHJuY21wKGxpbmUs ICItLSIsIDIpICYmDQogICAgICAgICAgICAgICAgICAgICAgICAhc3RybmNt cChsaW5lKzIsIGJvdW5kcC0+bGluZSwgc3RybGVuKGJvdW5kcC0+bGluZSkp KSB7ICAgICAgICAgICAgICAgICAgICAgICAgLyogcmlnaHQgYXQgdGhpcyBw b2ludCwgd2UgaGF2ZSBhbm90aGVyIHBhcnQgY29taW5nIHVwICovDQogICAg ICAgICAgICAgICAgICAgICAgICBpc2luaGVhZGVyID0gMTsgLyogYmFjayBv biBhIGtpbmQtb2YtaGVhZGVyICovDQoNCiNpZiAwICAgIA0KICAgICAgICAg ICAgICAgICAgICAgICAgcHJpbnRmKCJoaXQgJXNcbiIsIGxpbmUpOw0KI2Vu ZGlmDQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXN0cm5jbXAobGlu ZSsyK3N0cmxlbihib3VuZHAtPmxpbmUpLCAiLS0iLCAyKSkgew0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgIGJwID0gKHN0cnVjdCBib2R5ICopIGFk ZGJvZHkoYnAsICZscCwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBCT0RZX0hUTUxJWkVEfGJvZHlm bGFncyk7DQogICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm91 bmRwID0gYm91bmQoYm91bmRwLCBOVUxMKTsNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICBpZiAoIWJvdW5kcCkgew0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBib2R5ZmxhZ3MgJj0gfkJPRFlfQVRUQUNIRUQ7DQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgIGlmKGFsdGVybmF0aXZlcGFyc2VyKSB7DQogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgYm9keSAqbmV4dDsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIHdlIG5vIGxvbmdlciBo YXZlIGFsdGVybmF0aXZlcyAqLw0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgYWx0ZXJuYXRpdmVwYXJzZXIgPSBGQUxTRTsNCiNpZiAwDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludGYoIldlIERVTVAgYW4g b2xkIGFsdGVybmF0aXZlXG4iKTsNCiNlbmRpZg0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgd2hpbGUoYnApIHsNCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgb3JpZ2JwID0gYWRkYm9keShvcmlnYnAsICZvcmln bHAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgYnAtPmxpbmUsDQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgKGJwLT5oZWFkZXI/Qk9EWV9IRUFE RVI6MCl8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgKGJwLT5odG1sP0JPRFlfSFRNTElaRUQ6MCl8DQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg KGJwLT5hdHRhY2hlZD9CT0RZX0FUVEFDSEVEOjApDQogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTsNCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dD0gYnAtPm5leHQ7DQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUoYnAtPmxpbmUp Ow0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmVlKGJwKTsN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnA9bmV4dDsNCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIGJwID0gb3JpZ2JwOw0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgbHAgPSBvcmlnbHA7DQoNCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIGhlYWRwPSBOVUxMOw0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgIH0NCiNpZiAwDQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgaWYgKGJvdW5kcCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgcHJpbnRmKCJiYWNrICVzXG4iLCBib3VuZHAtPmxpbmUpOw0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgcHJpbnRmKCJiYWNrIHRvIE5PTkVcbiIpOw0K I2VuZGlmDQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgDQogICAg ICAgICAgICAgICAgICAgICAgICBpZiAoLTEgIT0gYmluZmlsZSkgew0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlKGJpbmZpbGUpOw0KICAg ICAgICAgICAgICAgICAgICAgICAgICAgIGJpbmZpbGU9LTE7DQogICAgICAg ICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICBj b250aW51ZTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAg ICAgIH0NCiAgICANCiAgICAgICAgICAgICAgICBzd2l0Y2ggKCBkZWNvZGUg KSB7DQogICAgICAgICAgICAgICAgICAgIGNhc2UgRU5DT0RFX1FQOg0KI2lm IDANCiAgICAgICAgICAgICAgICAgICAgICAgICBkZWNvZGVRUChmcCwgbGlu ZSwgbmV3YnVmZmVyLCBNQVhMSU5FKTsNCiAgICAgICAgICAgICAgICAgICAg ICAgICBkYXRhID0gbmV3YnVmZmVyOw0KI2Vsc2UNCiAgICAgICAgICAgICAg ICAgICAgICAgICBtZGVjb2RlUVAoZnAsIGxpbmUsICZkYXRhLCAmZGF0YWxl bik7DQojZW5kaWYNCiAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsN CiAgICAgICAgICAgICAgICAgICAgY2FzZSBFTkNPREVfQkFTRTY0Og0KICAg ICAgICAgICAgICAgICAgICAgICAgIGJhc2U2NERlY29kZShsaW5lLCBuZXdi dWZmZXIsICZkYXRhbGVuKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICBk YXRhID0gbmV3YnVmZmVyOw0KICAgICAgICAgICAgICAgICAgICAgICAgIGJy ZWFrOw0KICAgICAgICAgICAgICAgICAgICBjYXNlIEVOQ09ERV9VVUVOQ09E RToNCiAgICAgICAgICAgICAgICAgICAgICAgICB1dWRlY29kZShOVUxMLCBs aW5lLCBuZXdidWZmZXIsICZkYXRhbGVuLCBGQUxTRSk7DQogICAgICAgICAg ICAgICAgICAgICAgICAgZGF0YSA9IG5ld2J1ZmZlcjsNCiAgICAgICAgICAg ICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICAgICAgY2Fz ZSBFTkNPREVfTk9STUFMOg0KICAgICAgICAgICAgICAgICAgICAgICAgIGRh dGEgPSBsaW5lOw0KICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOw0K ICAgICAgICAgICAgICAgICAgICBkZWZhdWx0Og0KICAgICAgICAgICAgICAg ICAgICAgICAgIC8qIHdlIGhhdmUgbm8gY2x1ZSEgKi8NCiAgICAgICAgICAg ICAgICAgICAgICAgICBkYXRhID0gTlVMTDsNCiAgICAgICAgICAgICAgICAg ICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAg ICAgICAgaWYgKGRhdGEpIHsNCiAgICAgICAgICAgICAgICAgICAgaWYgKChj b250ZW50ID09IENPTlRFTlRfVEVYVCkgfHwgKGNvbnRlbnQ9PUNPTlRFTlRf SFRNTCkpIHsgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVjb2RlID4g RU5DT0RFX01VTFRJTElORUQpIHsNCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAvKiANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKiBUaGlz IGNhbiBiZSBtb3JlIHRoYW4gb25lIHJlc3VsdGluZyBsaW5lLCANCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAqKiBhcyB0aGUgZGVjb2RlZCB0aGUg c3RyaW5nIG1heSBsb29rIGxpa2U6DQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgIiMhL2Jpbi9zaFxyXG5cclxuaGVscCgpIHtcclxuIGVjaG8gJ1Vz YWdlOiBkaWZmdHJlZSINCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAq Lw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXIgKnA9ZGF0YTsN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFyICpuOw0KICAgICAg ICAgICAgICAgICAgICAgICAgICAgIGNoYXIgc3RvcmU7DQogICAgICAgICAg ICAgICAgICAgICAgICAgICAgd2hpbGUgKChuID0gKGNoYXIgKilzdHJjaHIo cCwgJ1xuJykpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICBzdG9yZSA9IG5bMV07DQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBuWzFdPTA7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICBicCA9IChzdHJ1Y3QgYm9keSAqKSBhZGRib2R5KGJwLCAmbHAsIHAsDQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAo bXVsdGlsaW5lbm9lbmQ/Qk9EWV9DT05USU5VRTowKXwNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvZHlmbGFncyk7 DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aWxpbmVu b2VuZCA9IEZBTFNFOyAvKiBmdWxsIGxpbmUgcHVzaGVkICovICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgblsxXT1zdG9yZTsNCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIHAgPSBuKzE7DQogICAgICAgICAg ICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAg ICAgIGlmIChzdHJsZW4ocCkpIHsNCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgLyogDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICoqIFRoaXMgbGluZSBkb2Vzbid0IHJlYWxseSBlbmQgaGVyZSwgDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqIHdlIHdpbGwgZ2V0IGFu b3RoZXIgbGluZSBzb29uIHRoYXQgDQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICoqIHNob3VsZCBnZXQgYXBwZW5kZWQhIA0KICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAqLw0KICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBicCA9IChzdHJ1Y3QgYm9keSAqKSBhZGRib2R5KGJw LCAmbHAsIHAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAobXVsdGlsaW5lbm9lbmQ/Qk9EWV9DT05USU5VRTowKXwN CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IGJvZHlmbGFncyk7DQogICAgDQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIC8qDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICoq IFdlIHdhbnQgdGhlIG5leHQgbGluZSB0byBnZXQgYXBwZW5kZWQgdG8gdGhp cyENCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKi8NCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlsaW5lbm9lbmQgPSBU UlVFOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAg ICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIGVs c2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJwID0gKHN0cnVj dCBib2R5ICopIGFkZGJvZHkoYnAsICZscCwgZGF0YSwgDQogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvbnRlbnQ9PUNP TlRFTlRfSFRNTD8NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBCT0RZX0hUTUxJWkVEOjApIHwgYm9keWZsYWdzICk7DQog ICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAg IH0NCiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29udGVudCA9PSBD T05URU5UX0JJTkFSWSkgew0KICAgICAgICAgICAgICAgICAgICAgICAgaWYg KC0xICE9IGJpbmZpbGUpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICBpZiAoZGF0YWxlbiA8IDApDQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIGRhdGFsZW4gPSBzdHJsZW4oZGF0YSk7DQogICAgICAgICAgICAg ICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLypmd3JpdGUoZGF0 YSwgZGF0YWxlbiwgMSwgYmluZmlsZSk7ICovDQogICAgICAgICAgICAgICAg ICAgICAgICAgICAgd3JpdGUoYmluZmlsZSwgZGF0YSwgZGF0YWxlbik7DQog ICAgICAgICAgICAgICAgICAgICAgICAgICAgLypicCA9IChzdHJ1Y3QgYm9k eSAqKSBhZGRib2R5KGJwLCAiZmlsZSBjb250ZW50cyIpOyovDQogICAgICAg ICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgIH0NCiAg ICANCiAgICAgICAgICAgICAgICAgICAgaWYgKEVOQ09ERV9RUCA9PSBkZWNv ZGUpDQogICAgICAgICAgICAgICAgICAgICAgICBmcmVlKGRhdGEpOyAvKiB0 aGlzIHdhcyBhbGxvY2F0ZCBieSBtZGVjb2RlUVAoKSAqLw0KICAgICAgICAg ICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgICBz dHJjcHltYXgob2xkbGluZSwgbGluZSwgTUFYTElORSk7DQogICAgfQ0KDQog ICAgaWYgKCFpc2luaGVhZGVyKSB7DQogICAgICAgIGlmICghaGFzc3ViamVj dCkNCiAgICAgICAgICAgIHN0cmNweShzdWJqZWN0LCBOT1NVQkpFQ1QpOw0K DQogICAgICAgIGlmICghaGFzZGF0ZSkNCiAgICAgICAgICAgIHN0cmNweShk YXRlLCBOT0RBVEUpOw0KDQogICAgICAgIGlmIChpbnJlcGx5WzBdID09ICdc MCcpDQogICAgICAgICAgICBvbmV1bnJlKGlucmVwbHksIHN1YmplY3QpOw0K DQogICAgICAgIHdoaWxlIChybWxhc3RsaW5lcyhicCkpOw0KDQogICAgICAg IGFkZGhhc2gobnVtLCBkYXRlLCBuYW1lLCBlbWFpbCwgbXNnaWQsIHN1Ympl Y3QsIGlucmVwbHksIGZyb21kYXRlLCBicCk7DQogICAgICAgIGF1dGhvcmxp c3QgPSAoc3RydWN0IGhlYWRlciAqKQ0KICAgICAgICAgICAgICAgICAgICAg IGFkZGhlYWRlcihhdXRob3JsaXN0LCBudW0sIG5hbWUsIHN1YmplY3QsIGRh dGUsIDEpOw0KICAgICAgICBzdWJqZWN0bGlzdCA9IChzdHJ1Y3QgaGVhZGVy ICopDQogICAgICAgICAgICAgICAgICAgICAgYWRkaGVhZGVyKHN1YmplY3Rs aXN0LCBudW0sIG5hbWUsIHVucmUoc3ViamVjdCksIGRhdGUsIDApOw0KICAg ICAgICBkYXRlbGlzdCA9IChzdHJ1Y3QgaGVhZGVyICopIA0KICAgICAgICAg ICAgICAgICAgICAgIGFkZGhlYWRlcihkYXRlbGlzdCwgbnVtLCBuYW1lLCBz dWJqZWN0LCBmcm9tZGF0ZSwgMik7DQogICAgICAgIG51bSsrOw0KICAgIH0N CiAgICANCiAgICBpZiAoc2hvd3Byb2dyZXNzICYmICFyZWFkb25lKQ0KICAg ICAgICBwcmludGYoIlxiXGJcYlxiJTRkIGFydGljbGVzLlxuIiwgbnVtKTsN CiAgICANCiAgICBpZiAoIXJlYWRvbmUpDQogICAgICAgIGJpZ251bSA9IG51 bSAtIDE7DQoNCiAgICBmY2xvc2UoZnApOw0KDQogICAgY3Jvc3NpbmRleCgp Ow0KICAgIHRocmVhZGxpc3QgPSBOVUxMOw0KICAgIHByaW50ZWR0aHJlYWRs aXN0ID0gTlVMTDsNCiAgICBjcm9zc2luZGV4dGhyZWFkMShkYXRlbGlzdCk7 DQogIA0KICAgIC8qIGNhbiB3ZSBjbGVhbiB1cCBhIGJpdCBwbGVhc2UuLi4g Ki8NCiAgDQogICAgaWYgKGJvdW5kcCAhPSBOVUxMKSB7DQogICAgICAgIGlm IChib3VuZHAtPmxpbmUpIA0KICAgICAgICAgICAgZnJlZShib3VuZHAtPmxp bmUpOw0KICAgICAgICBmcmVlKGJvdW5kcCk7DQogICAgfQ0KDQojaWYgMA0K ICAgIGlmIChwcmludGVkdGhyZWFkbGlzdCAhPSBOVUxMKSB7DQogICAgICAg IHN0cnVjdCBwcmludGVkICpwcDsNCg0KICAgICAgICBkbyB7DQogICAgICAg ICAgICBwcCA9IHByaW50ZWR0aHJlYWRsaXN0Ow0KICAgICAgICAgICAgcHJp bnRlZHRocmVhZGxpc3QgPSBwcmludGVkdGhyZWFkbGlzdC0+bmV4dDsNCiAg ICAgICAgICAgIGZyZWUocHApOw0KICAgICAgICB9IHdoaWxlIChwcmludGVk dGhyZWFkbGlzdCk7DQogICAgfQ0KI2VuZGlmDQp9DQoNCi8qDQoqKiBBbGwg dGhpcyBkb2VzIGlzIGdldCBhbGwgdGhlIHJlbGV2YW50IGhlYWRlciBpbmZv cm1hdGlvbiBmcm9tIHRoZQ0KKiogY29tbWVudCBmaWVsZHMgaW4gZXhpc3Rp bmcgYXJjaGl2ZSBmaWxlcy4gRXZlcnl0aGluZyBpcyBsb2FkZWQgaW50bw0K Kiogc3RydWN0dXJlcyBpbiB0aGUgZXhhY3Qgc2FtZSB3YXkgYXMgaWYgYXJ0 aWNsZXMgd2VyZSBiZWluZyByZWFkIGZyb20NCioqIHN0ZGluIG9yIGEgbWFp bGJveC4NCiovDQoNCnZvaWQgbG9hZG9sZGhlYWRlcnMoY2hhciAqZGlyKQ0K ew0KICAgIEZJTEUgKmZwOw0KICAgIGNoYXIgbmFtZVtOQU1FU1RSTEVOXSwg ZW1haWxbTUFJTFNUUkxFTl0sIGRhdGVbREFURVNUUkxFTl0sDQogICAgICAg IG1zZ2lkW01TR0RTVFJMRU5dLCBzdWJqZWN0W1NVQkpTVFJMRU5dLCBpbnJl cGx5W1JFUFlTVFJMRU5dLA0KICAgICAgICBsaW5lW01BWExJTkVdLCBmcm9t ZGF0ZVtEQVRFU1RSTEVOXSwgZmlsZW5hbWVbTUFYRklMRUxFTl07DQogICAg aW50IG51bTsNCg0KICAgIHN0cnVjdCBib2R5ICpicD1OVUxMOw0KICAgIHN0 cnVjdCBib2R5ICpscD1OVUxMOw0KDQogICAgbnVtID0gMDsNCiAgICBzcHJp bnRmKGZpbGVuYW1lLCAiJXMlcyUuNGQuaHRtbCIsIGRpciwgDQogICAgICAg ICAgICAgIChkaXJbc3RybGVuKGRpcikgLSAxXSA9PSAnLycpID8gIiIgOiAi LyIsIG51bSk7DQoNCiAgICBicCA9IChzdHJ1Y3QgYm9keSAqKSBhZGRib2R5 KGJwLCAmbHAsICJcMCIsIDApOw0KDQogICAgYXV0aG9ybGlzdCA9IHN1Ympl Y3RsaXN0ID0gZGF0ZWxpc3QgPSBOVUxMOw0KDQogICAgaWYgKHNob3dwcm9n cmVzcykNCiAgICAgICAgcHJpbnRmKCJSZWFkaW5nIG9sZCBoZWFkZXJzLi4u ICAgICIpOw0KDQogICAgLyoNCiAgICAqKiBXQVJOSU5HOiBUaGUgZm9sbG93 aW5nIHdoaWxlIGxvb3AgaXMgZGVwZW5kZW50IG9uIHRoZSBvcmRlciBvZiB0 aGUNCiAgICAqKiBjb21tZW50cyBpbiB0aGUgSFRNTCBmaWxlcy4gVGhlIGNv bW1lbnRzIG5lZWQgdG8gYmUgaW4gdGhlIG9yZGVyDQogICAgKiogcGFyc2Vk IGJlbG93IG9yIHRoaXMgbG9vcCBuZWVkIHRvIGJlIGNoYW5nZS4gKEl0IHJl YWxseSBuZWVkcyB0byBiZQ0KICAgICoqIHRvdGFsbHkgcmV3cml0dGVuIHRv IGJlIG1vcmUgcm9idXN0IGFuZCBmb3JnaXZpbmcuLi4gU29vbi4NCiAgICAq KiANCiAgICAqKiBmcm9tZGF0ZSA9PSA8IS0tIHJlY2VpdmVkPSJXZWQgSnVu ICAzIDEwOjEyOjAwIDE5OTggQ0RUIiAtLT4NCiAgICAqKiBkYXRlICAgICA9 PSA8IS0tIHNlbnQ9IldlZCwgMyBKdW4gMTk5OCAxMDoxMjowNyAtMDUwMCAo Q0RUKSIgLS0+DQogICAgKiogbmFtZSAgICAgPT0gPCEtLSBuYW1lPSJLZW50 IExhbmRmaWVsZCIgLS0+DQogICAgKiogZW1haWwgICAgPT0gPCEtLSBlbWFp bD0ia2VudEBsYW5kZmllbGQuY29tIiAtLT4NCiAgICAqKiBzdWJqZWN0ICA9 PSA8IS0tIHN1YmplY3Q9IlRlc3QgbWVzc2FnZSBvZiB0aGUgdGVzdG1haWwg bWFpbCBhZGRyZXNzLiIgLS0+DQogICAgKiogbXNnaWQgICAgPT0gPCEtLSBp ZD0iMTk5ODA2MDMxNTEyLktBQTIyMzIzQGxhbmRmaWVsZC5jb20iIC0tPg0K ICAgICoqIGlucmVwbHkgID09IDwhLS0gaW5yZXBseXRvPSIiIC0tPg0KICAg ICovDQoNCiAgICB3aGlsZSAoKGZwID0gZm9wZW4oZmlsZW5hbWUsICJyIikp ICE9IE5VTEwpIHsNCg0KICAgICAgICAvKiBza2lwIGFsbCBsaW5lcyBiZWZv cmUgdGhlIGZpcnN0IDwhLS0gKi8NCiAgICAgICAgd2hpbGUgKCBmZ2V0cyhs aW5lLCBzaXplb2YobGluZSksIGZwKSwgc3RybmNtcChsaW5lLCAiPCEtLSAi LCA1KSApOw0KDQogICAgICAgIHN0cmNweW1heChmcm9tZGF0ZSwgKGNoYXIg KikgZ2V0dmFsdWUobGluZSksIERBVEVTVFJMRU4pOw0KDQogICAgICAgIGZn ZXRzKGxpbmUsIHNpemVvZihsaW5lKSwgZnApOw0KICAgICAgICBzdHJjcHlt YXgoZGF0ZSwgKGNoYXIgKikgZ2V0dmFsdWUobGluZSksIERBVEVTVFJMRU4p Ow0KDQogICAgICAgIGZnZXRzKGxpbmUsIHNpemVvZihsaW5lKSwgZnApOw0K ICAgICAgICBzdHJjcHltYXgobmFtZSwgKGNoYXIgKikgZ2V0dmFsdWUobGlu ZSksIE5BTUVTVFJMRU4pOw0KDQogICAgICAgIGZnZXRzKGxpbmUsIHNpemVv ZihsaW5lKSwgZnApOw0KICAgICAgICBzdHJjcHltYXgoZW1haWwsIChjaGFy ICopIGdldHZhbHVlKGxpbmUpLCBNQUlMU1RSTEVOKTsNCg0KICAgICAgICBm Z2V0cyhsaW5lLCBzaXplb2YobGluZSksIGZwKTsNCiAgICAgICAgc3RyY3B5 bWF4KHN1YmplY3QsIChjaGFyICopIHVuY29udmNoYXJzKGdldHZhbHVlKGxp bmUpKSwgU1VCSlNUUkxFTik7DQoNCiAgICAgICAgZmdldHMobGluZSwgc2l6 ZW9mKGxpbmUpLCBmcCk7DQogICAgICAgIHN0cmNweW1heChtc2dpZCwgKGNo YXIgKikgZ2V0dmFsdWUobGluZSksIE1TR0RTVFJMRU4pOw0KDQogICAgICAg IGZnZXRzKGxpbmUsIHNpemVvZihsaW5lKSwgZnApOw0KICAgICAgICBzdHJj cHltYXgoaW5yZXBseSwgKGNoYXIgKikgdW5jb252Y2hhcnMoZ2V0dmFsdWUo bGluZSkpLCBNU0dEU1RSTEVOKTsNCg0KICAgICAgICBmY2xvc2UoZnApOw0K DQogICAgICAgIGFkZGhhc2gobnVtLCBkYXRlLCBuYW1lLCBlbWFpbCwgbXNn aWQsIHN1YmplY3QsIGlucmVwbHksIGZyb21kYXRlLCBicCk7ICAgICAgICBh dXRob3JsaXN0ID0gKHN0cnVjdCBoZWFkZXIgKikgYWRkaGVhZGVyKGF1dGhv cmxpc3QsIG51bSwgbmFtZSwgc3ViamVjdCwgZGF0ZSwgMSk7DQogICAgICAg IHN1YmplY3RsaXN0ID0gKHN0cnVjdCBoZWFkZXIgKikgYWRkaGVhZGVyKHN1 YmplY3RsaXN0LCBudW0sIG5hbWUsIHVucmUoc3ViamVjdCksIGRhdGUsIDAp Ow0KICAgICAgICBkYXRlbGlzdCA9IChzdHJ1Y3QgaGVhZGVyICopYWRkaGVh ZGVyKGRhdGVsaXN0LG51bSxuYW1lLHN1YmplY3QsZnJvbWRhdGUsMik7DQoN CiAgICAgICAgbnVtKys7DQogICAgICAgIGlmICghKG51bSAlIDEwKSAmJiBz aG93cHJvZ3Jlc3MpIHsNCiAgICAgICAgICAgIHByaW50ZigiXGJcYlxiXGIl NGQiLCBudW0pOw0KICAgICAgICAgICAgZmZsdXNoKHN0ZG91dCk7DQogICAg ICAgIH0NCg0KICAgICAgICBzcHJpbnRmKGZpbGVuYW1lLCAiJXMlcyUuNGQu aHRtbCIsIGRpciwNCiAgICAgICAgICAgICAgICAoZGlyW3N0cmxlbihkaXIp IC0gMV0gPT0gJy8nKSA/ICIiIDogIi8iLCBudW0pOw0KICAgIH0NCg0KICAg IGlmIChzaG93cHJvZ3Jlc3MpDQogICAgICAgIHByaW50ZigiXGJcYlxiXGIl NGQgYXJ0aWNsZXMuXG4iLCBudW0pOw0KDQogICAgaWYgKCFudW0pDQogICAg ICAgIGJpZ251bSA9IDA7DQogICAgZWxzZQ0KICAgICAgICBiaWdudW0gPSBu dW07DQoNCiAgICAvKiBjYW4gd2UgY2xlYW4gdXAgYSBiaXQgcGxlYXNlLi4u ICovDQogICAgaWYgKGJwICE9IE5VTEwpIHsNCiAgICAgICAgaWYgKGJwLT5s aW5lKSBmcmVlKGJwLT5saW5lKTsNCiAgICAgICAgZnJlZShicCk7DQogICAg fQ0KfQ0KDQovKg0KKiogQWRkcyBhICJOZXh0OiIgbGluayBpbiB0aGUgcHJv cGVyIGFydGljbGUsIGFmdGVyIHRoZSBhcmNoaXZlIGhhcyBiZWVuDQoqKiBp bmNyZW1lbnRhbGx5IHVwZGF0ZWQuDQoqLw0KDQp2b2lkIGZpeG5leHRoZWFk ZXIoY2hhciAqZGlyLCBpbnQgbnVtKQ0Kew0KICAgIGNoYXIgZmlsZW5hbWVb TUFYRklMRUxFTl0sIGxpbmVbTUFYTElORV0sIG5hbWVbTkFNRVNUUkxFTl0s DQogICAgICAgIGVtYWlsW01BSUxTVFJMRU5dLCBzdWJqZWN0W1NVQkpTVFJM RU5dLCBpbnJlcGx5W1JFUFlTVFJMRU5dLA0KICAgICAgICBkYXRlW0RBVEVT VFJMRU5dLCBmcm9tZGF0ZVtEQVRFU1RSTEVOXSwgbXNnaWRbTVNHRFNUUkxF Tl07DQogICAgc3RydWN0IGJvZHkgKmJwLCAqY3AsICpkcCwgKnN0YXR1cywg KmxwPU5VTEw7DQogICAgaW50IHVsOw0KICAgIEZJTEUgKmZwOw0KDQogICAg dWwgPSAwOw0KICAgIHNwcmludGYoZmlsZW5hbWUsICIlcyVzJS40ZC5odG1s IiwgZGlyLA0KICAgICAgICAgIChkaXJbc3RybGVuKGRpcikgLSAxXSA9PSAn LycpID8gIiIgOiAiLyIsIG51bSk7DQoNCiAgICBicCA9IE5VTEw7DQogICAg aWYgKChmcCA9IGZvcGVuKGZpbGVuYW1lLCAiciIpKSAhPSBOVUxMKSB7DQog ICAgICAgIHdoaWxlICgoZmdldHMobGluZSwgTUFYTElORSwgZnApKSAhPSBO VUxMKQ0KICAgICAgICAgICAgYnAgPSAoc3RydWN0IGJvZHkgKikgYWRkYm9k eShicCwgJmxwLCBsaW5lLCAwKTsNCiAgICB9DQogICAgZWxzZQ0KICAgICAg ICByZXR1cm47DQogICAgZmNsb3NlKGZwKTsNCg0KICAgIGNwID0gYnA7IC8q IHNhdmUgc3RhcnQgb2YgbGlzdCB0byBmcmVlIGxhdGVyICovDQoNCiAgICBp ZiAoKGZwID0gZm9wZW4oZmlsZW5hbWUsICJ3KyIpKSAhPSBOVUxMKSB7DQog ICAgICAgd2hpbGUgKGJwICE9IE5VTEwpIHsNCiAgICAgICAgICAgIGZwcmlu dGYoZnAsICIlcyIsIGJwLT5saW5lKTsNCiAgICAgICAgICAgIGlmICghc3Ry bmNtcChicC0+bGluZSwgIjwhLS0gbmV4dD0iLCAxMCkpIHsNCiAgICAgICAg ICAgICAgICBzdGF0dXMgPSAoc3RydWN0IGJvZHkgKikgaGFzaG51bWxvb2t1 cChudW0gKyAxLCBuYW1lLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAg ZW1haWwsIHN1YmplY3QsIGlucmVwbHksIGRhdGUsIGZyb21kYXRlLCBtc2dp ZCk7DQogICAgICAgICAgICAgICAgaWYgKHN0YXR1cyAhPSBOVUxMKSB7DQog ICAgICAgICAgICAgICAgICAgIGlmICh1c2V0YWJsZSkgew0KICAgICAgICAg ICAgICAgICAgICAgICAgZHAgPSBicC0+bmV4dDsNCiAgICAgICAgICAgICAg ICAgICAgICAgIGlmICghc3RybmNtcChkcC0+bGluZSwgIjxVTD4iLCA0KSkg ew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICIl cyIsIGRwLT5saW5lKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1 bCA9IDE7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAg ICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwg IjxMST48U1RST05HPk5leHQgbWVzc2FnZTo8L1NUUk9ORz4gIik7DQogICAg ICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICI8QSBIUkVGPVwiJS40ZC5o dG1sXCI+JXM6IFwiJXNcIjwvQT5cbiIsDQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgbnVtICsgMSwgbmFtZSwgY29udmNoYXJzKHN1Ympl Y3QpKTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKHVsKSB7DQogICAgICAg ICAgICAgICAgICAgICAgICBicCA9IGRwOw0KICAgICAgICAgICAgICAgICAg ICAgICAgdWwgPSAwOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAg ICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgYnAgPSBi cC0+bmV4dDsNCiAgICAgICB9DQogICAgfQ0KDQogICAgZmNsb3NlKGZwKTsN Cg0KICAgIC8qIGNhbiB3ZSBjbGVhbiB1cCBhIGJpdCBwbGVhc2UuLi4gKi8N CiAgICBicCA9IGNwOw0KICAgIHdoaWxlIChicCAhPSBOVUxMKSB7DQogICAg ICAgIGNwID0gYnAtPm5leHQ7DQogICAgICAgIGlmIChicC0+bGluZSkgZnJl ZShicC0+bGluZSk7DQogICAgICAgIGZyZWUoYnApOw0KICAgICAgICBicCA9 IGNwOw0KICAgIH0NCn0NCg0KLyoNCioqIEFkZHMgYSAiUmVwbHk6IiBsaW5r IGluIHRoZSBwcm9wZXIgYXJ0aWNsZSwgYWZ0ZXIgdGhlIGFyY2hpdmUgaGFz IGJlZW4NCioqIGluY3JlbWVudGFsbHkgdXBkYXRlZC4NCiovDQoNCnZvaWQg Zml4cmVwbHloZWFkZXIoY2hhciAqZGlyLCBpbnQgbnVtKQ0Kew0KICAgIGlu dCByZXBseW51bSwgc3Viam1hdGNoOw0KICAgIGNoYXIgZmlsZW5hbWVbTUFY RklMRUxFTl0sIGxpbmVbTUFYTElORV0sIG5hbWVbTkFNRVNUUkxFTl0sDQog ICAgICAgIGVtYWlsW01BSUxTVFJMRU5dLCBzdWJqZWN0W1NVQkpTVFJMRU5d LCBpbnJlcGx5W1JFUFlTVFJMRU5dLA0KICAgICAgICBkYXRlW0RBVEVTVFJM RU5dLCBmcm9tZGF0ZVtEQVRFU1RSTEVOXSwgbXNnaWRbTVNHRFNUUkxFTl0s DQogICAgICAgIG5hbWUyW05BTUVTVFJMRU5dLCBzdWJqZWN0MltTVUJKU1RS TEVOXTsNCiAgICBzdHJ1Y3QgYm9keSAqYnAsICpjcCwgKnN0YXR1czsNCiAg ICBzdHJ1Y3QgYm9keSAqbHAgPSBOVUxMOw0KICAgIEZJTEUgKmZwOw0KDQog ICAgc3RhdHVzID0gKHN0cnVjdCBib2R5ICopIGhhc2hudW1sb29rdXAobnVt LCBuYW1lLCBlbWFpbCwgc3ViamVjdCwgDQogICAgICAgICAgICAgIGlucmVw bHksIGRhdGUsIGZyb21kYXRlLCBtc2dpZCk7DQoNCiAgICBpZiAoc3RhdHVz ID09IE5VTEwgfHwgaW5yZXBseVswXSA9PSAnXDAnKQ0KICAgICAgICByZXR1 cm47DQoNCiAgICBpZiAoaW5yZXBseVswXSAhPSAnXDAnKSB7DQogICAgICAg IHJlcGx5bnVtID0gaGFzaHJlcGx5bG9va3VwKGlucmVwbHksIG5hbWUyLCBz dWJqZWN0MiwgJnN1YmptYXRjaCk7DQogICAgICAgIGlmIChyZXBseW51bSA9 PSAtMSkNCiAgICAgICAgICAgIHJldHVybjsNCiAgICB9DQoNCiAgICBzcHJp bnRmKGZpbGVuYW1lLCAiJXMlcyUuNGQuaHRtbCIsIGRpciwgDQogICAgICAg ICAgICAgICAgICAgICAgIChkaXJbc3RybGVuKGRpcikgLSAxXSA9PSAnLycp ID8gIiIgOiAiLyIsIHJlcGx5bnVtKTsNCg0KICAgIGJwID0gTlVMTDsNCiAg ICBpZiAoKGZwID0gZm9wZW4oZmlsZW5hbWUsICJyIikpICE9IE5VTEwpIHsN CiAgICAgICAgd2hpbGUgKChmZ2V0cyhsaW5lLCBNQVhMSU5FLCBmcCkpICE9 IE5VTEwpDQogICAgICAgICAgICBicCA9IChzdHJ1Y3QgYm9keSAqKSBhZGRi b2R5KGJwLCAmbHAsIGxpbmUsIDApOw0KICAgIH0NCiAgICBlbHNlDQogICAg ICAgIHJldHVybjsNCiAgICBmY2xvc2UoZnApOw0KDQogICAgY3AgPSBicDsg IC8qIHNhdmUgc3RhcnQgb2YgbGlzdCB0byBmcmVlIGxhdGVyICovDQoNCiAg ICBpZiAoKGZwID0gZm9wZW4oZmlsZW5hbWUsICJ3KyIpKSAhPSBOVUxMKSB7 DQogICAgICAgIHdoaWxlIChicCAhPSBOVUxMKSB7DQogICAgICAgICAgICBp ZiAoIXN0cm5jbXAoYnAtPmxpbmUsICI8IS0tIHJlcGx5IiwgMTApKSB7DQog ICAgICAgICAgICAgICAgZnByaW50ZihmcCwgIjxMST48U1RST05HPlJlcGx5 OjwvU1RST05HPiAiKTsNCiAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAi PEEgSFJFRj1cIiUuNGQuaHRtbFwiPiIsIG51bSk7DQogICAgICAgICAgICAg ICAgZnByaW50ZihmcCwgIiVzOiBcIiVzXCI8L0E+XG4iLCBuYW1lLCBjb252 Y2hhcnMoc3ViamVjdCkpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAg ZnByaW50ZihmcCwgIiVzIiwgYnAtPmxpbmUpOw0KICAgICAgICAgICAgYnAg PSBicC0+bmV4dDsNCiAgICAgICAgfQ0KICAgIH0NCiAgICBmY2xvc2UoZnAp Ow0KDQogICAgLyogY2FuIHdlIGNsZWFuIHVwIGEgYml0IHBsZWFzZS4uLiAq Lw0KICAgIGJwID0gY3A7DQogICAgd2hpbGUgKGJwICE9IE5VTEwpIHsNCiAg ICAgICAgY3AgPSBicC0+bmV4dDsNCiAgICAgICAgaWYgKGJwLT5saW5lKSBm cmVlKGJwLT5saW5lKTsNCiAgICAgICAgZnJlZShicCk7DQogICAgICAgIGJw ID0gY3A7DQogICAgfQ0KfQ0KDQovKg0KKiogQWRkcyBhICJOZXh0IGluIHRo cmVhZDoiIGxpbmsgaW4gdGhlIHByb3BlciBhcnRpY2xlLCBhZnRlciB0aGUg YXJjaGl2ZQ0KKiogaGFzIGJlZW4gaW5jcmVtZW50YWxseSB1cGRhdGVkLg0K Ki8NCg0Kdm9pZCBmaXh0aHJlYWRoZWFkZXIoY2hhciAqZGlyLCBpbnQgbnVt KQ0Kew0KICAgIGNoYXIgZmlsZW5hbWVbTUFYRklMRUxFTl0sbGluZVtNQVhM SU5FXSxuYW1lW05BTUVTVFJMRU5dOw0KICAgIGNoYXIgc3ViamVjdFtTVUJK U1RSTEVOXTsNCiAgICBGSUxFICpmcDsNCiAgICBzdHJ1Y3QgcmVwbHkgKnJw Ow0KICAgIHN0cnVjdCBib2R5ICpicCwgKmNwOw0KICAgIHN0cnVjdCBib2R5 ICpscD1OVUxMOw0KICAgIGludCB0aHJlYWRudW0gPSAwOw0KDQogICAgZm9y IChycCA9IHRocmVhZGxpc3Q7IHJwICE9IE5VTEw7IHJwID0gcnAtPm5leHQp IHsNCiAgICAgICAgaWYgKHJwLT5uZXh0ICE9IE5VTEwgJiYgcnAtPm5leHQt Pm1zZ251bSA9PSBudW0gJiYgcnAtPm1zZ251bSAhPSAtMSkgew0KICAgICAg ICAgICAgdGhyZWFkbnVtID0gcnAtPm1zZ251bTsNCiAgICAgICAgICAgIHN0 cmNweW1heChuYW1lLCBycC0+bmV4dC0+bmFtZSwgTkFNRVNUUkxFTik7DQog ICAgICAgICAgICBzdHJjcHltYXgoc3ViamVjdCwgcnAtPm5leHQtPnN1Ympl Y3QsIFNVQkpTVFJMRU4pOw0KICAgICAgICAgICAgYnJlYWs7DQogICAgICAg IH0NCiAgICB9DQoNCiAgICBpZiAocnAgPT0gTlVMTCkNCiAgICAgICAgcmV0 dXJuOw0KDQogICAgc3ByaW50ZihmaWxlbmFtZSwgIiVzJXMlLjRkLmh0bWwi LCBkaXIsDQogICAgKGRpcltzdHJsZW4oZGlyKSAtIDFdID09ICcvJykgPyAi IiA6ICIvIiwgdGhyZWFkbnVtKTsNCg0KICAgIGJwID0gTlVMTDsNCiAgICBp ZiAoKGZwID0gZm9wZW4oZmlsZW5hbWUsICJyIikpICE9IE5VTEwpIHsNCiAg ICAgICAgd2hpbGUgKChmZ2V0cyhsaW5lLCBNQVhMSU5FLCBmcCkpICE9IE5V TEwpDQogICAgICAgICAgICBicCA9IChzdHJ1Y3QgYm9keSAqKSBhZGRib2R5 KGJwLCAmbHAsIGxpbmUsIDApOw0KICAgIH0NCiAgICBlbHNlDQogICAgICAg IHJldHVybjsNCg0KICAgIGZjbG9zZShmcCk7DQoNCiAgICBjcCA9IGJwOyAg Lyogc2F2ZSBzdGFydCBvZiBsaXN0IHRvIGZyZWUgbGF0ZXIgKi8NCg0KICAg IGlmICgoZnAgPSBmb3BlbihmaWxlbmFtZSwgIncrIikpICE9IE5VTEwpIHsN CiAgICAgICAgd2hpbGUgKGJwICE9IE5VTEwpIHsNCiAgICAgICAgICAgIGZw cmludGYoZnAsICIlcyIsIGJwLT5saW5lKTsNCiAgICAgICAgICAgIGlmICgh c3RybmNtcChicC0+bGluZSwgIjwhLS0gbmV4dHRociIsIDEyKSkgew0KICAg ICAgICAgICAgICAgIGZwcmludGYoZnAsICI8TEk+PFNUUk9ORz5OZXh0IGlu IHRocmVhZDo8L1NUUk9ORz4gIik7DQogICAgICAgICAgICAgICAgZnByaW50 ZihmcCwgIjxBIEhSRUY9XCIlLjRkLmh0bWxcIj4iLCBudW0pOw0KICAgICAg ICAgICAgICAgIGZwcmludGYoZnAsICIlczogXCIlc1wiPC9BPlxuIiwNCiAg ICAgICAgICAgICAgICBuYW1lLCBjb252Y2hhcnMoc3ViamVjdCkpOw0KICAg ICAgICAgICAgfQ0KICAgICAgICAgICAgYnAgPSBicC0+bmV4dDsNCiAgICAg ICAgfQ0KICAgIH0NCiAgICBmY2xvc2UoZnApOw0KDQogICAgLyogY2FuIHdl IGNsZWFuIHVwIGEgYml0IHBsZWFzZS4uLiAqLw0KICAgIGJwID0gY3A7DQog ICAgd2hpbGUgKGJwICE9IE5VTEwpIHsNCiAgICAgICAgY3AgPSBicC0+bmV4 dDsNCiAgICAgICAgaWYgKGJwLT5saW5lKSBmcmVlKGJwLT5saW5lKTsNCiAg ICAgICAgZnJlZShicCk7DQogICAgICAgIGJwID0gY3A7DQogICAgfQ0KfQ0K DQo= ---559023410-851401618-901288998=:17635 Content-Type: TEXT/PLAIN; charset="US-ASCII"; name="print.c" Content-Transfer-Encoding: BASE64 Content-ID: Content-Disposition: attachment; filename="print.c" X-Sun-Content-Length: 53472 LyogDQoqKiBDb3B5cmlnaHQgKEMpIDE5OTQsIDE5OTUgRW50ZXJwcmlzZSBJ bnRlZ3JhdGlvbiBUZWNobm9sb2dpZXMgQ29ycC4NCioqICAgICAgICAgVmVy aUZvbmUgSW5jLi9IZXdsZXR0LVBhY2thcmQuIEFsbCBSaWdodHMgUmVzZXJ2 ZWQuDQoqKiBLZXZpbiBIdWdoZXMsIGtldkBrZXZjb20uY29tIDMvMTEvOTQN CioqIEtlbnQgTGFuZGZpZWxkLCBrZW50QGxhbmRmaWVsZC5jb20gNC82Lzk3 DQoqKiANCioqIFRoaXMgcHJvZ3JhbSBhbmQgbGlicmFyeSBpcyBmcmVlIHNv ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgDQoqKiBt b2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgKExpYnJhcnkp IEdlbmVyYWwgUHVibGljIExpY2Vuc2UgDQoqKiBhcyBwdWJsaXNoZWQgYnkg dGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24g MiANCioqIG9mIHRoZSBMaWNlbnNlLCBvciBhbnkgbGF0ZXIgdmVyc2lvbi4g DQoqKiANCioqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUg aG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCANCioqIGJ1dCBXSVRIT1VU IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJh bnR5IG9mIA0KKiogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEg UEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIA0KKiogR05VIChMaWJyYXJ5 KSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuIA0K KiogDQoqKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRo ZSBHTlUgKExpYnJhcnkpIEdlbmVyYWwgUHVibGljIExpY2Vuc2UNCioqIGFs b25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBG cmVlIFNvZnR3YXJlIA0KKiogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxl IFBsYWNlIC0gU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3LCBV U0EgDQoqLw0KDQojaW5jbHVkZSAiaHlwZXJtYWlsLmgiDQojaW5jbHVkZSA8 Y3R5cGUuaD4NCg0KI2RlZmluZSBGUk9NX0FVVEhPUiAgMA0KI2RlZmluZSBG Uk9NX0RBVEUgICAgMQ0KI2RlZmluZSBGUk9NX1RIUkVBRCAgMg0KI2RlZmlu ZSBGUk9NX1NVQkpFQ1QgMw0KDQojZGVmaW5lIFBBR0VfVE9QICAgICAxDQoj ZGVmaW5lIFBBR0VfQk9UVE9NICAyDQoNCnR5cGVkZWYgZW51bSB7REFURV9J TkRFWCwgVEhSRUFEX0lOREVYLCBTVUJKRUNUX0lOREVYLCBBVVRIT1JfSU5E RVgsDQogICAgICAgICAgICAgIE5PX0lOREVYfSBtaW5kZXhfdDsNCg0KLyoN CioqIFByaW50cyBhIHByb2dyYW0gZXJyb3Igc3RyaW5nIGFuZCBzdG9wcy4g SWYgZXJyb3JzdHIgaXMgTlVMTCwNCioqIHRoaXMgcHJpbnRzIHdoYXRldmVy IGhhcHBlbnMgdG8gYmUgaW4gZXJyc3RyW10gYXQgdGhlIHRpbWUuDQoqLw0K DQp2b2lkIHByb2dlcnIoY2hhciAqZXJyb3JzdHIpDQp7DQogICAgaWYgKGVy cm9yc3RyICE9IE5VTEwpDQogICAgICAgIGZwcmludGYoc3RkZXJyLCAiJXM6 ICVzXG4iLCBQUk9HTkFNRSwgZXJyb3JzdHIpOw0KICAgIGVsc2UNCiAgICAg ICAgZnByaW50ZihzdGRlcnIsICIlczogJXNcbiIsIFBST0dOQU1FLCBlcnJt c2cpOw0KICAgIGZwcmludGYoc3RkZXJyLCAiJXM6IHR5cGUgXCIlcyAtelwi IGZvciBvcHRpb25zLlxuIiwgUFJPR05BTUUsIFBST0dOQU1FKTsNCiAgICBl eGl0KC0xKTsNCn0NCg0KLyoNCioqIE91dHB1dCBhIG1lbnUgbGluZSB3aXRo IGh5cGVybGlua3MgZm9yIHRhYmxlIGRpc3BsYXkNCioqDQoqKiBBbGwgcGFy YW1ldGVycyBhcmUgaW5wdXRzIG9ubHkuICBQYXJhbWV0ZXJzOg0KKiogICBm cCAgICAgICA6IEhUTUwgb3V0cHV0IGZpbGUgcG9pbnRlcg0KKiogICBpZHgg ICAgICA6IFR5cGUgb2YgcGFnZSB0aGlzIG1lbnUgaXMgZm9yLg0KKiogICBh Ym91dCAgICA6ICJOT05FIiBvciBlbHNlIHRoZSBVUkwgb2YgaW5mbyBhYm91 dCB0aGlzIGFyY2hpdmUuDQoqKiAgIGFyY2hpdmVzIDogIk5PTkUiIG9yIGVs c2UgdGhlIFVSTCBvZiBtb3JlIGh5cGVybWFpbCBhcmNoaXZlcy4NCioqICAg Y3VycmVudGlkOiAiIiBvciBlbHNlIHRoZSBpZCBvZiB0aGUgImN1cnJlbnQi IG1lc3NhZ2UuDQoqKiAgIGN1cnN1YiAgIDogIiIgb3IgZWxzZSB0aGUgc3Vi amVjdCBvZiB0aGUgImN1cnJlbnQiIG1lc3NhZ2UuDQoqKiAgIHBvcyAgICAg IDogQ2FsbGVkIGF0IHRoZSB0b3Agb3IgYm90dG9tIG9mIHRoZSBwYWdlLg0K Ki8NCg0Kdm9pZCBmcHJpbnRfbWVudShGSUxFICpmcCwgbWluZGV4X3QgaWR4 LCBjaGFyICphYm91dCwgY2hhciAqYXJjaGl2ZXMsDQogICAgICAgICAgICAg ICAgIGNoYXIgKmN1cnJlbnRpZCwgY2hhciAqY3Vyc3ViLCBpbnQgcG9zKQ0K ew0KICAgZnByaW50ZihmcCwgIjxESVYgQUxJR049Q0VOVEVSPlxuPFRBQkxF IEJPUkRFUj0yIFdJRFRIPVwiMTAwJSVcIj5cbjxUUj5cbiIpOw0KDQogICBp ZiAobWFpbGNvbW1hbmQpIHsNCiAgICAgICBpZiAoKmhtYWlsKSB7DQogICAg ICAgICAgIGZwcmludGYoZnAsICI8VEg+PEEgSFJFRj1cIiVzXCI+TmV3IE1l c3NhZ2U8L0E+PC9USD5cbiIsDQogICAgICAgICAgICAgICAgICBtYWtlbWFp bGNvbW1hbmQoIm1haWx0bzokVE8iLCBobWFpbCwgIiIsICIiKSk7DQoNCiAg ICAgICAgICAgaWYoKGN1cnJlbnRpZCAhPSBOVUxMICYmIGN1cnJlbnRpZFsw XSAhPSAnXDAnKSB8fA0KICAgICAgICAgICAgICAoY3Vyc3ViICAgICE9IE5V TEwgJiYgY3Vyc3ViWzBdICAgICE9ICdcMCcpKQ0KICAgICAgICAgICAgICBm cHJpbnRmKGZwLCAiPFRIPjxBIEhSRUY9XCIlc1wiPlJlcGx5PC9BPjwvVEg+ XG4iLA0KICAgICAgICAgICAgICAgICAgIG1ha2VtYWlsY29tbWFuZChtYWls Y29tbWFuZCxobWFpbCxjdXJyZW50aWQsY3Vyc3ViKSk7DQogICAgICAgfQ0K ICAgfQ0KDQogICBpZiAoKmFib3V0KQ0KICAgICAgZnByaW50ZihmcCwiPFRI PjxBIEhSRUY9XCIlc1wiPkFib3V0IHRoaXMgbGlzdDwvQT48L1RIPlxuIixh Ym91dCk7DQoNCiAgIGlmIChpZHggIT0gTk9fSU5ERVggJiYgIXJldmVyc2Up IHsNCiAgICAgIGlmIChwb3MgPT0gUEFHRV9UT1ApDQogICAgICAgICAgZnBy aW50ZihmcCwiPFRIPjxBIEhSRUY9XCIjZW5kXCI+RW5kIG9mIE1lc3NhZ2Vz PC9BPjwvVEg+XG4iKTsNCiAgICAgIGVsc2UNCiAgICAgICAgICBmcHJpbnRm KGZwLCI8VEg+PEEgTkFNRT1cImVuZFwiIEhSRUY9XCIjXCI+U3RhcnQgb2Yg TWVzc2FnZXM8L0E+PC9USD5cbiIpOw0KICAgfQ0KICAgICAgICAgICANCiAg IGlmKGlkeCAhPSBEQVRFX0lOREVYKQ0KICAgICAgZnByaW50ZihmcCwiPFRI PjxBIEhSRUY9XCIlc1wiPkRhdGUgdmlldzwvQT48L1RIPlxuIixkYXRlbmFt ZSk7DQoNCiAgIGlmKGlkeCAhPSBUSFJFQURfSU5ERVgpDQogICAgICBmcHJp bnRmKGZwLCI8VEg+PEEgSFJFRj1cIiVzXCI+VGhyZWFkIHZpZXc8L0E+PC9U SD5cbiIsdGhyZG5hbWUpOw0KDQogICBpZihpZHggIT0gU1VCSkVDVF9JTkRF WCkNCiAgICAgIGZwcmludGYoZnAsIjxUSD48QSBIUkVGPVwiJXNcIj5TdWJq ZWN0IHZpZXc8L0E+PC9USD5cbiIsc3Viam5hbWUpOw0KDQogICBpZihpZHgg IT0gQVVUSE9SX0lOREVYKQ0KICAgICAgZnByaW50ZihmcCwiPFRIPjxBIEhS RUY9XCIlc1wiPkF1dGhvciB2aWV3PC9BPjwvVEg+XG4iLGF1dGhuYW1lKTsN Cg0KICAgaWYgKCphcmNoaXZlcykNCiAgICAgIGZwcmludGYoZnAsIjxUSD48 QSBIUkVGPVwiJXNcIj5PdGhlciBncm91cHM8L0E+PC9USD5cbiIsIGFyY2hp dmVzKTsNCg0KICAgZnByaW50ZihmcCwgIjwvVFI+XG48L1RBQkxFPlxuPC9E SVY+XG4iKTsNCn0NCg0KLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tKi8NCg0Kdm9pZCBmcHJpbnRfc3VtbWFyeShGSUxFICpmcCwgaW50IGZp cnN0X2QsIGludCBsYXN0X2QsIGludCBudW0pDQp7DQogICBmcHJpbnRmKGZw LCAiPERJViBBTElHTj1DRU5URVI+XG4iKTsNCiAgIGZwcmludGYoZnAsICI8 VEFCTEU+XG48VFI+XG4gIDxUSCBDT0xTUEFOPTQ+JWQgTWVzc2FnZXM8L1RI PlxuPC9UUj5cbiIsIG51bSk7DQogICBmcHJpbnRmKGZwLCAiPFRSPlxuIik7 DQogICBmcHJpbnRmKGZwLCAiICA8VEg+U3RhcnRpbmc6PC9USD48VEQ+PEVN PiVzPC9FTT48L1REPlxuIixnZXRkYXRlc3RyKGZpcnN0X2QpKTsNCiAgIGZw cmludGYoZnAsICIgIDxUSD5FbmRpbmc6PC9USD48VEQ+PEVNPiVzPC9FTT48 L1REPlxuIixnZXRkYXRlc3RyKGxhc3RfZCkpOw0KICAgZnByaW50ZihmcCwg IjwvVFI+XG48L1RBQkxFPlxuPC9ESVY+XG4iKTsNCn0NCg0KLyotLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8NCg0Kdm9pZCBwcmludF9pbmRl eF9oZWFkZXJfbGlua3MoRklMRSAqZnAsY2hhciAqYXJjaGl2ZXMsY2hhciAq YWJvdXQsaW50IGNhbGxlZCkNCnsNCiAgICAvKiANCiAgICAqKiBQcmludCBv dXQgdGhlIGxpbmtzIGZvcg0KICAgICoqIA0KICAgICoqICAgICAgQWJvdXQg dGhpcyBhcmNoaXZlIA0KICAgICoqICAgICAgTW9zdCByZWNlbnQgbWVzc2Fn ZXMgDQogICAgKiogICAgICBNZXNzYWdlcyBzb3J0ZWQgYnk6IFsgZGF0ZSBd WyBzdWJqZWN0IF1bIGF1dGhvciBdIA0KICAgICoqICAgICAgT3RoZXIgbWFp bCBhcmNoaXZlcyANCiAgICAqKg0KICAgICoqIGFzIGFwcHJvcHJpYXRlLg0K ICAgICovDQogICAgDQogICAgZnByaW50ZihmcCwgIjxVTD5cbiIpOw0KDQog ICAgaWYgKCphYm91dCkgew0KICAgICAgICBmcHJpbnRmKGZwLCAiPExJPjxT VFJPTkc+PEEgSFJFRj1cIiVzXCI+QWJvdXQgdGhpcyAiLCBhYm91dCk7DQog ICAgICAgIGZwcmludGYoZnAsICJhcmNoaXZlPC9BPjwvU1RST05HPlxuIik7 DQogICAgfQ0KDQogICAgaWYgKCFyZXZlcnNlICYmIChjYWxsZWQgIT0gRlJP TV9BVVRIT1IgJiYgY2FsbGVkICE9IEZST01fU1VCSkVDVCkpDQogICAgICAg IGZwcmludGYoZnAsDQogICAgICAgICI8TEk+PFNUUk9ORz48QSBIUkVGPVwi I2VuZFwiPk1vc3QgcmVjZW50IG1lc3NhZ2VzPC9BPjwvU1RST05HPlxuIik7 DQoNCiAgICBmcHJpbnRmKGZwLCAiPExJPjxTVFJPTkc+TWVzc2FnZXMgc29y dGVkIGJ5OjwvU1RST05HPiBcbiIpOw0KDQogICAgaWYgKGNhbGxlZCAhPSBG Uk9NX0FVVEhPUikNCiAgICAgICAgZnByaW50ZihmcCwgIjxBIEhSRUY9XCIl c1wiPlsgYXV0aG9yIF08L0E+XG4iLCBhdXRobmFtZSk7DQoNCiAgICBpZiAo Y2FsbGVkICE9IEZST01fREFURSkNCiAgICAgICAgIGZwcmludGYoZnAsICI8 QSBIUkVGPVwiJXNcIj5bIGRhdGUgXTwvQT5cbiIsIGRhdGVuYW1lKTsNCg0K ICAgIGlmIChjYWxsZWQgIT0gRlJPTV9USFJFQUQpDQogICAgICAgICBmcHJp bnRmKGZwLCAiPEEgSFJFRj1cIiVzXCI+WyB0aHJlYWQgXTwvQT5cbiIsIHRo cmRuYW1lKTsNCg0KICAgIGlmIChjYWxsZWQgIT0gRlJPTV9TVUJKRUNUKQ0K ICAgICAgICAgZnByaW50ZihmcCwgIjxBIEhSRUY9XCIlc1wiPlsgc3ViamVj dCBdPC9BPlxuIiwgc3Viam5hbWUpOw0KDQogICAgaWYgKCphcmNoaXZlcykg ew0KICAgICAgICBmcHJpbnRmKGZwLCAiPExJPjxTVFJPTkc+PEEgSFJFRj1c IiVzXCI+T3RoZXIgbWFpbCAiLCBhcmNoaXZlcyk7DQogICAgICAgIGZwcmlu dGYoZnAsICJhcmNoaXZlczwvQT48L1NUUk9ORz5cbiIpOw0KICAgIH0NCiAg ICBmcHJpbnRmKGZwLCAiPC9VTD5cbjxQPlxuIik7DQp9DQoNCnZvaWQgcHJp bnRfaW5kZXhfZm9vdGVyX2xpbmtzKEZJTEUgKmZwLCBjaGFyICphcmNoaXZl cywgaW50IGNhbGxlZCkNCnsNCiAgICAvKiANCiAgICAqKiBQcmludCBvdXQg dGhlIGxpbmtzIGZvcg0KICAgICoqIA0KICAgICoqICAgICAgTWVzc2FnZXMg c29ydGVkIGJ5OiBbIGRhdGUgXVsgc3ViamVjdCBdWyBhdXRob3IgXSANCiAg ICAqKiAgICAgIE90aGVyIG1haWwgYXJjaGl2ZXMgDQogICAgKioNCiAgICAq KiBhcyBhcHByb3ByaWF0ZS4NCiAgICAqLw0KDQogICAgZnByaW50ZihmcCwg IjxVTD5cbiIpOw0KICAgIGZwcmludGYoZnAsICI8TEk+PFNUUk9ORz5NZXNz YWdlcyBzb3J0ZWQgYnk6PC9TVFJPTkc+IFxuIik7DQoNCiAgICBpZiAoY2Fs bGVkICE9IEZST01fQVVUSE9SKQ0KICAgICAgICBmcHJpbnRmKGZwLCAiPEEg SFJFRj1cIiVzXCI+WyBhdXRob3IgXTwvQT5cbiIsIGF1dGhuYW1lKTsNCg0K ICAgIGlmIChjYWxsZWQgIT0gRlJPTV9EQVRFKQ0KICAgICAgICBmcHJpbnRm KGZwLCAiPEEgSFJFRj1cIiVzXCI+WyBkYXRlIF08L0E+XG4iLCBkYXRlbmFt ZSk7DQoNCiAgICBpZiAoY2FsbGVkICE9IEZST01fVEhSRUFEKQ0KICAgICAg ICBmcHJpbnRmKGZwLCAiPEEgSFJFRj1cIiVzXCI+WyB0aHJlYWQgXTwvQT5c biIsIHRocmRuYW1lKTsNCg0KICAgIGlmIChjYWxsZWQgIT0gRlJPTV9TVUJK RUNUKQ0KICAgICAgICBmcHJpbnRmKGZwLCAiPEEgSFJFRj1cIiVzXCI+WyBz dWJqZWN0IF08L0E+XG4iLCBzdWJqbmFtZSk7DQoNCiAgICBpZiAoKmFyY2hp dmVzKSB7DQogICAgICAgIGZwcmludGYoZnAsICI8TEk+PFNUUk9ORz48QSBI UkVGPVwiJXNcIj5PdGhlciBtYWlsICIsIGFyY2hpdmVzKTsNCiAgICAgICAg ZnByaW50ZihmcCwgImFyY2hpdmVzPC9BPjwvU1RST05HPlxuIik7DQogICAg fQ0KICAgIGZwcmludGYoZnAsICI8L1VMPlxuXG4iKTsNCn0NCg0KLyoNCioq IFByaW50cyBhIGNvbW1lbnQgaW4gdGhlIGZpbGUuDQoqLw0KDQp2b2lkIHBy aW50Y29tbWVudChGSUxFICpmcCwgY2hhciAqbGFiZWwsIGNoYXIgKnZhbHVl KQ0Kew0KICAgIGZwcmludGYoZnAsICI8IS0tICVzPVwiJXNcIiAtLT5cbiIs IGxhYmVsLCB2YWx1ZSk7DQp9DQoNCi8qDQoqKiBQcmludHMgYSBsaW5lIG9m IEhUTUwuIFVzZWQgdG8gZmlsdGVyIG9mZiB1bndhbnRlZCB0YWdzIGZyb20g dGhlIG91dHB1dC4NCiovDQoNCnZvaWQgcHJpbnRodG1sKEZJTEUgKmZwLCBj aGFyICpsaW5lKQ0Kew0KICAvKiB0aGUgYmFubmVkIHRhZ3MgaWdub3JlIGFs bCBvZiB0aGVtIHRoYXQgYmVnaW4gZXhhY3RseSBsaWtlICI8dGFnIiBvcg0K ICAgICAiPC90YWciIChjYXNlIGluc2Vuc2l0aXZlKS4gQW55IG90aGVyIGxl dHRlcnMgd2l0aGluIHRoZSB0YWdzIGRlc3Ryb3kNCiAgICAgdGhpcyBmaWx0 ZXIgY2FwYWJpbGl0eS4gKi8NCg0KICBjaGFyICpiYW5uZWRfdGFnc1tdPXsi aHRtbD4ifTsgLyogZW5kaW5nID4tbGV0dGVyIG11c3QgYmUgaW5jbHVkZWQg Ki8NCiAgaW50IGk7DQogIGludCBpbmRleDsNCiAgDQogIHdoaWxlKCpsaW5l KSB7DQogICAgaWYoJzwnICE9ICpsaW5lKQ0KICAgICAgZnB1dGMoKmxpbmUr KywgZnApOw0KICAgIGVsc2Ugew0KICAgICAgaWYoJy8nID09IGxpbmVbMV0p DQogICAgICAgIGluZGV4PTI7DQogICAgICBlbHNlDQogICAgICAgIGluZGV4 PTE7DQogICAgICBmb3IoaT0wOyBpPHNpemVvZihiYW5uZWRfdGFncykvc2l6 ZW9mKGJhbm5lZF90YWdzWzBdKTtpKyspIHsNCiAgICAgICAgaWYoIXN0cm5j YXNlY21wKCZsaW5lW2luZGV4XSwNCiAgICAgICAgICAgICAgICAgICAgICAg IGJhbm5lZF90YWdzW2ldLA0KICAgICAgICAgICAgICAgICAgICAgICAgc3Ry bGVuKGJhbm5lZF90YWdzW2ldKSkpIHsNCiAgICAgICAgICBsaW5lKz1zdHJs ZW4oYmFubmVkX3RhZ3NbaV0pK2luZGV4Ow0KICAgICAgICAgIGJyZWFrOw0K ICAgICAgICB9DQogICAgICB9DQogICAgICBpZihzaXplb2YoYmFubmVkX3Rh Z3MpL3NpemVvZihiYW5uZWRfdGFnc1swXSkgPT0gaSkgew0KICAgICAgICBm cHV0YygqbGluZSsrLCBmcCk7DQogICAgICAgIGlmKDIgPT0gaW5kZXgpDQog ICAgICAgICAgZnB1dGMoKmxpbmUrKywgZnApOw0KICAgICAgfQ0KICAgIH0N CiAgfQ0KDQp9DQoNCi8qDQoqKiBQcmV0dHktcHJpbnRzIHRoZSBkYXRlcyBp biB0aGUgaW5kZXggZmlsZXMuDQoqLw0KDQp2b2lkIHByaW50ZGF0ZXMoRklM RSAqZnAsIHN0cnVjdCBoZWFkZXIgKmhwKQ0Kew0KICAgIGlmIChocCAhPSBO VUxMKSB7DQogICAgICAgIHByaW50ZGF0ZXMoZnAsIGhwLT5sZWZ0KTsNCiAg ICAgICAgZnByaW50ZihmcCwgIjxMST48QSBIUkVGPVwiJS40ZC5odG1sXCI+ PFNUUk9ORz4lczwvU1RST05HPjwvQT4gIiwNCiAgICAgICAgICAgICAgICAg ICAgaHAtPm1zZ251bSwgY29udmNoYXJzKGhwLT5zdWJqZWN0KSk7DQogICAg ICAgIGZwcmludGYoZnAsICI8QSBOQU1FPVwiJWRcIj48RU0+JXM8L0VNPjwv QT5cbiIsIGhwLT5tc2dudW0sIGhwLT5uYW1lKTsNCiAgICAgICAgcHJpbnRk YXRlcyhmcCwgaHAtPnJpZ2h0KTsNCiAgICB9DQp9DQoNCmludCBzaG93aGVh ZGVyKGNoYXIgKmhlYWRlcikNCnsNCiAgIHJldHVybiAoaW5saXN0KHNob3df aGVhZGVycywgaGVhZGVyKSk7DQp9DQoNCg0KLyoNCioqIFRoZSBoZXVyaXN0 aWNzIGZvciBkaXNwbGF5aW5nIGFuIG90aGVyd2lzZSBvcmRpbmFyeSBsaW5l IChhIG5vbi1xdW90ZSwNCioqIG5vbi1zaWcsIG5vbi1pbmh0bWwsIG5vbi1i bGFuayBsaW5lKSBpZiAnc2hvd2h0bWwnIGlzIHRydWUgKHdoaWNoIHJlYWxs eQ0KKiogbWVhbnMgd2UncmUgKm5vdCogZG9pbmcgPFBSRT4gdG8gZm9ybWF0 IHRoZSB0ZXh0KSBoYXZlIGNoYW5nZWQgc28gdGhhdA0KKiogaW5kZW50ZWQg dGV4dCBzaG93cyB1cCBjb3JyZWN0bHkuICBGaXJzdCwgbGVhZGluZyBzcGFj ZXMgYmVjb21lIEhUTUwNCioqIG5vbi1icmVha2luZyBzcGFjZXMgKCZuYnNw OykuICBJbiBvcmRlciBmb3IgdGhpcyB0byB3b3JrLCB0aG9zZSBsaW5lcw0K KiogbXVzdCBoYXZlIGJlZW4gcHJlY2VkZWQgYnkgYSA8QlI+IG9yIDxQPi4g IFdlIGFjY29tcGxpc2ggdGhpcyBieSBjaGVja2luZw0KKiogYWhlYWQgd2hl biB3ZSBwcmludCBlYWNoIGxpbmUuLi4gaWYgd2UgZGV0ZXJtaW5lIHRoYXQg dGhlIG5leHQgbGluZQ0KKiogc2hvdWxkIGJlIGJyb2tlbiBiZWZvcmUsIHdl IGRvIHNvLg0KKi8NCg0Kdm9pZCBwcmludGJvZHkoRklMRSAqZnAsIHN0cnVj dCBib2R5ICpicCwgY2hhciAqaWQsIGNoYXIgKnN1YmplY3QpDQp7DQogICAg aW50IGluc2lnLCBpbmJsYW5rOw0KICAgIGludCBpbmh0bWw7DQogICAgY2hh ciBpbmhlYWRlcj1GQUxTRTsgLyogd2UgYWx3YXlzIHN0YXJ0IGluIGEgbWFp bCBoZWFkZXIgKi8NCiAgICBpbnQgcHJlPUZBTFNFOw0KDQogICAgaWYgKHNo b3docikNCiAgICAgICAgZnByaW50ZihmcCwgIjxIUj5cbiIpOw0KDQogICAg cHJpbnRjb21tZW50KGZwLCAiYm9keSIsICJzdGFydCIpOw0KDQogICAgaWYg KCFzaG93aHRtbCkgew0KICAgICAgZnByaW50ZihmcCwgIjxQUkU+XG4iKTsN CiAgICAgIHByZT1UUlVFOw0KICAgIH0NCiNpZiAwDQogICAgZWxzZQ0KICAg ICAgcHJpbnRmKCJTSE9XSFRNTCBpcyBPTlxuIik7DQojZW5kaWYNCiAgICBp bmJsYW5rID0gMTsNCiAgICBpbnNpZyA9IDA7DQoNCiAgICBpbmh0bWwgPSAw Ow0KDQogICAgd2hpbGUgKGJwICE9IE5VTEwpIHsNCiNpZiAxDQogICAgICAg ICAgaWYgKGJwLT5odG1sKSB7DQogICAgICAgICAgICAvKiBhbHJlYWR5IGlu IEhUTUwsIGRvbid0IHRvdWNoICovDQogICAgICAgICAgICBwcmludGh0bWwo ZnAsIGJwLT5saW5lKTsNCiNlbHNlDQogICAgICAgICAgaWYgKGJwLT5odG1s ICYmIChzdHJuY2FzZWNtcChicC0+bGluZSwgIjxIVE1MPiIsIDYpICYmIA0K ICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RybmNhc2VjbXAoYnAtPmxp bmUsICI8L0hUTUw+IiwgNykpKSB7DQogICAgICAgICAgICBmcHJpbnRmKGZw LCAiJXMiLCBicC0+bGluZSk7DQojZW5kaWYNCiAgICAgICAgICAgIGJwID0g YnAtPm5leHQ7DQogICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgICB9 DQoNCiAgICAgICAgICBpZihicC0+aGVhZGVyKSB7DQogICAgICAgICAgICBj aGFyIGhlYWRbMTI4XTsNCiAgICAgICAgICAgIGlmKCFpbmhlYWRlcikgew0K ICAgICAgICAgICAgICBpZighcHJlICYmIHNob3dodG1sICYmIHNob3doZWFk ZXJzKSB7DQogICAgICAgICAgICAgICAgZnByaW50ZihmcCwgIjxQUkU+XG4i KTsNCiAgICAgICAgICAgICAgICBwcmU9VFJVRTsNCiAgICAgICAgICAgICAg fQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgaW5oZWFkZXI9VFJVRTsN CiAgICAgICAgICAgIGlmKHNzY2FuZihicC0+bGluZSwgIiUxMjdbXjpdIiwg aGVhZCkgJiYNCiAgICAgICAgICAgICAgIHNob3dfaGVhZGVycyAmJiAhc2hv d2hlYWRlcihoZWFkKSkgew0KICAgICAgICAgICAgICAvKiB0aGUgc2hvdyBo ZWFkZXIga2V5d29yZCBoYXMgYmVlbiB1c2VkLCB0aGVuIHdlIHNraXAgYWxs IHRob3NlDQogICAgICAgICAgICAgICAgIHRoYXQgYXJlbid0IG1lbnRpb25l ZCEgKi8NCiAgICAgICAgICAgICAgaWYoaXNhbG51bSgqaGVhZCkgfHwgIXNo b3doZWFkZXJzKSB7DQogICAgICAgICAgICAgICAgLyogdGhpcyBjaGVjayBp cyBvbmx5IHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBsYXN0IGxpbmUgYW1vbmcg DQogICAgICAgICAgICAgICAgICAgdGhlIGhlYWRlcnMgKHRoZSAiXG4iIG9u ZSkgd29uJ3QgYmUgZmlsdGVyZWQgb2ZmICovDQogICAgICAgICAgICAgICAg YnAgPSBicC0+bmV4dDsNCiAgICAgICAgICAgICAgICBjb250aW51ZTsNCiAg ICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICAgIH0NCiAg ICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgIGlmKGluaGVhZGVyKSB7DQog ICAgICAgICAgICAgIGlmKHNob3dodG1sICYmIHNob3doZWFkZXJzICYmIHBy ZSkgew0KICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICI8L1BSRT5cbiIp Ow0KICAgICAgICAgICAgICAgIHByZT1GQUxTRTsNCiAgICAgICAgICAgICAg fQ0KICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPFA+XG4iKTsNCiAgICAg ICAgICAgIH0NCiAgICAgICAgICAgIGluaGVhZGVyPUZBTFNFOw0KICAgICAg ICAgIH0NCg0KICAgICAgICAgIGlmIChicC0+YXR0YWNoZWQgJiYgYnAtPmhl YWRlcikgew0KICAgICAgICAgICAgLyoNCiAgICAgICAgICAgICAqIFRoaXMg aXMgYW4gYXR0YWNoZWQgbWFpbCdzIGhlYWRlcnMuIE9ubHkgb3V0cHV0IHRo ZSBmZXcNCiAgICAgICAgICAgICAqIG9uZXMgd2UgbWlnaHQgYmUgaW50ZXJl c3RlZCBpbi4gSG1tbS4uLiBBcmUgdGhlcmUgb3RoZXJzID8NCiAgICAgICAg ICAgICAqLw0KI2lmIDANCiAgICAgICAgICAgIGlmICghc3RybmNtcChicC0+ bGluZSwgIkZyb206IiwgNSkgfHwNCiAgICAgICAgICAgICAgICFzdHJuY21w KGJwLT5saW5lLCAiVG86IiwgMykgfHwNCiAgICAgICAgICAgICAgICFzdHJu Y21wKGJwLT5saW5lLCAiRGF0ZToiLCA1KSB8fA0KICAgICAgICAgICAgICAg IXN0cm5jbXAoYnAtPmxpbmUsICJTdWJqZWN0OiIsIDgpICkgew0KI2VuZGlm DQogICAgICAgICAgICAgIGZwcmludGYoZnAsICI8U1RST05HPiVzPC9TVFJP Tkc+PEJSPlxuIiwgYnAtPmxpbmUpOw0KI2lmIDANCiAgICAgICAgICAgIH0N CiNlbmRpZg0KICAgICAgICAgICAgYnAgPSBicC0+bmV4dDsNCiAgICAgICAg ICAgIGNvbnRpbnVlOyAgICAgICAgICAgIA0KICAgICAgICAgIH0NCg0KICAg ICAgICBpZiAoKGJwLT5saW5lKVswXSA9PSAnXG4nKSB7DQojaWYgMA0KICAg ICAgICAgICAgaWYgKGJwLT5oZWFkZXIgJiYgc2hvd2h0bWwgJiYgc2hvd2hl YWRlcnMpDQogICAgICAgICAgICAgICAgZnByaW50ZihmcCwgIjwvUFJFPlxu Iik7DQojZW5kaWYNCiAgICAgICAgfQ0KICAgICAgICBlbHNlIGlmIChicC0+ aGVhZGVyICYmICFzaG93aGVhZGVycykgew0KICAgICAgICAgICAgYnAgPSBi cC0+bmV4dDsNCiAgICAgICAgICAgIGNvbnRpbnVlOw0KICAgICAgICB9DQoN CiAgICAgICAgaWYgKChicC0+bGluZSlbMF0gPT0gJ1xuJyAmJiBpbmJsYW5r KSB7DQogICAgICAgICAgICBicCA9IGJwLT5uZXh0Ow0KICAgICAgICAgICAg Y29udGludWU7DQogICAgICAgIH0NCiAgICAgICAgZWxzZQ0KICAgICAgICAg ICAgaW5ibGFuayA9IDA7DQoNCiAgICAgICAgaWYgKCFzdHJuY2FzZWNtcChi cC0+bGluZSwgIjxIVE1MPiIsIDYpKSB7DQogICAgICAgICAgICBpbmh0bWwg PSAxOw0KICAgICAgICAgICAgaWYgKCFzaG93aHRtbCAmJiBwcmUpIHsNCiAg ICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPC9QUkU+XG4iKTsNCiAgICAg ICAgICAgICAgICBwcmU9RkFMU0U7DQogICAgICAgICAgICB9DQogICAgICAg IH0NCiAgICAgICAgZWxzZSBpZiAoIXN0cm5jYXNlY21wKGJwLT5saW5lLCAi PC9IVE1MPiIsIDcpKSB7DQogICAgICAgICAgICBpbmh0bWwgPSAwOw0KICAg ICAgICAgICAgZnByaW50ZihmcCwgIiVzIiwgYnAtPmxpbmUpOw0KICAgICAg ICAgICAgaWYgKCFzaG93aHRtbCAmJiAhcHJlKSB7DQogICAgICAgICAgICAg ICAgZnByaW50ZihmcCwgIjxQUkU+XG4iKTsNCiAgICAgICAgICAgICAgICBw cmU9VFJVRTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGJwID0gYnAt Pm5leHQ7DQogICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgfQ0KDQog ICAgICAgIGlmIChpbmh0bWwpIHsNCiAgICAgICAgICAgIGZwcmludGYoZnAs ICIlcyIsIGJwLT5saW5lKTsNCiAgICAgICAgICAgIGJwID0gYnAtPm5leHQ7 DQogICAgICAgICAgICBjb250aW51ZTsNCiAgICAgICAgfQ0KICAgICAgICBp ZiAoc2hvd2h0bWwpIHsNCiAgICAgICAgICAgIGlmICghc3RyY21wKGJwLT5s aW5lLCAiLS1cbiIpIHx8DQogICAgICAgICAgICAgICAgIXN0cmNtcChicC0+ bGluZSwgIi0tIFxuIikgfHwNCiAgICAgICAgICAgICAgICAhc3RyY21wKGJw LT5saW5lLCAiLS0tXG4iKSkgew0KICAgICAgICAgICAgICAgIGluc2lnID0g MTsNCiAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPFBSRT5cbiIpOw0K ICAgICAgICAgICAgICAgIHByZT1UUlVFOw0KICAgICAgICAgICAgfQ0KDQog ICAgICAgICAgICBpZiAoKGJwLT5saW5lKVswXSA9PSAnXG4nKQ0KICAgICAg ICAgICAgICAgIDsNCiAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAg ICAgIGlmIChpbnNpZykNCiAgICAgICAgICAgICAgICAgICAgZnByaW50Zihm cCwgIiVzIiwgKGNoYXIgKiljb252dXJscyhicC0+bGluZSxpZCxzdWJqZWN0 KSk7DQogICAgICAgICAgICAgICAgZWxzZSBpZiAoaXNxdW90ZShicC0+bGlu ZSkpIHsNCiAgICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwgIiVzJXMl c1xuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChpcXVvdGVzKT8i PEVNPiI6IiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogRGFu aWVsIGNoYW5nZWQgdGhpcyAxMHRoIG9mIEp1bHkgMTk5OCBmcm9tDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udnVybHMocm1jcihicC0+ bGluZSksIGlkLCBzdWJqZWN0KSwgKi8NCiAgICAgICAgICAgICAgICAgICAg ICAgICAgIGNvbnZ1cmxzKGJwLT5saW5lLCBpZCwgc3ViamVjdCksDQogICAg ICAgICAgICAgICAgICAgICAgICAgICAoaXF1b3Rlcyk/IjwvRU0+IjoiIik7 DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIGVsc2UgaWYg KChicC0+bGluZSlbMF0gIT0gJ1wwJykgew0KICAgICAgICAgICAgICAgICAg ICBpbnQgc3A7DQogICAgICAgICAgICAgICAgICAgIGZvciAoc3AgPSAwO2lz c3BhY2UoYnAtPmxpbmVbc3BdKTtzcCsrKXsNCiAgICAgICAgICAgICAgICAg ICAgICAgIGlmIChicC0+bGluZVtzcF0gPT0gJ1x0JykNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiJm5ic3A7Jm5ic3A7Jm5i c3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Iik7DQogICAgICAg ICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgZnByaW50ZihmcCwgIiZuYnNwOyIpOw0KICAgICAgICAgICAgICAg ICAgICB9DQogICAgICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICIlcyIs Y29udnVybHMoJmJwLT5saW5lW3NwXSxpZCxzdWJqZWN0KSk7DQoNCiAgICAg ICAgICAgICAgICAgICAgLyoNCiAgICAgICAgICAgICAgICAgICAgKiogRGV0 ZXJtaW5lIHdoZXRoZXIgd2Ugc2hvdWxkIGJyZWFrLg0KICAgICAgICAgICAg ICAgICAgICAqKiBXZSBjb3VsZCBjaGVjayBmb3IgbGVhZGluZyBzcGFjZXMN CiAgICAgICAgICAgICAgICAgICAgKiogb3IgcXVvdGUgbGluZXMsIGJ1dCBp biBnZW5lcmFsLA0KICAgICAgICAgICAgICAgICAgICAqKiBub24tYWxwaGFu dW1lcmljIGxpbmVzIHNob3VsZCBiZQ0KICAgICAgICAgICAgICAgICAgICAq KiBicm9rZW4gYmVmb3JlLg0KICAgICAgICAgICAgICAgICAgICAqLw0KIA0K ICAgICAgICAgICAgICAgICAgICBpZiAoKHNob3diciAmJiAhYnAtPmhlYWRl cikgfHwNCiAgICAgICAgICAgICAgICAgICAgICAgICgoYnAtPm5leHQgIT0g TlVMTCkgJiYgIWlzYWxudW0oYnAtPm5leHQtPmxpbmVbMF0pKSkNCiAgICAg ICAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPEJSPiIpOw0KICAgICAg ICAgICAgICAgICAgICBpZighYnAtPmhlYWRlcikgew0KICAgICAgICAgICAg ICAgICAgICAgIGZwcmludGYoZnAsICJcbiIpOw0KICAgICAgICAgICAgICAg ICAgICB9DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICB9DQog ICAgICAgIH0NCiAgICAgICAgZWxzZSBpZiAoKGJwLT5saW5lKVswXSAhPSAn XDAnKSB7DQogICAgICAgICAgICBmcHJpbnRmKGZwLCAiJXMiLCAoY2hhciAq KSBjb252dXJscyhicC0+bGluZSwgaWQsIHN1YmplY3QpKTsNCiAgICAgICAg fQ0KICAgICAgICBicCA9IGJwLT5uZXh0Ow0KDQogICAgfQ0KDQogICAgaWYg KHByZSkgDQogICAgICAgIGZwcmludGYoZnAsICI8L1BSRT5cbiIpOw0KDQog ICAgcHJpbnRjb21tZW50KGZwLCAiYm9keSIsICJlbmQiKTsNCiAgICBpZiAo c2hvd2hyKQ0KICAgICAgICBmcHJpbnRmKGZwLCAiPEhSPlxuIik7DQp9DQoN Ci8qDQoqKiBQcmludGluZy4uLnRoZSBvdGhlciBtYWluIHBhcnQgb2YgdGhp cyBwcm9ncmFtIQ0KKiogVGhpcyB3cml0ZXMgb3V0IHRoZSBhcnRpY2xlcywg YmVnaW5uaW5nIHdpdGggdGhlIG51bWJlciBzdGFydG51bS4NCiovDQoNCnZv aWQgd3JpdGVhcnRpY2xlcyhjaGFyICpkaXIsY2hhciAqbGFiZWwsY2hhciAq YWJvdXQsaW50IG92ZXJ3cml0ZSxpbnQgc3RhcnRudW0pDQp7DQogICAgaW50 IG51bSwgc3RhdHVzbnVtLCBza2lwLCBzdWJqbWF0Y2gsIG5ld2ZpbGU7DQog ICAgY2hhciBuYW1lW05BTUVTVFJMRU5dLCBlbWFpbFtNQUlMU1RSTEVOXSwg c3ViamVjdFtTVUJKU1RSTEVOXSwNCiAgICAgICAgaW5yZXBseVtSRVBZU1RS TEVOXSwgZGF0ZVtEQVRFU1RSTEVOXSwgZnJvbWRhdGVbREFURVNUUkxFTl0s DQogICAgICAgIG1zZ2lkW01TR0RTVFJMRU5dOw0KICAgIGNoYXIgbmFtZTJb TkFNRVNUUkxFTl0sIGVtYWlsMltNQUlMU1RSTEVOXSwgc3ViamVjdDJbU1VC SlNUUkxFTl0sDQogICAgICAgIGlucmVwbHkyW1JFUFlTVFJMRU5dLCBkYXRl MltEQVRFU1RSTEVOXSwgZnJvbWRhdGUyW0RBVEVTVFJMRU5dLA0KICAgICAg ICBtc2dpZDJbTVNHRFNUUkxFTl07DQogICAgY2hhciBmaWxlbmFtZVtNQVhG SUxFTEVOXTsNCiAgICBzdHJ1Y3QgYm9keSAqYnAsICpzdGF0dXM7DQogICAg c3RydWN0IHJlcGx5ICpycDsNCiAgICBGSUxFICpmcDsNCg0KICAgIG51bSA9 IHN0YXJ0bnVtOw0KICAgIHNraXAgPSAwOw0KDQogICAgaWYgKHNob3dwcm9n cmVzcykNCiAgICAgICAgcHJpbnRmKCJXcml0aW5nIGFydGljbGVzIHRvIFwi JXNcIi4uLiAgICAiLCBkaXIpOw0KDQogICAgd2hpbGUgKChicCA9IChzdHJ1 Y3QgYm9keSAqKSBoYXNobnVtbG9va3VwKG51bSwgbmFtZSwgZW1haWwsDQog ICAgICAgICAgICBzdWJqZWN0LCBpbnJlcGx5LCBkYXRlLCBmcm9tZGF0ZSwg bXNnaWQpKSAhPSBOVUxMKSB7DQoNCiAgICAgICAgc3ByaW50ZihmaWxlbmFt ZSwgIiVzJXMlLjRkLmh0bWwiLCANCiAgICAgICAgICAgICAgICBkaXIsIChk aXJbc3RybGVuKGRpcikgLSAxXSA9PSAnLycpID8gIiIgOiAiLyIsIG51bSk7 DQoNCiAgICAgICAgLyoNCiAgICAgICAgKiogRGV0ZXJtaW5lIHRvIG92ZXJ3 cml0ZSBmaWxlcyBvciBub3QNCiAgICAgICAgKi8NCg0KICAgICAgICBpZiAo aXNmaWxlKGZpbGVuYW1lKSkNCiAgICAgICAgICAgIG5ld2ZpbGUgPSAwOw0K ICAgICAgICBlbHNlDQogICAgICAgICAgICBuZXdmaWxlID0gMTsNCg0KICAg ICAgICBpZiAoIW5ld2ZpbGUgJiYgIW92ZXJ3cml0ZSkgew0KICAgICAgICAg ICAgc2tpcCA9IDE7IC8qIGlzIHRoaXMgcmVhbGx5IG5lY2Vzc2FyeSB3aXRo IGNvbnRpbnVlID8/PyAqLw0KICAgICAgICAgICAgbnVtKys7DQogICAgICAg ICAgICBjb250aW51ZTsNCiAgICAgICAgfQ0KICAgICAgICBlbHNlIHsNCiAg ICAgICAgICAgIGlmICgoZnAgPSBmb3BlbihmaWxlbmFtZSwgInciKSkgPT0g TlVMTCkgew0KICAgICAgICAgICAgICAgIHNwcmludGYoZXJybXNnLCAiQ291 bGRuJ3Qgd3JpdGUgXCIlc1wiLiIsIGZpbGVuYW1lKTsNCiAgICAgICAgICAg ICAgICBwcm9nZXJyKChjaGFyICopIE5VTEwpOw0KICAgICAgICAgICAgfQ0K ICAgICAgICB9DQoNCiAgICAgICAgLyoNCiAgICAgICAgKiogQ3JlYXRlIHRo ZSBjb21tZW50IGZpZWxkcyBuZWNlc3NhcnkgZm9yIGluY3JlbWVudGFsIHVw ZGF0aW5nDQogICAgICAgICovDQoNCiAgICAgICAgcHJpbnRfbXNnX2hlYWRl cihmcCwgbGFiZWwsIHN1YmplY3QsIGRpciwgbmFtZSwgZW1haWwsIG1zZ2lk KTsNCg0KICAgICAgICBwcmludGNvbW1lbnQoZnAsICJyZWNlaXZlZCIsIGZy b21kYXRlKTsNCiAgICAgICAgcHJpbnRjb21tZW50KGZwLCAic2VudCIsIGRh dGUpOw0KICAgICAgICBwcmludGNvbW1lbnQoZnAsICJuYW1lIiwgbmFtZSk7 DQogICAgICAgIHByaW50Y29tbWVudChmcCwgImVtYWlsIiwgZW1haWwpOw0K ICAgICAgICBwcmludGNvbW1lbnQoZnAsICJzdWJqZWN0IiwgY29udmNoYXJz KHN1YmplY3QpKTsNCiAgICAgICAgcHJpbnRjb21tZW50KGZwLCAiaWQiLCBt c2dpZCk7DQogICAgICAgIHByaW50Y29tbWVudChmcCwgImlucmVwbHl0byIs IGNvbnZjaGFycyhpbnJlcGx5KSk7DQoNCiAgICAgICAgaWYgKHVzZXRhYmxl KSB7DQogICAgICAgICAgICBmcHJpbnRfbWVudShmcCxOT19JTkRFWCxhYm91 dCwiIixtc2dpZCxzdWJqZWN0LFBBR0VfVE9QKTsNCiAgICAgICAgICAgIGZw cmludGYoZnAsICI8UD5cbiIpOw0KICAgICAgICB9DQoNCiAgICAgICAgLyoN CiAgICAgICAgKiogUHJpbnQgdGhlIG1lc3NhZ2UncyBhdXRob3IgaW5mbyBh bmQgZGF0ZS4NCiAgICAgICAgKi8NCg0KICAgICAgICBpZiAoIXN0cmNtcChu YW1lLCBlbWFpbCkpIHsNCiAgICAgICAgICAgIGlmICh1c2VfbWFpbGNvbW1h bmQpIHsNCiAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPEEgSFJFRj1c IiVzXCI+IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgbWFrZW1haWxj b21tYW5kKG1haWxjb21tYW5kLGVtYWlsLG1zZ2lkLHN1YmplY3QpKTsNCiAg ICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPEVNPiVzPC9FTT48L0E+PEJS PlxuIiwgbmFtZSk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNl DQogICAgICAgICAgICAgICAgZnByaW50ZihmcCwgIjxFTT4lczwvRU0+PEJS PlxuIiwgbmFtZSk7DQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAg ICAgICAgICBpZiAodXNlX21haWxjb21tYW5kKSB7ICANCiAgICAgICAgICAg ICAgICBmcHJpbnRmKGZwLCI8U1RST05HPiVzPC9TVFJPTkc+ICg8QSBIUkVG PVwiJXNcIj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSxtYWtl bWFpbGNvbW1hbmQobWFpbGNvbW1hbmQsZW1haWwsbXNnaWQsc3ViamVjdCkp Ow0KICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICI8RU0+JXM8L0VNPjwv QT4pPEJSPlxuIiwgZW1haWwpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAg ICAgZWxzZQ0KICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICIlcyAoPEVN PiVzPC9FTT4pPEJSPlxuIiwgbmFtZSwgZW1haWwpOw0KICAgICAgICB9DQog ICAgICAgIGZwcmludGYoZnAsICI8RU0+JXM8L0VNPlxuPFA+XG4iLCBkYXRl KTsNCiANCiAgICAgICAgLyoNCiAgICAgICAgKiogVGhpcyBpcyBoZXJlIGJl Y2F1c2UgaXQgbG9va3MgYmV0dGVyIGhlcmUuIFRoZSB0YWJsZSBsb29rcw0K ICAgICAgICAqKiBiZXR0ZXIgYmVmb3JlIHRoZSBBdXRob3IgaW5mby4gVGhp cyBzdHVmZiBzaG91bGQgYmUgaW4gDQogICAgICAgICoqIHByaW50ZmlsZSgp IHNvIGl0IGNvdWxkIGJlIGxhaWQgb3V0IGFzIHRoZSB1c2VyIHdhbnRzLi4u DQogICAgICAgICovDQoNCiAgICAgICAgaWYgKCF1c2V0YWJsZSkgew0KICAg ICAgICAgICAgZnByaW50ZihmcCwgIjxVTD5cbiIpOw0KICAgICAgICAgICAg ZnByaW50ZihmcCwgIjxMST48U1RST05HPk1lc3NhZ2VzIHNvcnRlZCBieTo8 L1NUUk9ORz4gXG4iKTsNCiAgICAgICAgICAgIGZwcmludGYoZnAsICI8QSBI UkVGPVwiJXMjJWRcIj5bIGRhdGUgXTwvQT5cbiIsIGRhdGVuYW1lLCBudW0p Ow0KICAgICAgICAgICAgZnByaW50ZihmcCwgIjxBIEhSRUY9XCIlcyMlZFwi PlsgdGhyZWFkIF08L0E+XG4iLCB0aHJkbmFtZSwgbnVtKTsNCiAgICAgICAg ICAgIGZwcmludGYoZnAsICI8QSBIUkVGPVwiJXMjJWRcIj5bIHN1YmplY3Qg XTwvQT5cbiIsIHN1YmpuYW1lLCBudW0pOw0KICAgICAgICAgICAgZnByaW50 ZihmcCwgIjxBIEhSRUY9XCIlcyMlZFwiPlsgYXV0aG9yIF08L0E+XG4iLCBh dXRobmFtZSxudW0pOw0KICAgICAgICB9DQoNCiAgICAgICAgLyoNCiAgICAg ICAgKiogU2hvdWxkIHdlIHByaW50IG1lc3NhZ2UgbGlua3MgPw0KICAgICAg ICAqLw0KDQogICAgICAgIGlmIChzaG93X21zZ19saW5rcykgew0KICAgICAg ICAgICAgcHJpbnRjb21tZW50KGZwLCAibmV4dCIsICJzdGFydCIpOw0KICAg ICAgICAgICAgaWYgKHVzZXRhYmxlKQ0KICAgICAgICAgICAgICAgIGZwcmlu dGYoZnAsICI8VUw+XG4iKTsNCiAgICANCiAgICAgICAgICAgIC8qDQogICAg ICAgICAgICAqKiBJcyB0aGVyZSBhIG5leHQgbWVzc2FnZT8NCiAgICAgICAg ICAgICovDQogICAgDQogICAgICAgICAgICBzdGF0dXMgPSAoc3RydWN0IGJv ZHkgKikgaGFzaG51bWxvb2t1cChudW0gKyAxLCBuYW1lMiwgZW1haWwyLA0K ICAgICAgICAgICAgICAgICAgICAgIHN1YmplY3QyLCBpbnJlcGx5MiwgZGF0 ZTIsIGZyb21kYXRlMiwgbXNnaWQyKTsNCiAgICAgICAgICAgIGlmIChzdGF0 dXMgIT0gTlVMTCkgew0KICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICI8 TEk+PFNUUk9ORz5OZXh0IG1lc3NhZ2U6PC9TVFJPTkc+ICIpOw0KICAgICAg ICAgICAgICAgIGZwcmludGYoZnAsICI8QSBIUkVGPVwiJS40ZC5odG1sXCI+ JXM6IFwiJXNcIjwvQT5cbiIsDQogICAgICAgICAgICAgICAgbnVtICsgMSwg bmFtZTIsIGNvbnZjaGFycyhzdWJqZWN0MikpOw0KICAgICAgICAgICAgfQ0K ICAgIA0KICAgICAgICAgICAgLyoNCiAgICAgICAgICAgICoqIElzIHRoZXJl IGEgcHJldmlvdXMgbWVzc2FnZT8NCiAgICAgICAgICAgICovDQogICAgDQog ICAgICAgICAgICBzdGF0dXMgPSAoc3RydWN0IGJvZHkgKikgaGFzaG51bWxv b2t1cChudW0gLSAxLCBuYW1lMiwgZW1haWwyLA0KICAgICAgICAgICAgICAg ICAgICAgIHN1YmplY3QyLCBpbnJlcGx5MiwgZGF0ZTIsIGZyb21kYXRlMiwg bXNnaWQyKTsNCiAgICAgICAgICAgIGlmIChzdGF0dXMgIT0gTlVMTCkgew0K ICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICI8TEk+PFNUUk9ORz5QcmV2 aW91cyBtZXNzYWdlOjwvU1RST05HPiAiKTsNCiAgICAgICAgICAgICAgICBm cHJpbnRmKGZwLCAiPEEgSFJFRj1cIiUuNGQuaHRtbFwiPiVzOiBcIiVzXCI8 L0E+XG4iLA0KICAgICAgICAgICAgICAgIG51bSAtIDEsIG5hbWUyLCBjb252 Y2hhcnMoc3ViamVjdDIpKTsNCiAgICAgICAgICAgIH0NCiAgICANCiAgICAg ICAgICAgIC8qDQogICAgICAgICAgICAqKiBJcyB0aGlzIG1lc3NhZ2UgYSBy ZXBseSB0byBhbm90aGVyPw0KICAgICAgICAgICAgKi8NCiAgICANCiAgICAg ICAgICAgIGlmIChpbnJlcGx5WzBdICE9ICdcMCcpIHsNCiAgICAgICAgICAg ICAgICBzdGF0dXNudW0gPSBoYXNocmVwbHlsb29rdXAoaW5yZXBseTIsbmFt ZTIsc3ViamVjdDIsJnN1YmptYXRjaCk7DQogICAgICAgICAgICAgICAgaWYg KHN0YXR1c251bSAhPSAtMSkgew0KICAgICAgICAgICAgICAgICAgICBpZiAo c3Viam1hdGNoKQ0KICAgICAgICAgICAgICAgICAgICAgICAgZnByaW50Zihm cCwiPExJPjxTVFJPTkc+TWF5YmUgaW4gcmVwbHkgdG86PC9TVFJPTkc+Iik7 DQogICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAgICAgICAg ICAgICAgIGZwcmludGYoZnAsIjxMST48U1RST05HPkluIHJlcGx5IHRvOjwv U1RST05HPiIpOw0KICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCIg PEEgSFJFRj1cIiUuNGQuaHRtbFwiPiIsc3RhdHVzbnVtKTsNCiAgICAgICAg ICAgICAgICAgICAgZnByaW50ZihmcCwiJXM6IFwiJXNcIjwvQT5cbiIsbmFt ZTIsY29udmNoYXJzKHN1YmplY3QyKSk7DQogICAgICAgICAgICAgICAgfQ0K ICAgICAgICAgICAgfQ0KICAgIA0KICAgICAgICAgICAgLyoNCiAgICAgICAg ICAgICoqIElzIHRoZXJlIGEgbWVzc2FnZSBuZXh0IGluIHRoZSB0aHJlYWQ/ DQogICAgICAgICAgICAqLw0KICAgIA0KICAgICAgICAgICAgcHJpbnRjb21t ZW50KGZwLCAibmV4dHRocmVhZCIsICJzdGFydCIpOw0KICAgIA0KICAgICAg ICAgICAgZm9yIChycCA9IHRocmVhZGxpc3Q7IHJwICE9IE5VTEw7IHJwID0g cnAtPm5leHQpDQogICAgICAgICAgICAgICAgaWYgKHJwLT5tc2dudW0gPT0g bnVtICYmIHJwLT5uZXh0ICE9IE5VTEwgJiYNCiAgICAgICAgICAgICAgICAg ICAgcnAtPm5leHQtPm1zZ251bSAhPSAtMSkgew0KICAgICAgICAgICAgICAg ICAgICBmcHJpbnRmKGZwLCAiPExJPjxTVFJPTkc+TmV4dCBpbiB0aHJlYWQ6 PC9TVFJPTkc+ICIpOw0KICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKGZw LCAiPEEgSFJFRj1cIiUuNGQuaHRtbFwiPiIsIHJwLT5uZXh0LT5tc2dudW0p Ow0KICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiJXM6IFwiJXNc IjwvQT5cbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcnAtPm5l eHQtPm5hbWUsIGNvbnZjaGFycyhycC0+bmV4dC0+c3ViamVjdCkpOw0KICAg ICAgICAgICAgICAgIH0NCiAgICANCiAgICAgICAgICAgICAgICAvKg0KICAg ICAgICAgICAgICAgICoqIERvZXMgdGhpcyBtZXNzYWdlIGhhdmUgcmVwbGll cz8gSWYgc28sIHByaW50IHRoZW0gYWxsIQ0KICAgICAgICAgICAgICAgICov DQogICAgDQogICAgICAgICAgICAgICAgaWYgKHNob3dyZXBsaWVzKSB7DQog ICAgICAgICAgICAgICAgICAgIGZvciAocnAgPSByZXBseWxpc3Q7IHJwICE9 IE5VTEw7IHJwID0gcnAtPm5leHQpIHsNCiAgICAgICAgICAgICAgICAgICAg ICAgIGlmIChycC0+bXNnbnVtID09IG51bSkgew0KICAgICAgICAgICAgICAg ICAgICAgICAgICAgIGlmIChycC0+bWF5YmVyZXBseSkNCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwiPExJPjxTVFJPTkc+ TWF5YmUgcmVwbHk6PC9TVFJPTkc+Iik7DQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICBmcHJpbnRmKGZwLCAiPExJPjxTVFJPTkc+UmVwbHk6PC9TVFJPTkc+Iik7 DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwiIDxB IEhSRUY9XCIlLjRkLmh0bWxcIj4iLHJwLT5mcm9tbXNnbnVtKTsNCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCIlczogXCIlc1wi PC9BPlxuIixycC0+bmFtZSxjb252Y2hhcnMocnAtPnN1YmplY3QpKTsNCiAg ICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAg fQ0KICAgICAgICAgICAgICAgICAgICBwcmludGNvbW1lbnQoZnAsICJyZXBs eSIsICJlbmQiKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgIH0NCg0K ICAgICAgICBmcHJpbnRmKGZwLCAiPC9VTD5cbiIpOw0KDQoNCiAgICAgICAg LyoNCiAgICAgICAgKiogRmluYWxseS4uLnByaW50IHRoZSBib2R5IQ0KICAg ICAgICAqLw0KDQogICAgICAgIHByaW50Ym9keShmcCwgYnAsIG1zZ2lkLCBz dWJqZWN0KTsNCg0KICAgICAgICAvKg0KICAgICAgICAqKiBTaG91bGQgd2Ug cHJpbnQgb3V0IHRoZSBtZXNzYWdlIGxpbmtzID8NCiAgICAgICAgKi8NCg0K ICAgICAgICBpZiAoc2hvd19tc2dfbGlua3MpIHsNCiAgICAgICAgICAgIGZw cmludGYoZnAsICI8UD5cbjxVTD5cbiIpOw0KICAgIA0KICAgICAgICAgICAg cHJpbnRjb21tZW50KGZwLCAibmV4dCIsICJzdGFydCIpOw0KICAgIA0KICAg ICAgICAgICAgc3RhdHVzID0gKHN0cnVjdCBib2R5ICopIGhhc2hudW1sb29r dXAobnVtICsgMSwgbmFtZTIsDQogICAgICAgICAgICAgICAgICAgICAgZW1h aWwyLCBzdWJqZWN0MiwgaW5yZXBseTIsIGRhdGUyLCBmcm9tZGF0ZTIsIG1z Z2lkMik7DQogICAgICAgICAgICBpZiAoc3RhdHVzICE9IE5VTEwpIHsNCiAg ICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPExJPjxTVFJPTkc+TmV4dCBt ZXNzYWdlOjwvU1RST05HPiAiKTsNCiAgICAgICAgICAgICAgICBmcHJpbnRm KGZwLCAiPEEgSFJFRj1cIiUuNGQuaHRtbFwiPiVzOiBcIiVzXCI8L0E+XG4i LA0KICAgICAgICAgICAgICAgICAgICAgICAgbnVtICsgMSwgbmFtZTIsIGNv bnZjaGFycyhzdWJqZWN0MikpOw0KICAgICAgICAgICAgfQ0KICAgIA0KICAg ICAgICAgICAgc3RhdHVzID0gKHN0cnVjdCBib2R5ICopIGhhc2hudW1sb29r dXAobnVtIC0gMSwgbmFtZTIsDQogICAgICAgICAgICAgICAgICAgICAgZW1h aWwyLCBzdWJqZWN0MiwgaW5yZXBseTIsIGRhdGUyLCBmcm9tZGF0ZTIsIG1z Z2lkMik7DQogICAgICAgICAgICBpZiAoc3RhdHVzICE9IE5VTEwpIHsNCiAg ICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPExJPjxTVFJPTkc+UHJldmlv dXMgbWVzc2FnZTo8L1NUUk9ORz4gIik7DQogICAgICAgICAgICAgICAgZnBy aW50ZihmcCwgIjxBIEhSRUY9XCIlLjRkLmh0bWxcIj4lczogXCIlc1wiPC9B PlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIG51bSAtIDEsIG5hbWUy LCBjb252Y2hhcnMoc3ViamVjdDIpKTsNCiAgICAgICAgICAgIH0NCiAgICAN CiAgICAgICAgICAgIGlmIChpbnJlcGx5WzBdICE9ICdcMCcpIHsNCiAgICAg ICAgICAgICAgICBzdGF0dXNudW0gPSBoYXNocmVwbHlsb29rdXAoaW5yZXBs eTIsbmFtZTIsc3ViamVjdDIsJnN1YmptYXRjaCk7DQogICAgICAgICAgICAg ICAgaWYgKHN0YXR1c251bSAhPSAtMSkgew0KICAgICAgICAgICAgICAgICAg ICBpZiAoc3Viam1hdGNoKQ0KICAgICAgICAgICAgICAgICAgICAgICAgZnBy aW50ZihmcCwiPExJPjxTVFJPTkc+TWF5YmUgaW4gcmVwbHkgdG86PC9TVFJP Tkc+Iik7DQogICAgICAgICAgICAgICAgICAgIGVsc2UNCiAgICAgICAgICAg ICAgICAgICAgICAgIGZwcmludGYoZnAsIjxMST48U1RST05HPkluIHJlcGx5 IHRvOjwvU1RST05HPiIpOw0KICAgICAgICAgICAgICAgICAgICBmcHJpbnRm KGZwLCIgPEEgSFJFRj1cIiUuNGQuaHRtbFwiPiIsc3RhdHVzbnVtKTsNCiAg ICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwiJXM6IFwiJXNcIjwvQT5c biIsbmFtZTIsY29udmNoYXJzKHN1YmplY3QyKSk7DQogICAgICAgICAgICAg ICAgfQ0KICAgICAgICAgICAgfQ0KICAgIA0KICAgICAgICAgICAgcHJpbnRj b21tZW50KGZwLCAibmV4dHRocmVhZCIsICJzdGFydCIpOw0KICAgIA0KICAg ICAgICAgICAgZm9yIChycCA9IHRocmVhZGxpc3Q7IHJwICE9IE5VTEw7IHJw ID0gcnAtPm5leHQpIHsNCiAgICAgICAgICAgICAgICBpZiAocnAtPm1zZ251 bSA9PSBudW0gJiYgcnAtPm5leHQgIT0gTlVMTCAmJg0KICAgICAgICAgICAg ICAgICAgICBycC0+bmV4dC0+bXNnbnVtICE9IC0xKSB7DQogICAgICAgICAg ICAgICAgICAgIGZwcmludGYoZnAsICI8TEk+PFNUUk9ORz5OZXh0IGluIHRo cmVhZDo8L1NUUk9ORz4gIik7DQogICAgICAgICAgICAgICAgICAgIGZwcmlu dGYoZnAsICI8QSBIUkVGPVwiJS40ZC5odG1sXCI+IiwgcnAtPm5leHQtPm1z Z251bSk7DQogICAgICAgICAgICAgICAgICAgIGZwcmludGYoZnAsICIlczog XCIlc1wiPC9BPlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBy cC0+bmV4dC0+bmFtZSwgY29udmNoYXJzKHJwLT5uZXh0LT5zdWJqZWN0KSk7 DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgIA0KICAg ICAgICAgICAgaWYgKHNob3dyZXBsaWVzKSB7DQogICAgICAgICAgICAgICAg Zm9yIChycCA9IHJlcGx5bGlzdDsgcnAgIT0gTlVMTDsgcnAgPSBycC0+bmV4 dCkgew0KICAgICAgICAgICAgICAgICAgICBpZiAocnAtPm1zZ251bSA9PSBu dW0pIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChycC0+bWF5YmVy ZXBseSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKGZw LCAiPExJPjxTVFJPTkc+TWF5YmUgcmVwbHk6PC9TVFJPTkc+Iik7DQogICAg ICAgICAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgICAg ICAgICAgICAgZnByaW50ZihmcCwgIjxMST48U1RST05HPlJlcGx5OjwvU1RS T05HPiIpOw0KICAgICAgICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwg IiA8QSBIUkVGPVwiJS40ZC5odG1sXCI+IiwgcnAtPmZyb21tc2dudW0pOw0K ICAgICAgICAgICAgICAgICAgICAgICAgZnByaW50ZihmcCwgIiVzOiBcIiVz XCI8L0E+XG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBy cC0+bmFtZSwgY29udmNoYXJzKHJwLT5zdWJqZWN0KSk7DQogICAgICAgICAg ICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAg ICAgcHJpbnRjb21tZW50KGZwLCAicmVwbHkiLCAiZW5kIik7DQogICAgICAg ICAgICB9DQogICAgICAgICAgICBmcHJpbnRmKGZwLCAiPC9VTD5cbiIpOw0K ICAgIA0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKHVzZXRhYmxlKQ0KICAg ICAgICAgICAgZnByaW50X21lbnUoZnAsTk9fSU5ERVgsYWJvdXQsIiIsbXNn aWQsc3ViamVjdCxQQUdFX0JPVFRPTSk7DQoNCiAgICAgICAgcHJpbnRmb290 ZXIoZnAsIG1odG1sZm9vdGVyLCBsYWJlbCwgZGlyLCBzdWJqZWN0KTsNCg0K ICAgICAgICBmY2xvc2UoZnApOw0KDQogICAgICAgIGlmIChuZXdmaWxlICYm IGNobW9kKGZpbGVuYW1lLCBmaWxlbW9kZSkgPT0gLTEpIHsNCiAgICAgICAg ICAgIHNwcmludGYoZXJybXNnLCAiQ291bGRuJ3QgY2htb2QgXCIlc1wiIHRv ICVvLiIsDQogICAgICAgICAgICBmaWxlbmFtZSwgZmlsZW1vZGUpOw0KICAg ICAgICAgICAgcHJvZ2VycigoY2hhciAqKSBOVUxMKTsNCiAgICAgICAgfQ0K DQogICAgICAgIGlmICghKG51bSAlIDUpICYmIHNob3dwcm9ncmVzcyAmJiAh c2tpcCkgew0KICAgICAgICAgICAgcHJpbnRmKCJcYlxiXGJcYiUzLjBmJWMi LCgoZmxvYXQpIG51bSAvIChmbG9hdCkgYmlnbnVtKSAqIDEwMCwnJScpOw0K ICAgICAgICAgICAgZmZsdXNoKHN0ZG91dCk7DQogICAgICAgIH0NCg0KICAg ICAgICBudW0rKzsNCiAgICB9DQogICAgaWYgKHNob3dwcm9ncmVzcykNCiAg ICAgICAgcHJpbnRmKCJcYlxiXGJcYiAgICBcbiIpOw0KICAgIGlmICghb3Zl cndyaXRlKQ0KICAgICAgICBiaWdudW0gPSBudW0gLSAxOw0KfQ0KDQoNCi8q DQoqKiBXcml0ZSB0aGUgZGF0ZSBpbmRleC4uLg0KKi8NCg0Kdm9pZCB3cml0 ZWRhdGVzKGNoYXIgKmRpciwgY2hhciAqbGFiZWwsIGNoYXIgKmFyY2hpdmVz LCBjaGFyICphYm91dCkNCnsNCiAgICBpbnQgbmV3ZmlsZTsNCiAgICBjaGFy IGZpbGVuYW1lW01BWEZJTEVMRU5dOw0KICAgIEZJTEUgKmZwOw0KDQogICAg c3ByaW50ZihmaWxlbmFtZSwgIiVzJXMlcyIsIGRpciwNCgkoZGlyW3N0cmxl bihkaXIpIC0gMV0gPT0gJy8nKSA/ICIiIDogIi8iLCBkYXRlbmFtZSk7DQoN CiAgICBpZiAoaXNmaWxlKGZpbGVuYW1lKSkNCiAgICAgICAgbmV3ZmlsZSA9 IDA7DQogICAgZWxzZQ0KICAgICAgICBuZXdmaWxlID0gMTsNCg0KICAgIGlm ICgoZnAgPSBmb3BlbihmaWxlbmFtZSwgInciKSkgPT0gTlVMTCkgew0KICAg ICAgICBzcHJpbnRmKGVycm1zZywgIkNvdWxkbid0IHdyaXRlIFwiJXNcIi4i LCBmaWxlbmFtZSk7DQogICAgICAgIHByb2dlcnIoKGNoYXIgKikgTlVMTCk7 DQogICAgfQ0KDQogICAgaWYgKHNob3dwcm9ncmVzcykNCiAgICAgICAgcHJp bnRmKCJXcml0aW5nIGRhdGUgaW5kZXggdG8gXCIlc1wiLi4uIiwgZmlsZW5h bWUpOw0KDQogICAgLyoNCiAgICAqKiBQcmludCBvdXQgdGhlIGluZGV4IGZp bGUgaGVhZGVyIA0KICAgICovDQogICAgcHJpbnRfaW5kZXhfaGVhZGVyKGZw LCBsYWJlbCwgZGlyLCAiQnkgRGF0ZSIpOw0KDQogICAgaWYgKCF1c2V0YWJs ZSkgew0KICAgICAgICAvKiANCiAgICAgICAgKiogUHJpbnQgb3V0IGFyY2hp dmUgaW5mb3JtYXRpb24gbGlua3MgYXQgdGhlIHRvcCBvZiB0aGUgaW5kZXgN CiAgICAgICAgKi8gDQogICAgICAgIHByaW50X2luZGV4X2hlYWRlcl9saW5r cyhmcCwgYXJjaGl2ZXMsIGFib3V0LCBGUk9NX0RBVEUpOw0KICAgIA0KICAg ICAgICBpZiAoc2hvd2hyKQ0KICAgICAgICAgICAgZnByaW50ZihmcCwgIjxI Uj5cbiIpOw0KDQogICAgICAgIC8qDQogICAgICAgICoqIFByaW50b3V0IHRo ZSBEYXRlcyBmb3IgdGhlIFN0YXJ0aW5nIGFuZCBFbmRpbmcgbWVzc2FnZXMg DQogICAgICAgICoqIGluIHRoZSBhcmNoaXZlLCBhbG9uZyB3aXRoIGEgY291 bnQgb2YgdGhlIG1lc3NhZ2VzLg0KICAgICAgICAqLw0KDQogICAgICAgIGZw cmludGYoZnAsICI8U1RST05HPlN0YXJ0aW5nOjwvU1RST05HPiA8RU0+JXM8 L0VNPjxCUj5cbiIsIA0KICAgICAgICAgICAgICAgIGdldGRhdGVzdHIoZmly c3RkYXRlbnVtKSk7DQogICAgICAgIGZwcmludGYoZnAsICI8U1RST05HPkVu ZGluZzo8L1NUUk9ORz4gPEVNPiVzPC9FTT48QlI+XG4iLCANCiAgICAgICAg ICAgICAgICBnZXRkYXRlc3RyKGxhc3RkYXRlbnVtKSk7DQogICAgICAgIGZw cmludGYoZnAsICI8U1RST05HPk1lc3NhZ2VzOjwvU1RST05HPiAlZFxuPFA+ XG4iLCBiaWdudW0gKyAxKTsNCiAgICB9DQogICAgZWxzZSB7DQogICAgICAg IGZwcmludF9tZW51KGZwLCBEQVRFX0lOREVYLCBhYm91dCwgYXJjaGl2ZXMs ICIiLCAiIiwgUEFHRV9UT1ApOw0KICAgICAgICBmcHJpbnRfc3VtbWFyeShm cCwgZmlyc3RkYXRlbnVtLCBsYXN0ZGF0ZW51bSwgYmlnbnVtICsgMSk7DQog ICAgICAgIGlmIChzaG93aHIpDQogICAgICAgICAgICBmcHJpbnRmKGZwLCAi PEhSPlxuIik7DQogICAgfQ0KDQogICAgLyoNCiAgICAqKiBQcmludCBvdXQg dGhlIGFjdHVhbCBtZXNzYWdlIGluZGV4IGxpc3RzLiBIZXJlJ3MgdGhlIGJl ZWYuDQogICAgKi8NCg0KICAgIGZwcmludGYoZnAsICI8VUw+XG4iKTsNCiAg ICBwcmludGRhdGVzKGZwLCBkYXRlbGlzdCk7DQogICAgZnByaW50ZihmcCwg IjwvVUw+XG48UD5cbiIpOw0KDQogICAgaWYgKCF1c2V0YWJsZSkgew0KICAg ICAgICAvKg0KICAgICAgICAqKiBQcmludG91dCB0aGUgZGF0ZXMgZm9yIHRo ZSBsYXN0IG1lc3NhZ2UgaW4gdGhlIGFyY2hpdmUNCiAgICAgICAgKiogYWxv bmcgd2l0aCB0aGUgZGF0ZSB0aGUgYXJjaGl2ZSB3YXMgZ2VuZXJhdGVkIG9u Lg0KICAgICAgICAqLw0KDQogICAgICAgIGZwcmludGYoZnAsIjxBIE5BTUU9 XCJlbmRcIj48U1RST05HPkxhc3QgbWVzc2FnZSBkYXRlOjwvU1RST05HPjwv QT4gIik7DQogICAgICAgIGZwcmludGYoZnAsIjxFTT4lczwvRU0+PEJSPlxu IiwgZ2V0ZGF0ZXN0cihsYXN0ZGF0ZW51bSkpOw0KICAgICAgICBmcHJpbnRm KGZwLCI8U1RST05HPkFyY2hpdmVkIG9uOjwvU1RST05HPiA8RU0+JXM8L0VN PjxQPlxuIixnZXRsb2NhbHRpbWUoKSk7DQogICAgICAgIGlmIChzaG93aHIp DQogICAgICAgICAgICBmcHJpbnRmKGZwLCAiPEhSPlxuIik7DQoNCiAgICAg ICAgLyogDQogICAgICAgICoqIFByaW50IG91dCBhcmNoaXZlIGluZm9ybWF0 aW9uIGxpbmtzIGF0IHRoZSBib3R0b20gb2YgdGhlIGluZGV4DQogICAgICAg ICovIA0KICAgICAgICBwcmludF9pbmRleF9mb290ZXJfbGlua3MoZnAsIGFy Y2hpdmVzLCBGUk9NX0RBVEUpOw0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAg ICAgZnByaW50X21lbnUoZnAsIERBVEVfSU5ERVgsIGFib3V0LCBhcmNoaXZl cywgIiIsICIiLCBQQUdFX0JPVFRPTSk7DQogICAgfQ0KDQogICAgLyogDQog ICAgKiogUHJpbnQgdGhlIGluZGV4IHBhZ2UgZm9vdGVyLg0KICAgICovDQog ICAgcHJpbnRmb290ZXIoZnAsIGlodG1sZm9vdGVyLCBsYWJlbCwgZGlyLCAi QnkgRGF0ZSIpOw0KDQogICAgZmNsb3NlKGZwKTsNCg0KICAgIGlmIChuZXdm aWxlICYmIGNobW9kKGZpbGVuYW1lLCBmaWxlbW9kZSkgPT0gLTEpIHsNCiAg ICAgICAgc3ByaW50ZihlcnJtc2csICJDb3VsZG4ndCBjaG1vZCBcIiVzXCIg dG8gJW8uIiwgZmlsZW5hbWUsDQogICAgICAgIGZpbGVtb2RlKTsNCiAgICAg ICAgcHJvZ2VycigoY2hhciAqKSBOVUxMKTsNCiAgICB9DQoNCiAgICBpZiAo c2hvd3Byb2dyZXNzKQ0KICAgICAgICBwdXRjaGFyKCdcbicpOw0KfQ0KDQov Kg0KKiogV2hpbGUgcHJpbnRpbmcgdGhlIHRocmVhZCBpbmRleCwgcHJpbnRz IGFueSByZXBsaWVzIHRvIHJlcGxpZXMuDQoqLw0KDQp2b2lkIGNoZWNrcmVw bGllcyhGSUxFICpmcCwgaW50IG51bSwgaW50IGxldmVsKQ0Kew0KICAgIHN0 cnVjdCByZXBseSAqcnA7DQoNCiAgICBmb3IgKHJwID0gcmVwbHlsaXN0OyBy cCAhPSBOVUxMOyBycCA9IHJwLT5uZXh0KSB7DQogICAgICAgIGlmIChycC0+ bXNnbnVtID09IG51bSkgew0KICAgICAgICAgICAgaWYgKGxldmVsIDwgdGhy ZGxldmVscykNCiAgICAgICAgICAgICAgICBmcHJpbnRmKGZwLCAiPFVMPlxu Iik7DQogICAgICAgICAgICBmcHJpbnRmKGZwLCI8TEk+PEEgSFJFRj1cIiUu NGQuaHRtbFwiPiIscnAtPmZyb21tc2dudW0pOw0KICAgICAgICAgICAgcHJp bnRlZGxpc3QgPSAoc3RydWN0IHByaW50ZWQgKikNCiAgICAgICAgICAgICAg ICAgICAgICAgICAgIG1hcmthc3ByaW50ZWQocHJpbnRlZGxpc3QsIHJwLT5m cm9tbXNnbnVtKTsNCiAgICAgICAgICAgIGZwcmludGYoZnAsIjxTVFJPTkc+ JXMgPC9TVFJPTkc+PC9BPiAiLGNvbnZjaGFycyhycC0+c3ViamVjdCkpOw0K ICAgICAgICAgICAgZnByaW50ZihmcCwgIjxBIE5BTUU9XCIlZFwiPjxFTT4l czwvRU0+PC9BPlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJw LT5mcm9tbXNnbnVtLCBycC0+bmFtZSk7DQogICAgICAgICAgICBjaGVja3Jl cGxpZXMoZnAsIHJwLT5mcm9tbXNnbnVtLCBsZXZlbCArIDEpOw0KICAgICAg ICAgICAgaWYgKGxldmVsIDwgdGhyZGxldmVscykNCiAgICAgICAgICAgICAg ICBmcHJpbnRmKGZwLCAiPC9VTD5cbiIpOw0KICAgICAgICB9DQogICAgfQ0K fQ0KDQovKg0KKiogUHJpbnRzIHRoZSBhcnRpY2xlIHBvaW50ZXJzIGluIHRo ZSB0aHJlYWQgaW5kZXggYnkgZGF0ZS4NCiovDQoNCnZvaWQgcHJpbnR0aHJl YWRzKEZJTEUgKmZwLCBzdHJ1Y3QgaGVhZGVyICpocCkNCnsNCiAgICBpbnQg aGFzcmVwbHk7DQogICAgc3RydWN0IHJlcGx5ICpycDsNCg0KICAgIGlmICho cCAhPSBOVUxMKSB7DQogICAgICAgIHByaW50dGhyZWFkcyhmcCwgaHAtPmxl ZnQpOw0KDQogICAgICAgIGZvciAoaGFzcmVwbHkgPSAwLCBycCA9IHJlcGx5 bGlzdDsgcnAgIT0gTlVMTDsgcnAgPSBycC0+bmV4dCkgew0KICAgICAgICAg ICAgaWYgKHJwLT5mcm9tbXNnbnVtID09IGhwLT5tc2dudW0pIHsNCiAgICAg ICAgICAgICAgICBoYXNyZXBseSA9IDE7DQogICAgICAgICAgICAgICAgYnJl YWs7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBpZiAo IWhhc3JlcGx5ICYmICF3YXNwcmludGVkKHByaW50ZWRsaXN0LCBocC0+bXNn bnVtKSkgew0KICAgICAgICAgICAgZnByaW50ZihmcCwgIjxMST48QSBIUkVG PVwiJS40ZC5odG1sXCI+PFNUUk9ORz4lczwvU1RST05HPjwvQT4gIiwNCiAg ICAgICAgICAgICAgICAgICAgaHAtPm1zZ251bSwgY29udmNoYXJzKGhwLT5z dWJqZWN0KSk7DQogICAgICAgICAgICBmcHJpbnRmKGZwLCI8QSBOQU1FPVwi JWRcIj48RU0+JXM8L0VNPjwvQT5cbiIsaHAtPm1zZ251bSxocC0+bmFtZSk7 DQogICAgICAgICAgICBwcmludGVkbGlzdCA9IChzdHJ1Y3QgcHJpbnRlZCAq KQ0KICAgICAgICAgICAgICAgICAgICBtYXJrYXNwcmludGVkKHByaW50ZWRs aXN0LCBocC0+bXNnbnVtKTsNCg0KICAgICAgICAgICAgY2hlY2tyZXBsaWVz KGZwLCBocC0+bXNnbnVtLCAxKTsNCiAgICAgICAgfQ0KICAgICAgICBwcmlu dHRocmVhZHMoZnAsIGhwLT5yaWdodCk7DQogICAgfQ0KfQ0KDQovKg0KKiog V3JpdGUgdGhlIHRocmVhZCBpbmRleC4uLg0KKi8NCg0Kdm9pZCB3cml0ZXRo cmVhZHMoY2hhciAqZGlyLCBjaGFyICpsYWJlbCwgY2hhciAqYXJjaGl2ZXMs IGNoYXIgKmFib3V0KQ0Kew0KICAgIGludCBuZXdmaWxlOw0KICAgIGNoYXIg ZmlsZW5hbWVbTUFYRklMRUxFTl07DQogICAgRklMRSAqZnA7DQoNCiAgICBz dHJ1Y3QgcHJpbnRlZCAqcHA7DQoNCiAgICB3aGlsZSAocHJpbnRlZGxpc3Qp IHsgLyogY2xlYW51cCBuZWVkZWQgPz8gKi8NCiAgICAgICAgIHBwID0gcHJp bnRlZGxpc3Q7DQogICAgICAgICBwcmludGVkbGlzdCA9IHByaW50ZWRsaXN0 LT5uZXh0Ow0KICAgICAgICAgZnJlZShwcCk7DQogICAgfQ0KDQogICAgcHJp bnRlZGxpc3QgPSBOVUxMOw0KDQogICAgc3ByaW50ZihmaWxlbmFtZSwgIiVz JXMlcyIsIA0KICAgICAgICAgICAgZGlyLCAoZGlyW3N0cmxlbihkaXIpIC0g MV0gPT0gJy8nKSA/ICIiIDogIi8iLCB0aHJkbmFtZSk7DQoNCiAgICBpZiAo aXNmaWxlKGZpbGVuYW1lKSkNCiAgICAgICAgbmV3ZmlsZSA9IDA7DQogICAg ZWxzZQ0KICAgICAgICBuZXdmaWxlID0gMTsNCg0KICAgIGlmICgoZnAgPSBm b3BlbihmaWxlbmFtZSwgInciKSkgPT0gTlVMTCkgew0KICAgICAgICBzcHJp bnRmKGVycm1zZywgIkNvdWxkbid0IHdyaXRlIFwiJXNcIi4iLCBmaWxlbmFt ZSk7DQogICAgICAgIHByb2dlcnIoKGNoYXIgKikgTlVMTCk7DQogICAgfQ0K DQogICAgaWYgKHNob3dwcm9ncmVzcykNCiAgICAgICAgcHJpbnRmKCJXcml0 aW5nIHRocmVhZCBpbmRleCB0byBcIiVzXCIuLi4iLCBmaWxlbmFtZSk7DQoN CiAgICBwcmludF9pbmRleF9oZWFkZXIoZnAsIGxhYmVsLCBkaXIsICJCeSBU aHJlYWQiKTsNCg0KICAgIGlmICghdXNldGFibGUpIHsNCiAgICAgICAgLyog DQogICAgICAgICoqIFByaW50IG91dCB0aGUgaW5kZXggcGFnZSBsaW5rcyAN CiAgICAgICAgKi8gDQogICAgICAgIHByaW50X2luZGV4X2hlYWRlcl9saW5r cyhmcCwgYXJjaGl2ZXMsIGFib3V0LCBGUk9NX1RIUkVBRCk7DQogICAgICAg IA0KICAgICAgICBpZiAoc2hvd2hyKQ0KICAgICAgICAgICAgZnByaW50Zihm cCwgIjxIUj5cbiIpOw0KICAgIA0KICAgICAgICBmcHJpbnRmKGZwLCAiPFNU Uk9ORz5TdGFydGluZzo8L1NUUk9ORz4gPEVNPiVzPC9FTT48QlI+XG4iLA0K ICAgICAgICAgICAgICAgIGdldGRhdGVzdHIoZmlyc3RkYXRlbnVtKSk7DQog ICAgICAgIGZwcmludGYoZnAsICI8U1RST05HPkVuZGluZzo8L1NUUk9ORz4g PEVNPiVzPC9FTT48QlI+XG4iLCANCiAgICAgICAgICAgICAgICBnZXRkYXRl c3RyKGxhc3RkYXRlbnVtKSk7DQogICAgICAgIGZwcmludGYoZnAsICI8U1RS T05HPk1lc3NhZ2VzOjwvU1RST05HPiAlZFxuPFA+XG4iLCBiaWdudW0gKyAx KTsNCiAgICB9DQogICAgZWxzZSB7DQogICAgICAgIGZwcmludF9tZW51KGZw LCBUSFJFQURfSU5ERVgsIGFib3V0LCBhcmNoaXZlcywgIiIsICIiLCBQQUdF X1RPUCk7DQogICAgICAgIGZwcmludF9zdW1tYXJ5KGZwLCBmaXJzdGRhdGVu dW0sIGxhc3RkYXRlbnVtLCBiaWdudW0gKyAxKTsNCiAgICAgICAgaWYgKHNo b3docikNCiAgICAgICAgICAgIGZwcmludGYoZnAsICI8SFI+XG4iKTsNCiAg ICB9DQoNCiAgICBmcHJpbnRmKGZwLCAiPFVMPlxuIik7DQogICAgcHJpbnR0 aHJlYWRzKGZwLCBkYXRlbGlzdCk7DQogICAgZnByaW50ZihmcCwgIjwvVUw+ XG48UD5cbiIpOw0KDQogICAgaWYgKCF1c2V0YWJsZSkgew0KICAgICAgICBm cHJpbnRmKGZwLCAiPEEgTkFNRT1cImVuZFwiPjxTVFJPTkc+TGFzdCBtZXNz YWdlIGRhdGU6PC9TVFJPTkc+PC9BPiAiKTsNCiAgICAgICAgZnByaW50Zihm cCwgIjxFTT4lczwvRU0+PEJSPlxuIiwgZ2V0ZGF0ZXN0cihsYXN0ZGF0ZW51 bSkpOw0KICAgICAgICBmcHJpbnRmKGZwLCAiPFNUUk9ORz5BcmNoaXZlZCBv bjo8L1NUUk9ORz4gPEVNPiVzPC9FTT48UD5cbiIsIGdldGxvY2FsdGltZSgp KTsNCiAgICAgICAgICAgICANCiAgICAgICAgaWYgKHNob3docikNCiAgICAg ICAgICAgIGZwcmludGYoZnAsICI8SFI+XG4iKTsNCiAgICANCiAgICAgICAg LyogDQogICAgICAgICoqIFByaW50IG91dCBhcmNoaXZlIGluZm9ybWF0aW9u IGxpbmtzIGF0IHRoZSBib3R0b20gb2YgdGhlIGluZGV4DQogICAgICAgICov IA0KICAgICAgICBwcmludF9pbmRleF9mb290ZXJfbGlua3MoZnAsIGFyY2hp dmVzLCBGUk9NX1RIUkVBRCk7DQogICAgDQogICAgfQ0KICAgIGVsc2Ugew0K ICAgICAgICBmcHJpbnRfbWVudShmcCwgVEhSRUFEX0lOREVYLCBhYm91dCwg YXJjaGl2ZXMsICIiLCAiIiwgUEFHRV9CT1RUT00pOw0KICAgIH0NCg0KICAg IHByaW50Zm9vdGVyKGZwLCBpaHRtbGZvb3RlciwgbGFiZWwsIGRpciwgIkJ5 IFRocmVhZCIpOw0KDQogICAgZmNsb3NlKGZwKTsNCg0KICAgIGlmIChuZXdm aWxlICYmIGNobW9kKGZpbGVuYW1lLCBmaWxlbW9kZSkgPT0gLTEpIHsNCiAg ICAgICAgc3ByaW50ZihlcnJtc2csICJDb3VsZG4ndCBjaG1vZCBcIiVzXCIg dG8gJW8uIiwgZmlsZW5hbWUsIGZpbGVtb2RlKTsNCiAgICAgICAgcHJvZ2Vy cigoY2hhciAqKSBOVUxMKTsNCiAgICB9DQoNCiAgICBpZiAoc2hvd3Byb2dy ZXNzKQ0KICAgICAgICBwdXRjaGFyKCdcbicpOw0KfQ0KDQovKg0KKiogUHJp bnQgdGhlIHN1YmplY3QgaW5kZXggcG9pbnRlcnMgYWxwaGFiZXRpY2FsbHku DQoqLw0KDQp2b2lkIHByaW50c3ViamVjdHMoRklMRSAqZnAsIHN0cnVjdCBo ZWFkZXIgKmhwKQ0Kew0KICAgIHN0YXRpYyBjaGFyIG9sZHN1YmplY3RbU1VC SlNUUkxFTl07DQoNCiAgICBpZiAoaHAgIT0gTlVMTCkgew0KICAgICAgICBw cmludHN1YmplY3RzKGZwLCBocC0+bGVmdCk7DQogICAgICAgIGlmIChzdHJj YXNlY21wKGhwLT5zdWJqZWN0LCBvbGRzdWJqZWN0KSkNCiAgICAgICAgICAg IGZwcmludGYoZnAsICI8TEk+PFNUUk9ORz4lczwvU1RST05HPlxuIixjb252 Y2hhcnMoaHAtPnN1YmplY3QpKTsNCiAgICAgICAgZnByaW50ZihmcCwgIjxV TD5cbiIpOw0KICAgICAgICBmcHJpbnRmKGZwLCI8TEk+PEEgSFJFRj1cIiUu NGQuaHRtbFwiPiVzPC9BPiAiLGhwLT5tc2dudW0saHAtPm5hbWUpOw0KICAg ICAgICBmcHJpbnRmKGZwLCI8QSBOQU1FPVwiJWRcIj48RU0+JXM8L0VNPjwv QT5cbiIsIGhwLT5tc2dudW0saHAtPmRhdGVzdHIpOw0KICAgICAgICBmcHJp bnRmKGZwLCAiPC9VTD5cbiIpOw0KICAgICAgICBzdHJjcHkob2xkc3ViamVj dCwgaHAtPnN1YmplY3QpOw0KICAgICAgICBwcmludHN1YmplY3RzKGZwLCBo cC0+cmlnaHQpOw0KICAgIH0NCn0NCg0KLyoNCioqIFByaW50cyB0aGUgc3Vi amVjdCBpbmRleC4NCiovDQoNCnZvaWQgd3JpdGVzdWJqZWN0cyhjaGFyICpk aXIsIGNoYXIgKmxhYmVsLCBjaGFyICphcmNoaXZlcywgY2hhciAqYWJvdXQp DQp7DQogICAgaW50IG5ld2ZpbGU7DQogICAgY2hhciBmaWxlbmFtZVtNQVhG SUxFTEVOXTsNCiAgICBGSUxFICpmcDsNCg0KICAgIHNwcmludGYoZmlsZW5h bWUsICIlcyVzJXMiLCANCiAgICAgICAgICAgIGRpciwgKGRpcltzdHJsZW4o ZGlyKSAtIDFdID09ICcvJykgPyAiIiA6ICIvIiwgc3Viam5hbWUpOw0KDQog ICAgaWYgKGlzZmlsZShmaWxlbmFtZSkpDQogICAgICAgIG5ld2ZpbGUgPSAw Ow0KICAgIGVsc2UNCiAgICAgICAgbmV3ZmlsZSA9IDE7DQoNCiAgICBpZiAo KGZwID0gZm9wZW4oZmlsZW5hbWUsICJ3IikpID09IE5VTEwpIHsNCiAgICAg ICAgc3ByaW50ZihlcnJtc2csICJDb3VsZG4ndCB3cml0ZSBcIiVzXCIuIiwg ZmlsZW5hbWUpOw0KICAgICAgICBwcm9nZXJyKChjaGFyICopIE5VTEwpOw0K ICAgIH0NCg0KICAgIGlmIChzaG93cHJvZ3Jlc3MpDQogICAgICAgIHByaW50 ZigiV3JpdGluZyBzdWJqZWN0IGluZGV4IHRvIFwiJXNcIi4uLiIsIGZpbGVu YW1lKTsNCg0KICAgIHByaW50X2luZGV4X2hlYWRlcihmcCwgbGFiZWwsIGRp ciwgIkJ5IFN1YmplY3QiKTsNCg0KICAgIGlmICghdXNldGFibGUpIHsNCiAg ICAgICAgLyogDQogICAgICAgICoqIFByaW50IG91dCB0aGUgaW5kZXggcGFn ZSBsaW5rcyANCiAgICAgICAgKi8gDQogICAgICAgIHByaW50X2luZGV4X2hl YWRlcl9saW5rcyhmcCwgYXJjaGl2ZXMsIGFib3V0LCBGUk9NX1NVQkpFQ1Qp Ow0KICAgIA0KICAgICAgICBpZiAoc2hvd2hyKQ0KICAgICAgICAgICAgZnBy aW50ZihmcCwgIjxIUj5cbiIpOw0KDQogICAgICAgIGZwcmludGYoZnAsICI8 U1RST05HPlN0YXJ0aW5nOjwvU1RST05HPiA8RU0+JXM8L0VNPjxCUj5cbiIs DQogICAgICAgICAgICAgICAgZ2V0ZGF0ZXN0cihmaXJzdGRhdGVudW0pKTsN CiAgICAgICAgZnByaW50ZihmcCwgIjxTVFJPTkc+RW5kaW5nOjwvU1RST05H PiA8RU0+JXM8L0VNPjxCUj5cbiIsIA0KICAgICAgICAgICAgICAgIGdldGRh dGVzdHIobGFzdGRhdGVudW0pKTsNCiAgICAgICAgZnByaW50ZihmcCwgIjxT VFJPTkc+TWVzc2FnZXM6PC9TVFJPTkc+ICVkXG48UD5cbiIsIGJpZ251bSAr IDEpOw0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAgICAgZnByaW50X21lbnUo ZnAsIFNVQkpFQ1RfSU5ERVgsIGFib3V0LCBhcmNoaXZlcywgIiIsICIiLCBQ QUdFX1RPUCk7DQogICAgICAgIGZwcmludF9zdW1tYXJ5KGZwLCBmaXJzdGRh dGVudW0sIGxhc3RkYXRlbnVtLCBiaWdudW0gKyAxKTsNCiAgICAgICAgaWYg KHNob3docikNCiAgICAgICAgICAgIGZwcmludGYoZnAsICI8SFI+XG4iKTsN CiAgICB9DQoNCiAgICBmcHJpbnRmKGZwLCAiPFVMPlxuIik7DQogICAgcHJp bnRzdWJqZWN0cyhmcCwgc3ViamVjdGxpc3QpOw0KICAgIGZwcmludGYoZnAs ICI8L1VMPlxuPFA+XG4iKTsNCg0KICAgIGlmICghdXNldGFibGUpIHsNCiAg ICAgICAgZnByaW50ZihmcCwgIjxTVFJPTkc+TGFzdCBtZXNzYWdlIGRhdGU6 PC9TVFJPTkc+IDxFTT4lczwvRU0+PEJSPlxuIiwNCiAgICAgICAgICAgICAg ICBnZXRkYXRlc3RyKGxhc3RkYXRlbnVtKSk7DQogICAgICAgIGZwcmludGYo ZnAsICI8U1RST05HPkFyY2hpdmVkIG9uOjwvU1RST05HPiA8RU0+JXM8L0VN PjxQPlxuIiwgDQogICAgICAgICAgICAgICAgZ2V0bG9jYWx0aW1lKCkpOw0K DQogICAgICAgIGlmIChzaG93aHIpDQogICAgICAgICAgICBmcHJpbnRmKGZw LCAiPEhSPlxuIik7DQoNCiAgICAgICAgLyogDQogICAgICAgICoqIFByaW50 IG91dCBhcmNoaXZlIGluZm9ybWF0aW9uIGxpbmtzIGF0IHRoZSBib3R0b20g b2YgdGhlIGluZGV4DQogICAgICAgICovIA0KICAgICAgICBwcmludF9pbmRl eF9mb290ZXJfbGlua3MoZnAsIGFyY2hpdmVzLCBGUk9NX1NVQkpFQ1QpOw0K ICAgIH0NCiAgICBlbHNlIHsNCiAgICAgICAgZnByaW50X21lbnUoZnAsIFNV QkpFQ1RfSU5ERVgsIGFib3V0LCBhcmNoaXZlcywgIiIsICIiLCBQQUdFX0JP VFRPTSk7DQogICAgfQ0KDQogICAgcHJpbnRmb290ZXIoZnAsIGlodG1sZm9v dGVyLCBsYWJlbCwgZGlyLCAiQnkgU3ViamVjdCIpOw0KDQogICAgZmNsb3Nl KGZwKTsNCg0KICAgIGlmIChuZXdmaWxlICYmIGNobW9kKGZpbGVuYW1lLCBm aWxlbW9kZSkgPT0gLTEpIHsNCiAgICAgICAgc3ByaW50ZihlcnJtc2csICJD b3VsZG4ndCBjaG1vZCBcIiVzXCIgdG8gJW8uIiwgZmlsZW5hbWUsDQogICAg ICAgIGZpbGVtb2RlKTsNCiAgICAgICAgcHJvZ2VycigoY2hhciAqKSBOVUxM KTsNCiAgICB9DQoNCiAgICBpZiAoc2hvd3Byb2dyZXNzKQ0KICAgICAgICBw dXRjaGFyKCdcbicpOw0KfQ0KDQovKg0KKiogUHJpbnRzIHRoZSBhdXRob3Ig aW5kZXggbGlua3Mgc29ydGVkIGFscGhhYmV0aWNhbGx5Lg0KKi8NCg0Kdm9p ZCBwcmludGF1dGhvcnMoRklMRSAqZnAsIHN0cnVjdCBoZWFkZXIgKmhwKQ0K ew0KICAgIHN0YXRpYyBjaGFyIG9sZG5hbWVbU1VCSlNUUkxFTl07DQoNCiAg ICBpZiAoaHAgIT0gTlVMTCkgew0KICAgICAgICBwcmludGF1dGhvcnMoZnAs IGhwLT5sZWZ0KTsNCiAgICAgICAgaWYgKHN0cmNhc2VjbXAoaHAtPm5hbWUs IG9sZG5hbWUpKQ0KICAgICAgICAgICAgZnByaW50ZihmcCwgIjxMST48U1RS T05HPiVzPC9TVFJPTkc+XG4iLCBocC0+bmFtZSk7DQogICAgICAgIGZwcmlu dGYoZnAsIjxVTD5cbiIpOw0KICAgICAgICBmcHJpbnRmKGZwLCI8TEk+PEEg SFJFRj1cIiUuNGQuaHRtbFwiPiVzPC9BPiAiLA0KICAgICAgICAgICAgICAg ICAgICAgaHAtPm1zZ251bSwgY29udmNoYXJzKGhwLT5zdWJqZWN0KSk7DQog ICAgICAgIGZwcmludGYoZnAsIjxBIE5BTUU9XCIlZFwiPjxFTT4lczwvRU0+ PC9BPlxuIiwgaHAtPm1zZ251bSxocC0+ZGF0ZXN0cik7DQogICAgICAgIGZw cmludGYoZnAsIjwvVUw+XG4iKTsNCiAgICAgICAgc3RyY3B5KG9sZG5hbWUs IGhwLT5uYW1lKTsNCiAgICAgICAgcHJpbnRhdXRob3JzKGZwLCBocC0+cmln aHQpOw0KICAgIH0NCn0NCg0KLyoNCioqIFByaW50cyB0aGUgYXV0aG9yIGlu ZGV4IGZpbGUgYW5kIGxpbmtzIHNvcnRlZCBhbHBoYWJldGljYWxseS4NCiov DQoNCnZvaWQgd3JpdGVhdXRob3JzKGNoYXIgKmRpciwgY2hhciAqbGFiZWws IGNoYXIgKmFyY2hpdmVzLCBjaGFyICphYm91dCkNCnsNCiAgICBpbnQgbmV3 ZmlsZTsNCiAgICBjaGFyIGZpbGVuYW1lW01BWEZJTEVMRU5dOw0KICAgIEZJ TEUgKmZwOw0KDQogICAgc3ByaW50ZihmaWxlbmFtZSwgIiVzJXMlcyIsIA0K ICAgICAgICAgICAgZGlyLCAoZGlyW3N0cmxlbihkaXIpIC0gMV0gPT0gJy8n KSA/ICIiIDogIi8iLCBhdXRobmFtZSk7DQoNCiAgICBpZiAoaXNmaWxlKGZp bGVuYW1lKSkNCiAgICAgICAgbmV3ZmlsZSA9IDA7DQogICAgZWxzZQ0KICAg ICAgICBuZXdmaWxlID0gMTsNCg0KICAgIGlmICgoZnAgPSBmb3BlbihmaWxl bmFtZSwgInciKSkgPT0gTlVMTCkgew0KICAgICAgICBzcHJpbnRmKGVycm1z ZywgIkNvdWxkbid0IHdyaXRlIFwiJXNcIi4iLCBmaWxlbmFtZSk7DQogICAg ICAgIHByb2dlcnIoKGNoYXIgKilOVUxMKTsNCiAgICB9DQoNCiAgICBpZiAo c2hvd3Byb2dyZXNzKQ0KICAgICAgICBwcmludGYoIldyaXRpbmcgYXV0aG9y IGluZGV4IHRvIFwiJXNcIi4uLiIsIGZpbGVuYW1lKTsNCg0KICAgIHByaW50 X2luZGV4X2hlYWRlcihmcCwgbGFiZWwsIGRpciwgIkJ5IEF1dGhvciIpOw0K DQogICAgaWYgKCF1c2V0YWJsZSkgew0KICAgICAgICAvKiANCiAgICAgICAg KiogUHJpbnQgb3V0IHRoZSBpbmRleCBwYWdlIGxpbmtzIA0KICAgICAgICAq LyANCiAgICAgICAgcHJpbnRfaW5kZXhfaGVhZGVyX2xpbmtzKGZwLCBhcmNo aXZlcywgYWJvdXQsIEZST01fQVVUSE9SKTsNCiAgICAgICAgDQogICAgICAg IGlmIChzaG93aHIpDQogICAgICAgICAgICBmcHJpbnRmKGZwLCAiPEhSPlxu Iik7DQogICAgDQogICAgICAgIGZwcmludGYoZnAsICI8U1RST05HPlN0YXJ0 aW5nOjwvU1RST05HPiA8RU0+JXM8L0VNPjxCUj5cbiIsDQogICAgICAgICAg ICAgICAgZ2V0ZGF0ZXN0cihmaXJzdGRhdGVudW0pKTsNCiAgICAgICAgZnBy aW50ZihmcCwgIjxTVFJPTkc+RW5kaW5nOjwvU1RST05HPiA8RU0+JXM8L0VN PjxCUj5cbiIsIA0KICAgICAgICAgICAgICAgIGdldGRhdGVzdHIobGFzdGRh dGVudW0pKTsNCiAgICAgICAgZnByaW50ZihmcCwgIjxTVFJPTkc+TWVzc2Fn ZXM6PC9TVFJPTkc+ICVkXG48UD5cbiIsIGJpZ251bSArIDEpOw0KICAgIH0N CiAgICBlbHNlIHsNCiAgICAgICAgZnByaW50X21lbnUoZnAsIEFVVEhPUl9J TkRFWCwgYWJvdXQsIGFyY2hpdmVzLCAiIiwgIiIsIFBBR0VfVE9QKTsNCiAg ICAgICAgZnByaW50X3N1bW1hcnkoZnAsIGZpcnN0ZGF0ZW51bSwgbGFzdGRh dGVudW0sIGJpZ251bSArIDEpOyAgICAgICAgDQogICAgICAgIGlmIChzaG93 aHIpDQogICAgICAgICAgICBmcHJpbnRmKGZwLCAiPEhSPlxuIik7DQogICAg fQ0KDQogICAgZnByaW50ZihmcCwgIjxVTD5cbiIpOw0KICAgIHByaW50YXV0 aG9ycyhmcCwgYXV0aG9ybGlzdCk7DQogICAgZnByaW50ZihmcCwgIjwvVUw+ XG48UD5cbiIpOw0KDQogICAgaWYgKCF1c2V0YWJsZSkgew0KICAgICAgICBm cHJpbnRmKGZwLCAiPFNUUk9ORz5MYXN0IG1lc3NhZ2UgZGF0ZTo8L1NUUk9O Rz4gPEVNPiVzPC9FTT48QlI+XG4iLA0KICAgICAgICAgICAgICAgICAgICBn ZXRkYXRlc3RyKGxhc3RkYXRlbnVtKSk7DQogICAgICAgIGZwcmludGYoZnAs IjxTVFJPTkc+QXJjaGl2ZWQgb246PC9TVFJPTkc+IDxFTT4lczwvRU0+PFA+ XG4iLGdldGxvY2FsdGltZSgpKTsNCg0KICAgICAgICBpZiAoc2hvd2hyKQ0K ICAgICAgICAgICAgZnByaW50ZihmcCwgIjxIUj5cbiIpOw0KDQogICAgICAg IC8qIA0KICAgICAgICAqKiBQcmludCBvdXQgYXJjaGl2ZSBpbmZvcm1hdGlv biBsaW5rcyBhdCB0aGUgYm90dG9tIG9mIHRoZSBpbmRleA0KICAgICAgICAq LyANCiAgICAgICAgcHJpbnRfaW5kZXhfZm9vdGVyX2xpbmtzKGZwLCBhcmNo aXZlcywgRlJPTV9BVVRIT1IpOw0KICAgIH0NCiAgICBlbHNlIHsNCiAgICAg ICAgZnByaW50X21lbnUoZnAsIEFVVEhPUl9JTkRFWCwgYWJvdXQsIGFyY2hp dmVzLCAiIiwgIiIsIFBBR0VfQk9UVE9NKTsNCiAgICB9DQoNCiAgICBwcmlu dGZvb3RlcihmcCwgaWh0bWxmb290ZXIsIGxhYmVsLCBkaXIsICJCeSBBdXRo b3IiKTsNCg0KICAgIGZjbG9zZShmcCk7DQoNCiAgICBpZiAobmV3ZmlsZSAm JiBjaG1vZChmaWxlbmFtZSwgZmlsZW1vZGUpID09IC0xKSB7DQogICAgICAg IHNwcmludGYoZXJybXNnLCAiQ291bGRuJ3QgY2htb2QgXCIlc1wiIHRvICVv LiIsIGZpbGVuYW1lLCBmaWxlbW9kZSk7DQogICAgICAgIHByb2dlcnIoKGNo YXIqKU5VTEwpOw0KICAgIH0NCg0KICAgIGlmIChzaG93cHJvZ3Jlc3MpDQog ICAgICAgIHB1dGNoYXIoJ1xuJyk7DQp9DQo= ---559023410-851401618-901288998=:17635-- ================================================ FILE: tests/mboxes/critmail.mbox ================================================ From owner-hypermail Fri Sep 25 20:23 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id UAA06103 for hypermail-outgoing; Fri, 25 Sep 2000 20:22:37 -0500 (CDT) Received: from runningman.rs.itd.umich.edu (runningman.rs.itd.umich.edu [141.211.144.15]) by landfield.com (8.9.0/8.9.0) with ESMTP id UAA06097 for ; Fri, 25 Sep 2000 20:21:33 -0500 (CDT) Received: from umich.edu (dialin224193.isdn.umich.edu [198.111.224.193]) by runningman.rs.itd.umich.edu (8.8.5/2.3) with ESMTP id VAA19384; Fri, 25 Sep 2000 21:19:37 -0400 (EDT) Message-ID: <360C40A1.A8FAF28C@umich.edu> Date: Fri, 25 Sep 2000 21:17:21 -0400 From: "Jeffrey K. MacKie-Mason" Organization: University of Michigan X-Mailer: Mozilla 4.5b2 [en] (WinNT; I) X-Accept-Language: en MIME-Version: 1.0 To: hypermail@landfield.com CC: Charles Hall , "Gordon H. Buchan" Subject: Re: adding new messages to prior hypermail archive Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Jeffrey K. MacKie-Mason" X-Lines: 54 Content-Type: text/plain; charset="us-ascii" Content-Length: 2276 Status: OR Charles and Gordon offered helpful suggestions. However, I think there is a problem. Here is what I'm trying to do: I have an existing Hypermail archive (from 1.02) with 467 messages already in it. I do *NOT* have the original mailbox file for it. I now have 65 new messages in a mailbox that I want to add. I've tried a standard run, as Gordon suggested (those are Gordon's paths): /home/gordon/bin/hypermail \ -b "http://cusidnet.anadas.com/" \ -a "http://cusidnet.anadas.com/" \ -m "/home/gordon/mail/cusid" \ -l "CUSIDnet Web Mirror" \ -d "/home/gordon/www/cusidnet/fall2000/" \ -c "/home/gordon/bin/.cusidnethyprc" > /dev/null That had the following result: The new index files overwrote the existing index files, and showed the information for the 65 *new* messages but no listings for the 467 original messages. However, the archive in fact contained the 467 html files for the original messages, but did *not* contain files for any of the new messages. (Click on New #1 in the index, and it goes to file 0000.html which is Old #1.) Then I tried what Charles suggested: I inserted 467 "dummy" messages in my mailbox file so that Hypermail could count down those and only add the "new" messages. That *almost* worked. The message files were correctly created: an addition 65 nnnn.html files were added to the archive. However, the original 467 message entries in the index were overwritten with the header information from the 467 dummy messages. So my index files are now useless.... The (filler added here to make the line 40+ chars) two hyphen- ated words in the original verision of this sentence should have no spaces in- serted where the hyphens were. From owner-hypermail Fri Sep 25 20:59 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id UAA06348 for hypermail-outgoing; Fri, 25 Sep 2000 20:59:15 -0500 (CDT) Received: from ns.totalsports.net (ns.totalsports.net [207.175.67.50]) by landfield.com (8.9.0/8.9.0) with ESMTP id UAA06340 for ; Fri, 25 Sep 2000 20:58:30 -0500 (CDT) Received: from klaatu.totalsports.net (chall3.totalsports.net [207.175.67.217]) by ns.totalsports.net (Post.Office MTA v3.5 release 215 ID# 0-55440U300L200S0V35) with SMTP id net; Fri, 25 Sep 2000 21:53:37 -0400 Message-ID: <360C4737.6946@totalsports.net> Date: Fri, 25 Sep 2000 21:45:27 -0400 From: chall@totalsports.net (Charles Hall) Organization: Total Sports X-Mailer: Mozilla 3.01Gold (Win95; I) MIME-Version: 1.0 To: "Jeffrey K. MacKie-Mason" CC: hypermail@landfield.com Subject: Re: adding new messages to prior hypermail archive References: <360C40A1.A8FAF28C@umich.edu> Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: chall@totalsports.net (Charles Hall) X-Lines: 25 Content-Type: text/plain; charset="us-ascii" Content-Length: 1005 Status: OR Jeffrey K. MacKie-Mason wrote: > > Then I tried what Charles suggested... However, the original 467 message > entries in the index were overwritten with the 467 dummy messages. So > my index files are now useless.... Ouch! I hope you can recover from this. I didn't realize. Sorry. >The (filler added here to make the line 40+ chars) two hyphen- >ated words in the original verision of this sentence should have no spaces in- >serted where the hyphens were. This message should be formatted adequately if set_showhtml = 2. Expect many problems if set_showhtml = 1. Test the ability of set_showhtml = 2 to handle tables column1 column2 column3 ===================================================================== 1 2 3 one two three 1 3 The columns above should be centered under the appropriate 'u'. --------------------------------------------------------- You should see a horizontal rule above. 1. This should look like a list item numbered one. 2. This should look like a list item numbered two. - first line of a sublist entry, filler added here to make it longer than a single line. * a sublist nested a 2nd level deep. * a sublist nested a 2nd level deep. - closing the singly nested list 3. This should look like a list item numbered three of the outer list. leftmost left left | There should be vertical | left aligned in | bars aligned on either | right tabular format. | side of me. | The second and last words of this sentence should have carets (^'s) under them. ^^^^^^ ^^^^ !!THIS LINE SHOULD BE SURROUNDED BY STRONG TAGS BECAUSE IT IS ALL UPPER CASE!! oooooooo line these up ..... with these up ================================================ FILE: tests/mboxes/embedded.msg ================================================ From rene Tue Mar 2 22:53:38 1999 Return-Path: Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA03065; Tue, 2 Mar 1999 22:53:38 +0100 Date: Tue, 2 Mar 1999 22:53:38 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA03065@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA03065.920411618/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) X-Status: X-Keywords: X-UID: 384 Status: OR This is a MIME-encapsulated message --WAA03065.920411618/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:37 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA03065.920411618/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:37 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:38 +0100 --WAA03065.920411618/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA03040 for sms@sms; Tue, 2 Mar 1999 22:53:37 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA02947; Tue, 2 Mar 1999 22:53:37 +0100 Date: Tue, 2 Mar 1999 22:53:37 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA02947@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA02947.920411617/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA02947.920411617/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:36 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA02947.920411617/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:36 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:37 +0100 --WAA02947.920411617/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA02936 for sms@sms; Tue, 2 Mar 1999 22:53:36 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA02204; Tue, 2 Mar 1999 22:53:28 +0100 Date: Tue, 2 Mar 1999 22:53:28 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA02204@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA02204.920411608/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA02204.920411608/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:28 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA02204.920411608/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:28 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:28 +0100 --WAA02204.920411608/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA02195 for sms@sms; Tue, 2 Mar 1999 22:53:28 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA02135; Tue, 2 Mar 1999 22:53:28 +0100 Date: Tue, 2 Mar 1999 22:53:28 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA02135@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA02135.920411608/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA02135.920411608/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:26 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA02135.920411608/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:26 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:28 +0100 --WAA02135.920411608/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA02104 for sms@sms; Tue, 2 Mar 1999 22:53:26 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA02048; Tue, 2 Mar 1999 22:53:26 +0100 Date: Tue, 2 Mar 1999 22:53:26 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA02048@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA02048.920411606/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA02048.920411606/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:25 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA02048.920411606/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:25 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:26 +0100 --WAA02048.920411606/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA02041 for sms@sms; Tue, 2 Mar 1999 22:53:25 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA02014; Tue, 2 Mar 1999 22:53:25 +0100 Date: Tue, 2 Mar 1999 22:53:25 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA02014@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA02014.920411605/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA02014.920411605/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:25 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA02014.920411605/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:25 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:25 +0100 --WAA02014.920411605/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA02001 for sms@sms; Tue, 2 Mar 1999 22:53:25 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA01939; Tue, 2 Mar 1999 22:53:24 +0100 Date: Tue, 2 Mar 1999 22:53:24 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA01939@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA01939.920411604/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA01939.920411604/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:23 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA01939.920411604/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:23 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:24 +0100 --WAA01939.920411604/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA01927 for sms@sms; Tue, 2 Mar 1999 22:53:23 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA01891; Tue, 2 Mar 1999 22:53:23 +0100 Date: Tue, 2 Mar 1999 22:53:23 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA01891@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA01891.920411603/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA01891.920411603/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:22 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA01891.920411603/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:22 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:23 +0100 --WAA01891.920411603/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA01874 for sms@sms; Tue, 2 Mar 1999 22:53:22 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA01842; Tue, 2 Mar 1999 22:53:22 +0100 Date: Tue, 2 Mar 1999 22:53:22 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA01842@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: rene@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA01842.920411602/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA01842.920411602/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:21 +0100 from rene@localhost ----- The following addresses had permanent fatal errors ----- sms@sms ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms... Local configuration error --WAA01842.920411602/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:21 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:22 +0100 --WAA01842.920411602/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from rene@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA01837 for sms@sms; Tue, 2 Mar 1999 22:53:21 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA01780; Tue, 2 Mar 1999 22:53:20 +0100 Date: Tue, 2 Mar 1999 22:53:20 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA01780@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: horstf@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA01780.920411600/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01714318424 SMS-TYPE: SUBJECT This is a MIME-encapsulated message --WAA01780.920411600/homer.bos-systemhaus.de The original message was received at Tue, 2 Mar 1999 22:53:19 +0100 from horstf@localhost ----- The following addresses had permanent fatal errors ----- sms@sms.bos-systemhaus.de ----- Transcript of session follows ----- 553 mail.bos-systemhaus.de config error: mail loops back to me (MX problem?) 554 sms@sms.bos-systemhaus.de... Local configuration error --WAA01780.920411600/homer.bos-systemhaus.de Content-Type: message/delivery-status Reporting-MTA: dns; homer.bos-systemhaus.de Arrival-Date: Tue, 2 Mar 1999 22:53:19 +0100 Final-Recipient: RFC822; sms@killer.bos-systemhaus.de Action: failed Status: 5.5.0 Remote-MTA: DNS; mail.bos-systemhaus.de Last-Attempt-Date: Tue, 2 Mar 1999 22:53:20 +0100 --WAA01780.920411600/homer.bos-systemhaus.de Content-Type: message/rfc822 Return-Path: Received: (from horstf@localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) id WAA01775 for sms@sms.bos-systemhaus.de; Tue, 2 Mar 1999 22:53:19 +0100 Received: from localhost (localhost) by homer.bos-systemhaus.de (8.8.7/8.8.7) with internal id WAA01749; Tue, 2 Mar 1999 22:53:19 +0100 Date: Tue, 2 Mar 1999 22:53:19 +0100 From: Mail Delivery Subsystem Message-Id: <199903022153.WAA01749@homer.bos-systemhaus.de> To: postmaster@homer.bos-systemhaus.de To: horstf@homer.bos-systemhaus.de MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="WAA01749.920411599/homer.bos-systemhaus.de" Subject: Returned mail: Local configuration error Auto-Submitted: auto-generated (failure) SMS-NUMBER: 01716455134 SMS-TYPE: SUBJECT --WAA01780.920411600/homer.bos-systemhaus.de-- --WAA01842.920411602/homer.bos-systemhaus.de-- --WAA01891.920411603/homer.bos-systemhaus.de-- --WAA01939.920411604/homer.bos-systemhaus.de-- --WAA02014.920411605/homer.bos-systemhaus.de-- --WAA02048.920411606/homer.bos-systemhaus.de-- --WAA02135.920411608/homer.bos-systemhaus.de-- --WAA02204.920411608/homer.bos-systemhaus.de-- --WAA02947.920411617/homer.bos-systemhaus.de-- --WAA03065.920411618/homer.bos-systemhaus.de-- ================================================ FILE: tests/mboxes/t1 ================================================ From owner-hypermail Fri Sep 25 20:23 CDT 1998 Received: by landfield.com (8.9.0/8.9.0) id UAA06103 for hypermail-outgoing; Fri, 25 Sep 1998 20:22:37 -0500 (CDT) Received: from runningman.rs.itd.umich.edu (runningman.rs.itd.umich.edu [141.211.144.15]) by landfield.com (8.9.0/8.9.0) with ESMTP id UAA06097 for ; Fri, 25 Sep 1998 20:21:33 -0500 (CDT) Received: from umich.edu (dialin224193.isdn.umich.edu [198.111.224.193]) by runningman.rs.itd.umich.edu (8.8.5/2.3) with ESMTP id VAA19384; Fri, 25 Sep 1998 21:19:37 -0400 (EDT) Message-ID: <360C40A1.A8FAF28C@umich.edu> Date: Fri, 25 Sep 1998 21:17:21 -0400 From: "Jeffrey K. MacKie-Mason" Organization: University of Michigan X-Mailer: Mozilla 4.5b2 [en] (WinNT; I) X-Accept-Language: en MIME-Version: 1.0 To: hypermail@landfield.com CC: Charles Hall , "Gordon H. Buchan" Subject: Re: adding new messages to prior hypermail archive Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Jeffrey K. MacKie-Mason" X-Lines: 54 Content-Type: text/plain; charset="us-ascii" Content-Length: 2276 Status: OR Charles and Gordon offered helpful suggestions. However, I think there is a problem. Here is what I'm trying to do: I have an existing Hypermail archive (from 1.02) with 467 messages already in it. I do *NOT* have the original mailbox file for it. I now have 65 new messages in a mailbox that I want to add. I've tried a standard run, as Gordon suggested (those are Gordon's paths): /home/gordon/bin/hypermail \ -b "http://cusidnet.anadas.com/" \ -a "http://cusidnet.anadas.com/" \ -m "/home/gordon/mail/cusid" \ -l "CUSIDnet Web Mirror" \ -d "/home/gordon/www/cusidnet/fall1998/" \ -c "/home/gordon/bin/.cusidnethyprc" > /dev/null That had the following result: The new index files overwrote the existing index files, and showed the information for the 65 *new* messages but no listings for the 467 original messages. However, the archive in fact contained the 467 html files for the original messages, but did *not* contain files for any of the new messages. (Click on New #1 in the index, and it goes to file 0000.html which is Old #1.) Then I tried what Charles suggested: I inserted 467 "dummy" messages in my mailbox file so that Hypermail could count down those and only add the "new" messages. That *almost* worked. The message files were correctly created: an addition 65 nnnn.html files were added to the archive. However, the original 467 message entries in the index were overwritten with the header information from the 467 dummy messages. So my index files are now useless.... Obviously, the solution could be to chop the 65 new messages and deliver them one at a time to Hypermail for a single message append. (Can someone suggest an easy way to script that?) However, shouldn't Hypermail be able to do this? Perhaps have a switch for "append to existing archive" when we have a new mbox file but have lost the mbox for the original archive? (Likewise, a way to merge hypermail archives without having the original mboxes?) thanks, jmm -- Prof. Jeffrey MacKie-Mason http://www-personal.umich.edu/~jmm/ Dept. of Economics jmm@umich.edu and School of Information +1 (734) 647-4856 (voice) University of Michigan +1 (734) 764-2475 (fax) Ann Arbor, MI 48109 ================================================ FILE: tests/mboxes/t2 ================================================ From owner-hypermail Fri Sep 25 20:59 CDT 1998 Received: by landfield.com (8.9.0/8.9.0) id UAA06348 for hypermail-outgoing; Fri, 25 Sep 1998 20:59:15 -0500 (CDT) Received: from ns.totalsports.net (ns.totalsports.net [207.175.67.50]) by landfield.com (8.9.0/8.9.0) with ESMTP id UAA06340 for ; Fri, 25 Sep 1998 20:58:30 -0500 (CDT) Received: from klaatu.totalsports.net (chall3.totalsports.net [207.175.67.217]) by ns.totalsports.net (Post.Office MTA v3.5 release 215 ID# 0-55440U300L200S0V35) with SMTP id net; Fri, 25 Sep 1998 21:53:37 -0400 Message-ID: <360C4737.6946@totalsports.net> Date: Fri, 25 Sep 1998 21:45:27 -0400 From: chall@totalsports.net (Charles Hall) Organization: Total Sports X-Mailer: Mozilla 3.01Gold (Win95; I) MIME-Version: 1.0 To: "Jeffrey K. MacKie-Mason" CC: hypermail@landfield.com Subject: Re: adding new messages to prior hypermail archive References: <360C40A1.A8FAF28C@umich.edu> Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: chall@totalsports.net (Charles Hall) X-Lines: 25 Content-Type: text/plain; charset="us-ascii" Content-Length: 1005 Status: OR Jeffrey K. MacKie-Mason wrote: > > Then I tried what Charles suggested... However, the original 467 message > entries in the index were overwritten with the 467 dummy messages. So > my index files are now useless.... Ouch! I hope you can recover from this. I didn't realize. Sorry. > Perhaps have a switch for "append to existing archive" when we have a new > mbox file Yes, Yes! I need this functionality too. I prefer not to add messages one at a time through the day as Hypermail would go re-indexing over and over again, so I let my mail collect till the end of the month, and run hypermail once nightly. Since there's no append function, Hypermail has to churn through all that month's mail each night. If I could append, I could erase the mailbox each night and only process that day's mail. MHonArc has this feature, but I believe it keeps a small database to remember what's been done before. Perhaps such info could be hidden in the indexes as HTML comments?? -- Charles Hall Raleigh, NC ================================================ FILE: tests/mboxes/t3 ================================================ From owner-hypermail Sat Sep 26 06:16 CDT 1998 Received: by landfield.com (8.9.0/8.9.0) id GAA20916 for hypermail-outgoing; Sat, 26 Sep 1998 06:16:19 -0500 (CDT) Received: from relay7.UU.NET (relay7.UU.NET [192.48.96.17]) by landfield.com (8.9.0/8.9.0) with ESMTP id GAA20890 for ; Sat, 26 Sep 1998 06:14:42 -0500 (CDT) Received: from relay7.UU.NET by relay7.UU.NET with ESMTP (peer crosschecked as: root@localhost) id QQfijh19139; Fri, 25 Sep 1998 10:17:34 -0400 (EDT) Received: from morrison.matrox.com by relay7.UU.NET with ESMTP (peer crosschecked as: [204.50.136.19]) id QQfijh19076; Fri, 25 Sep 1998 10:17:28 -0400 (EDT) Received: (from mtxmail@localhost) by morrison.matrox.com (8.8.8/8.8.8) id KAA23068; Fri, 25 Sep 1998 10:14:08 -0400 (EDT) Received: from venus.matrox.com(138.11.0.5) by morrison-250 via smap (V2.0) id xma022977; Fri, 25 Sep 98 10:13:18 -0400 Received: from focus.matrox.com (focus.matrox.com [192.168.16.2]) by venus.matrox.com (8.8.7/8.8.7) with ESMTP id KAA09310; Fri, 25 Sep 1998 10:13:17 -0400 (EDT) Received: from gbuchan.matrox.com ([192.168.17.51]) by focus.matrox.com (8.7.5/8.7.3) with SMTP id KAA15383; Fri, 25 Sep 1998 10:13:14 -0400 (EDT) Message-Id: <199809251413.KAA15383@focus.matrox.com> X-Sender: gbuchan@focus.matrox.com X-Mailer: QUALCOMM Windows Eudora Pro Version 4.0 Date: Fri, 25 Sep 1998 10:13:10 -0400 To: "Jeffrey K. MacKie-Mason" , hypermail@landfield.com From: "Gordon H. Buchan" Subject: Re: adding new messages to prior hypermail archive In-Reply-To: <360B2905.E41100C9@umich.edu> Mime-Version: 1.0 Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Gordon H. Buchan" X-Lines: 40 Content-Type: text/plain; charset="us-ascii" Content-Length: 1590 Status: OR At 01:24 AM 9/25/98 -0400, Jeffrey K. MacKie-Mason wrote: > >I archived some 460 messages from a mailbox with Hypermail 1.02 about 3 >years ago. Now I want to use hypermail 2.03b to process a new mailbox >and add the messages to the prior archive. I've tested 2.03b on the new >mailbox, and it works fine when I give it an empty directory in which to >create a new hypermail archive. However, when I point it at the >directory with the prior 460-message archive, it changes the date stamp >on the index files to today, but it doesn't append the 65 new messages >to the archive. > >As far as I can see, the default behavior is supposed to be to append >messages to an existing archive. I'm not using the -u or -x flags. >Suggestions? With a slight modification (removal of the -x switch, since this is to append, not replace), here is one of my batch files. Change paths and parameters to match your environment. /home/gordon/bin/hypermail \ -b "http://cusidnet.anadas.com/" \ -a "http://cusidnet.anadas.com/" \ -m "/home/gordon/mail/cusid" \ -l "CUSIDnet Web Mirror" \ -d "/home/gordon/www/cusidnet/fall1998/" \ -c "/home/gordon/bin/.cusidnethyprc" > /dev/null Note 1: /home/gordon/mail/cusid is a standard UNIX mail folder. Note 2: /home/gordon/www/cusidnet/fall1998 contains an existing hypermail archive. ---- Gordon H. Buchan Technical Writer Matrox Networks / Matrox Electronic Systems email: gbuchan@matrox.com 1055 St-Regis Blvd. voice: +1 (514) 685-7230 x2523 Dorval, Quebec fax: +1 (514) 822-6272 Canada H9P 2T4 http://www.matrox.com/networks ================================================ FILE: tests/mboxes/t4 ================================================ From owner-hypermail Fri Oct 9 16:11 CDT 1998 Received: by landfield.com (8.9.0/8.9.0) id QAA21334 for hypermail-outgoing; Fri, 9 Oct 1998 16:11:02 -0500 (CDT) Received: from fw-es06.hac.com (fw-es06.HAC.COM [128.152.1.6]) by landfield.com (8.9.0/8.9.0) with ESMTP id QAA21322 for ; Fri, 9 Oct 1998 16:10:20 -0500 (CDT) Received: from pepperoni.pizza.hac.com (bdarr@[192.27.36.100]) by fw-es06.hac.com (8.8.4/8.8.4) with ESMTP id OAA22596 for ; Fri, 9 Oct 1998 14:07:50 -0700 (PDT) Received: (from bdarr@localhost) by pepperoni.pizza.hac.com (8.8.6/8.8.6) id OAA03350; Fri, 9 Oct 1998 14:07:50 -0700 (PDT) Date: Fri, 9 Oct 1998 14:07:50 -0700 (PDT) Message-Id: <199810092107.OAA03350@pepperoni.pizza.hac.com> From: "Byron C. Darrah" To: hypermail@landfield.com In-reply-to: <199810091757.KAA03184@pepperoni.pizza.hac.com> (bdarr@sed.hac.com) Subject: Re: replace() function Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Byron C. Darrah" Content-Type: text Content-Length: 4325 Status: OR Good morning, I did a little more checking on this, so here's the skinny if you're interested. I noticed that some attention to this bug was indeed paid in an early version of the new hypermail. However, the "fix" was more of a work-around than a real fix... The problem tends to manifest itself most often for single-character substitutions. (Eg: replacing single-character '%' with "%25"). So the work-around provided was to implement a whole seperate version of "replace()", called "replacechar()" that is used for certain single-character substitutions. However, "replace()" is still used for some other subsitutions. "replace()", as it is now, is still buggy and will blow up anytime it is used to replace an old string with a new one that happens to contain the old one. For example, if trying to replace "$SUBJECT" with the string "Re: Hypermail crashes when $SUBJECT is used in the subject" :-). --Byron Darrah PS: On the Y2K subject. If anyone wants a fairly simple date class for C or C++ that can add, subtract, convert to text, and parse dates reliably, I've got one at http://www.cs.ucla.edu/~darrah/date_t.tgz that you can try. Not to be confused with the dates.c file in hypermail, which does other stuff. My date class is "guranteed" to correctly account for century boundaries, leap years, quad leap years, leap centuries, quad leap centuries, and the Papal decree in 1752, or your money back :-). _______________________________________________________________________________ Date: Fri, 9 Oct 1998 10:57:36 -0700 (PDT) From: "Byron C. Darrah" Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Byron C. Darrah" Hi, I noticed a bug in an old variant version of hypermail so I inspected the sources of the latest beta release and it seems to be there, too. I'm a little surprised that it hasn't been caught by now. Anyway, there's a function called replace() in strings.c that is used to do things like variable substitution and url encoding. (eg: replace occurrences of "$TO" with an email address.) Well, this function is written such that if the new text *contains* the pattern you are replacing, you get incorrect results. In fact, you get infinite recursion. For example, try to replace "%" with "%25" (for url-encoding), and you end up with an endless sequence of "%%%%%%%%%%%%%%%%%%%%%%%...". I noticed the new version is slightly better than my crummy old deviant version because it uses strcpymax() instead of strcpy() at one place, but I think the basic problem is still there. Here is a possible replacement for replace(). Besides the main problem, replace() is tail-recursive which is unnecessary, and also tends to do some unnecessary recopying of a static buffer onto itself due to the recursion. So I cleaned that up a bit, too. --Byron Darrah /* Given a string, replaces all instances of "oldpiece" with "newpiece". * * Modified this routine to eliminate recursion and to avoid infinite * expansion of string when newpiece contains oldpiece. --Byron */ char *replace(char *string, char *oldpiece, char *newpiece) { int str_index, newstr_index, oldpiece_index, end, new_len, old_len, cpy_len; char *c; static char newstring[MAXLINE]; if ((c = (char *) strstr(string, oldpiece)) == NULL) return string; new_len = strlen(newpiece); old_len = strlen(oldpiece); end = strlen(string) - old_len; oldpiece_index = c - string; newstr_index = 0; str_index = 0; while(str_index <= end && c != NULL) { /* Copy characters from the left of matched pattern occurence */ cpy_len = oldpiece_index-str_index; strncpy(newstring+newstr_index, string+str_index, cpy_len); newstr_index += cpy_len; str_index += cpy_len; /* Copy replacement characters instead of matched pattern */ strcpy(newstring+newstr_index, newpiece); newstr_index += new_len; str_index += old_len; /* Check for another pattern match */ if((c = (char *) strstr(string+str_index, oldpiece)) != NULL) oldpiece_index = c - string; } /* Copy remaining characters from the right of last matched pattern */ strcpy(newstring+newstr_index, string+str_index); return newstring; } ================================================ FILE: tests/mboxes/t5 ================================================ From craig@cni.org Tue Oct 6 18:26 CDT 1998 Received: from a.cni.org (a.cni.org [192.100.21.1]) by landfield.com (8.9.0/8.9.0) with SMTP id SAA18925; Tue, 6 Oct 1998 18:26:01 -0500 (CDT) Received: by a.cni.org id ; Tue, 6 Oct 1998 19:20:00 -0400 From: Craig A Summerhill Message-Id: <9810062320.AA05549@a.cni.org> Subject: Re: another bug To: hypermail@landfield.com Date: Tue, 6 Oct 1998 19:20:00 -0400 (EDT) Cc: kent@landfield.com In-Reply-To: <199810061703.MAA13834@landfield.com> from "Kent Landfield" at Oct 6, 98 12:03:19 pm X-Mailer: ELM [version 2.4 PL23] Content-Type: text Content-Length: 2299 X-Lines: 53 Status: OR Kent Landfield wrote: > > # This problem has been around since version 1.02, but I forgot about it > # because it doesn't come up too often... > # > # If you run Hypermail against an existing mailbox... > # > # hypermail -c -m -l "whatever" -d > # > # and the mbox file that you are processing only has one message in it... > # > # hypermail goes out and creates the HTMLed message (0000.html), but > # before the date, author, subject, and thread indexes are created it > # dumps core with this error: > # > # Floating exception (core dumped) > > I don't get this when I tried it on the latest version. It may be that > the problem isn't the single message in the mailbox but the message itself. > It may be triggering a memory corruption bug. If you have a copy of the > offending message you can send me I'll verify if it is a problem still. Kent, Hmm. That's odd. It happens consistently on my system; everytime there is a mailbox with only one message in it. It must be some combination of the defaults that I set when I compiled the code (I changed some of the suggested settings), and the settings in the .hmrc file I am calling. I'll send you my compile time settings and .hmrc file later, and see if you can find something in there that is causing it to happen. (I have been up and working on a system problem for thirty-some hours, I need to go home, shower, and get in bed -- so it may be tomorrow). It does dump core on me to, BTW. Is there a core analysis tool I could used that would give you some helpful information? P.S. One other thought occured to me. I was wondering if it might be related to the parsing problem I wrote about earlier (which you have fixed in the next release -- thank you). Perhaps it is expecting a trailing line with white space on it, or something? The trouble with this idea is that the single message problem was also present in version 1.02, and came along to version 2.x. However, the parsing problem wasn't present in version 1.02... -- Craig A. Summerhill, Systems Coordinator and Program Officer Coalition for Networked Information 21 Dupont Circle, N.W., Washington, D.C. 20036 Internet: craig@cni.org AT&Tnet (202) 296-5098 ================================================ FILE: tests/mboxes/t6 ================================================ From brian@hyperreal.org Wed Apr 22 23:13 CDT 1998 Received: from hyperreal.org (taz.hyperreal.org [204.62.130.147]) by landfield.com (8.8.8/8.8.8) with SMTP id XAA27903 for ; Wed, 22 Apr 1998 23:13:13 -0500 (CDT) Received: (qmail 7191 invoked by uid 24); 23 Apr 1998 04:11:20 -0000 Message-Id: <3.0.3.32.19980422211640.00a31100@hyperreal.org> X-Sender: brian@hyperreal.org X-Mailer: QUALCOMM Windows Eudora Pro Version 3.0.3 (32) Date: Wed, 22 Apr 1998 21:16:40 -0700 To: Kent Landfield From: Brian Behlendorf Subject: thoughts on ml archives Cc: mike@hyperreal.org Mime-Version: 1.0 X-Lines: 128 Content-Type: text/plain; charset="us-ascii" Content-Length: 5529 Status: OR Here's a message about a system we've been scheming up here, but I haven't had the time to implement. I've got another right after this which is my comments on this proposal. We wouldn't mind at all if you wanted to base your efforts on this; I just wish I had any time to do anything with it. Brian >Delivered-To: brian@hyperreal.org >From: mike@hyperreal.org >MBOX-Line: From mike Fri Dec 26 18:38:31 1997 remote from taz.hyperreal.org >Subject: thoughts on ml archives >To: brian@hyperreal.org (Brian Behlendorf) >Date: Fri, 26 Dec 1997 18:38:31 -0800 (PST) >Cc: est@hyperreal.org (Eric Tiedemann), tint@hyperreal.org (Mike Perkowitz) >X-Mailer: ELM [version 2.4ME+ PL37 (25)] >Sender: mike@hyperreal.org > >Well here are the ideas I had over the summer regarding an ideal mailing >list archival system. I was thinking of using a database. > >goals: > >for general browsing through the archives, a set of static index files, >updated daily. >indexes by date or by thread. > >monthly (or whatever) mbox file structure preserved. >individual messages accessible without having every message broken out into >its own file. > >html-ization of individual messages on the fly, upon delivery. > >searchability - searches must be fast, using a pre-built index rather than >scanning through all the mbox files every time. >desired: new messages added to index as they arrive. > >suggested method: > >relational databse using mysql. tables as follows: > >MESSAGE_INFO table >================================== >umid = unique message id# >message_id = message id field from headers >mbox_file = name of mbox file containing message >mbox_byte_offset = byte offset of start of message within mbox file >from = From: field from headers. if none, glean from first line of headers >(^From user@foo ...) >subject = subject field from headers >date = date field from headers >gmt_date = date field converted to gmt, for proper ordering and better >searching (e.g., 3pm EST comes well before 2:45pm PST) > >MESSAGE_THREAD table >================================= >umid = unique message id# >xrefs = other umids from headers (In-Reply-To, References) >possible_xrefs = other umids guessed from subject, date > >KEYWORDS tables (one of these for every letter & number) >======================================================== >keyword = keyword that appears in a message >location = umids where that keyword can be found > > >I think that's all you'd need. > >When doing a search, you'd enter keywords >to look for in a form. The script would use the KEYWORDS tables >(KEYWORD_A, KEYWORD_B, KEYWORD_C, etc, depending on the >first letter of the keywords in your query) to build lists of umids which >correspond to the messages where those words are found. The lists are >then combined, depending on the nature of the query (AND, OR, NOT >would be really easy to do this way), and a list of matching umids is >produced. > >Then the script would look up each umid in the MESSAGE_INFO >table to find out exactly where that message is, and it would get info >like the subject line, date and sender, all without actually going into >the mbox file itself. At this point the list of umids might shrink a little >because the query might have specified that the search only applied >to certain mbox files. (A possible inefficiency... if only certain mbox >files are to be checked, the simple KEYWORDS tables shouldn't >have to return hundreds, possibly thousands of umids that >correspond to messages located across the entire archive). > >Of course the search result is going to have to link to the message >somehow, and you may want to include a couple lines of context from >the message. Both are accomplished by looking at the mbox_file and >mbox_byte_offset. > >To get the link, a URL can be calculated. It will point to a script >that is given the mbox filename and byte offset as arguments. This >script will take care of extracting the message and html-izing it and >chucking it out to the user. > >example: http://hyperreal/extract?mbox=idm.9706&offset=229148 >extract.cgi would go look for a message that starts at byte 229148 >in the file idm.9706. > >The script could even take umid as an argument instead, and do >the necessary lookups to determine the mbox and offset. > >To get the lines of context for the search results, a similar script >would extract the message, but rather than HTML-ize the whole >thing, it would just do a context grep and highlight the >appropriate keywords. (This might be inefficient to run such >a script on every message in the search results, though.) > >html-ization would involve more lookups, because you want to have >links in the message to the rest of the thread. The extraction script >will already have the current message's umid, so it just needs to get >some other umids for xref messages out of the MESSAGE_THREAD >table. There may be messages UP the thread chain (xrefs listed for >the current umid) and there may be messages DOWN the thread >chain (umids that have the current umid listed in their xrefs), so >that's two additional lookups. > >General browsing requires building indices ahead of time. Not >sure of the best way to generate them, but shouldn't be too >difficult to do the by-date lists, at least. Thread lists are probably >trickier. > > --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-- "Optimism is a strategy for making brian@apache.org a better future." - Noam Chomsky brian@hyperreal.org ================================================ FILE: tests/mboxes/t7 ================================================ From owner-hypermail Thu Apr 23 12:22 CDT 1998 Received: (from lists@localhost) by landfield.com (8.8.8/8.8.8) id MAA15666 for hypermail-outgoing; Thu, 23 Apr 1998 12:20:58 -0500 (CDT) Received: (from root@localhost) by landfield.com (8.8.8/8.8.8) id MAA15660 for hypermail; Thu, 23 Apr 1998 12:20:50 -0500 (CDT) From: Kent Landfield Message-Id: <199804231720.MAA15660@landfield.com> Subject: Re: Ideas To: hypermail Date: Thu, 23 Apr 1998 12:20:47 -0500 (CDT) In-Reply-To: <9804230546.AA06415@a.cni.org> from "Craig A Summerhill" at Apr 23, 98 01:46:19 am X-Mailer: ELM [version 2.4 PL25] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: Kent Landfield X-Lines: 62 Content-Type: text/plain; charset="US-ASCII" Content-Length: 2971 Status: OR # It occurs to me that one of the first things you need to do is to get # some sense of prioritization on that list of proposed enhancements. # In that manner, you can perhaps break it into manageable chunks. This makes total sense. 0) Merge existing contributed patches # Off the top of my head, I will offer my top priorities for Hypermail: # # 1) Full MIME compliance -- Daniel Stenberg submitted a patch that is a first step to supporting MIME. It replaces attachments with the message "** attachment type 'application/octet-stream;' left out". It does the proper parsing for most everything else so extending that to deal with the attachments will need to be done. It is a great start. I'd like to see the attachments dealt with so that certain types of know formats could be automagically converted, much like MHonArc does. One issue will be storage. While many messages have just one enclosure, some have more than one so we will need to handle those. # 2) Correct RFC821/822 Header Parsing -- this is the single biggest # reason that Hypermail dumps core on me. I have compensated for # the most offending instances of this by using Perl and shell # pre-processing to "re-write" headers before they are handed # off Hypermail. But this is really inefficient, and I keep finding # new instances of such problems cropping up all the time. Yes this is a biggy. I'd be interested in any sample headers sets or needed workarounds that could be used in testing and verification of fixes. # 3) Configurable Setting (.hmrc file) to a Pointer/URL for Custom # Header and Footer Files -- currently, Hypermail does not include # anything except the HTML message body (payload, I guess) when # it does it's output. Yes. My {list}_print.c method of the past needs to be left there. ;) We need to be able to specify a template in some fashion that would allow for list index and list message page customzation. # 4) Configurable Setting (.hmrc file) or Compile Time Variable to # Domain-ize Addresses -- addresses appearing in the RFC822 field # which lack hostname can't be made into proper HREFs when Hypermail # does it's thing. For a good example of the problem I am talking # about, look at message numbers 0001.html and 0002.html on # ftp://ftp.landfield.com/hypermail/mail-archive/1998/. Hmmmm... You know I've not been paying attention. You are right. This should be easy enough to fix and it needs to be. Thanks Craig. Good set of priorities. Sounds like a good plan. -- Kent Landfield Phone: 1-817-545-2502 Email: kent@landfield.com http://www.landfield.com/ Email: kent@nfr.net http://www.nfr.net/ Please send comp.sources.misc related mail to kent@landfield.com Search the Usenet Hypertext FAQ Archive at http://www.faqs.org/faqs/ ================================================ FILE: tests/mboxes/t8 ================================================ From ftp-wg-owner@hethmon.com Tue May 26 15:41 CDT 1998 Received: from mail.hethmon.com (mail.hethmon.com [208.147.156.6]) by landfield.com (8.8.8/8.8.8) with SMTP id PAA28800 for ; Tue, 26 May 1998 15:40:28 -0500 (CDT) Received: from mail (mail.hethmon.com [208.147.156.6] ) by mail.hethmon.com (Hethmon Brothers Smtpd) ; Tue, 26 May 1998 16:33:06 -0400 Received: from www.disa.mil (www.disa.mil [209.22.99.13] ) by mail.hethmon.com (Hethmon Brothers Smtpd) ; Tue, 26 May 1998 16:32:45 -0400 Received: from ftm.disa.mil by www.disa.mil (SMI-8.6/SMI-SVR4) id QAA23321; Tue, 26 May 1998 16:15:57 -0400 Message-ID: <356B25D6.2A1920CD@ftm.disa.mil> X-Mailer: Mozilla 4.03 [en] (WinNT; U) MIME-Version: 1.0 Date: Tue, 26 May 1998 16:32:47 -0400 X-OldDate: Tue, 26 May 1998 16:28:07 -0400 Sender: ftp-wg-owner X-Listname: ftp-wg@hethmon.com Reply-To: FTPEXT Working Group From: Bill Curtin To: ftp-wg@hethmon.com Subject: Ftp-WG: v5 of I18N draft Content-Type: multipart/mixed; boundary="=_AAAYDgAABLM1bB/O" X-Lines: 2201 Content-Length: 205226 Status: OR --=_AAAYDgAABLM1bB/O Content-Type: text/html; charset="us-ascii" From ftp-wg-owner@hethmon.com Tue May 26 15:41 CDT 1998 Received: from ftm.disa.mil by www.disa.mil (SMI-8.6/SMI-SVR4) id QAA23321; Tue, 26 May 1998 16:15:57 -0400 Message-ID: <356B25D6.2A1920CD@ftm.disa.mil> X-Mailer: Mozilla 4.03 [en] (WinNT; U) MIME-Version: 1.0 Date: Tue, 26 May 1998 16:32:47 -0400 X-OldDate: Tue, 26 May 1998 16:28:07 -0400 Sender: ftp-wg-owner X-Listname: ftp-wg@hethmon.com Reply-To: FTPEXT Working Group From: Bill Curtin To: ftp-wg@hethmon.com Subject: Ftp-WG: v5 of I18N draft Content-Length: 204493 Status: OR X-Sun-Content-Length: 204492 Sorry for the delay. Below is the 5th edition of the I18N draft. I believe it incorporates all of the suggestions sent to the list. I've also sent a copy to the ID editor.

                                        bill



     
     
     
     
     
     
     

              FTPEXT Working Group                                         B. Curtin
              INTERNET DRAFT                      Defense Information Systems Agency
              Expires 01 December 1998                             01 June, 1998
     

                     Internationalization of the File Transfer Protocol
                             <draft-ietf-ftpext-intl-ftp-05.txt>
     

              Status of this Memo

                 This document is an Internet-Draft.  Internet-Drafts are
                 working documents of the Internet Engineering Task Force
                 (IETF), its areas, and its working groups. Note that other
                 groups may also distribute working documents as
                 Internet-Drafts.

                 Internet-Drafts are draft documents valid for a maximum of
                 six months. Internet-Drafts may be updated, replaced, or
                 obsoleted by other documents at any time.  It is not
                 appropriate to use Internet-Drafts as reference material or
                 to cite them other than as a "working draft" or "work in
                 progress".

                 To view the entire list of current Internet-Drafts, please
                 check the 1id-abstracts.txt listing contained in the
                 Internet-Drafts Shadow Directories on ftp.is.co.za (Africa),
                 ftp.nordu.net (Europe), munnari.oz.au (Pacific Rim),
                 ds.internic.net (US East Coast), or ftp.isi.edu (US West
                 Coast).

                 Distribution of this document is unlimited.  Please send
                 comments to the FTP Extension working group (FTPEXT-WG) of
                 the Internet Engineering Task Force (IETF) at
                 <ftp-wg@hops.ag.utk.edu>. Subscription address is
                 <ftp-wg-request@hops.ag.utk.edu>. Discussions of the group
                 are archived at <URL:ftp://hops.ag.utk.edu/ftp-wg/archives/>.

                 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
                 NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
                 "OPTIONAL" in this document are to be interpreted as
                 described in RFC 2119 [RFC 2119].
     
     
     
     
     
     
     
     
     
     
     

                                 Expires 01 December 1998                   [Page 1]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

              Abstract

                 The File Transfer Protocol, as defined in RFC 959 [RFC959]
                 and RFC 1123 Section 4 [RFC1123], is one of the oldest and
                 widely used protocols on the Internet. The protocol's primary
                 character set, 7 bit ASCII, has served the protocol well
                 through the early growth years of the Internet. However, as
                 the Internet becomes more global, there is a need to support
                 character sets beyond 7 bit ASCII.

                 This document addresses the internationalization (I18n) of
                 FTP, which includes supporting the multiple character sets
                 found throughout the Internet community.  This is achieved by
                 extending the FTP specification and giving recommendations
                 for proper internationalization support.
     
     
     
     
     

              Table of Contents

              1 INTRODUCTION....................................................3
              2 INTERNATIONALIZATION............................................3
               2.1  International Character Set.................................4
               2.2  Transfer Encoding...........................................4
              3 CONFORMANCE.....................................................5
               3.1  General.....................................................5
               3.2  International Servers.......................................7
               3.3  International Clients.......................................7
              4 SECURITY........................................................8
              5 ACKNOWLEDGMENTS.................................................8
              6 GLOSSARY........................................................8
              7 BIBLIOGRAPHY....................................................9
              8 AUTHOR'S ADDRESS...............................................10
              APPENDIX A - IMPLEMENTATION CONSIDERATIONS......................A-1
               A.1  General Considerations....................................A-1
               A.2  Transition Considerations.................................A-2
              APPENDIX B - SAMPLE CODE AND EXAMPLES...........................B-1
               B.1  Valid UTF-8 check.........................................B-1
               B.2  Conversions...............................................B-2
                B.2.1 Conversion from local character set to UTF-8............B-2
                B.2.2 Conversion from UTF-8 to local character set............B-5
                B.2.3  ISO/IEC 8859-8 Example.................................B-7
                B.2.4 Vendor Codepage Example.................................B-7
               B.3  Pseudo Code for translating servers.......................B-8
     
     
     
     
     
     
     
     

                                 Expires 01 December 1998            [Page 2 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

              1 Introduction

                 As the Internet grows throughout the world the requirement to
                 support character sets outside of the ASCII [ASCII] / Latin-1
                 [ISO-8859] character set becomes ever more urgent.  For FTP,
                 because of the large installed base, it is paramount that
                 this be done without breaking existing clients and servers.
                 This document addresses this need. In doing so it defines a
                 solution which will still allow the installed base to
                 interoperate with new international clients and servers.

                 This document enhances the capabilities of the File Transfer
                 Protocol by removing the 7-bit restrictions on pathnames used
                 in client commands and server responses, recommends the use
                 of a Universal Character Set (UCS) ISO/IEC 10646 [ISO-10646],
                 and recommends a UCS transformation format (UTF) UTF-8
                 [UTF-8].

                 The recommendations made in this document are consistent with
                 the recommendations expressed by the 29 Feb - 1 Mar 1996 IAB
                 Character Set Workshop as expressed in RFC 2130 [RFC 2130].

              2 Internationalization

                 The File Transfer Protocol was developed when the predominate
                 character sets were 7 bit ASCII and 8 bit EBCDIC. Today these
                 character sets cannot support the wide range of characters
                 needed by multinational systems. Given that there are a
                 number of character sets in current use that provide more
                 characters than 7-bit ASCII, it makes sense to decide on a
                 convenient way to represent the union of those possibilities.
                 To work globally either requires support of a number of
                 character sets and to be able to convert between them, or the
                 use of a single preferred character set. To assure global
                 interoperability this document RECOMMENDS the latter approach
                 and defines a single character set, in addition to NVT ASCII
                 and EBCDIC, which is understandable by all systems. For FTP
                 this character set SHALL be ISO/IEC 10646:1993. For support
                 of global compatibility it is STRONGLY RECOMMENDED that
                 clients and servers use UTF-8 encoding when exchanging
                 pathnames. Clients and servers are, however, under no
                 obligation to perform any conversion on the contents of a
                 file for operations such as STOR or RETR.

                 The character set used to store files SHALL remain a local
                 decision and MAY depend on the capability of local operating
                 systems. Prior to the exchange of pathnames they should be
                 converted into a ISO/IEC 10646 format and UTF-8 encoded. This
                 approach, while allowing international exchange of pathnames,
                 will still allow backward compatibility with older systems
                 because the code set positions for ASCII characters are
                 identical to the one byte sequence in UTF-8.
     
     
     

                                 Expires 01 December 1998            [Page 3 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                 Sections 2.1 and 2.2 give a brief description of the
                 international character set and transfer encoding recommended
                 by this document. A more thorough description of UTF-8,
                 ISO/IEC 10646, and UNICODE [UNICODE], beyond that given in
                 this document, can be found in RFC 2279 [RFC2279].

              2.1 International Character Set

                 The character set defined for international support of FTP
                 SHALL be the Universal Character Set as defined in ISO
                 10646:1993 as amended. This standard incorporates the
                 character sets of many existing international, national, and
                 corporate standards. ISO/IEC 10646 defines two alternate
                 forms of encoding, UCS-4 and UCS-2. UCS-4 is a four byte (31
                 bit) encoding containing 2**31 code positions divided into
                 128 groups of 256 planes. Each plane consists of 256 rows of
                 256 cells. UCS-2 is a 2 byte (16 bit) character set
                 consisting of plane zero or the Basic Multilingual Plane
                 (BMP).  Currently, no codesets have been defined outside of
                 the 2 byte BMP.

                 The Unicode standard version 2.0 [UNICODE] is consistent with
                 the UCS-2 subset of ISO/IEC 10646. The Unicode standard
                 version 2.0 includes the repertoire of IS 10646 characters,
                 amendments 1-7 of IS 10646, and editorial and technical
                 corrigenda.
     

              2.2 Transfer Encoding

                 UCS Transformation Format 8 (UTF-8), in the past referred to
                 as UTF-2 or UTF-FSS, SHALL be used as a transfer encoding to
                 transmit the international character set. UTF-8 is a file
                 safe encoding which avoids the use of byte values that have
                 special significance during the parsing of pathname character
                 strings. UTF-8 is an 8 bit encoding of the characters in the
                 UCS. Some of UTF-8's benefits are that it is compatible with
                 7 bit ASCII, so it doesn't affect programs that give special
                 meanings to various ASCII characters; it is immune to
                 synchronization errors; its encoding rules allow for easy
                 identification; and it has enough space to support a large
                 number of character sets.

                 UTF-8 encoding represents each UCS character as a sequence of
                 1 to 6 bytes in length. For all sequences of one byte the
                 most significant bit is ZERO. For all sequences of more than
                 one byte the number of ONE bits in the first byte, starting
                 from the most significant bit position, indicates the number
                 of bytes in the UTF-8 sequence followed by a ZERO bit. For
                 example, the first byte of a 3 byte UTF-8 sequence would have
                 1110 as its most significant bits. Each additional bytes
                 (continuing bytes) in the UTF-8 sequence, contain a ONE bit
                 followed by a ZERO bit as their most significant bits. The
                 remaining free bit positions in the continuing bytes are used
     

                                 Expires 01 December 1998            [Page 4 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                 to identify characters in the UCS. The relationship between
                 UCS and UTF-8 is demonstrated in the following table:

                 UCS-4 range(hex)          UTF-8 byte sequence(binary)
                 00000000 - 0000007F       0xxxxxxx
                 00000080 - 000007FF       110xxxxx 10xxxxxx
                 00000800 - 0000FFFF       1110xxxx 10xxxxxx 10xxxxxx
                 00010000 - 001FFFFF       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                 00200000 - 03FFFFFF       111110xx 10xxxxxx 10xxxxxx 10xxxxxx
                                           10xxxxxx
                 04000000 - 7FFFFFFF       1111110x 10xxxxxx 10xxxxxx 10xxxxxx
                                           10xxxxxx 10xxxxxx
     
     

                 A beneficial property of UTF-8 is that its single byte
                 sequence is consistent with the ASCII character set. This
                 feature will allow a transition where old ASCII-only clients
                 can still interoperate with new servers that support the
                 UTF-8 encoding.

                 Another feature is that the encoding rules make it very
                 unlikely that a character sequence from a different character
                 set will be mistaken for a UTF-8 encoded character sequence.
                 Clients and servers can use a simple routine to determine if
                 the character set being exchanged is valid UTF-8. Section B.1
                 shows a code example of this check.
     

              3 Conformance

              3.1 General

                 - The 7-bit restriction for pathnames exchanged is dropped.

                 - Many operating system allow the use of spaces <SP>,
                   carriage return <CR>, and line feed <LF> characters as part
                   of the pathname. The exchange of pathnames with these
                   special command characters will cause the pathnames to be
                   parsed improperly. This is because ftp commands associated
                   with pathnames have the form:

                        COMMAND <SP> <pathname> <CRLF>.

                   To allow the exchange of pathnames containing these
                   characters, the definition of pathname is changed from
                    <pathname> ::= <string>   ; in BNF format
                   to
                    pathname = 1*(%x01..%xFF) ; in ABNF format [ABNF]

                   To avoid mistaking these characters within pathnames as
                   special command characters the following rules will apply:
     
     
     

                                 Expires 01 December 1998            [Page 5 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                     There MUST be only one <SP> between a ftp command and the
                     pathname. Implementations MUST assume <SP> characters
                     following the initial <SP> as part of the pathname. For
                     example the pathname in STOR <SP><SP><SP>foo.bar<CRLF> is
                     <SP><SP>foo.bar .

                     Current implementations, which may allow multiple <SP>
                     characters as separators between the command and
                     pathname, MUST assure that they comply with this single
                     <SP> convention. Note: Implementations which treat 3
                     character commands (e.g. CWD, MKD, etc.) as a fixed 4
                     character command by padding the command with a trailing
                     <SP> are in non-compliance to this specification.

                  When a <CR> character is encountered as part of a pathname
                   it MUST be padded with a <NUL> character prior to sending
                   the command. On receipt of a pathname containing a <CR><NUL>
                   sequence the <NUL> character MUST be stripped away. This
                   approach is described in the Telnet protocol [RFC854] on
                   pages 11 and 12. For example, to store a pathname
                   foo<CR><LF>boo.bar the pathname would become
                   foo<CR><NUL><LF>boo.bar prior to sending the command STOR
                   <SP>foo<CR><NUL><LF>boo.bar<CRLF> .
                   Upon receipt of the altered pathname the <NUL> character
                   following the <CR> would be stripped away to form the
                   original pathname.

                 - Conforming internationalized clients and servers MUST
                   support UTF-8 for the transfer and receipt of pathnames.
                   Clients and servers MAY in addition give users a choice of
                   specifying interpretation of pathnames in another encoding.
                   Note that configuring clients and servers to use character
                   sets / encoding other than UTF-8 is outside of the scope of
                   this document. While it is recognized that in certain
                   operational scenarios this may be desirable, this is left as
                   a quality of implementation and operational issue.

                 - Pathnames are sequences of bytes.  The encoding of names
                   that are valid UTF-8 sequences is assumed to be UTF-8.  The
                   character set of other names is undefined. Clients and
                   servers, unless otherwise configured to support a specific
                   native character set, MUST check for a valid UTF-8 byte
                   sequence to determine if the pathname being presented is
                   UTF-8.

                 - To avoid data loss, clients and servers SHOULD use the UTF-
                   8 encoded pathnames when unable to convert them to a usable
                   code set.

                 - There may be cases when the code set / encoding presented
                   to the server or client cannot be determined. In such cases
                   the raw bytes SHOULD be used.
     
     
     

                                 Expires 01 December 1998            [Page 6 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

              3.2 International Servers

                 - Servers MUST support the UTF-8 feature in response to the
                   FEAT command [FEAT]. The UTF-8 feature is a line containing
                   the exact string "UTF8". This string is not case sensitive,
                   but SHOULD be transmitted in upper case. The response to a
                   FEAT command SHOULD be:

                        C> feat
                        S> 211- <any descriptive text>
                        S>  ...
                        S> UTF8
                        S>  ...
                        S> 211 end

                   The ellipses indicate placeholders where other features may
                   be included, and are not required. The one space indentation
                   of the feature lines is mandatory [FEAT].

                 - Mirror servers may want to exactly reflect the site that
                   they are mirroring. In such cases servers MAY store and
                   present the exact pathname bytes that it received from the
                   main server.

              3.3 International Clients

                 - Clients which do not require display of pathnames are under
                   no obligation to do so. Non-display clients do not need to
                   conform to requirements associated with display.

                 - Clients, which are presented UTF-8 pathnames by the server,
                   SHOULD parse UTF-8 correctly and attempt to display the
                   pathname within the limitation of the resources available.

                 - Clients MUST support the FEAT command and recognize the
                   "UTF8" feature (defined in 3.2 above) to determine if a
                   server supports UTF-8 encoding.

                 - Character semantics of other names shall remain undefined.
                   If a client detects that a server is non UTF-8, it SHOULD
                   change its display appropriately. How a client
                   implementation handles non UTF-8 is a quality of
                   implementation issue. It MAY try to assume some other
                   encoding, give the user a chance to try to assume something,
                   or save encoding assumptions for a server from one FTP
                   session to another.

                 - Glyph rendering is outside the scope of this document. How
                   a client presents characters it cannot display is a quality
                   of implementation issue. This document RECOMMENDS that
                   octets corresponding to non-displayable characters SHOULD be
                   presented in URL %HH format defined in RFC 1738 [RFC1738].
                   They MAY, however, display them as question marks, with
     
     

                                 Expires 01 December 1998            [Page 7 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                   their UCS hexadecimal value, or in any other suitable
                   fashion.

                 - Many existing clients interpret 8-bit pathnames as being in
                   the local character set. They MAY continue to do so for
                   pathnames that are not valid UTF-8.
     

              4 Security

                 This document addresses the support of character sets beyond
                 1 byte. Conformance to this document should not induce a
                 security threat.
     

              5 Acknowledgments

                 The following people have contributed to this document:

                 D. J. Bernstein
                 Martin J. Duerst
                 Mark Harris
                 Paul Hethmon
                 Alun Jones
                 James Matthews
                 Keith Moore
                 Sandra O'Donnell
                 Benjamin Riefenstahl
                 Stephen Tihor

                 (and others from the FTPEXT working group)

              6 Glossary

                BIDI - abbreviation for Bi-directional, a reference to mixed
                right-to-left and left-to-right text.

                Character Set -  a collection of characters used to represent
                textual information in which each character has a numeric
                value

                Code Set -  (see character set).

                Glyph - a character image represented on a display device.

                I18N - "I eighteen N", the first and last letters of the word
                "internationalization" and the eighteen letters in between.

                UCS-2 - the ISO/IEC 10646 two octet Universal Character Set
                form.

                UCS-4 - the ISO/IEC 10646 four octet Universal Character Set
                form.
     
     

                                 Expires 01 December 1998            [Page 8 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                UTF-8 - the UCS Transformation Format represented in 8 bits.

                UTF-16 - A 16-bit format including the BMP (directly encoded)
                and surrogate pairs to represent characters in planes 01-16;
                equivalent to Unicode.
     
     

              7 Bibliography

                [ABNF]

                   D. Crocker, P. Overell, Augmented BNF for Syntax
                   Specifications: ABNF, RFC 2234, November 1997.

                [ASCII]

                   ANSI X3.4:1986 Coded Character Sets - 7 Bit American
                   National Standard Code for Information Interchange (7-bit
                   ASCII)

                [FEAT]

                   R. Elz, P. Hethmon, "Feature Negotiation Mechanism for the
                   File Transfer Protocol", Work in Progress, <draft-ietf-
                   ftpext-feat-02.txt> November 1997.

                [ISO-8859]

                   ISO 8859.  International standard -- Information processing
                   -- 8-bit single-byte coded graphic character sets -- Part 1:
                   Latin alphabet No. 1 (1987) -- Part 2: Latin alphabet No. 2
                   (1987) -- Part 3: Latin alphabet No. 3 (1988) -- Part 4:
                   Latin alphabet No. 4 (1988) -- Part 5: Latin/Cyrillic
                   alphabet (1988) -- Part 6: Latin/Arabic alphabet (1987) --
                   Part : Latin/Greek alphabet (1987) -- Part 8: Latin/Hebrew
                   alphabet (1988) -- Part 9: Latin alphabet No. 5 (1989) --
                   Part10: Latin alphabet No. 6 (1992)

                [ISO-10646]

                   ISO/IEC 10646-1:1993. International standard -- Information
                   technology -- Universal multiple-octet coded character set
                   (UCS) -- Part 1: Architecture and basic multilingual plane.

                 [RFC854]

                   J. Postel, J Reynolds, "Telnet Protocol Specification", RFC
                   854, May 1983.
     
     
     
     
     
     

                                 Expires 01 December 1998            [Page 9 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                [RFC959]

                   J. Postel, J Reynolds, "File Transfer Protocol (FTP)", RFC
                   959, October 1985.

                [RFC1123]

                   R. Braden, "Requirements for Internet Hosts -- Application
                   and Support", RFC 1123, October 1989.

                [RFC1738]

                   T. Berners-Lee, L. Masinter, M.McCahill, "Uniform Resource
                   Locators (URL)", RFC 1738, December 1994.

                [RFC2279]

                   F. Yergeau, "UTF-8, a transformation format of ISO 10646",
                   RFC 2279, January 1998.

                [RFC 2119]
                   S. Bradner, " Key words for use in RFCs to Indicate
                   Requirement Levels", RFC 2119, March 1997.

                [RFC 2130]

                   C. Weider, C. Preston, K.Simonsen, H. Alvestrand, " The
                   Report of the IAB Character Set Workshop held 29 February -
                   1 March, 1996", RFC 2130, April, 1997.

                [UNICODE]

                   The Unicode Consortium, "The Unicode Standard - Version
                   2.0", Addison Westley Developers Press, July 1996.

                [UTF-8]

                   ISO/IEC 10646-1:1993 AMENDMENT 2 (1996). UCS Transformation
                   Format 8 (UTF-8).
     
     
     
     

              8 Author's Address

                JIEO
                Attn JEBBD (Bill Curtin)
                Ft. Monmouth, N.J.
                  07703-5613
                curtinw@ftm.disa.mil
     
     
     
     

                                 Expires 01 December 1998           [Page 10 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     
     

                          Annex A - Implementation Considerations
     

              A.1 General Considerations
     

                 - Implementers should ensure that their code accounts for
                   potential problems, such as using a NULL character to
                   terminate a string or no longer being able to steal the high
                   order bit for internal use, when supporting the extended
                   character set.

                 - Implementers should be aware that there is a chance that
                   pathnames that are non UTF-8 may be parsed as valid UTF-8.
                   The probabilities are low for some encoding or statistically
                   zero to zero for others. A recent non-scientific analysis
                   found that EUC encoded Japanese words had a 2.7% false
                   reading; SJIS had a 0.0005% false reading; other encoding
                   such as ASCII or KOI-8 have a 0% false reading. This
                   probability is highest for short pathnames and decreases as
                   pathname size increases. Implementers may want to look for
                   signs that pathnames which parse as UTF-8 are not valid UTF-
                   8, such as the existence of multiple local character sets in
                   short pathnames. Hopefully, as more implementations conform
                   to UTF-8 transfer encoding there will be a smaller need to
                   guess at the encoding.

                 - Client developers should be aware that it will be possible
                   for pathnames to contain mixed characters (e.g.
                   /Latin1DirectoryName/HebrewFileName). They should be
                   prepared to handle the Bi-directional (BIDI) display of
                   these character sets (i.e. right to left display for the
                   directory and left to right display for the filename). While
                   bi-directional display is outside the scope of this document
                   and more complicated than the above example, an algorithm
                   for bi-directional display can be found in the UNICODE 2.0
                   [UNICODE] standard. Also note that pathnames can have
                   different byte ordering yet be logically and display-wise
                   equivalent due to the insertion of BIDI control characters
                   at different points during composition. Also note that mixed
                   character sets may also present problems with font swapping.

                 - A server that copies pathnames transparently from a local
                   filesystem may continue to do so. It is then up to the local
                   file creators to use UTF-8 pathnames.

                 - Servers can supports charset labeling of files and/or
                   directories, such that different pathnames may have
                   different charsets. The server should attempt to convert all
                   pathnames to UTF-8, but if it can't then it should leave
                   that name in its raw form.
     
     
     
     

                                 Expires 01 December 1998          [Page A-1 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                  - Some server's OS do not mandate character sets, but allow
                   administrators to configure it in the FTP server. These
                   servers should be configured to use a particular mapping
                   table (either external or built-in). This will allow the
                   flexibility of defining different charsets for different
                   directories.

                 - If the server's OS does not mandate the character set and
                   the FTP server cannot be configured, the server should
                   simply use the raw bytes in the file name.  They might be
                   ASCII or UTF-8.

                 - If the server is a mirror, and wants to look just like the
                   site it is mirroring, it should store the exact file name
                   bytes that it received from the main server.

              A.2 Transition Considerations

                 -Clients and servers can transition to UTF-8 by either
                   converting to/from the local encoding, or the users can
                   store UTF-8 filenames. The former approach is easier on
                   tightly controlled file systems (e.g. PCs and MACs). The
                   latter approach is easier on more free form file systems
                   (e.g. Unix).

                 -For interactive use attention should be focused on user
                   interface and ease of use. Non-interactive use requires a
                   consistent and controlled behavior.

                 -There may be many applications which reference files under
                   their old raw pathname (e.g. linked URLs). Changing the
                   pathname to UTF-8 will cause access to the old URL to fail.
                   A solution may be for the server to act as if there was 2
                   different pathnames associated with the file. This might be
                   done internal to the server on controlled file systems or by
                   using symbolic links on free form systems. While this
                   approach may work for single file transfer non-interactive
                   use, a non-interactive transfer of all of the files in a
                   directory will produce duplicates. Interactive users may be
                   presented with lists of files which are double the actual
                   number files.
     
     
     
     
     
     
     
     
     
     
     
     
     
     

                                 Expires 01 December 1998          [Page A-2 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     
     

                            Annex B - Sample Code and Examples
     

              B.1 Valid UTF-8 check

                 The following routine checks if a byte sequence is valid UTF-
                 8. This is done by checking for the proper tagging of the
                 first and following bytes to make sure they conform to the
                 UTF-8 format. It then checks to assure that the data part of
                 the UTF-8 sequence conforms to the proper range allowed by
                 the encoding. Note: This routine will not detect characters
                 that have not been assigned and therefore do not exist.

                 int utf8_valid(const unsigned char *buf, unsigned int len)
                 {
                  const unsigned char *endbuf = buf + len;
                     unsigned char byte2mask=0x00, c;
                  int trailing = 0;               // trailing (continuation)
                 bytes to follow

                  while (buf != endbuf)
                  {
                      c = *buf++;
                    if (trailing)
                     if ((c&0xC0) == 0x80)  // Does trailing byte follow UTF-8
                                               format?
                       {if (byte2mask)      // Need to check 2nd byte for
                                               proper range?
                          if (c&byte2mask)  // Are appropriate bits set?
                           byte2mask=0x00;
                          else
                           return 0;
                         trailing--; }
                     else
                        return 0;
                    else
                     if ((c&0x80) == 0x00)  continue;      // valid 1 byte
                                                              UTF-8
                     else if ((c&0xE0) == 0xC0)            // valid 2 byte
                                                              UTF-8
                           if (c&0x1E)                     // Is UTF-8 byte in
                                                              proper range?
                             trailing =1;
                           else
                             return 0;
                     else if ((c&0xF0) == 0xE0)           // valid 3 byte
                                                             UTF-8
                           {if (!(c&0x0F))                // Is UTF-8 byte in
                                                             proper range?
                             byte2mask=0x20;              // If not set mask
                                                             to check next byte
                             trailing = 2;}
     
     
     

                                 Expires 01 December 1998          [Page B-1 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                     else if ((c&0xF8) == 0xF0)           // valid 4 byte
                                                             UTF-8
                           {if (!(c&0x07))                // Is UTF-8 byte in
                                                             proper range?
                             byte2mask=0x30;              // If not set mask
                                                             to check next byte
                             trailing = 3;}
                     else if ((c&0xFC) == 0xF8)           // valid 5 byte
                                                             UTF-8
                           {if (!(c&0x03))                // Is UTF-8 byte in
                                                             proper range?
                             byte2mask=0x38;              // If not set mask
                                                             to check next byte
                             trailing = 4;}
                     else if ((c&0xFE) == 0xFC)           // valid 6 byte
                                                             UTF-8
                           {if (!(c&0x01))                // Is UTF-8 byte in
                                                             proper range?
                             byte2mask=0x3C;              // If not set mask
                                                             to check next byte
                             trailing = 5;}
                     else  return 0;
                  }
                  return trailing == 0;
                 }
     
     

              B.2 Conversions

                 The code examples in this section closely reflect the
                 algorithm in ISO 10646 and may not present the most efficient
                 solution for converting to / from UTF-8 encoding. If
                 efficiency is an issue, implementers should use the
                 appropriate bitwise operators.

                 Additional code examples and numerous mapping tables can be
                 found at the Unicode site, HTTP://www.unicode.org or
                 FTP://unicode.org.

                 Note that the conversion examples below assume that the local
                 character set supported in the operating system is something
                 other than UCS2/UTF-16. There are some operating systems that
                 already support UCS2/UTF-16 (notably Plan 9 and Windows NT).
                 In this case no conversion will be necessary from the local
                 character set to the UCS.

              B.2.1 Conversion from local character set to UTF-8

                 Conversion from the local filesystem character set to UTF-8
                 will normally involve a two step process. First convert the
                 local character set to the UCS; then convert the UCS to
                 UTF-8.
     
     

                                 Expires 01 December 1998          [Page B-2 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                 The first step in the process can be performed by maintaining
                 a mapping table that includes the local character set code
                 and the corresponding UCS code. For instance the ISO/IEC
                 8859-8 [ISO-8859] code for the Hebrew letter "VAV" is 0xE4.
                 The corresponding 4 byte ISO/IEC 10646 code is 0x000005D5.

                 The next step is to convert the UCS character code to the
                 UTF-8 encoding. The following routine can be used to
                 determine and encode the correct number of bytes based on the
                 UCS-4 character code:
     

              unsigned int ucs4_to_utf8 (unsigned long *ucs4_buf, unsigned int
                                         ucs4_len, unsigned char *utf8_buf)

              {
               const unsigned long *ucs4_endbuf = ucs4_buf + ucs4_len;
               unsigned int utf8_len = 0;        // return value for UTF8 size
               unsigned char *t_utf8_buf = utf8_buf; // Temporary pointer
                                                     // to load UTF8 values

               while (ucs4_buf != ucs4_endbuf)
               {
                if ( *ucs4_buf <= 0x7F)    // ASCII chars no conversion needed
                {
                 *t_utf8_buf++ = (unsigned char) *ucs4_buf;
                 utf8_len++;
                 ucs4_buf++;
                }
                else
                 if ( *ucs4_buf <= 0x07FF ) // In the 2 byte utf-8 range
                 {
                   *t_utf8_buf++= (unsigned char) (0xC0 + (*ucs4_buf/0x40));
                   *t_utf8_buf++= (unsigned char) (0x80 + (*ucs4_buf%0x40));
                   utf8_len+=2;
                   ucs4_buf++;
                 }
                 else
                   if ( *ucs4_buf <= 0xFFFF ) /* In the 3 byte utf-8 range. The
                                               values 0x0000FFFE, 0x0000FFFF
                                               and 0x0000D800 - 0x0000DFFF do
                                               not occur in UCS-4 */
                   {
                    *t_utf8_buf++= (unsigned char) (0xE0 +
              (*ucs4_buf/0x1000));
                    *t_utf8_buf++= (unsigned char) (0x80 +
                                   ((*ucs4_buf/0x40)%0x40));
                    *t_utf8_buf++= (unsigned char) (0x80 + (*ucs4_buf%0x40));
                    utf8_len+=3;
                    ucs4_buf++;

                   }
                   else
                    if ( *ucs4_buf <= 0x1FFFFF ) //In the 4 byte utf-8 range
     

                                 Expires 01 December 1998          [Page B-3 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                    {
                     *t_utf8_buf++= (unsigned char) (0xF0 +
              (*ucs4_buf/0x040000));
                     *t_utf8_buf++= (unsigned char) (0x80 +
                                    ((*ucs4_buf/0x10000)%0x40));
                     *t_utf8_buf++= (unsigned char) (0x80 +
                                    ((*ucs4_buf/0x40)%0x40));
                     *t_utf8_buf++= (unsigned char) (0x80 + (*ucs4_buf%0x40));
                     utf8_len+=4;
                     ucs4_buf++;

                    }
                    else
                     if ( *ucs4_buf <= 0x03FFFFFF )//In the 5 byte utf-8 range
                     {
                      *t_utf8_buf++= (unsigned char) (0xF8 +
                                     (*ucs4_buf/0x01000000));
                      *t_utf8_buf++= (unsigned char) (0x80 +
                                     ((*ucs4_buf/0x040000)%0x40));
                      *t_utf8_buf++= (unsigned char) (0x80 +
                                     ((*ucs4_buf/0x1000)%0x40));
                      *t_utf8_buf++= (unsigned char) (0x80 +
                                     ((*ucs4_buf/0x40)%0x40));
                      *t_utf8_buf++= (unsigned char) (0x80 +
                                     (*ucs4_buf%0x40));
                      utf8_len+=5;
                      ucs4_buf++;
                     }
                     else
                     if ( *ucs4_buf <= 0x7FFFFFFF )//In the 6 byte utf-8 range
                      {
                        *t_utf8_buf++= (unsigned char)
                                       (0xF8 +(*ucs4_buf/0x40000000));
                        *t_utf8_buf++= (unsigned char) (0x80 +
                                       ((*ucs4_buf/0x01000000)%0x40));
                        *t_utf8_buf++= (unsigned char) (0x80 +
                                       ((*ucs4_buf/0x040000)%0x40));
                        *t_utf8_buf++= (unsigned char) (0x80 +
                                       ((*ucs4_buf/0x1000)%0x40));
                        *t_utf8_buf++= (unsigned char) (0x80 +
                                       ((*ucs4_buf/0x40)%0x40));
                        *t_utf8_buf++= (unsigned char) (0x80 +
                                       (*ucs4_buf%0x40));
                        utf8_len+=6;
                        ucs4_buf++;

                      }
               }
               return (utf8_len);
              }
     
     
     
     
     

                                 Expires 01 December 1998          [Page B-4 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

              B.2.2 Conversion from UTF-8 to local character set
     

                 When moving from UTF-8 encoding to the local character set
                 the reverse procedure is used. First the UTF-8 encoding is
                 transformed into the UCS-4 character set. The UCS-4 is then
                 converted to the local character set from a mapping table
                 (i.e. the opposite of the table used to form the UCS-4
                 character code).

                 To convert from UTF-8 to UCS-4 the free bits (those that do
                 not define UTF-8 sequence size or signify continuation bytes)
                 in a UTF-8 sequence are concatenated as a bit string. The
                 bits are then distributed into a four-byte sequence starting
                 from the least significant bits. Those bits not assigned a
                 bit in the four-byte sequence are padded with ZERO bits. The
                 following routine converts the UTF-8 encoding to UCS-4
                 character codes:
     

              int utf8_to_ucs4 (unsigned long *ucs4_buf, unsigned int utf8_len,
                             unsigned char *utf8_buf)
              {

              const unsigned char *utf8_endbuf = utf8_buf + utf8_len;
              unsigned int ucs_len=0;
     

               while (utf8_buf != utf8_endbuf)
               {

                if ((*utf8_buf & 0x80) == 0x00)  /*ASCII chars no conversion
                                                 needed */
                {
                 *ucs4_buf++ = (unsigned long) *utf8_buf;
                 utf8_buf++;
                 ucs_len++;
                }
                else
                 if ((*utf8_buf & 0xE0)== 0xC0) //In the 2 byte utf-8 range
                 {
                   *ucs4_buf++ = (unsigned long) (((*utf8_buf - 0xC0) * 0x40)
                                  + ( *(utf8_buf+1) - 0x80));
                   utf8_buf += 2;
                   ucs_len++;
                 }
                 else
                   if ( (*utf8_buf & 0xF0) == 0xE0 ) /*In the 3 byte utf-8
                                                       range */
                   {
                   *ucs4_buf++ = (unsigned long) (((*utf8_buf - 0xE0) * 0x1000)
                                   + (( *(utf8_buf+1) -  0x80) * 0x40)
                                   + ( *(utf8_buf+2) - 0x80));
                    utf8_buf+=3;
     

                                 Expires 01 December 1998          [Page B-5 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                    ucs_len++;
                   }
                   else
                    if ((*utf8_buf & 0xF8) == 0xF0) /* In the 4 byte utf-8
                                                       range */
                    {
                     *ucs4_buf++ = (unsigned long)
                                        (((*utf8_buf - 0xF0) * 0x040000)
                                     + (( *(utf8_buf+1) -  0x80) * 0x1000)
                                     + (( *(utf8_buf+2) -  0x80) * 0x40)
                                     + ( *(utf8_buf+3) - 0x80));
                     utf8_buf+=4;
                     ucs_len++;
                    }
                    else
                     if ((*utf8_buf & 0xFC) == 0xF8) /* In the 5 byte utf-8
                                                        range */
                     {
                      *ucs4_buf++ = (unsigned long)
                                        (((*utf8_buf - 0xF8) * 0x01000000)
                                     + ((*(utf8_buf+1) - 0x80) * 0x040000)
                                     + (( *(utf8_buf+2) -  0x80) * 0x1000)
                                     + (( *(utf8_buf+3) -  0x80) * 0x40)
                                     + ( *(utf8_buf+4) - 0x80));
                      utf8_buf+=5;
                      ucs_len++;
                     }
                     else
                      if ((*utf8_buf & 0xFE) == 0xFC) /* In the 6 byte utf-8
                                                         range */
                      {
                        *ucs4_buf++ = (unsigned long)
                                         (((*utf8_buf - 0xFC) * 0x40000000)
                                       + ((*(utf8_buf+1) - 0x80) * 0x010000000)
                                       + ((*(utf8_buf+2) - 0x80) * 0x040000)
                                       + (( *(utf8_buf+3) -  0x80) * 0x1000)
                                       + (( *(utf8_buf+4) -  0x80) * 0x40)
                                       + ( *(utf8_buf+5) - 0x80));
                        utf8_buf+=6;
                        ucs_len++;
                      }

               }
              return (ucs_len);
              }
     
     
     
     
     
     
     
     
     
     

                                 Expires 01 December 1998          [Page B-6 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

              B.2.3  ISO/IEC 8859-8 Example

                 This example demonstrates mapping ISO/IEC 8859-8 character
                 set to UTF-8 and back to ISO/IEC 8859-8. As noted earlier,
                 the Hebrew letter "VAV" is convertd from the ISO/IEC 8859-8
                 character code 0xE4 to the corresponding 4 byte ISO/IEC 10646
                 code of 0x000005D5 by a simple lookup of a conversion/mapping
                 file.

                 The UCS-4 character code is transformed into UTF-8 using the
                 ucs4_to_utf8 routine described earlier by:

                   1. Because the UCS-4 character is between 0x80 and 0x07FF it
                      will map to a 2 byte UTF-8 sequence.
                   2. The first byte is defined by (0xC0 + (0x000005D5 / 0x40))
                      = 0xD7.
                   3. The second byte is defined by (0x80 + (0x000005D5 %
                      0x40)) = 0x95.

                 The UTF-8 encoding is transferred back to UCS-4 by using the
                 utf8_to_ucs4 routine described earlier by:

                   1. Because the first byte of the sequence, when the '&'
                      operator with a value of 0xE0 is applied, will produce
                      0xC0 (0xD7 & 0xE0 = 0xC0) the UTF-8 is a 2 byte sequence.
                   2.  The four byte UCS-4 character code is produced by
                      (((0xD7 - 0xC0) * 0x40) + (0x95 -0x80)) = 0x000005D5.

                 Finally, the UCS-4 character code is converted to ISO/IEC
                 8859-8 character code (using the mapping table which matches
                 ISO/IEC 8859-8 to UCS-4 ) to produce the original 0xE4 code
                 for the Hebrew letter "VAV".

              B.2.4 Vendor Codepage Example

                 This example demonstrates the mapping of a codepage to UTF-8
                 and back to a vendor codepage. Mapping between vendor
                 codepages can be done in a very similar manner as described
                 above. For instance both the PC and Mac codepages reflect the
                 character set from the Thai standard TIS 620-2533. The
                 character code on both platforms for the Thai letter "SO SO"
                 is 0xAB. This character can then be mapped into the UCS-4 by
                 way of a conversion/mapping file to produce the UCS-4 code of
                 0x0E0B.

                 The UCS-4 character code is transformed into UTF-8 using the
                 ucs4_to_utf8 routine described earlier by:

                   1. Because the UCS-4 character is between 0x0800 and 0xFFFF
                      it will map to a 3 byte UTF-8 sequence.
                   2. The first byte is defined by (0xE0 + (0x00000E0B /
                      0x1000) =  0xE0.
                   3. The second byte is defined by (0x80 + ((0x00000E0B /
                      0x40) % 0x40))) = 0xB8.
     

                                 Expires 01 December 1998          [Page B-7 ]

     

              INTERNET DRAFT    FTP Internationalization           01 June, 1998
     

                   4. The third byte is defined by (0x80 + (0x00000E0B % 0x40))
                      = 0x8B.

                 The UTF-8 encoding is transferred back to UCS-4 by using the
                 utf8_to_ucs4 routine described earlier by:

                   1. Because the first byte of the sequence, when the '&'
                      operator with a value of 0xF0 is applied, will produce
                      0xE0 (0xE0 & 0xF0 = 0xE0) the UTF-8 is a 3 byte sequence.
                   2.  The four byte UCS-4 character code is produced by
                      (((0xE0 - 0xE0) * 0x1000) + ((0xB8 - 0x80) * 0x40) +
                      (0x8B -0x80) = 0x0000E0B.

                 Finally, the UCS-4 character code is converted to either the
                 PC or MAC codepage character code (using the mapping table
                 which matches codepage to UCS-4 ) to produce the original
                 0xAB code for the Thai letter "SO SO".
     

              B.3 Pseudo Code for a high-quality translating server
     

              if utf8_valid(fn)
                {
                attempt to convert fn to the local charset, producing localfn
                if (conversion fails temporarily) return error
                if (conversion succeeds)
                   {
                 attempt to open localfn
                 if (open fails temporarily) return error
                 if (open succeeds) return success
                   }
                }
              attempt to open fn
              if (open fails temporarily) return error
              if (open succeeds) return success
              return permanent error
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

                                 Expires 01 December 1998          [Page B-8 ]
    --=_AAAYDgAABLM1bB/O-- ================================================ FILE: tests/mboxes/y2k.mbox ================================================ From owner-hypermail Fri Sep 25 20:23 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id UAA06103 for hypermail-outgoing; Fri, 25 Sep 2000 20:22:37 -0500 (CDT) Received: from runningman.rs.itd.umich.edu (runningman.rs.itd.umich.edu [141.211.144.15]) by landfield.com (8.9.0/8.9.0) with ESMTP id UAA06097 for ; Fri, 25 Sep 2000 20:21:33 -0500 (CDT) Received: from umich.edu (dialin224193.isdn.umich.edu [198.111.224.193]) by runningman.rs.itd.umich.edu (8.8.5/2.3) with ESMTP id VAA19384; Fri, 25 Sep 2000 21:19:37 -0400 (EDT) Message-ID: <360C40A1.A8FAF28C@umich.edu> Date: Fri, 25 Sep 2000 21:17:21 -0400 From: "Jeffrey K. MacKie-Mason" Organization: University of Michigan X-Mailer: Mozilla 4.5b2 [en] (WinNT; I) X-Accept-Language: en MIME-Version: 1.0 To: hypermail@landfield.com CC: Charles Hall , "Gordon H. Buchan" Subject: Re: adding new messages to prior hypermail archive Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Jeffrey K. MacKie-Mason" X-Lines: 54 Content-Type: text/plain; charset="us-ascii" Content-Length: 2276 Status: OR Charles and Gordon offered helpful suggestions. However, I think there is a problem. Here is what I'm trying to do: I have an existing Hypermail archive (from 1.02) with 467 messages already in it. I do *NOT* have the original mailbox file for it. I now have 65 new messages in a mailbox that I want to add. I've tried a standard run, as Gordon suggested (those are Gordon's paths): /home/gordon/bin/hypermail \ -b "http://cusidnet.anadas.com/" \ -a "http://cusidnet.anadas.com/" \ -m "/home/gordon/mail/cusid" \ -l "CUSIDnet Web Mirror" \ -d "/home/gordon/www/cusidnet/fall2000/" \ -c "/home/gordon/bin/.cusidnethyprc" > /dev/null That had the following result: The new index files overwrote the existing index files, and showed the information for the 65 *new* messages but no listings for the 467 original messages. However, the archive in fact contained the 467 html files for the original messages, but did *not* contain files for any of the new messages. (Click on New #1 in the index, and it goes to file 0000.html which is Old #1.) Then I tried what Charles suggested: I inserted 467 "dummy" messages in my mailbox file so that Hypermail could count down those and only add the "new" messages. That *almost* worked. The message files were correctly created: an addition 65 nnnn.html files were added to the archive. However, the original 467 message entries in the index were overwritten with the header information from the 467 dummy messages. So my index files are now useless.... Obviously, the solution could be to chop the 65 new messages and deliver them one at a time to Hypermail for a single message append. (Can someone suggest an easy way to script that?) However, shouldn't Hypermail be able to do this? Perhaps have a switch for "append to existing archive" when we have a new mbox file but have lost the mbox for the original archive? (Likewise, a way to merge hypermail archives without having the original mboxes?) thanks, jmm -- Prof. Jeffrey MacKie-Mason http://www-personal.umich.edu/~jmm/ Dept. of Economics jmm@umich.edu and School of Information +1 (734) 647-4856 (voice) University of Michigan +1 (734) 764-2475 (fax) Ann Arbor, MI 48109 From owner-hypermail Fri Sep 25 20:59 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id UAA06348 for hypermail-outgoing; Fri, 25 Sep 2000 20:59:15 -0500 (CDT) Received: from ns.totalsports.net (ns.totalsports.net [207.175.67.50]) by landfield.com (8.9.0/8.9.0) with ESMTP id UAA06340 for ; Fri, 25 Sep 2000 20:58:30 -0500 (CDT) Received: from klaatu.totalsports.net (chall3.totalsports.net [207.175.67.217]) by ns.totalsports.net (Post.Office MTA v3.5 release 215 ID# 0-55440U300L200S0V35) with SMTP id net; Fri, 25 Sep 2000 21:53:37 -0400 Message-ID: <360C4737.6946@totalsports.net> Date: Fri, 25 Sep 2000 21:45:27 -0400 From: chall@totalsports.net (Charles Hall) Organization: Total Sports X-Mailer: Mozilla 3.01Gold (Win95; I) MIME-Version: 1.0 To: "Jeffrey K. MacKie-Mason" CC: hypermail@landfield.com Subject: Re: adding new messages to prior hypermail archive References: <360C40A1.A8FAF28C@umich.edu> Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: chall@totalsports.net (Charles Hall) X-Lines: 25 Content-Type: text/plain; charset="us-ascii" Content-Length: 1005 Status: OR Jeffrey K. MacKie-Mason wrote: > > Then I tried what Charles suggested... However, the original 467 message > entries in the index were overwritten with the 467 dummy messages. So > my index files are now useless.... Ouch! I hope you can recover from this. I didn't realize. Sorry. > Perhaps have a switch for "append to existing archive" when we have a new > mbox file Yes, Yes! I need this functionality too. I prefer not to add messages one at a time through the day as Hypermail would go re-indexing over and over again, so I let my mail collect till the end of the month, and run hypermail once nightly. Since there's no append function, Hypermail has to churn through all that month's mail each night. If I could append, I could erase the mailbox each night and only process that day's mail. MHonArc has this feature, but I believe it keeps a small database to remember what's been done before. Perhaps such info could be hidden in the indexes as HTML comments?? -- Charles Hall Raleigh, NC From owner-hypermail Sat Sep 26 06:16 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id GAA20916 for hypermail-outgoing; Sat, 26 Sep 2000 06:16:19 -0500 (CDT) Received: from relay7.UU.NET (relay7.UU.NET [192.48.96.17]) by landfield.com (8.9.0/8.9.0) with ESMTP id GAA20890 for ; Sat, 26 Sep 2000 06:14:42 -0500 (CDT) Received: from relay7.UU.NET by relay7.UU.NET with ESMTP (peer crosschecked as: root@localhost) id QQfijh19139; Fri, 25 Sep 2000 10:17:34 -0400 (EDT) Received: from morrison.matrox.com by relay7.UU.NET with ESMTP (peer crosschecked as: [204.50.136.19]) id QQfijh19076; Fri, 25 Sep 2000 10:17:28 -0400 (EDT) Received: (from mtxmail@localhost) by morrison.matrox.com (8.8.8/8.8.8) id KAA23068; Fri, 25 Sep 2000 10:14:08 -0400 (EDT) Received: from venus.matrox.com(138.11.0.5) by morrison-250 via smap (V2.0) id xma022977; Fri, 25 Sep 98 10:13:18 -0400 Received: from focus.matrox.com (focus.matrox.com [192.168.16.2]) by venus.matrox.com (8.8.7/8.8.7) with ESMTP id KAA09310; Fri, 25 Sep 2000 10:13:17 -0400 (EDT) Received: from gbuchan.matrox.com ([192.168.17.51]) by focus.matrox.com (8.7.5/8.7.3) with SMTP id KAA15383; Fri, 25 Sep 2000 10:13:14 -0400 (EDT) Message-Id: <200009251413.KAA15383@focus.matrox.com> X-Sender: gbuchan@focus.matrox.com X-Mailer: QUALCOMM Windows Eudora Pro Version 4.0 Date: Fri, 25 Sep 2000 10:13:10 -0400 To: "Jeffrey K. MacKie-Mason" , hypermail@landfield.com From: "Gordon H. Buchan" Subject: Re: adding new messages to prior hypermail archive In-Reply-To: <360B2905.E41100C9@umich.edu> Mime-Version: 1.0 Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Gordon H. Buchan" X-Lines: 40 Content-Type: text/plain; charset="us-ascii" Content-Length: 1590 Status: OR At 01:24 AM 9/25/98 -0400, Jeffrey K. MacKie-Mason wrote: > >I archived some 460 messages from a mailbox with Hypermail 1.02 about 3 >years ago. Now I want to use hypermail 2.03b to process a new mailbox >and add the messages to the prior archive. I've tested 2.03b on the new >mailbox, and it works fine when I give it an empty directory in which to >create a new hypermail archive. However, when I point it at the >directory with the prior 460-message archive, it changes the date stamp >on the index files to today, but it doesn't append the 65 new messages >to the archive. > >As far as I can see, the default behavior is supposed to be to append >messages to an existing archive. I'm not using the -u or -x flags. >Suggestions? With a slight modification (removal of the -x switch, since this is to append, not replace), here is one of my batch files. Change paths and parameters to match your environment. /home/gordon/bin/hypermail \ -b "http://cusidnet.anadas.com/" \ -a "http://cusidnet.anadas.com/" \ -m "/home/gordon/mail/cusid" \ -l "CUSIDnet Web Mirror" \ -d "/home/gordon/www/cusidnet/fall2000/" \ -c "/home/gordon/bin/.cusidnethyprc" > /dev/null Note 1: /home/gordon/mail/cusid is a standard UNIX mail folder. Note 2: /home/gordon/www/cusidnet/fall2000 contains an existing hypermail archive. ---- Gordon H. Buchan Technical Writer Matrox Networks / Matrox Electronic Systems email: gbuchan@matrox.com 1055 St-Regis Blvd. voice: +1 (514) 685-7230 x2523 Dorval, Quebec fax: +1 (514) 822-6272 Canada H9P 2T4 http://www.matrox.com/networks From nobody Thu Oct 1 19:10 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id TAA11412 for kent@landfield.com; Thu, 1 Oct 2000 19:10:49 -0500 (CDT) Date: Thu, 1 Oct 2000 19:10:49 -0500 (CDT) From: Nobody Message-Id: <200010020010.TAA11412@landfield.com> Reply-to: minerva@phix.com (Darci Chapman) Subject: HYPERMAIL Development Center Suggestion Content-Type: text Content-Length: 492 Status: OR minerva@phix.com (Darci Chapman) sent the following Hypermail Resource location information: ------------------------------------------------------------ Location: http://www.wildheart.org/archives/networker/ Description: A user-based list for Legato's Networker (back up) software. (I can't believe I'm archiving ANOTHER list ;-) ------------------------------------------------------------ Server protocol: HTTP/1.0 Remote host: barrier241.nike.com Remote IP address: 198.107.239.205 From kent Thu Oct 1 22:01 CDT 2000 Received: (from kent@localhost) by landfield.com (8.9.0/8.9.0) id WAA13318; Thu, 1 Oct 2000 22:01:32 -0500 (CDT) From: Kent Landfield Message-Id: <200010020301.WAA13318@landfield.com> Subject: Re: Hypermail pages To: vanes002@umn.edu (John Van Essen) Date: Thu, 1 Oct 2000 22:01:31 -0500 (CDT) Cc: kent (Kent Landfield) In-Reply-To: <81725.vanes002@umn.edu> from "John Van Essen" at Oct 1, 98 07:51:07 pm X-Mailer: ELM [version 2.4 PL25] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII Content-Length: 565 Status: OR # # How come the landfield.com home page doesn't mention or link to # the hypermail home page (/hypermail)? # # :) # # John Van Essen Well now that you mention it... I'm going to have to fix that. ;) Thanks. -- Kent Landfield Phone: 1-817-545-2502 Email: kent@landfield.com http://www.landfield.com/ Email: kent@nfr.net http://www.nfr.net/ Please send comp.sources.misc related mail to kent@landfield.com Search the Usenet FAQ Archive at http://www.faqs.org/faqs/ From tva@pobox.com Sat Oct 3 22:54 CDT 2000 Received: from pop1.cyberhighway.net (qmailr@pop1.cyberhighway.net [209.161.0.35]) by landfield.com (8.9.0/8.9.0) with SMTP id WAA01614 for ; Sat, 3 Oct 2000 22:54:09 -0500 (CDT) Received: (qmail 22325 invoked from network); 3 Oct 2000 21:52:11 -0600 Received: from ts19-31.boi.cyberhighway.net (HELO pobox.com) (209.161.10.170) by pop1.cyberhighway.net with SMTP; 3 Oct 2000 21:52:11 -0600 Message-ID: <3616F164.20EE5A03@pobox.com> Date: Sat, 03 Oct 2000 21:54:12 -0600 From: Tom von Alten X-Mailer: Mozilla 4.04 [en] (Win95; U) MIME-Version: 1.0 To: archive@landfield.com Subject: Another Mail Archive Mgmt Tool X-Corel-MessageType: EMail Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii Content-Length: 593 Status: OR Hey: I'm back, I couldn't wait until Monday to see your code. :-) And I found the "others.html" page. Pretty classy. One that probably belongs on the list is something called "newsgate," at ftp://ftp.isc.org/isc/inn/contrib/ (mentioned in the majordomo FAQ, http://www.cis.ohio-state.edu/~barr/majordomo-faq.html) for piping email into News; the IT-run half of our division is actually working to install that to replace what we're doing with hypermail. It suits them because they're using majordomo; we've been doing our list maintenance more manually. (The race is on.) Tom von Alten From craig@cni.org Tue Oct 6 18:26 CDT 2000 Received: from a.cni.org (a.cni.org [192.100.21.1]) by landfield.com (8.9.0/8.9.0) with SMTP id SAA18925; Tue, 6 Oct 2000 18:26:01 -0500 (CDT) Received: by a.cni.org id ; Tue, 6 Oct 2000 19:20:00 -0400 From: Craig A Summerhill Message-Id: <9810062320.AA05549@a.cni.org> Subject: Re: another bug To: hypermail@landfield.com Date: Tue, 6 Oct 2000 19:20:00 -0400 (EDT) Cc: kent@landfield.com In-Reply-To: <200010061703.MAA13834@landfield.com> from "Kent Landfield" at Oct 6, 98 12:03:19 pm X-Mailer: ELM [version 2.4 PL23] Content-Type: text Content-Length: 2299 Status: OR Kent Landfield wrote: > > # This problem has been around since version 1.02, but I forgot about it > # because it doesn't come up too often... > # > # If you run Hypermail against an existing mailbox... > # > # hypermail -c -m -l "whatever" -d > # > # and the mbox file that you are processing only has one message in it... > # > # hypermail goes out and creates the HTMLed message (0000.html), but > # before the date, author, subject, and thread indexes are created it > # dumps core with this error: > # > # Floating exception (core dumped) > > I don't get this when I tried it on the latest version. It may be that > the problem isn't the single message in the mailbox but the message itself. > It may be triggering a memory corruption bug. If you have a copy of the > offending message you can send me I'll verify if it is a problem still. Kent, Hmm. That's odd. It happens consistently on my system; everytime there is a mailbox with only one message in it. It must be some combination of the defaults that I set when I compiled the code (I changed some of the suggested settings), and the settings in the .hmrc file I am calling. I'll send you my compile time settings and .hmrc file later, and see if you can find something in there that is causing it to happen. (I have been up and working on a system problem for thirty-some hours, I need to go home, shower, and get in bed -- so it may be tomorrow). It does dump core on me to, BTW. Is there a core analysis tool I could used that would give you some helpful information? P.S. One other thought occured to me. I was wondering if it might be related to the parsing problem I wrote about earlier (which you have fixed in the next release -- thank you). Perhaps it is expecting a trailing line with white space on it, or something? The trouble with this idea is that the single message problem was also present in version 1.02, and came along to version 2.x. However, the parsing problem wasn't present in version 1.02... -- Craig A. Summerhill, Systems Coordinator and Program Officer Coalition for Networked Information 21 Dupont Circle, N.W., Washington, D.C. 20036 Internet: craig@cni.org AT&Tnet (202) 296-5098 From owner-hypermail Wed Oct 7 01:44 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id BAA00188 for hypermail-outgoing; Wed, 7 Oct 2000 01:44:22 -0500 (CDT) Received: from atlantis.csc.umd.edu (IDENT:root@atlantis.csc.umd.edu [129.2.8.129] (may be forged)) by landfield.com (8.9.0/8.9.0) with ESMTP id BAA00057 for ; Wed, 7 Oct 2000 01:43:31 -0500 (CDT) Received: from atlantis.csc.umd.edu ((IDENT sendmail)@localhost [127.0.0.1]) by atlantis.csc.umd.edu (8.9.0.Beta6/8.9.0.Beta6) with SMTP id CAA09509 for ; Wed, 7 Oct 2000 02:41:30 -0400 (EDT) Received: from localhost by atlantis.csc.umd.edu (8.9.0.Beta6/8.9.0.Beta6) with SMTP id CAA09504 for ; Wed, 7 Oct 2000 02:41:28 -0400 (EDT) X-Authentication-Warning: atlantis.csc.umd.edu: rsw owned process doing -bs Date: Wed, 7 Oct 2000 02:41:24 -0400 (EDT) From: "Randall S. Winchester" To: hypermail@landfield.com Subject: I would like to have avaliable a couple Hypermail variables. Message-ID: MIME-Version: 1.0 Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Randall S. Winchester" Content-Type: TEXT/PLAIN; charset=US-ASCII Content-Length: 2671 Status: OR I am considering using Hypermail for a large number of automatically generated lists. To ease installation woes, it would be helpful to have some more generic capabilities for many of hypermails options. I would like something like: HM_LISTNAME listname hm_listname = [ listname | NONE ] -L This options specifies the name of the list being archived. This is a convienent variable to have defined as it can be used as a cookie or environemntal variable in documentation references. -H Set this to the hostname you want added to a mail address appearing in the RFC822 field which lack a hostname. It is usefull on the command line when servicing virtual hosts. %L - name of current list %H - name of current host. Convienient for archiving with virtual hosting. For example for a default .hmrc file: hm_label = Hypermail discussion list for %L@%H hm_archives = http://%H hm_about = http://%H/%L hm_dir = /var/hypermail/%H/%L/%y/%M hm_ihtmlheaderfile = /var/hypermail/%H/%L/owner/idxheader.hyp hm_ihtmlfooterfile = /var/hypermail/%H/%L/owner/idxfooter.hyp hm_mhtmlheaderfile = /var/hypermail/%H/%L/owner/msgheader.hyp hm_mhtmlfooterfile = /var/hypermail/%H/%L/owner/msgfooter.hyp hm_hmail = %L@%H And for those default header and footer .hyp files: Welcome to the %L archive at %H. To subscibe to this list send email to with the word "subscribe" on its on line in the message body. Once subscribed, you can send mail to the list at . If you have a content issue with something on the list, please mail to Does this seem reasonable enough? Mostly a more frequently used variable substitution routine. A more difficult endevor which could also be helpful would be to leverage off of the case where %L is used in the hm_dir variable along with other date formats (%y, %M, etc) being used. In this case, it would be nice to have Hypermail generate the "homepage(s)" for the directory traversals on the fly. The page would need to be created initially (-d option) and then updated anytime a new directory was automaticaly created. If this were done, then two addition .hyp files would be good: hm_lhtmlheaderfile = /var/hypermail/%H/%L/owner/lstheader.hyp hm_lhtmlfooterfile = /var/hypermail/%H/%L/owner/lstfooter.hyp Probably put a link to my search engine in "hm_lhtmlfooterfile".... Not sure how much of this has been discussed before, or how active development is, having recently joined your list. Seems like a nice tool though... I have alot of users who would appreciate Hypermail. Randall From ashley@pcraft.com Wed Oct 7 10:12 CDT 2000 Received: from mail.pcraft.com (mail.pcraft.com [206.168.220.51]) by landfield.com (8.9.0/8.9.0) with ESMTP id KAA18195; Wed, 7 Oct 2000 10:12:11 -0500 (CDT) Received: from mail.pcraft.com (mail.pcraft.com [206.168.220.51]) by mail.pcraft.com (8.9.1/8.9.1-NOSPAM) with SMTP id JAA02986; Wed, 7 Oct 2000 09:24:26 -0600 Date: Wed, 7 Oct 2000 09:24:26 -0600 (MDT) From: "Ashley M. Kirchner" To: Kent Landfield cc: hypermail@landfield.com Subject: Re: change extension In-Reply-To: <200010071414.JAA17429@landfield.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Content-Length: 958 Status: OR On Wed, 7 Oct 2000, Kent Landfield wrote: > # I just created a mail archive in which I'd like all generated pages to be > # .shtml to better allow them to dynamically use current header and footer and > > - Ability to save files with suffix ".htm" or ".html" Why not make it an rc option, with the default set to .html? If someone wants others, they change the variable to .htm, .shtml, .phtml, or whatever they want. AMK4 | | Row, row, row your bits, gently down the pipe... |____________________________________________________________________ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ashley M. Kirchner . 303.442.6410 x130 SysAdmin / Websmith . 800.441.3873 x130 Photo Craft Laboratories, Inc. . 3550 Arapahoe Ave http://www.pcraft.com . Boulder, CO 80303 .................. . . . . From owner-hypermail Wed Oct 7 10:33 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id KAA18439 for hypermail-outgoing; Wed, 7 Oct 2000 10:33:06 -0500 (CDT) Received: (from kent@localhost) by landfield.com (8.9.0/8.9.0) id KAA18421 for hypermail; Wed, 7 Oct 2000 10:32:07 -0500 (CDT) From: Kent Landfield Message-Id: <200010071532.KAA18421@landfield.com> Subject: Re: I would like to have avaliable a couple Hypermail variables. To: hypermail Date: Wed, 7 Oct 2000 10:32:06 -0500 (CDT) In-Reply-To: from "Randall S. Winchester" at Oct 7, 98 02:41:24 am X-Mailer: ELM [version 2.4 PL25] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: Kent Landfield Content-Type: text/plain; charset=US-ASCII Content-Length: 7259 Status: OR # I am considering using Hypermail for a large number of automatically # generated lists. To ease installation woes, it would be helpful to have # some more generic capabilities for many of hypermails options. # # I would like something like: # # HM_LISTNAME listname # # hm_listname = [ listname | NONE ] # # -L # This options specifies the name of the list being archived. This is a # convienent variable to have defined as it can be used as a cookie or # environemntal variable in documentation references. # # -H # Set this to the hostname you want added to a mail # address appearing in the RFC822 field which lack a # hostname. It is usefull on the command line when servicing # virtual hosts. These are easy enough and needed for other reasons as well. The first (-L) will need to be added completely while the (-H) is already there as DOMAINADDR, hm_domainaddr. This was done since usually it is not a hostname that you want there but instead is a domain name. It can be used either way. # %L - name of current list # %H - name of current host. Convienient for archiving with virtual hosting. These would be very useful in the list's header and footer .hyp files. I can see how this would be useful for virtual hosts. I could use it here as well ;) I do have some questions about the .hmrc file usage though. # For example for a default .hmrc file: # # hm_label = Hypermail discussion list for %L@%H # hm_archives = http://%H # hm_about = http://%H/%L # hm_dir = /var/hypermail/%H/%L/%y/%M # hm_ihtmlheaderfile = /var/hypermail/%H/%L/owner/idxheader.hyp # hm_ihtmlfooterfile = /var/hypermail/%H/%L/owner/idxfooter.hyp # hm_mhtmlheaderfile = /var/hypermail/%H/%L/owner/msgheader.hyp # hm_mhtmlfooterfile = /var/hypermail/%H/%L/owner/msgfooter.hyp # hm_hmail = %L@%H What is done if there are no values for %H and %L when first encountered ? It is possible to '#define LISTNAME "NONE"' in options.h, not set the HM_LISTNAME environment variable and then find no hm_listname or hm_hostname in the .hmrc file for the list. Then the above config file input would be hm_label = Hypermail discussion list for @ hm_archives = http:// hm_about = http:/// hm_dir = /var/hypermail///%y/%M hm_ihtmlheaderfile = /var/hypermail///owner/idxheader.hyp hm_ihtmlfooterfile = /var/hypermail///owner/idxfooter.hyp hm_mhtmlheaderfile = /var/hypermail///owner/msgheader.hyp hm_mhtmlfooterfile = /var/hypermail///owner/msgfooter.hyp hm_hmail = @ Should it bail if hypermail is called without a value in a substitution cookie ? Today it doesn't. # Does this seem reasonable enough? Mostly a more frequently used variable # substitution routine. Yes it is quite reasonable. # A more difficult endevor which could also be helpful would be to leverage # off of the case where %L is used in the hm_dir variable along with other # date formats (%y, %M, etc) being used. In this case, it would be nice to # have Hypermail generate the "homepage(s)" for the directory traversals on # the fly. The page would need to be created initially (-d option) and then # updated anytime a new directory was automaticaly created. # # If this were done, then two addition .hyp files would be good: # hm_lhtmlheaderfile = /var/hypermail/%H/%L/owner/lstheader.hyp # hm_lhtmlfooterfile = /var/hypermail/%H/%L/owner/lstfooter.hyp # # Probably put a link to my search engine in "hm_lhtmlfooterfile".... So... In essence be able to create a top level index for all the year/month directories ? For example, in the hypermail list archives here I have two types of directories at the Top level, 1. hypermail generated archives separated by month/year, 2. a mailbox directory that keeps a copy of the inbond messages in unix mailboxes separated by month Here is what I mean. hypermail/mail-archive: drwxr-xr-x 9 lists daemon 512 Oct 6 11:48 2000 lrwxrwxrwx 1 kent kent 13 Apr 23 23:45 index.html drwxr-xr-x 2 lists daemon 512 Oct 2 20:27 mailbox hypermail/mail-archive/2000: drwxr-xr-x 2 lists daemon 1536 Oct 6 11:31 Apr drwxr-xr-x 2 lists daemon 1024 Oct 6 11:33 Aug drwxr-xr-x 2 lists daemon 512 Oct 6 11:33 Jul drwxr-xr-x 2 lists daemon 1536 Oct 6 11:33 Jun drwxr-xr-x 2 lists daemon 1024 Oct 6 11:32 May drwxrwxr-x 2 lists daemon 512 Oct 7 10:12 Oct drwxr-xr-x 2 lists daemon 1536 Oct 6 11:34 Sep hypermail/mail-archive/2000/Apr: -rw-r--r-- 1 lists daemon 4678 Oct 6 11:31 0000.html ... -rw-r--r-- 1 lists daemon 8813 Oct 6 11:31 author.html -rw-r--r-- 1 lists daemon 7469 Oct 6 11:31 date.html -rw-r--r-- 1 lists daemon 7753 Oct 6 11:31 index.html /ftp/hypermail/mail-archive/2000/May: /ftp/hypermail/mail-archive/2000/Jun: /ftp/hypermail/mail-archive/2000/Jul: /ftp/hypermail/mail-archive/2000/Aug: /ftp/hypermail/mail-archive/2000/Sep: /ftp/hypermail/mail-archive/2000/Oct: /ftp/hypermail/mail-archive/mailbox: -rw-r--r-- 1 lists daemon 159819 May 25 23:09 hypermail.9804 ... -rw-r--r-- 1 lists daemon 33048 Oct 7 10:12 hypermail.9810 So in this case I would need to create a Top level index in the hypermail/mail-archive directory that links in the entire archive. I would then need to have a year index file in hypermail/mail-archive/2000 that linked in the separate months. The individual months are already handled. ;) Then when I incorporate the ability for hypermail to save a copy of the inbound message in mailbox format prior to generating a html page for it, I'll need to have an index generated for that. Is this the type of thing that we are talking about ? Don't get me wrong... I'm trying to understand what we looking at so that I can see how to make it generic enough to implement and administer. # Not sure how much of this has been discussed before, or how active # development is, having recently joined your list. The indexing has not been discussed as to how to do it right... As of this morning, the TODO list has the following items on it about indexing.: ----------- - Make it optional as to what, if any, indexes are generated. - Make the formating of index pages use magic cookies for all parts of the page. - Make it optional that a site generate index files with the listings sorted by date in one file and reverse sorted in the other index. This pertains to all index types as well. For example: one thread-index with the newest mails topmost one thread-index with the oldest mails topmost one author-index in alphabetical order one author-index in reversed alphabetical or etc. - Generate an index listing of all stored attachments. Also have links to the mail that contained them. ----------- We need to discuss how it might be used so we can see what can be done about improving it... -- Kent Landfield Phone: 1-817-545-2502 Email: kent@landfield.com http://www.landfield.com/ Email: kent@nfr.net http://www.nfr.net/ Please send comp.sources.misc related mail to kent@landfield.com Search the Usenet FAQ Archive at http://www.faqs.org/faqs/ From owner-hypermail Wed Oct 7 11:55 CDT 2000 Received: by landfield.com (8.9.0/8.9.0) id LAA19556 for hypermail-outgoing; Wed, 7 Oct 2000 11:55:28 -0500 (CDT) Received: from fw-es06.hac.com (fw-es06.HAC.COM [128.152.1.6]) by landfield.com (8.9.0/8.9.0) with ESMTP id LAA19549 for ; Wed, 7 Oct 2000 11:55:11 -0500 (CDT) Received: from pepperoni.pizza.hac.com (bdarr@[192.27.36.100]) by fw-es06.hac.com (8.8.4/8.8.4) with ESMTP id JAA25234 for ; Wed, 7 Oct 2000 09:52:41 -0700 (PDT) Received: (from bdarr@localhost) by pepperoni.pizza.hac.com (8.8.6/8.8.6) id JAA02634; Wed, 7 Oct 2000 09:52:41 -0700 (PDT) Date: Wed, 7 Oct 2000 09:52:41 -0700 (PDT) Message-Id: <200010071652.JAA02634@pepperoni.pizza.hac.com> From: "Byron C. Darrah" To: hypermail@landfield.com In-reply-to: (message from Daniel Stenberg on Wed, 7 Oct 2000 16:10:39 +0200 (MET DST)) Subject: Re: indexes Sender: owner-hypermail@landfield.com Precedence: bulk Reply-To: "Byron C. Darrah" Content-Type: text Content-Length: 1545 Status: OR > On Wed, 7 Oct 2000, Mark Clear wrote: > > > Ohmygoodness, optional, please! With over 5K messages in some of my > > archives (the client is always right), it's already all my poor little > > CPU can do to crunch the index before the next message comes flying in. Humble suggestion: If you really have messages coming in that frequently, and they get piped to hypermail so that there's a chance two hypermail processes could be competing to write the index files then there's probably a better way to do what you want, so that you can eliminate the risk of corrupted indexes. For example, what I do at my site (and I would not be surprised to learn that a lot of other people do too) is direct incoming mail for an archive to an mbox file instead of piping it to hypermail. Then, at periodic intervals a cron job runs a Makefile that runs hypermail if and only if there are any new messages to be added to the archive. Of course, you would set the cron job's period to something greater than the amount of time it takes for your computer to update the hypermail archive to gurantee that two hypermail processes wont compete. Make can check the status of an archive extremely efficiently with a rule something like this: index.html: mbox # Do stuff to add new messages to archive So even if you have ten archives set up this way and let the cron jobs run as often as once per minute, you probably won't even be able to notice any load on your system except when there are actually new messages being processed. Cheers. From owner-wu-ftpd@wugate.wustl.edu Wed Oct 7 12:09 CDT 2000 Received: from wugate.wustl.edu (wugate.wustl.edu [128.252.120.1]) by landfield.com (8.9.0/8.9.0) with ESMTP id MAA19743 for ; Wed, 7 Oct 2000 12:09:32 -0500 (CDT) Received: from host (wugate.wustl.edu [128.252.120.1]) by wugate.wustl.edu (8.8.8/8.8.5) with SMTP id MAA08274; Wed, 7 Oct 2000 12:07:31 -0500 (CDT) Message-Id: <200010071703.MAA30380@wugate.wustl.edu> Date: Wed, 7 Oct 2000 12:03:55 -0500 (CDT) Reply-To: listproc@wugate.wustl.edu Sender: owner-wu-ftpd@wugate.wustl.edu From: listproc@wugate.wustl.edu To: nadeem@wugate.wustl.edu, kent@landfield.com Subject: Error Condition Re: Warning: could not send message for past 4 hours X-Listprocessor-Version: 8.0 -- ListProcessor(tm) by CREN Content-Type: text Content-Length: 3701 Status: OR Rejected message: sent to wu-ftpd@wugate.wustl.edu by MAILER-DAEMON follows. Reason for rejection: message addressed to owners. Recorded new error message: ... DEFERRED: CONNECTION TIMED OUT WITH GALA.WASHTENAW.CC.MI.US. ------------------------------------------------------------------------------- >From MAILER-DAEMON Wed Oct 7 12:03:55 2000 Received: from localhost (localhost) by wugate.wustl.edu (8.8.8/8.8.5) with internal id MAA30380; Wed, 7 Oct 2000 12:03:55 -0500 (CDT) Date: Wed, 7 Oct 2000 12:03:55 -0500 (CDT) From: Mail Delivery Subsystem Message-Id: <200010071703.MAA30380@wugate.wustl.edu> To: MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="MAA30380.907779835/wugate.wustl.edu" Subject: Warning: could not send message for past 4 hours This is a MIME-encapsulated message --MAA30380.907779835/wugate.wustl.edu ********************************************** ** THIS IS A WARNING MESSAGE ONLY ** ** YOU DO NOT NEED TO RESEND YOUR MESSAGE ** ********************************************** The original message was received at Wed, 7 Oct 2000 07:55:07 -0500 (CDT) from wugate.wustl.edu [128.252.120.1] ----- The following addresses had transient non-fatal errors ----- ----- Transcript of session follows ----- ... Deferred: Connection timed out with gala.washtenaw.cc.mi.us. Warning: message still undelivered after 4 hours Will keep trying until message is 5 days old --MAA30380.907779835/wugate.wustl.edu Content-Type: message/delivery-status Reporting-MTA: dns; wugate.wustl.edu Arrival-Date: Wed, 7 Oct 2000 07:55:07 -0500 (CDT) Final-Recipient: RFC822; rex@gala.washtenaw.cc.mi.us Action: delayed Status: 4.4.1 Remote-MTA: DNS; gala.washtenaw.cc.mi.us Last-Attempt-Date: Wed, 7 Oct 2000 12:03:55 -0500 (CDT) Will-Retry-Until: Mon, 12 Oct 2000 07:55:07 -0500 (CDT) --MAA30380.907779835/wugate.wustl.edu Content-Type: message/rfc822 Return-Path: Received: from host (wugate.wustl.edu [128.252.120.1]) by wugate.wustl.edu (8.8.8/8.8.5) with SMTP id HAA29962; Wed, 7 Oct 2000 07:55:07 -0500 (CDT) Received: from mail.vr.net (lundberg@mail.vr.net [205.133.13.8]) by wugate.wustl.edu (8.8.8/8.8.5) with ESMTP id HAA30939 for ; Wed, 7 Oct 2000 07:47:54 -0500 (CDT) Received: from localhost (lundberg@localhost) by mail.vr.net (8.9.1a/8.9.1) with ESMTP id IAA05683; Wed, 7 Oct 2000 08:46:35 -0400 Message-Id: Date: Wed, 7 Oct 2000 08:46:35 -0400 (EDT) Reply-To: lundberg+wuftpd@vr.net Sender: owner-wu-ftpd@wugate.wustl.edu From: Gregory A Lundberg To: thianlengvictor.tan@bnpgroup.com Cc: Wu-Ftpd@wugate.wustl.edu Subject: Re: malloc error In-Reply-To: <48256696.0010619C.00@SMTP_PARIS1.bnpgroup.com> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Listprocessor-Version: 8.0 -- ListProcessor(tm) by CREN On Wed, 7 Oct 2000 thianlengvictor.tan@bnpgroup.com wrote: > I've just tried to ftp download a file from my server (AIX 4.3.1 running > wuftpd ver 2.4.2 beta-18 vr8 aix.3.2.5) using EXCEED as my FTP client. This > is the error message I got : > > 451 local resource failure : malloc : Invalid argument Can you get a log of the commands so I can see what's happening and track this down? -- Gregory A Lundberg Senior Partner, VRnet Company 1441 Elmdale Drive lundberg+wuftpd@vr.net Kettering, OH 45409-1615 USA 1-800-809-2195 --MAA30380.907779835/wugate.wustl.edu-- ================================================ FILE: tests/stdintest.pl ================================================ #!/usr/local/bin/perl require POSIX; use POSIX; $sec = time(); print `rm -f testdir/*`; $hypermail="../src/hypermail -i -1 -u -d testdir -l foo "; for(1 .. 15) { @now=localtime($sec); $nowfrom = strftime("%a %b %d %H:%M:%S %Y", @now); $nowdate = strftime("%a, %d %b %Y %H:%M:%S +0100 (%Z)", @now); open(HMAIL, "|$hypermail") || die "can't run it"; print HMAIL "From anon0\@anon.net $nowfrom\n", "Date: $nowdate\n", "Message-ID: \n", "Subject: What about a message number $_\n", "From: $_ Loser \n", "To: $_ Anonymous \n", "\n", "DUMMY MESSAGE BODY $_\n"; close(HMAIL); $sec += 1; } ================================================ FILE: tests/test-footer.hyp ================================================

    [ Usenet Hypertext FAQ Archive | Search Mail Archive | Authors | Usenet ]
    [ 1993 | 1994 | 1995 | 1996 | 1997 ]

    ---------

    This archive was generated by %u on %g

    %m

    © Copyright The Internet FAQ Consortium, 1997
    All rights reserved

    ================================================ FILE: tests/test-index.hyp ================================================ %l %s %A %S

    %l
    %s

    ---------

    ================================================ FILE: tests/test-msg.hyp ================================================ %l: %s %A %S

    %s

    ---------

    ================================================ FILE: tests/test.rc ================================================ # # This is the hypermail test rc config file. # language = en htmlsuffix = html mbox = testmail archives = ../ about = ../ label = We Be TeStInG List Software List dir = testdir defaultindex = subject overwrite = 1 inlinehtml = 1 increment = 1 readone = 0 reverse = 1 #progress = 0 #progress = 1 progress = 2 #showheaders = 0 show_headers = * #show_headers = Subject,Date,From show_headers = X-Mailer,Status showhtml = 1 showbr = 1 showreplies = 1 show_msg_links = 1 show_index_links = 1 #usetable = 1 usetable = 0 #indextable = 1 indextable = 0 iquotes = 1 eurodate = 0 discard_dup_msgids = 0 require_msgids = 1 usemeta = 0 #dateformat = %Y/%m/%d - %H:%M %Z attachmentlink = attachmentsindex = On uselock = 1 locktime = 3600 thrdlevels = 9 dirmode = 0755 filemode = 0644 #mailcommand = mailto:$TO?subject=$SUBJECT&replyto=$ID #newmsg_command=mailto:$TO #replymsg_command=mailto:$TO?Subject=$SUBJECT mailto = webmusket@hypermail.org domainaddr = hypermail.org #hmail = hypermail@hypermail.org stripsubject = [hypermail] linkquotes = 0 searchbackmsgnum = 500 quote_hide_threshold = 100 quote_link_string = Link link_to_replies = Reply monthly_index = 0 yearly_index = 0 #thread_file_depth = 1 #folder_by_date = %y%m #msgsperfolder = 100 latest_folder = current describe_folder = "%b %Y" iso2022jp = 0 isodate = 1 gmtime = 0 usegdbm = 0 append = 1 append_filename = $DIR/INBOX #avoid_indices = subject author #avoid_top_indices = date thread #base_url = http://www.hypermail.org/mail-archive/ #txtsuffix = txt #delete_older = "Wed, 14 Mar 2001 12:59:51 +0200" #delete_newer = "Wed, 28 Mar 2001 12:59:51 +0200" deleted = "X-Hypermail-Deleted X-No-Archive" expires = Expires #delete_msgnum = 0 42 666 delete_level = 1 #filter_out=From:.+@spammers.com #filter_require = hypermail #filter_out_full_body = BUY #filter_require_full_body = [Ff]ree #save_alts = 2 alts_text = "alternate version of message" warn_suppressions = 1 unsafe_chars = "." #spamprotect = 1 #spamprotect_id = Off # antispamdomain = #correctly ignored # antispamdomain = "" #leaves quote marks in the url # antispamdomain = " " #works, leaves a space in the url # antispamdomain = "email_protected" #works #antispamdomain = "email.domain.hidden" #works text_types = message/DELIVERY-STATUS inline_types = "image/gif image/jpeg image/png" ignore_types = text/x-vcard ignore_types = application/x-msdownload prefered_types = text/plain text/html #ihtmlheaderfile = test-index.hyp #ihtmlfooterfile = test-footer.hyp #mhtmlheaderfile = test-msg.hyp #mhtmlfooterfile = test-footer.hyp #applemail_hack = On ================================================ FILE: tests/testhm.in ================================================ #!/bin/sh # # Stupid script for running strange command lines... # Uncomment the ones you want to play with. # You need a mailbox named testmail in the current directory to # use this as is. The t1 ... t12 files are individual messages. # set -x HYPERMAIL=../src/hypermail@suffix@ LABEL="I B TeStInG List" ABOUT="../" TESTMAIL=testmail cleanup_testdir() { if [ -d testdir ]; then rm -rf testdir fi } ################## # Test with a mailbox that has had all the dates changes to 2000+ # to test y2k capabilities ################## # test_configuration_file_with_mailbox_usage_y2k() { cleanup_testdir $HYPERMAIL -c test.rc -m mboxes/y2k.mbox } ################## # Test updating an existing archive with a single message from # a mailbox ################## # test_single_msg_archive_update_from_mailbox() { # Test the ability of hypermail to update an archive by only # one message when the message comes from a mailbox. cleanup_testdir $HYPERMAIL -p -m $TESTMAIL -d testdir -l "${LABEL}" -a "${ABOUT}" $HYPERMAIL -p -u -m mboxes/1msg.mbox -d testdir -l "${LABEL}" -a "${ABOUT}" } ################## # Test generating an archive from a mailbox with no config file used ################## # test_archive_gen_with_no_overwrite_from_mailbox_no_config_file() { cleanup_testdir $HYPERMAIL -p -m $TESTMAIL -d testdir -l "${LABEL}" -a "${ABOUT}" } ################## # Test overwriting an archive from a mailbox with no # config file used ################## # test_overwrite_archives_from_mailbox_no_config_file() { cleanup_testdir cat $TESTMAIL > mboxes/overwrite.mbox $HYPERMAIL -p -x -m mboxes/overwrite.mbox -d testdir -l "${LABEL}" -a "${ABOUT}" cat mboxes/1msg.mbox >> mboxes/overwrite.mbox $HYPERMAIL -p -x -m mboxes/overwrite.mbox -d testdir -l "${LABEL}" -a "${ABOUT}" rm mboxes/overwrite.mbox } ################## # Test using a configuration file # and specifying a mailbox to read. ################## # test_configuration_file_with_mailbox_usage() { cleanup_testdir $HYPERMAIL -c test.rc -m $TESTMAIL } ################## # Test messages coming in on stdin with no configuration file used ################## # test_messages_coming_on_stdin() { cleanup_testdir for i in mboxes/t[0-9]* do cat $i | $HYPERMAIL -p -i -u -l "test" \ -d "testdir" \ -b "http://www.wildheart.org/archives/wire/about.html" \ -a "http://www.wildheart.org/archives/" sleep 1 if [ -r core ]; then echo "It cooooored" exit fi done } ################## # Test messages coming in on stdin with a configuration file used # and overriding some command line options ################## # test_messages_coming_on_stdin_with_config_file_used() { cleanup_testdir for i in mboxes/t[0-9]* do cat $i | $HYPERMAIL -p -i -u -l "test" \ -c "test.rc" \ -d "testdir" \ -b "http://www.wildheart.org/archives/wire/about.html" \ -a "http://www.wildheart.org/archives/" sleep 1 done } ################## # Test messages from mailbox with a configuration file used # and overriding some command line options ################## # test_msgs_from_mailbox_config_file_used_and_overriding_options() { cleanup_testdir $HYPERMAIL -p -m "$TESTMAIL" -x -l "test" \ -c "test.rc" \ -d "testdir" } ################## # Test messages from mailbox with a configuration file used # and overriding some command line options ################## # test_embedded_msg() { cleanup_testdir cat test.rc | sed "s/^discard_dup_msgids.*$/discard_dup_msgids = 0/" > dtest.rc $HYPERMAIL -p -m "mboxes/embedded.msg" -x -c "dtest.rc" rm -f dtest.rc } # test_configuration_file_with_mailbox_usage_y2k # test_single_msg_archive_update_from_mailbox # test_archive_gen_with_no_overwrite_from_mailbox_no_config_file # test_overwrite_archives_from_mailbox_no_config_file # test_messages_coming_on_stdin # test_messages_coming_on_stdin_with_config_file_used # test_msgs_from_mailbox_config_file_used_and_overriding_options # test_embedded_msg test_configuration_file_with_mailbox_usage exit 1